优秀的编程知识分享平台

网站首页 > 技术文章 正文

C++/C入门之Gnu make进阶(__gnuc__)

nanyue 2024-07-19 23:59:49 技术文章 3 ℃

接上一篇《C++/C入门之Gnu make》。下面是上一篇中用到的一个makefile的例子。

#Alias definistion

OUTPUT_OPTION = -o $@

interim_obj = interim_target1.o interim_target2.o

CC = gcc

CPPFLAGS = -lstdc++

COMPILE.cpp = $(CC) $(CFLAGS) -c

LINK.cpp = $(CC) $(CFLAGS) $(CPPFLAGS)

# Pattern matching rules

Final_Target: $(interim_obj)

$(LINK.cpp) $(interim_obj) $(OUTPUT_OPTION)

$(interim_obj):%.o: %.cpp

$(COMPILE.cpp) lt; $(OUTPUT_OPTION)

run:Final_Target

./Final_Target

clean:

rm $(interim_obj) Final_Target

下面从make的视角,来逐一解读这个文件。解读的同时,会引申出一些makefile的规则。

这个makefile的第一个target是Final_Target。它又依赖于由变量interim_obj定义一些列文件。这些文件的生成规则由$(interim_obj):%.o:%.cpp指定。这是个多目标生成规则,之前没接触过,所以要引入一个新makefile的规则:静态模式。

静态模式规则可以抽象成:

<targets ...>: <target-pattern>: <prereq-patterns ...>

<commands>

其中targets是一个或多个目标集合。对于对象中的每个集合,如果它能匹配target-pattern(%.o),并且能找到匹配prereq-pattern的文件(%.cpp),且prereq-pattern的文件较新或目标文件不存在,则执行command的内容。

例子中的command翻译过来就是 gcc -c lt; -o $@,其中$@代表目标文件,lt;代表由prereq-pattern匹配的一系列文件。lt;和$@都是由make预定义的宏变量。

%是一个通配符。它能匹配一个或多个字符,但是同一次匹配中,target-pattern和prereq-pattern中的匹配部分要一致。

对上述文件执行完make后,输出是:

gcc -c interim_target1.cpp -o interim_target1.o

gcc -c interim_target2.cpp -o interim_target2.o

gcc -lstdc++ interim_target1.o interim_target2.o -o Final_Target

读者如果希望写出更强大的makefile来适应自己的工程编译的需要,下面是一些建议。

  1. 最简单的,复制上面的例子,重新指定interim_obj的文件列表。注意,command命令之前的空白不是空格,而是一个tab制表符。

  2. 如果你的源文件包含头文件,简单的做法是另行定义规则。gcc编译器能通过gcc -MM <源文件>来为你指出源文件所依赖的头文件。gcc -M则会同时包含被依赖的标准库文件。

  3. 更为复杂一点,如果你的源文件或者头文件分布在不同的目录,则可用vpath告诉make源文件的位置。如vpath %.h /usr/local/headlib/告诉makefile去对应的目录读取头文件集。

  4. 如果你希望一次make执行多个目标,则可用伪目标。如makefile的第一条规则是all:target1 target2,后边不跟任何命令。命令行输入make,实际效果是target1和target2被执行,all被执行时不做任何动作。

  5. GNU的make工作时的执行步骤入下:

    1、读入所有的Makefile。

    2、读入被include的其它Makefile。

    3、初始化文件中的变量。

    4、推导隐晦规则,并分析所有规则。

    5、为所有的目标文件创建依赖关系链。

    6、根据依赖关系,决定哪些目标要重新生成。

    7、执行生成命令。

  6. 掌握以上make的知识,将足够阅读和编写一下简单的make文件。

Tags:

最近发表
标签列表