Skip to content

LV150-GCC宏的使用

本文主要是通过 makefile 读取配置文件中的宏定义,然后使用 GCC 的 -D 选项传入 C 语言文件实现不同的编译代码的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正 😃。

一、在 Makefile 中包含文件

在前边的学习中,我们知道,我们可以使用 include 来包含相关文件,但是当时并没有深入去了解,也没有写例子,现在我们来看一看 Makefile 的文件包含吧。

1. mk 文件

我们可以将被包含的文件命名为 filename.mk 文件,在整个.mk 文件中,我们可以定义一些变量来让 Makefile 读取,例如我们新建一个 config.mk 的文件,内容如下:

makefile
TEST1=n
TEST2=n
TEST3=y

2. Makefile 包含

上边准备好文件后,我们在 makefile 文件中包含上边的文件并打印出相关的变量的值:

makefile
include config.mk

print:
	@echo "TEST1=$(TEST1)"
	@echo "TEST2=$(TEST2)"
	@echo "TEST3=$(TEST3)"
	@echo "TEST4=$(TEST4)"

然后我们执行 make 命令,会看到如下输出:

shell
TEST1=n
TEST2=n
TEST3=y
TEST4=

可以看到,makefile 中并没有定义这几个变量,但是都是将变量的值正常打印出来了,除了 TEST4 为空,因为我们并没有在.mk 文件中定义这个变量。

二、GCC 的-D 选项

在这里,复习一下 GCC 的-D 选项,我们准备一个 c 语言源文件如下:

c
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("start!!!\n");
    #ifdef TEST1
    printf("TEST1 has been defined!!\n");
    #endif
    #ifdef TEST2
    printf("TEST2 has been defined!!\n");
    #endif
    #ifdef TEST3
    printf("TEST3 has been defined!!\n");
    #endif

    return 0;
}

然后我们编译这个文件,执行以下命令:

shell
gcc main.c -Wall

然后执行生成的可执行文件 a.out ,可以得到如下输出:

shell
start!!!

会发现,只有第一个输出,后边的都没有输出,原因在哪里呢?我们根本就没有定义上边的 TEST1、TEST2 和 TEST3 宏,肯定不会有输出啊。

我们现在更换以下编译命令(注意每一个需要传入的宏都需要使用-D):

shell
gcc -DTEST1 -DTEST2 main.c -Wall

然后我们再执行可执行文件,就会得到下列输出信息:

shell
start!!!
TEST1 has been defined!!
TEST2 has been defined!!

发现,我们可以通过-D 选项来达到在 C 语言文件中的#define 关键字一样的效果,这也就意味着,我们可以在一套代码中通过不同的编译命令来选择编译出不同的内容。

三、makefile 与 GCC

一般来说,对于大型工程,我们都会使用 makefile 来管理,但是他本质上还是在调用 GCC 来编译工程,所以,这两者可以结合起来,我们在.mk 文件中定义宏,选择使用哪些宏,选择不使用哪些宏。接下来我们就来看一看吧。

1. config.mk

我们还是使用上边的 config.mk 文件,里边只定义宏,并以 y 表示将其作为 GCC 的参数,n 表示不定义该宏:

makefile
CONFIG_TEST1=y
CONFIG_TEST2=n
CONFIG_TEST3=y

2. makefile

我们的 makefile 文件修改如下:

makefile
include config.mk

ifeq ($(CONFIG_TEST1), y)
	DFLAG +=-DTEST1
endif

ifeq ($(CONFIG_TEST2), y)
	DFLAG +=-DTEST2
endif

ifeq ($(CONFIG_TEST3), y)
	DFLAG +=-DTEST3
endif

main:
	gcc $(DFLAG) main.c -Wall

print:
	@echo "CONFIG_TEST1=$(CONFIG_TEST1)"
	@echo "CONFIG_TEST2=$(CONFIG_TEST2)"
	@echo "CONFIG_TEST3=$(CONFIG_TEST3)"
	@echo "DFLAG=$(DFLAG)"

3. main.c

c
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("start!!!\n");
    #ifdef TEST1
    printf("TEST1 has been defined!!\n");
    #endif
    #ifdef TEST2
    printf("TEST2 has been defined!!\n");
    #endif
    #ifdef TEST3
    printf("TEST3 has been defined!!\n");
    #endif

    return 0;
}

4. 编译测试

我们执行 make print 命令看一下各变量的值,会看到如下输出:

shell
CONFIG_TEST1=y
CONFIG_TEST2=n
CONFIG_TEST3=y
DFLAG=-DTEST1 -DTEST3

然后执行 make 命令,我们会看到如下输出:

shell
gcc -DTEST1 -DTEST3 main.c -Wall

可以看到被设置成 y 的两个配置项已经成为 GCC 的-D 选项的参数啦。

接下来我们执行./a.out,也就是执行可执行文件,会看到如下输出:

shell
start!!!
TEST1 has been defined!!
TEST3 has been defined!!

如此这般,我们的目的就达到了,在.mk 文件中进行配置,在 makefile 文件中进行判断,判断过后将开启的宏添加到 GCC 编译命令中,这样我们就实现了对整个工程的配置。