简体   繁体   English

如何根据Makefile中各自的标头依赖关系来构建多个源文件?

[英]How to build multiple Source files according to their respective headers Dependency in Makefile?

I found it obscure to use make utility to generate header dependencies makefile for the source file and using this build the library or create executable accordingly. 我发现使用make实用程序为源文件生成标头依赖项makefile并使用此构建库或相应地创建可执行文件是晦涩的。

1) 1)

As suggested in the manual: 如手册中所建议:

http://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites http://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites

I tried with the approach mentioned over there (In my case dependency files are present under obj/): 我尝试了上面提到的方法(在我的情况下,依赖文件位于obj /下):

obj/%.d:%.cpp
    @set -e; rm -f $@; \
    g++ -MM $(CPPFLAGS) ${INC_FLAGS} $< > $@.$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    rm -f $@.$$$$

But this throws a shell error: 但这会引发外壳错误:

/bin/sh: cannot create obj/xyz.d.23030: Directory nonexistent

However obj directory is present, I didn't understand the use of sed command. 但是存在obj目录,我不理解sed命令的使用。 The manual explains that it replaces any " .obj : .cpp " rule to ". obj .dep : .cpp ", But How ? 该手册解释说,它将“ .obj:.cpp ”规则替换为“ .obj.dep:.cpp ”,但是如何?

2) I also tried the approach mentioned over here : 2)我也尝试过这里提到的方法:
http://mad-scientist.net/make/autodep.html http://mad-scientist.net/make/autodep.html

obj/%.o : %.c
    g++ -MMD ${CPPFLAGS} ${INC_FLAGS} -c $$<  -o $$@
    @cp obj/$*.d obj/$*.P; \
    sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
        -e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
    rm -f $*.d

Using this dependency file is generated but following error message is asserted: 使用此依赖项文件已生成,但断言了以下错误消息:

"/bin/sh: cannot open obj/%.P: No such file"
sed: -e expression #2, char 4: unterminated `s' command

Again use of sed is not clear. 再次使用sed尚不清楚。

This becomes more obfuscate ... Here In the second approach if I don't add separate rule to create dependency files and generate them at the time of object creation, As "g++ -MP -MMD -c" creates both .o and .d. 在第二种方法中,如果我不添加单独的规则来创建依赖文件并在创建对象时生成依赖文件,则在第二种方法中,由于“ g ++ -MP -MMD -c”会同时创建.o和。 d。 But how .o will be compiled again using the dependency makefile which is generated in the same command ? 但是,如何使用在同一命令中生成的依赖关系生成文件再次编译.o呢?

I appreciate any help in resolving the errors occurred, And helping me in understanding this. 感谢您为解决发生的错误提供的帮助,并帮助我了解了这一点。 Or Please suggest some elegant approach to do the same. 或者,请提出一些优雅的方法来做到这一点。

EDIT : (As suggested in the comment) In the second approach using both -MMD and -MP it works as expected, But I can't understand how it's working. 编辑:(如注释中所建议)在同时使用-MMD和-MP的第二种方法中,它按预期工作,但是我不明白它的工作方式。 Here sed comamnd is not required, and source gets rebuild if related header is modified: 此处不需要sed comamnd,并且如果修改了相关标头,则源将得到重建:

obj/%.o : %.c g++ -MMD -MP ${CPPFLAGS} ${INC_FLAGS} -c $$< -o $$@ obj /%。o:%。c g ++ -MMD -MP $ {CPPFLAGS} $ {INC_FLAGS} -c $$ <-o $$ @

But As described in gcc manual page , If I didn't interpreted it wrong -MMD used to generate the dependency(excluding system header) file and -MP used to generate empty rule for each header, But it only modifies the object rule: ie, 但是,如gcc手册页所述 ,如果我没有解释错,-MMD用于生成依赖项(不包括系统头文件),而-MP用于为每个头生成空规则,但它只会修改对象规则:即,

obj/%.o obj/%.d : %.cpp (This is what sed is doing as mentioned in GNU make manual) obj/%.o obj/%.d : %.cpp (这是sed所做的,如GNU make手册中所述)

or something like, 或类似的东西,

obj/%.o : %.cpp (list of dependent headers for particular .cpp file)

What is the use of following two commands and how it works ? 以下两个命令的用途是什么?它是如何工作的?

a) sed 's,\\($*\\)\\.o[ :]*,\\1.o $@ : ,g' < $@.$$$$ > $@; a) sed 's,\\($*\\)\\.o[ :]*,\\1.o $@ : ,g' < $@.$$$$ > $@;

