当前位置 : 主页 > 手机开发 > 其它 >

单独编译相互依赖的C模块

来源:互联网 收集:自由互联 发布时间:2021-06-22
假设我们有一组相互依赖的C模块,我们想创建一个GNU Makefile,用于为几个不同的构建(例如,单元测试,用户工具,多个版本)单独编译它们. 每个模块虽然对整个应用程序至关重要,但它们可以
假设我们有一组相互依赖的C模块,我们想创建一个GNU Makefile,用于为几个不同的构建(例如,单元测试,用户工具,多个版本)单独编译它们.

每个模块虽然对整个应用程序至关重要,但它们可以单独使用,也可以与其他模块以任何合理的组合方式使用 – 始终暴露最具特色的API,这些API是由为特定构建选择的其他模块提供的组件的可用性产生的.

为了一个最小和完整的例子,让我们假设我们的程序有三个模块(红色,绿色和蓝色),所有可能的条件功能都通过条件编译来切换.每个模块具有两个这样的条件块,每个条件块由两个可能的邻居之一的存在来启用.这为我们提供了三种可能的单一构建(红色,绿色,蓝色),三种双重构建(青色,洋红色,黄色)和一种三重构建(白色) – 每个构建都包含一个专用的主程序(Core),构建在一组构建的特征.

期望的情况

图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 $@ $<

这里明显暴露了问题:最后一条规则没有区分特定的构建 – 上下文丢失了.此外,我需要最终得到每个模块的不同二进制版本,以满足不同的构建.这样做的正确方法是什么?

这应该工作.虽然没试过.我认为从这一点开始制定其他规则会很容易.

BINARY = build

CC = gcc

SOURCES_RGB = rgb.c mod_red.c mod_green.c mod_blue.c
OBJECTS_RGB = $(SOURCES_RGB:.c=_rgb.o)

BINARY_RGB = $(addprefix RGB-,$(BINARY))

CFLAGS_RGB = -include mod_rgb.h

$(BINARY_RGB): $(OBJECTS_RGB)
        $(CC) -o $@ $^

%_rgb.o: %.c
        $(CC) -c $(CFLAGS_RGB) -o $@ $<
网友评论