如何通过一个非常简单的示例使用Makefile

我试图学习Makefile的工作原理,所以我决定用一个非常简单的代码来尝试它。这是我写的:

/* justify.c */

#include <stdio.h>
#include "line.h"
#include "word.h"

int main(void) {
    printf("I'm in the main.\n");
    read_word();
    write_line();
}
/* line.h */

void write_line(void);
/* line.c */

#include <stdio.h>
#include "line.h"

void write_line(void) {
    printf("write_line\n");
}
/* word.h */

void read_word(void);
/* word.c */

#include <stdio.h>
#include "word.h"

void read_word(void) {
    printf("read_word\n");
}

现在...如果我从终端执行所有操作,则可以正常工作:

> gcc -c justify.c
> gcc -c line.c
> gcc -c word.c
> gcc -o justify justify.c line.c word.c

但是如果我尝试使用Makefile进行所有操作,则会给我一个错误:

# Makefile 

justify: justify.o line.o word.o
    gcc -o justify.o line.o word.o

justify.o: justify.c line.h word.h
    gcc -c justify.c

line.o: line.c line.h
    gcc -c line.c

word.o: word.c word.h
    gcc -c word.c
> make justify

Undefined symbols for architecture x86_64:
  "_main",referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
xiashiwei1 回答:如何通过一个非常简单的示例使用Makefile

没有双关语,但是您正在使它变得比所需的要难。对于源和标头都在同一目录中的情况,使用通配符让make处理其余部分非常简单。例如,在Makefile中使用三个简单的变量声明,可以告诉您源文件,包含文件以及如何为不是应用程序名称的每个源文件生成目标文件。

对于初学者,请指定您的应用程序名称:

# application name
APPNAME := justify

如果需要,请设置您的编译器变量,例如

# compiler
CC      := gcc
CCLD    := $(CC)

现在让您知道您的应用程序名称保存在APPNAME中,您可以像访问Makefile中的其他变量一样将其保存为$(APPNAME)

现在只需使用wildcard收集所有源并包括变量,然后让make关联目标文件输出:

# source/include/object variables
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:%.c=%.o)

设置您的编译器/链接器/库标志:

# compiler and linker flags
CFLAGS  := -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
LDFLAGS :=
# libraries
LIBS    :=

现在为make创建默认目标(注意:每个规则前面必须有一个 tab字符 '\t'):

