【发布时间】:2013-09-24 22:52:33
【问题描述】:
假设我们有一组相互依赖的 C 模块,并且我们想要创建一个 GNU Makefile,以便为几个不同的构建(例如,单元测试、用户工具、多个版本)单独编译它们。
每个模块虽然对于完整的应用程序至关重要,但旨在单独使用或与其他模块以任何合理的方式组合使用——始终公开功能最强大的 API,这是由为特定构建选择的其他模块提供的组件的可用性而产生的.
为了一个最小且完整的示例,假设我们的程序具有三个模块(红色、绿色和蓝色),所有可能的条件功能都通过条件编译进行切换。每个模块都有两个这样的条件块,每一个都由两个可能的邻居之一启用。这为我们提供了三种可能的单一构建(红色、绿色、蓝色)、三个双重构建(青色、洋红色、黄色)和一个三重构建(白色)——每个构建都包含一个专用的主程序(核心),构建在一组 profided 之上特征。
期望的情况
图 1 显示了三个模块(mod_red.c、mod_green.c 和 mod_blue.c «RGB»);跨模块功能的三个区域(青色、洋红色和黄色«CMY»)在相邻模块内实现;和三个核心(白色,在大的锐化顶部具有物理依赖性«RGB»,在小顶部具有逻辑依赖性«CMY»)。每个方向(六个方向)都表示一个功能方面,因此指向主三角形的 CMY 顶部表明协同作用可能会提供额外的功能。
所需的 Makefile 应该为所有可能的构建提供配方,因此使用三个模块和七个不同内核的四个版本。它还应该足够聪明以避免残酷的解决方案(每个配方的完整块 gcc 命令)并保持单独编译的优势。
如果没有单独编译,问题很容易(至少对于单边依赖项):主程序包含必要的源,并且依赖块由预处理器标志启用,例如由其他模块设置的包括警卫。但是,通过单独编译,编译器不知道包含特定构建的模块集。
手动方法
可以使用下面列出的 shell 命令手动实现所需的情况。
# Single objects:
gcc -c -o mod_green.o mod_green.c
# Double objects
gcc -c -include mod_blue.h -o mod_red+B.o mod_red.c
gcc -c -include mod_red.h -o mod_blue+R.o mod_blue.c
# Triple objects
gcc -c -include mod_green.h -include mod_blue.h -o mod_red+G+B.o mod_red.c
gcc -c -include mod_red.h -include mod_blue.h -o mod_green+R+B.o mod_green.c
gcc -c -include mod_red.h -include mod_green.h -o mod_blue+R+G.o mod_blue.c
# Builds
gcc -o green green.c mod_green.o
gcc -o magenta magenta.c mod_red+B.o mod_blue+R.o
gcc -o white white.c mod_red+G+B.o mod_green+R+B.o mod_blue+R+G.o
至于所需的情况,此示例仅显示了三个具有代表性的构建:绿色、洋红色和白色。其他类似形成。
经典方法
使用经典的 Makefile 解决方案,Green 构建保持不变,但其他两个缺少逻辑依赖项(即 CMY 提供的符号)。之所以如此,是因为构建过程当前(并且通常)定义如下:
white: white.c mod_red.o mod_green.o mod_blue.o
gcc -o $@ $^
magenta: magenta.c mod_blue.o mod_red.o
gcc -o $@ $^
green: green.c mod_green.o
gcc -o $@ $^
%.o: %.c
gcc -c -o $@ $<
这里的问题很明显:最后一条规则没有区分特定的构建——上下文丢失了。此外,我需要为每个模块提供不同的二进制版本以满足不同的构建。正确的做法是什么?
【问题讨论】:
-
也许我的术语已经过时了,但我发现这个问题不清楚。如果您不使用 Make,您将如何构建
Blue-red?你会使用什么序列的gcc命令? -
@Beta 你说得对,理想情况和当前情况之间没有明显的区别——我会改变它。至于
gcc,我用~:gcc -c -include mod_blue.h -o mod_red.o mod_red.c,然后mod_blue.o反之,最后第三次调用编译链接项目。 -
那么您实际上需要 13 个不同的目标文件?
-
@Beta 对于所有情况,我需要其中的 9 个(每个 RGB 模块 3 个,CMY 功能在三个模块中实现)。然后,将主程序作为源文件传递给
gcc。 -
这毫无意义。有四种不同的版本涉及 Red 模块:R、RG、RB、RGB。哪两个使用相同的 Red 对象文件?
标签: c gcc compilation makefile