我想知道是否有人有时间回答有关GNU makefile的一些问题......
这是我当前的makefile
OBJPATH=./obj
COMPILER=gcc
Output: main.o Base64.o
$(COMPILER) -o Output.exe $(OBJPATH)/main.o $(OBJPATH)/Base64.o
strip Output.exe
main.o: main.c main.h
$(COMPILER) -c main.c -o $(OBJPATH)/main.o
Base64.o: Base64.c Base64.h
$(COMPILER) -c Base64.c -o $(OBJPATH)/Base64.o
感谢。
答案 0 :(得分:2)
对于第一个问题,你可以在其他任何一个之前放置一个假目标,如下所示:
preamble:
-mkdir obj
main.o: preamble main.c
blah blah blah
在构建其他任何内容之前,它将自动执行前导码中的所有内容(您必须使其成为每个规则中的第一个依赖项)。 -
开头的mkdir
会忽略失败,例如,如果目录已经存在。
对于第二个问题,您可以提供类似的内容:
all: debug release
debug: blah blah blah
release: blah blah blah
实际上将调试和发布代码放在单独的子目录中。这样,您可以使用make release
或make debug
进行构建,并使用make all
构建两者。
第三个问题:你的makefile每次都会构建,因为规则告诉它。例如,Output: main.o Base64.o
将始终尝试构建,因为Output
永远不存在(正确的目标似乎是Output.exe
)。
同样,您的目标文件规则将始终执行,因为main.o
和Base64.o
都不会被其语句更新(它们会更新obj
目录中的文件)。
你可以通过制作目标$(OBJPATH)/main.o
来解决这个问题,但说实话,我通常不担心将对象和可执行文件分成不同的目录。我倾向于将它们全部放在一个目录中,让make -clean
清理它们。
所以我开始的makefile将是:
COMPILER=gcc
# Meta rules
all: release debug
release: Output.exe
debug: Output-d.exe
# Release stuff
Output.exe: main.o Base64.o
$(COMPILER) -o Output.exe main.o Base64.o
strip Output.exe
main.o: main.c main.h
$(COMPILER) -c main.c -o main.o
Base64.o: Base64.c Base64.h
$(COMPILER) -c Base64.c -o Base64.o
# Debug stuff
Output-d.exe: main-d.o Base64-d.o
$(COMPILER) -g -o Output-d.exe main-d.o Base64-d.o
main-d.o: main.c main.h
$(COMPILER) -g -DDEBUG -c main.c -o main-d.o
Base64-d.o: Base64.c Base64.h
$(COMPILER) -g -DDEBUG -c Base64.c -o Base64-d.o
回应您的评论问题:
无论如何我可以根据目标选择重新设置变量吗?例如,如果选择了调试OBJPATH =“。/ obj / Debug”,如果选择的版本OBJPATH将是“./obj/Release”?
GNU Make可能比我习惯的更强大,但你可以通过设置环境变量然后重新运行make来实现这一点:
all: release debug
release:
( export zzvar=release ; $(MAKE) zz_Output.exe )
debug:
( export zzvar=debug ; $(MAKE) zz_Output-d.exe )
zz_Output.exe:
echo $(zzvar)
touch zz_Output.exe
zz_Output-d.exe: zz_main-d.o zz_Base64-d.o
echo $(zzvar)
touch zz_Output-d.exe
输出:
( export zzvar=release ; make zz_Output.exe )
make[1]: Entering directory '/home/pax'
echo release
release <==
touch zz_Output.exe
make[1]: Leaving directory '/home/pax'
( export zzvar=debug ; make zz_Output-d.exe )
make[1]: Entering directory '/home/pax'
echo debug
debug <==
touch zz_Output-d.exe
make[1]: Leaving directory '/home/pax'
您可以看到上面标有<==
的两个独立变量。
正如我所说,使用GNU Make可能有一种更简单的方法,但这会让你开始。
答案 1 :(得分:1)
如果目录不存在(“./obj”)用于输出,如何创建目录?
rm -Rf ./obj && mkdir ./obj
我有一个makefile,但我有2个构建方法“Debug”和“Release”,我可以同时拥有1个makefile以及如何告诉它构建哪个?
您可以拥有多个顶级构建目标。 makefile中的Output
是顶级目标。做两个。一个叫做“Debug”,另一个叫“Release”。然后,您可以为调试版本说make Debug
,为发布版本说make Release
。
我一直在使用Code :: Blocks,它只构建已更改的文件,但我的makefile每次调用make命令时都会构建它们,而不会触及任何文件。我怎样才能让它只构建更改的文件?
我没有使用Code::Blocks
(我不知道它是什么)但是如果你的Makefile正确编写(即正确指定了依赖项),它只会重建所需的目标。
答案 2 :(得分:0)
回应您的评论问题:
无论如何我可以根据目标选择重新设置变量吗? 例如,如果选择的释放OBJPATH将是“./obj/Release” 选择调试OBJPATH =“./ obj / Debug”?
以下是没有递归的方法:
COMPILER=gcc
release: OBJPATH = obj
release: Output.exe
debug: OBJPATH = obj-dbg
debug: Outputd.exe
Output%.exe: main.o Base64.o
$(COMPILER) -o $@ $(OBJPATH)/main.o $(OBJPATH)/Base64.o
strip $@
main.o: main.c main.h
$(COMPILER) -c main.c -o $(OBJPATH)/main.o
Base64.o: Base64.c Base64.h
$(COMPILER) -c Base64.c -o $(OBJPATH)/Base64.o