一、怎样实现配置文件

实现一个简单的配置文件,然后通过配置文件自动生成 config.h

实现配置文件的方式有很多,不管是哪种做法,最终的目的都是为了生成一个config.h
并在config.h中定义相关的宏定义,以打开和关闭相应的条件编译

配置文件有如下两种实现方式:

1. 使用Makefile文件来实现

在我们的这里的例子中,就是使用Makefile来实现的,Makefile就是一个配置文件,
后面讲Uboot的移植时,Uboot 的配置文件其实也是一个Makefile

Makefile文件到底是个啥?

Makefile文件主要作用是用于管理C工程项目中的所有.c.h
以便让编译器更好的去编译所有的文件

不过我们还可以让Makefile附带的生成config.h头文件,
也就是说生成config.h并不是Makefile的主要作用

如何得到Makefile这个文件?

  1. 自己手动写
  2. 使用工具软件自动生成

我们这里举的Makefile的例子是自己写的,但是实际开发中,大型c工程项目的Makefile都是自动生成的


2. 使用configure.in来实现

configure.in是一个典型的配置文件,同样的,这个配置文件的作用有很多,
生成config.h只是其中的一个附带功能而已

由于configure.in这种方式比较复杂,所以我们这里只简单提一下,
后面的课程具体涉及到时,再来详细介绍这个文件

如何得到configure.in

  1. 自己手动写
  2. 使用autotools工具链(包含好多工具),自动生成configure.in

对大型C工程来说,需要的configure.in会很复杂,自己手动写的话非常麻烦,
所以都是使用autotools来自动生成的,不过由于我们几乎不需要自己制作配置文件,
所以我们不需要掌握autotools的使用,我们只要能够修改别人制作好的configure.in就可以了

autotools自动生成configure.in的原理?

autotools 工具会去自动扫描源码中所有的.c.h
根据.c/.h中的条件编译情况,然后自动生成configure.in文件

如何利用configure.in得到config.h

有了configure.in这个配置文件后,在命令行执行./configure命令,
该命令就回去处理configure.in文件,然后得到config.h

前面说过,configure.in的作用很多,生成config.h只是其中的一个作用,
有关configure.in更多的内容,我们后面课程用到时再来具体介绍


二、手动实现配置文件


C文件:helloworld.c

#include "config.h" //我们需要使用“配置文件”来生成config.h

#ifdef WINDOWS
# include <windows.h>
#elif defined LINUX
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <fcntl.h>
#endif

int main(void)
{
    /* 通用代码 */
    int i = 0;

    while(1)
    {
        if(i>100) break;
        else i++;
    }


#ifdef WINDOWS
    /* 平台相关代码:windows的操作文件的OS API */
    HANDLE hfile = CreateFileA(".\file", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE \
    | FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
    int dwRead = 0;
    WrieFile(hfile, &i, sizeof(i), &dwRead, 0);   //将i写到file中
#elif defined LINUX
    /* 平台相关代码:Linux的操作文件的OS API */
    int fd = open("./file", O_RDWR | O_CREAT, 0774);
    write(fd, &i, sizeof(i));  //将i写到file中
#endif

    return 0;
}

Makefile 文件:注意间隔都是使用tab,空格会报错

make -f makefile # -f 指定makefile文件名,如果文件名是Makefile,可以省略
make Win         # 执行config脚本文件,创建config.h,然后在里面定义WINDOWS宏
make Linux       # 执行config脚本文件,创建config.h,然后在里面定义LINUX宏
all:
        gcc -o helloworld helloworld.c

configure:
        #执行脚本文件 config,config 会创建 congfig.h
        #如果传给脚本的参数是 win,就往 config.h 中写入 #define WINDOWS
        #如果传给脚本的参数是 Linux,就往 config.h 中写入 #define LINUX
        #./config win
        ./config linux


clean:
        #执行脚本文件config,传入参数为clean
        #脚本文件会删除可执行文件helloworld和config.h
        ./config clean

脚本文件:config

#!/bin/sh -e

#如果config.h文件之前就存在,就使用原来的文件
touch config.h

#清空文件内容
:>config.h


#将 pragma once 输入 config.h,防止头文件重复包含
# >: 会覆盖以前的内容
echo "#pragma once" > config.h


#如果脚本文件参数为win,将#define WINDOWS追加到configh中,>>为追加
if [ "$1" = "win" ] ; then

echo "#define WINDOWS" >> config.h

fi

#如果脚本文件参数为 linux,将#define LINUX追加 config.h
if [ "$1" = "linux" ] ; then

echo "#define LINUX" >> config.h

fi

> 代表覆盖,>> 代表会追加


写好 C源码文件、脚本文件conifg、Makefile文件后:

$ make configure
#执行脚本文件 config,config 会创建 congfig.h
#如果传给脚本的参数是 win,就往 config.h 中写入 #define WINDOWS
#如果传给脚本的参数是 Linux,就往 config.h 中写入 #define LINUX
#./config win
./config linux

$ make all
gcc -o helloworld helloworld.c

$ ./helloworld