教你如何使用Makefile编译工程代码

  • 作者:邹祁峰
  • 邮箱:[email protected]
  • 博客:http://blog.csdn.net/qifengzou
  • 日期:2012.11.23
  • 转载请注明来自"祁峰"的CSDN博客

1 前言概述

  《跟我一起学Makefile》是一篇全面学习编写Makefile基本规则的很好的文章,初学者应该好好理解里面的知识要点。但是很多人学完之后,并不能站在一个系统的高度通过Makefile来组织整个工程的编译。麻雀虽小,五脏俱全 —— 此篇的目的就是想通过简单的实例,来说明如何使用Makefile组织大型工程项目。

2 工程框架



图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
#include

#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
#include

#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;
}

3 编写Makefile

  在project目录下新建make目录,所有makefile文件都放在此目录下。则Makefile文件包含:

1) 宏开关模块

  宏开关模块:是通过一个开关(switch)来控制某个宏的开启和关闭,以此达到控制软件平台某个功能的开启和关闭。

// switch.mak
CFG_ADD_SUPPORT = TRUE # FALSE # 加法开关
CFG_SUB_SUPPORT = FALSE # TRUE # 减法开关

2) 宏加载模块

  宏加载模块:根据宏开关模块的设置,将宏加入编译选项

// option.mak
ifeq (TRUE, $(strip $(CFG_ADD_SUPPORT))) # 注意:ifeq后面有空格,否则可能会报错
    OPTIONS += __ADD__
endif

ifeq (TRUE, $(strip $(CFG_SUB_SUPPORT)))
    OPTIONS += __SUB__
endif

3) 路径设置模块

// 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*/ 
  
 
  

4) 编译模块

// Makefile
# 引入makefile文件
include switch.mak
include options.mak
include paths.mak

CC := gcc

CFLAGS := -Wall -g -fPIC $(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) 

5) 编译和执行

#cd project/make
#make
#cd ../test

6) 运行结果

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

4 最终框架



图2 最终框架

 


你可能感兴趣的:(教你如何使用Makefile编译工程代码)