b) b)

sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
                -e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P;

However obj directory is present, 但是存在obj目录,

Apparently it isn't. 显然不是。 That's the first thing you need to solve. 那是您需要解决的第一件事。

I didn't understand the use of sed command. 我不了解sed命令的用法。 The manual explains that it replaces any ".obj : .cpp" rule to ".obj .dep : .cpp" , But How ? 该手册解释说,它将“ .obj:.cpp”规则替换为“ .obj .dep:.cpp”规则,但是如何?

The special make variable $* contains the stem that matched the pattern of the target, which will be the part of the target that matches the pattern % 特殊的make变量$*包含与目标模式匹配的词干,它将是目标与模式%匹配的部分

The sed command replaces obj/%.o: with obj.o obj.d: , exactly as the Make manual says. sed命令完全按照Make手册中的说明将obj/%.o: obj.o obj.d:替换为obj.o obj.d: To explain "how" you need to understand sed, but it's not a very complicated sed command. 要解释“如何”,您需要了解sed,但这不是一个非常复杂的sed命令。

Using this dependency file is generated but following error message is asserted: 使用此依赖项文件已生成,但断言了以下错误消息:

That make recipe has a # character, which means everything after it is a comment, you need to escape it with \\# 该make配方具有#字符,这意味着注释后的所有内容,都需要使用\\#进行转义

However, if you're using GCC it's easier to just add -MMD to the normal recipe for generating object files, which will produce the .d files as a side-effect of compilation, so you don't need a separate target for the .d files. 但是,如果您使用的是GCC,则将-MMD添加到用于生成目标文件的常规配方中会更容易,这将生成.d文件作为编译的副作用,因此您不需要为该目标创建单独的目标.d文件。

So this is a makefile I wrote for one of my modules at university, you can try using it, when you call make it generates all the files and links all the files without needing to define anything extra in the file. 因此,这是我在大学为我的一个模块编写的makefile,可以尝试使用它,当调用make时,它会生成所有文件并链接所有文件,而无需在文件中定义任何其他内容。 There is a lot of excess stuff here, but I did this quite a while ago, but you can take things out and play around with it to see what you can remove. 这里有很多多余的东西,但是我很早以前就这样做了,但是您可以将其取出来并尝试使用它,看看可以删除什么。 Hope this helps =) 希望这可以帮助=)

CC=g++

WARNING_FLAGS=-Wall -Wextra -Weffc++ -Winit-self -Wmissing-include-dirs \
-Wswitch-default -Wswitch-enum -Wunused-parameter -Wstrict-overflow=5 \
-Wfloat-equal -Wshadow -Wc++0x-compat -Wconversion -Wsign-conversion \
-Wmissing-declarations -Wstrict-null-sentinel -Woverloaded-virtual -Wsign-promo\
-Werror -pedantic
FORMATTING_FLAGS=-fno-pretty-templates -fmessage-length=80 -fdiagnostics-show-option
CFLAGS=${WARNING_FLAGS} ${FORMATTING_FLAGS} -g -std=c++0x -pipe  -frepo

LDFLAGS=
LDLIBS=-lGL -lGLEW -lglut -lGLU -lX11 -lXi -lm -lpng

TARGET=main
OBJECTS=$(addsuffix .o, $(basename $(shell ls *.C | grep -v Test)))
HEADERS=$(addsuffix .h, $(basename $(shell ls *.h | grep -v Test)))

TEST_LDFLAGS=-lboost_unit_test_framework
TEST_LDLIBS=${LDLIBS}
TEST_TARGET=test
TEST_OBJECTS=$(addsuffix .o, $(basename $(shell ls *.C | grep -v main)))

CLEAN_TARGETS=$(addsuffix .o, $(basename $(shell ls *.C))) ${TARGET} ${TEST_TARGET} *.rpo *.gch makefile.dep

all: ${OBJECTS} 
    ${CC} ${LDFLAGS} ${LDLIBS} $^ -o ${TARGET}

test: ${TEST_OBJECTS}
    ${CC} ${TEST_LDFLAGS} ${TEST_LDLIBS} $^ -o ${TEST_TARGET}

%.o:
    ${CC} ${CFLAGS} -c ${LDFLAGS} $< -o $@

Test.o: Test.C Makefile
    ${CC} -c $< -o $@

clean:
    rm ${CLEAN_TARGETS}

makefile.dep: *.[Ch]
    for i in *.C; do gcc -std=c++0x -MM "$${i}"; done > $@
include makefile.dep

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM