我通常使用选项:-Dname = value将宏定义从"make命令行"传递给"makefile".该定义可在makefile中访问.
我还使用类似的编译器选项将宏定义从"makefile"传递到"源代码":-Dname = value(在许多编译器中都支持).可以在源代码中访问此定义.
我现在需要的是允许我的makefile用户能够立即将"make.exe命令行"中的任意宏定义传递给"源代码",而无需更改makefile中的任何内容.
所以用户可以输入:make -f mymakefile.mk -SOMEOPTION var = 5
然后直接代码main.c可以看到var:
int main()
{
int i = var;
}
Run Code Online (Sandbox Code Playgroud) 我知道CFLAGS(或CXXFLAGS for C++)是针对编译器的,而CPPFLAGS是由预处理器使用的.
但我仍然不明白其中的区别.
我需要为#include包含的头文件指定一个包含路径 - 因为#include是一个预处理器指令,是我唯一关心的预处理器(CPPFLAGS)吗?
在什么情况下我需要给编译器一个额外的包含路径?
通常,如果预处理器找到并包含所需的头文件,为什么需要告知额外的包含目录?CFLAGS有什么用?
(在我的情况下,我实际上发现这两个允许我编译我的程序,这增加了混乱...我可以使用CFLAGS 或 CPPFLAGS来实现我的目标(至少在autoconf上下文中.)给出了什么?)
首先Makefile这里有
CFLAGS = -g -Wall -lm
Run Code Online (Sandbox Code Playgroud)
C那个时候我在玩。现在我开始了C++,我必须添加-I eigen,快速 google 上它并发现CXXFLAGS为C++世界而CFLAGS存在,而为C世界而存在。所以我更新Makefile到
CFLAGS = -g -Wall -lm
CXXFLAGS = -I eigen
Run Code Online (Sandbox Code Playgroud)
然后我找到了https://wiki.gentoo.org/wiki/GCC_optimization,受到启发再次更新
CFLAGS = -g -Wall -lm
CXXFLAGS = ${CFLAGS} -I eigen
Run Code Online (Sandbox Code Playgroud)
完整的东西:
CC = g++
CFLAGS = -g -Wall -lm
CXXFLAGS = ${CFLAGS} -I eigen
OBJS = main.o multiply.o
PROGRAM = multitply
$(PROGRAM): $(OBJS)
$(CC) $(OBJS) $(CFLAGS) -o $(PROGRAM)
Run Code Online (Sandbox Code Playgroud)
我要补充-I eigen …
典型的 makefile 通常使用内置变量CFLAGS、等CXXFLAGS1来设置传递给 C、C++ 或其他编译器/工具的标志。原则上,有时这甚至可以让您完全避免编写编译配方,因为各种内置规则使用这些标志。CPPFLAGS
一般来说,makefile 可能会向所需的FLAGS变量中添加内容添加内容,例如包含目录、指示要使用哪种语言标准的参数等。这些变量还可能包括“可选”或“默认”参数,例如优化级别、警告级别和其他可以有效更改或删除的设置。
由于CFLAGS和 字段是“众所周知的”变量,因此它们显然也是最终用户的配置点。例如,如果默认情况下项目在没有调试信息的情况下进行编译,则预期CFLAGS=-g在make命令行上会导致-g添加到 $(CC) 编译器命令行,从而导致生成调试信息。同样,对于最终用户可能想要控制的其他选项,例如优化级别、-marchgcc 的设置等。
然而,这两种用途对我来说似乎不兼容。如果用户覆盖,$(CFLAGS)他们将删除如上所述的任何内部“必需”标志,并且项目可能无法编译或可能编译不正确。
有处理这个问题的最佳实践吗?对于“单值”变量来说,实际上不会出现同样的问题,$(CC)因为它们通常只有一个值:在本例中,是要使用的 C 编译器。如果用户覆盖它,您就使用它们的值。原则上,诸如此类$(CFLAGS)的内容是一个值列表,其中一些是内部的,不应被覆盖,而另一些则是用户可能想要覆盖的。
直观上,解决方案似乎是$(CFLAGS)在 makefile 中将 and Friends 保留为空且未使用,更喜欢CFLAGS_INTERNAL在 makefile 中指定参数,然后将两者都放在命令行上。然而,我很好奇是否有最佳实践,或者我是否遗漏了一些明显的东西。
1对于这个问题的其余部分,我通常会简单地引用它,$(CFLAGS)并理解这只是整个众所周知的编译器标志变量系列的方便代表,例如$(CPPFLAGS),$(CXXFLAGS)等等。
我想知道当我执行类似g++ main.cpp.
我知道我可以运行g++ -v编译器版本,例如返回:
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: arm64-apple-darwin22.1.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Run Code Online (Sandbox Code Playgroud)
但我不确定这里使用的默认 C++ 语言版本是什么。
我也知道我可以用来-std=c++(version)更改它,但是,最好将默认值设置为 c++20 以保持最新状态并且不必使用标志。