一、前言概述
《跟我一起学Makefile》是一篇全面学习编写Makefile基本规则的很好的文章,初学者应该好好理解里面的知识要点。但是很多人学完之后,并不能站在一个系统的高度通过Makefile来组织整个工程的编译。麻雀虽小,五脏俱全 ——此篇的目的就是想通过简单的实例,来说明如何使用Makefile组织大型工程项目。
二、工程框架
图1 工程框架
假设现有一个如图1所示的工程:其各自代码如下:
// add.h
#if !defined(__ADD_H__)
#define __ADD_H__
#if defined(__ADD__)
extern int add(int a, int b);
#endif /*__ADD__*/
#endif /*__ADD_H__*/
// add.c
#include<stdio.h>
#include<stdlib.h>
#if defined(__ADD__)
int add(int a, int b)
{
return a+b;
}
#endif /*__ADD__*/
// sub.h
#if !defined(__SUB_H__)
#define __SUB_H__
#if defined(__SUB__)
extern int sub(int a, int b);
#endif /*__SUB__*/
#endif /*__SUB_H__*/
// sub.c
#include<stdio.h>
#include<stdlib.h>
#if defined(__SUB__)
int sub(int a, int b)
{
return a-b;
}
#endif /*__SUB__*/
// test.c
#include
#include
#if defined(__ADD__)
#include "add.h"
#endif /*__ADD__*/
#if defined(__SUB__)
#include "sub.h"
#endif /*__SUB__*/
int main(int argc, const char *argv[])
{
int a = 10, b = 20;
#if defined(__ADD__)
printf("%d+%d = %d\n", a, b, add(a, b));
#endif /*__ADD__*/
#if defined(__SUB__)
printf("%d-%d = %d\n", a, b, sub(a, b));
#endif /*__SUB__*/
return 0;
}
三、编写Makefile
在project目录下新建make目录,所有makefile文件都放在此目录下。则Makefile文件包含:
①、宏开关模块
宏开关模块:是通过一个开关(switch)来控制某个宏的开启和关闭,以此达到控制软件平台某个功能的开启和关闭。
// switch.mak
CFG_ADD_SUPPORT = TRUE # FALSE # 加法开关
CFG_SUB_SUPPORT = FALSE # TRUE # 减法开关
②、宏加载模块
宏加载模块:根据宏开关模块的设置,将宏加入编译选项
// option.mak
ifeq(TRUE, $(strip $(CFG_ADD_SUPPORT)))
OPTIONS += __ADD__
endif
ifeq(TRUE, $(strip $(CFG_SUB_SUPPORT)))
OPTIONS += __SUB__
endif
③、路径设置模块
// paths.mak
# 设置头文件路径(相对路径)
INCLUDED := -I../add \
-I../sub
# 设置源文件路径
ADD_PATH = ../add # 加法源文件路径(相对路径)
SUB_PATH = ../sub # 减法源文件路径(相对路径)
SRC_PATH = ../src # 测试源文件路径(相对路径)
# 加载源文件
SRC_LIST := $(SRC_PATH)/test.c # 加载测试源文件
#ifeq(TRUE, $(strip $(CFG_ADD_SUPPORT)))
SRC_LIST += $(ADD_PATH)/add.c # 加载加法源文件
#endif /*CFG_ADD_SUPPORT*/
#ifeq(TRUE, $(strip $(CFG_SUB_SUPPORT)))
SRC_LIST += $(SUB_PATH)/sub.c # 加载减法源文件
#endif /*CFG_SUB_SUPPORT*/
④、编译模块
// Makefile
# 引入makefile文件
include switch.mak
include options.mak
include paths.mak
CC := gcc
CFLAGS := -O2 $(INCLUDED)
CFLAGS += $(patsubst %, -D%, $(OPTIONS)) # patsubst起拼接作用
OBJS := $(subst .c, .o, $(SRC_LIST)) # subst起替换作用
TARGET := $(SRC_PATH)/test.elf
.PHONY: all clean clean_all
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
$(OBJS): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -fr $(OBJS)
⑤、编译和执行
#cd project/make
#make
#cd ../test
⑥、运行结果
1. 如果CFG_ADD_SUPPORT = TRUE ,并且CFG_SUB_SUPPORT = FALSE,则运行结果为:
10+20 = 30
2. 如果CFG_ADD_SUPPORT = TRUE ,并且CFG_SUB_SUPPORT = TURE,则运行结果为:
10+20 = 30
10-20 = -10
3. 如果CFG_ADD_SUPPORT =FALSE ,并且CFG_SUB_SUPPORT = TRUE,则运行结果为:
10-20 = -10
四、最终框架
图2 最终框架
作者:邹祁峰
2012年11月23日
分享到:
相关推荐
通用版,Makefile C++和c混合编译
VS的工程为VS2015的工程文件,使用VC140工具集,如果没有2015,也可以用Makefile.mak文件来编译。 nmake /f Makefile.mak [DLL] [DEBUG] 指定 DLL=1 编译dll版本,默认是lib版本,libiconv.lib , libintl.lib。 ...
linux一般通过makefile控制编译。linux代码目录结构是 ...全编译工程: cd scons_project_root scons 总结,每个目录都可以单独编译,对于某工程师只负责某部门lib,提高编译效率。这个是非常方便的。
实现通过makefile来管理编译代码,包括生成静态库和动态库,多目录管理文件等等一系列架构组织,完成一个通用的Makefile模板。包括: 1. 构建工程 2. 自动添加目标对头文件的依赖 3. 目录管理源文件 4. 目录管理目标...
这里我会用一个工程来说明怎么做,有一些步骤不是必须的,但是如果你看不出来哪些步骤不是必须的,最好跟着一步步走,因为某些步骤省略了,代码也需要做出相应修改(如修改路径等)。 步骤 首先安装autoconf sudo ...
1, 下载libcurl http://curl.haxx.se/dlwiz/?type=source 选择"platform independent", 下载, 在winbuid目录下, 执行...2, 在builds 中找到 libcurl_debug.lib, 加载到 vs工程中, 执行测试工程代码, 下载baidu页面内容
linux 工程编译 makefile 工程目录下所有的C文件,工程目录下可以有子目录
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、...
VS的工程为VS2017的工程文件,使用VC141工具集,SDK10.0.17134.12,如果没有2017,也可以用Makefile.mak文件来编译。 或者你自己降低版本,我最初使用的最低版本是VC140_xp,SDK7.1A,也就是VS2015默认安装的兼容xp...
一份关于makefile编写的代码案例,仔细看看注释,多多了解一下make。 老师,要带着大家,从无到有产生这套 通讯架构源代码【项目/工程】 项目 肯定会有多个源文件,头文件,会分别存放到多个目录;我们要规划项目...
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、...
工程中根据源文件的修改情况来进行代码的编译正是使用了make的这个特征。make执行时,根据Makefile的规则检查文件的修改情况,决定是否执行定义的动作(那些修改过的文件将会被重新编译)。这是GNU make的执行依据。
来自google的开源日志类源码,在window下编译通过,亲测。而且使用这些动态库、静态库和头文件编写了对应的Demo,源码也已上传,请自行查找。
qt工程代码 也有Makefile 直接使用make编译也可
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 ...
该包只限用于WINDOWS下编译PHP缺少LDAP相关依赖包时使用。...请注意,libldap的dll,采用的liblber的静态库,因为你必须首先编译lib版本。使用如下命令: nmake /f makefile.mak nmake /f makefile.mak dll=1
/20200318/4271ace044c760b540134ec23141f91b.rar
对于大型工程源代码最好分目录存放便于管理,但是编写makefile就相对麻烦点。 这里是我写的一个makefile demo,它的关键之处在编译前导入config_xxx_file_list.mk,这个文件可以看成是IDE环境的代码目录树。具体...
常见开源项目采用makefile来组织源代码的编译。cbp2make可以很好的将CB的工程文件转换为makefile 文件。 1、下载cbp2make的源代码; 2、解压后打开工程文件cbp2make.cbp,然后在CB中建造工程。 3、为长期使用方便...
2. makefile使用 2 2.1. 基本过程处理 2 2.2. 特殊处理与伪目标 3 2.3. 变量、函数与规则 5 3. 程序调试 8 3.1. gdb常用命令 8 3.2. gdb 应用举例 9 3.3. assert断言宏 12 3.4. 错误处理函数和进程退出函数 13 3.5. ...