>情况
我正在使用一个手写的GNUmakefile,其中CXXFLAGS
,CPPFLAGS
和LDFLAGS
被附加到+=
分配中,如下所示:
CXXFLAGS += -std=c++11 $(MODENV) $(WARNINGS) $(OPTIMS)
CPPFLAGS += $(DMACROS) $(INCDIRS)
LDFLAGS += $(MODENV) $(LIBDIRS) $(EXTRA_LIBS)
问题
当用户在命令行定义自己的标志时,将忽略 Makefile 中的追加。这样,变量就完全取决于用户设置的变量。(就我而言,构建将失败。此问题的通用解决方案是override
变量,如下所示:
override CXXFLAGS += -std=c++11 $(MODENV) $(WARNINGS) $(OPTIMS)
override CPPFLAGS += $(DMACROS) $(INCDIRS)
override LDFLAGS += $(MODENV) $(LIBDIRS) $(EXTRA_LIBS)
这样,必要的内容将附加到用户的变量中。
问题
- 覆盖变量是否被视为不良做法?
- 在生成文件中设置上述标志是否被视为不良做法?
- 如果对上述两个问题都是"是",那么如果不在
CXXFLAGS
中,我应该把-std=c++11
放在哪里?
如果用户覆盖了变量,则假定用户知道他们在做什么。他们正在使用的系统可能有非常不同的要求,需要覆盖变量。不要让困难变得不可能。
我不打算评论好/坏的做法,因为它取决于用例(这个 makefile 的用户是谁?他们都和你一起工作吗,所以你可以告诉他们如何使用它?你能在makefile注释或项目README
中记录你的约定吗?
但。。。
如果不在
CXXFLAGS
中,我应该把-std=c++11
放在哪里?
如果您有必不可少的标志并且不得被用户覆盖,则可以找到另一种方法将它们放在编译命令中。
例如:
CXX := g++ -std=c++11
或:
foo.o: foo.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++11 -o $@ $^
更好的可能是使用变量,以便它仍然可以由用户设置(例如,改用-std=c++14
(,但不由CXXFLAGS
设置:
STD := -std=c++11
foo.o: foo.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(STD) -o $@ $^
(或者只是将-std
选项放在CXXFLAGS
之前,以便CXXFLAGS
中的不同std
选项优先(。
由于使用make
进行构建管理的用例如此多样化,因此根本没有理由客观地将其判断为"不良做法"。如果您正在为多个平台以及未知的受众和时间范围编写 OSS,则应应用 POLA/POLS 。也就是说,一个用户惊讶地发现比她在命令行上给出的标志更多的标志是一个相当不切实际的极端情况,所以-override
有它的位置。最后,您添加的值对于构建是绝对必要的,不是吗?
PS:当然,POLA 应该应用于所有工程活动——只是"惊喜"的定义会随着相关任务而变化。