• 4. CMake 系列


    1. 项目目录结构

    test3
    ├── add
    │   ├── add.c
    │   ├── add.h
    │   └── CMakeLists.txt
    ├── build
    ├── CMakeLists.txt
    ├── config.h.in
    ├── example
    │   ├── CMakeLists.txt
    │   └── test.c
    └── sub
        ├── CMakeLists.txt
        ├── sub.c
        └── sub.h
    

    很多开源项目都支持编译选项控制编译,用户可以根据编译选项定制需要的功能,典型例子如linux内核,用户可根据自身裁剪内核。

    CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。

    编译选项控制编译的核心思想:通过CMake生成config.h, config.h文件定义一些宏,项目代码包含config.h文件,通过这些宏控制代码模块。

    2. 相关代码

    2.1 add 模块

    add.h

    #ifndef _ADD_H
    #define _ADD_H
    
    int add(const int a, const int b);
    
    #endif
    
    

    add.c

    #include "add.h"
    
    int add(const int a, const int b)
    {
        return a+b;
    }
    
    

    CMakeLists.txt

    # 递归获取目录下所有的C文件
    file(GLOB_RECURSE c_files ./*.c)
    
    
    # 递归获取目录下所有的h文件
    file(GLOB_RECURSE h_files ./*.h)
    
    #生成动态库和静态库
    add_library(add_lib_shared  SHARED ${c_files})
    add_library(add_lib_static STATIC ${c_files})
    
    #将动态库和静态库的名字设置为 add
    set_target_properties(add_lib_shared PROPERTIES OUTPUT_NAME "add")
    set_target_properties(add_lib_static PROPERTIES OUTPUT_NAME "add")
    
    #设置动态库版本
    set_target_properties(add_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)
    
    #安装动态库和静态库
    INSTALL(TARGETS add_lib_shared add_lib_static
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)
    
    #安装头文件
    INSTALL(FILES ${h_files}  DESTINATION include)
    
    

    2.2 sub 模块

    sub.h

    #ifndef _SUB_H
    #define _SUB_H
    
    int sub(const int a, const int b);
    
    #endif
    
    

    sub.c

    #include "sub.h"
    
    int sub(const int a, const int b)
    {
        return a - b;
    }
    
    

    CMakeLists.txt

    #递归获取目录下所有的C文件
    file(GLOB_RECURSE c_files ./*.c)
    
    # 递归获取目录下所有的h文件
    file(GLOB_RECURSE h_files ./*.h)
    
    #生成动态库和静态库
    add_library(sub_lib_shared  SHARED ${c_files})
    add_library(sub_lib_static STATIC ${c_files})
    
    #将动态库和静态库的名字设置为 sub
    set_target_properties(sub_lib_shared PROPERTIES OUTPUT_NAME "sub")
    set_target_properties(sub_lib_static PROPERTIES OUTPUT_NAME "sub")
    
    #设置动态库版本
    set_target_properties(sub_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)
    
    #设置动态库版本
    set_target_properties(sub_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)
    
    #安装动态库和静态库
    INSTALL(TARGETS sub_lib_shared sub_lib_static
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)
    
    #安装头文件
    INSTALL(FILES ${h_files}  DESTINATION include)
    
    

    2.3 example 模块

    test.c

    #include "config.h"
    
    #ifdef ENABLE_ADD
    #include "add.h"
    #endif
    
    #ifdef ENABLE_SUB
    #include "sub.h"
    #endif
    
    #include <stdio.h>
    
    
    int main(int argc, char **argv)
    {
        int a = 10;
        int b = 8;
    #ifdef ENABLE_ADD
        printf("%d + %d = %d
    ", a, b, add(a, b));
    #endif
    
    #ifdef ENABLE_SUB
        printf("%d - %d = %d
    ", a, b, sub(a, b));
    #endif
    
    
        return 0;
    }
    
    

    CMakeLists.txt

    # 添加头文件路径
    include_directories(${PROJECT_SOURCE_DIR}/add)
    include_directories(${PROJECT_SOURCE_DIR}/sub)
    include_directories(${PROJECT_SOURCE_DIR})
    
    # 添加第三方库(add)头文件路径
    link_directories(${PROJECT_SOURCE_DIR}/lib)
    
    # 生成执行文件
    add_executable(test_add_sub test.c)
    
    # 链接库文件
    if(ENABLE_ADD)
    target_link_libraries(test_add_sub add)
    endif(ENABLE_ADD)
    
    if(ENABLE_SUB)
    target_link_libraries(test_add_sub sub)
    endif(ENABLE_SUB)
    
    INSTALL(TARGETS test_add_sub 
        RUNTIME DESTINATION bin)
    
    

    2.4 顶层 CMakeLists.txt

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.10)
    
    # 设置库文件输出目录
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
    
    # 设置执行文件输出目录
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
    
    
    # 添加编译选项
    option(ENABLE_ADD "enable add" ON)
    option(ENABLE_SUB "enable sub" ON)
    
    if(ENABLE_ADD)
        add_subdirectory(add)
    endif(ENABLE_ADD)
    
    if(ENABLE_SUB)
        add_subdirectory(sub)
    endif(ENABLE_SUB)
    
    # 加入一个头文件配置,让cmake对源码进行操作
    configure_file(
        "${PROJECT_SOURCE_DIR}/config.h.in"
        "${PROJECT_SOURCE_DIR}/config.h"
        )
    
    add_subdirectory(example)
    
    

    说明

    configure_file命令用于加入一个配置头文件config.h ,这个文件由CMake从config.h.in生成,通过这样的机制,将可以通过预定义一些参数和变量来控制代码的生成。

    option命令添加了ENABLE_ADD 选项
    ENABLE_SUB选项,并且默认值为ON

    cmake 可以根据ENABLE_ADD 选项
    ENABLE_SUB选项的值来控制是否编译add模块和sub模块。

    要想在config.h生成对应的宏,需要对config.h.in进行如下配置

    config.h.in

    #cmakedefine ENABLE_ADD
    #cmakedefine ENABLE_SUB
    
    

    3. 配置&编译

    默认配置&编译

    $ cd build
    $ cmake ..
    $ make
    $ cd ..
    $ tree bin lib
    

    效果如下:

    bin
    └── test_add_sub
    lib
    ├── libadd.a
    ├── libadd.so -> libadd.so.1
    ├── libadd.so.1 -> libadd.so.1.0
    ├── libadd.so.1.0
    ├── libsub.a
    ├── libsub.so -> libsub.so.1
    ├── libsub.so.1 -> libsub.so.1.0
    └── libsub.so.1.0
    
    

    从生成的lib库,可以看出,add模块和sub模块都生成了。

    查看config.h

    #define ENABLE_ADD
    #define ENABLE_SUB
    
    

    自定义配置&编译

    $ cd build
    $ cmake -DENABLE_ADD=OFF ..
    $ make
    $ cd ..
    $ tree bin lib
    

    效果如下:

    bin
    └── test_add_sub
    lib
    ├── libsub.a
    ├── libsub.so -> libsub.so.1
    ├── libsub.so.1 -> libsub.so.1.0
    └── libsub.so.1.0
    
    

    从生成的lib库,可以看出,add模块并未生成了。

    查看config.h

    /* #undef ENABLE_ADD */
    #define ENABLE_SUB
    

    使用ccmake工具进行配置

    当我们的项目很大且配置选项很多的时候,可以选择ccmake工具进行配置编译选项,这个是交互式配置工具,有点类似内核的menuconfigure的功能。

    说明

    enter: 编辑选项

    c: 配置

    g:生成makefile

    q:退出

    h: 帮助

  • 相关阅读:
    fastjson转对象的一些属性设置
    Linux下重命名文件或文件夹(mv命令与rename命令)
    Linux下打包压缩war、解压war包和jar命令
    linux如何复制文件夹和移动文件夹
    linux下使用tar命令
    linux压缩和解压缩命令大全
    2019第11周日
    Git上传空文件夹的方法
    SpringBoot2
    Spring Boot 历史
  • 原文地址:https://www.cnblogs.com/standardzero/p/10798603.html
Copyright © 2020-2023  润新知