玩转Makefile | 编译有共用文件的多个程序

简介: 玩转Makefile | 编译有共用文件的多个程序


1. 使用场景


在企业项目中,经常有这样的场景:多个应用程序同时共用某几个文件。如果把这几个应用程序分别用一个文件夹管理的话,将出现文件冗余的情况。而且不易管理,譬如,当共用文件需要修改时,每个程序所对应的那个共同文件都应该修改一遍,以保证一致。


针对这样的问题,完全可以把共用的代码放在一个文件夹,另外每个应用程序再单独放在自己的文件夹里。编译的时候每个应用程序编译自己的文件及共用文件即可。这样结构比较明了,也比较容易管理。


2. 代码展示


在此我们模拟了上述的情景,有两个应用程序,分别为application1及application2,分别共用了common.h及common.c这两个文件。完整代码可以在公众号内回复mk3免费获取。


文件夹的结构如下:


image.png


源代码如下:


//common.h 就一个共用变量及函数声明  
#define COMMON_VAR 1024  
void common_fun();  
//common.c 就一个共用函数  
void common_fun()  
{  
    printf("this is a common function.\n");  
}  
//application1.h  
#define APP1_GREETING "this is app1"  
//application1.c  
int main()  
{  
    printf("hello, %s\n", APP1_GREETING);  
    printf("common var is: %d\n", COMMON_VAR); //此处用到了共用变量  
    common_fun();   //此处调用了共用函数  
}  
//application2.h  
#define APP2_GREETING "this is app2"  
//application2.c  
int main()  
{  
    printf("hello, %s\n", APP2_GREETING);  
    printf("common var is: %d\n", COMMON_VAR); //此处用到了共用变量  
    common_fun();   //此处调用了共用函数  
}


Makefile如下:


NAME_APP1 = app1  
NAME_APP2 = app2  
TARGETS = $(NAME_APP1) $(NAME_APP2)  
SOURCE_COMMON = $(wildcard ./00_Common/*.c)  
SOURCE_APP1 = $(SOURCE_COMMON) $(wildcard ./01_Application1/*.c)  
SOURCE_APP2 = $(SOURCE_COMMON) $(wildcard ./02_Application2/*.c)  
OBJ_APP1 = $(patsubst %.c, %.o, $(SOURCE_APP1))  
OBJ_APP2 = $(patsubst %.c, %.o, $(SOURCE_APP2))  
INCLUDE_COMMON = -I./00_Common/  
CFLAGS = -Wall -c  
CC = gcc  
all: $(TARGETS)  
$(NAME_APP1): $(OBJ_APP1)  
    @mkdir -p output/  
    $(CC) $(OBJ_APP1) -o output/$(NAME_APP1)  
$(NAME_APP2): $(OBJ_APP2)  
    @mkdir -p output/  
    $(CC) $(OBJ_APP2) -o output/$(NAME_APP2)  
%.o: %.c  
    $(CC) $(INCLUDE_COMMON) $(CFLAGS) $< -o $@  
.PHONY: clean  
clean:  
    rm -rf $(OBJ_APP1) $(OBJ_APP2) output/


3. 编写思路


1. 使用wildcard函数将共用文件及各自的文件全部找出。各个应用程序还应加上共用文件,否则编译不过。


SOURCE_COMMON = $(wildcard ./00_Common/*.c)  
SOURCE_APP1 = $(SOURCE_COMMON) $(wildcard ./01_Application1/*.c)  
SOURCE_APP2 = $(SOURCE_COMMON) $(wildcard ./02_Application2/*.c)


2. 使用patsubst将应用程序的.c文件转化为.o文件,如下:


OBJ_APP1 = $(patsubst %.c, %.o, $(SOURCE_APP1))  
OBJ_APP2 = $(patsubst %.c, %.o, $(SOURCE_APP2))


3. 加上共用头文件路径:


INCLUDE_COMMON = -I./00_Common/


4. 编写规则:


all: $(TARGETS) #主要目标为所有将要编译的程序  
$(NAME_APP1): $(OBJ_APP1)   #各个要编译的目标,依赖从以上几步已经获取完毕  
        @mkdir -p output/  
        $(CC) $(OBJ_APP1) -o output/$(NAME_APP1)  
$(NAME_APP2): $(OBJ_APP2)  
        @mkdir -p output/  
        $(CC) $(OBJ_APP2) -o output/$(NAME_APP2)


4. 编译完毕执行效果


image.png






目录
相关文章
源文件与模块生成时的文件不同,是否希望调试器使用它?如何解决
源文件与模块生成时的文件不同,是否希望调试器使用它?如何解决
|
2月前
|
Ubuntu JavaScript Java
程序从源代码到可执行程序
这篇文章介绍了从源代码到可执行程序的转换过程,包括预处理、编译、汇编和链接四个主要步骤,并提到了解释性语言、脚本语言和超文本语言的不同处理方式。
30 0
|
7月前
|
算法 网络协议 Linux
Linux模块文件编译到内核与独立编译成.ko文件的方法
Linux模块文件编译到内核与独立编译成.ko文件的方法
1783 0
|
C++
VS下源文件中有多个代码时如何指定运行特定的代码(一个源文件下有多个代码时运行指定代码)
VS下源文件中有多个代码时如何指定运行特定的代码(一个源文件下有多个代码时运行指定代码)
300 0
|
NoSQL 编译器 Linux
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(三)
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解
317 0
【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(三)
|
编译器 Linux C语言
在C语言/C++中把资源编译进exe可执行文件,并运行时释放资源
在C语言/C++中把资源编译进exe可执行文件,并运行时释放资源
390 0
|
机器学习/深度学习 编译器 C语言
【程序的编译和预处理】源文件到可执行程序到底经历了什么?
【程序的编译和预处理】源文件到可执行程序到底经历了什么?
139 0
【程序的编译和预处理】源文件到可执行程序到底经历了什么?