我想使用include指令仅针对特定目标.当不需要目标时,我不想运行其他makefile,因为这意味着makefile不必要地生成.
那么有条件地使用include指令的方法是有条件的吗?或者以某种方式使include指令成为目标的先决条件.
这是我到目前为止
# Flags INCDIR = $(CURDIR)/include CFLAGS = -Wall -Wno-overflow -Wno-uninitialized -pedantic -std=c99 -I$(INCDIR) -O3 LFLAGS = -flat_namespace -dynamiclib -undefined dynamic_lookup # Directory names # Set vpath search paths vpath %.h include vpath %.c src vpath %.o build vpath %.d build # Get files for the core library CORE_FILES = $(wildcard src/*.c) CORE_OBJS = $(patsubst src/%.c,build/%.o,$(CORE_FILES)) CORE_DEPS = $(CORE_OBJS:.o=.d) # Core library target linking core : $(CORE_OBJS) | bin $(CC) $(LFLAGS) -o bin/libcbitcoin.2.0.dylib $(CORE_OBJS) # Include header prerequisites (How to do only for "core" target?) include $(CORE_DEPS) # Makefiles for header dependencies. $(CORE_DEPS): build/%.d: src/%.c | build rm -f $@; \ $(CC) -I$(INCDIR) -MM $< -MT '$(@:.d=.o) $@' > $@ # Objects depend on directory $(CORE_OBS) : | build # Create build directory build: mkdir build # Create bin directory bin: mkdir bin # Core Compilation $(CORE_OBJS): build/%.o: src/%.c $(CC) -c $(CFLAGS) $< -o $@ # Depencies require include/CBDependencies.h as a prerequisite build/CBOpenSSLCrypto.o: include/CBDependencies.h # Crypto library target linking crypto : build/CBOpenSSLCrypto.o -lcrypto -lssl | bin $(CC) $(LFLAGS) -o bin/libcbitcoin-crypto.2.0.dylib build/CBOpenSSLCrypto.o -lcrypto -lssl # Crypto library compile build/CBOpenSSLCrypto.o: dependencies/crypto/CBOpenSSLCrypto.c $(CC) -c $(CFLAGS) $< -o $@ #Clean clean: rm -f $(CORE_OBJS) $(CORE_DEPS) build/CBOpenSSLCrypto.o
正如你应该能够告诉我不需要包含“.”文件为“加密”,但我做“核心”(默认目标).
感谢您的任何帮助.
解决方法
制作不是一种程序性的语言,所以把它当作一种对付粮食;您的makefile将难以扩展,并且可能会导致细微的错误.
Tom Tromey有一个better way是干净,高效和可扩展的.诀窍是意识到您可以在与目标文件相同的步骤中构建依赖关系文件.依赖关系简单地告诉Make当对象被重建时;您首先构建对象时不需要它们,因为Make知道必须构建对象.如果依赖关系发生变化,那只能是因为源或旧依赖关系中的东西已经改变,所以再次知道对象必须重建. (这不是很明显,所以可能需要一点心血.)
$(CORE_OBJS): build/%.o: src/%.c $(CC) -c $(CFLAGS) $< -o $@ $(CC) -MM -MF build/$*.d $< -include build/*.d
还有一个问题:如果您更改代码以删除依赖关系,并删除该文件,则无法重建,因为旧的依赖关系列表仍将要求不能再找到的文件.复杂的解决方案是处理依赖关系文件,以便使自己的每个先决条件(例如,头)本身都没有任何命令,从而可以假定在需要时重建它:
$(CORE_OBJS): build/%.o: src/%.c $(CC) -c $(CFLAGS) $< -o $@ $(CC) -MM -MF build/$*.d $< @cp build/$*.d build/$*.P @sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < build/$*.P >> build/$*.d; @rm build/$*.P
一个粗鲁的方法,但几乎是万无一失的,是为标题和来源提供全面的规则:
$(CORE_OBJS): build/%.o: src/%.c $(CC) -c $(CFLAGS) $< -o $@ $(CC) -MM -MF build/$*.d $< %.cc %.h:
编辑:
要分解新的命令:
-MM选项告诉gcc为目标文件生成一个make规则,而不是预处理或编译.默认是将规则发送到发送预处理输出的地方,通常是stdout.
-MF选项与-MM一起使用,指定输出文件.所以-MM -MF build / $* .d将把规则放在我们想要的地方.
所以以下两个命令(几乎总是)等效:
$(CC) -MM -MF build/$*.d $< $(CC) -MM $< > build/$*.d
(我已经省略了-I $(…)和使用-MMD选项的可能性,因为两者都有点复杂,而不是真正的问题.)