我希望 GNU Make 中的食谱使用环境变量而不是命令行参数,以使它们更短,以便我可以更好地专注于每个命令中的更改。例如,而不是看到:
g++ -g -I/path1 -I/path2 -DFLAG -Wall -c hello.cpp -o hello.o
我想看到类似的东西:
g++ -c hello.cpp -o hello.o
whereg++
将从环境变量中读取包含目录和其他所有内容。因此,不要使用这个:
compile.cxx = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
%.o: %.cpp
$(compile.cxx) $< -o $@
我正在使用这个:
compile.cxx = CPATH="$(CPATH)" LIBRARY_PATH="$(LIBRARY_PATH)" bash -c $(CXX) -c
%.o: %.cpp
$(compile.cxx) $< -o $@
但我得到这个输出:
CPATH="irrelevant" LIBRARY_PATH="irrelevant" bash -c g++ -c hello.cpp -o hello.o
g++: fatal error: no input files
因此,似乎g++
没有收到其论点。
我也愿意接受能够达到类似效果的替代方案(即:简短的食谱)。
答案1
您可能想使用所谓的编译器响应文件,这在微软工具链。显然最新版本的 GCC 也支持它(参见手册)。
CXX = g++
CPPFLAGS = -I/path1 -I/path2 -DFLAG
CXXFLAGS = -g -Wall
CXXOPTS = $(CURDIR)/cxx.opts
%.o: %.cpp $(CXXOPTS)
$(CXX) @$(CXXOPTS) -c -o $@ $<
$(CXXOPTS):
echo "$(CPPFLAGS) $(CXXFLAGS)" >$@
clean:
rm -f *.o
rm -f $(CXXOPTS)
会话示例:
$ touch a.cpp b.cpp c.cpp
$ make a.o b.o c.o
echo "-I/path1 -I/path2 -DFLAG -g -Wall" >cxx.opts
g++ @cxx.opts -c -o a.o a.cpp
g++ @cxx.opts -c -o b.o b.cpp
g++ @cxx.opts -c -o c.o c.cpp
$ make clean
rm -f *.o
rm -f cxx.opts
答案2
这不是完整的答案,而是第一个提示,它看起来很丑陋
v:=bash -x -c "
all:
$vls -l"
但它有效。
答案3
你的问题很简单, bash -c 仅需要 1 个参数,而且很简单,你不需要它。尝试:
compile.cxx = CPATH="$(CPATH)" LIBRARY_PATH="$(LIBRARY_PATH)" $(CXX) -c
答案4
有些 makefile 被设置为通过使用可能很复杂的宏来打印一个命令并执行另一条命令。这是一个简单的方法:
ifeq(debug,)
cc = $(CC) $(CFLAGS)
else
cc = @cc () { echo "\$$(CC) $<"; $(CC) $(CFLAGS) "$$@" }; cc
endif
foo.o: foo.c
$(cc) $<
如果变量debug
具有非空值,则此代码片段将正常打印命令。否则,此代码片段会隐藏命令(命令行以 开头@
)并在执行实际命令之前打印替换的、更简单的命令。
我举了一个非常简单的例子。不同的项目中存在几个更复杂的变体。例如Linux内核使用了相当先进的方案。
我不建议这样做,因为它们使调试 makefile 变得更加困难。由于包含路径错误或其他原因,某些操作失败,并且 make 输出不会告诉您。将整个命令记录到文件并在终端上显示缩写命令的复杂方案是可以的。
为了使 make 的输出更具可读性,请考虑色彩制作反而。