all:    $(OBJECTS)
    $(CCLD) -o $(APPNAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(LIBS)

将所有源编译为对象的规则:

$(OBJECTS): %.o : %.c
    $(CC) $(CFLAGS) -c -o $@ $<

(有关使用的自动变量的说明,请参见What do the makefile symbols $@ and $< mean?

最后是clean:

的目标
clean:
    rm -rf $(APPNAME) *.o

完整的文件示例为:

# application name
APPNAME := justify
# compiler
CC      := gcc
CCLD    := $(CC)
# compiler and linker flags
CFLAGS  := -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
LDFLAGS :=
# libraries
LIBS    :=
# source/include/object variables
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:%.c=%.o)

# target for all
all:    $(OBJECTS)
    $(CCLD) -o $(APPNAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(LIBS)
# strip only if -DDEBUG not set
ifneq ($(debug),-DDEBUG)
    strip -s $(APPNAME)
endif

$(OBJECTS): %.o : %.c
    $(CC) $(CFLAGS) -c -o $@ $<

clean:
    rm -rf $(APPNAME) *.o

注意strip可执行文件的规则也已添加到all:目标中)

示例构建

使用您的Makefile源,并将文件包含在公共目录中,例如

$ ll
total 24
-rw-r--r-- 1 david david 668 Nov  6 12:38 Makefile
-rw-r--r-- 1 david david 161 Nov  6 12:31 justify.c
-rw-r--r-- 1 david david 106 Nov  6 12:32 line.c
-rw-r--r-- 1 david david  37 Nov  6 12:31 line.h
-rw-r--r-- 1 david david 104 Nov  6 12:32 word.c
-rw-r--r-- 1 david david  36 Nov  6 12:32 word.h

只需键入make即可构建您的应用程序:

$ make
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o word.o word.c
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o line.o line.c
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o justify.o justify.c
gcc -o justify word.o line.o justify.o -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
strip -s justify

没有错误,您可以检查所有文件是否按预期创建:

$ ll
total 44
-rw-r--r-- 1 david david  668 Nov  6 12:38 Makefile
-rwxr-xr-x 1 david david 6312 Nov  6 13:01 justify
-rw-r--r-- 1 david david  161 Nov  6 12:31 justify.c
-rw-r--r-- 1 david david 1760 Nov  6 13:01 justify.o
-rw-r--r-- 1 david david  106 Nov  6 12:32 line.c
-rw-r--r-- 1 david david   37 Nov  6 12:31 line.h
-rw-r--r-- 1 david david 1496 Nov  6 13:01 line.o
-rw-r--r-- 1 david david  104 Nov  6 12:32 word.c
-rw-r--r-- 1 david david   36 Nov  6 12:32 word.h
-rw-r--r-- 1 david david 1496 Nov  6 13:01 word.o

测试您的可执行文件:

$ ./justifiy
I'm in the main.
read_word
write_line

最后,用make clean清理构建目录,例如

$ make clean

并确认已删除所有构建文件。

这是编写最少的make文件的最简单方法。您可以单独列出每个对象,并且必须包含支持它们的对象,但是为什么呢?自动变量将为您解决这一问题。您可以使用Makefile做更多的事情,但是对于入门而言,这将使您的生活更轻松。

,

您可以大大简化您拥有的64。 Make提供了许多有用的变量。

--#SET TERMINATOR @
CREATE OR REPLACE FUNCTION COUNT_DATABASE_ROWS()
RETURNS TABLE (P_TABSCHEMA VARCHAR(128),P_TABNAME VARCHAR(128),P_ROWS BIGINT)
BEGIN
  DECLARE L_STMT VARCHAR(256);
  DECLARE L_ROWS BIGINT;

  FOR V1 AS 
    SELECT TABSCHEMA,TABNAME 
    FROM SYSCAT.TABLES 
    WHERE TYPE IN ('T','S')
    FETCH FIRST 10 ROWS ONLY
  DO
    SET L_STMT = 'SET ? = (SELECT COUNT(*) FROM "'||V1.TABSCHEMA||'"."'||V1.TABNAME||'")';
    PREPARE S FROM L_STMT;
    EXECUTE S INTO L_ROWS;
    PIPE(V1.TABSCHEMA,V1.TABNAME,L_ROWS);
  END FOR;
  RETURN;
END@

SELECT * FROM TABLE(COUNT_DATABASE_ROWS())@
inlined compound

添加--#SET TERMINATOR @ CREATE OR REPLACE PROCEDURE COUNT_DATABASE_ROWS_DPF(OUT P_DOC XML) READS SQL DATA BEGIN DECLARE L_STMT VARCHAR(256); DECLARE L_ROWS BIGINT; DECLARE L_NODE XML; SET P_DOC = XMLELEMENT(NAME "DOC"); FOR V1 AS SELECT TABSCHEMA,'S') FETCH FIRST 10 ROWS ONLY DO SET L_STMT = 'SET ? = (SELECT COUNT(*) FROM "'||V1.TABSCHEMA||'"."'||V1.TABNAME||'")'; PREPARE S FROM L_STMT; EXECUTE S INTO L_ROWS; SET L_NODE = XMLELEMENT ( NAME "NODE",XMLELEMENT(NAME "TABSCHEMA",V1.TABSCHEMA),XMLELEMENT(NAME "TABNAME",V1.TABNAME),XMLELEMENT(NAME "ROWS",L_ROWS) ); SET P_DOC = XMLQUERY ( 'transform copy $mydoc := $doc modify do insert $node as last into $mydoc return $mydoc' passing P_DOC as "doc",L_NODE as "node" ); END FOR; END@ CREATE OR REPLACE FUNCTION COUNT_DATABASE_ROWS_DPF() RETURNS TABLE (P_TABSCHEMA VARCHAR(128),P_ROWS BIGINT) BEGIN ATOMIC DECLARE L_DOC XML; CALL COUNT_DATABASE_ROWS_DPF(L_DOC); RETURN SELECT * FROM XMLTABLE ('$D/NODE' PASSING L_DOC AS "D" COLUMNS TYPESCHEMA VARCHAR(128) PATH 'TABSCHEMA',TABNAME VARCHAR(128) PATH 'TABNAME',LENGTH BIGINT PATH 'ROWS' ); END@ -- Usage. Either CALL or SELECT: CALL COUNT_DATABASE_ROWS_DPF(?)@ SELECT * FROM TABLE(COUNT_DATABASE_ROWS_DPF())@

也是个好主意
Makefile
$@ - target name
$< - first prequisite
$^ - all prequsites
,

make文件中存在错误。生成目标justify:的命令缺少输出文件名。应该是这样的。

gcc -o justify justify.o line.o word.o

在您当前的命令行中,gcc将尝试通过链接line.o和word.o来输出justify.o,并且找不到_main,这在line.o和word.o中没有定义

make命令已经知道如何将.c文件转换为.o,因此您无需在make文件中告诉它再次进行make。请记住,以下make文件足以满足您的测试用例。

# Makefile 
justify: justify.o line.o word.o
    gcc -o justify justify.o line.o word.o

您可以使用make的内置自动变量进一步简化此操作。 $@$^$@变量包含规则目标的名称。 $^包含规则的所有前提条件的名称。因此,使用这两个变量,您的make文件将会是。

justify: justify.o line.o word.o
        gcc -o $@ $^
本文链接:https://www.f2er.com/3149782.html

大家都在问