• 3. CMake 系列


    1. 项目目录结构

    test2
    ├── add
    │   ├── add.c
    │   ├── add.h
    │   └── CMakeLists.txt
    ├── build
    ├── CMakeLists.txt
    ├── example
    │   ├── CMakeLists.txt
    │   ├── test_add.c
    │   └── test_sub.c
    └── sub
        ├── CMakeLists.txt
        ├── sub.c
        └── sub.h
    

    说明

    add: 这个模块是加法模块,会生成动态库和静态库。

    sub:这个模块是减法模块,会生成动态库和静态库。

    example:这个模块是测试addsub模块程序。

    CMakeLists.txt:这里有4个CMakeLists.txt,顶层CMakeLists.txt文件管理其它模块CMakeLists.txt文件,每个模块CMakeLists.txt文件都只需管理自己编译。

    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 测试模块

    test_add.c

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

    test_sub.c

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

    CMakeLists.txt

    # 添加头文件路径
    include_directories(${PROJECT_SOURCE_DIR}/add)
    include_directories(${PROJECT_SOURCE_DIR}/sub)
    
    # 添加第三方库(add)头文件路径
    link_directories(${PROJECT_SOURCE_DIR}/lib)
    
    # 生成执行文件
    add_executable(test_add test_add.c)
    add_executable(test_sub test_sub.c)
    
    # 链接库文件
    target_link_libraries(test_add add)
    target_link_libraries(test_sub sub)
    
    # 安装执行文件
    INSTALL(TARGETS test_add test_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)
    
    # 添加子目录
    add_subdirectory(add)
    add_subdirectory(sub)
    add_subdirectory(example)
    

    说明
    顶层CMakeLists.txt管理子目录的CMakeLists.txt, 从而实现模块化编译和管理。

    3. 编译 & 安装

    $ cd build
    $ cmake -DCMAKE_INSTALL_PREFIX=/home/mark/code/cmake/test2/_install ..
    $ make
    $ make install
    $ cd ..
    $ tree _install

    查看效果

    _install/
    ├── bin
    │   ├── test_add
    │   └── test_sub
    ├── include
    │   ├── add.h
    │   └── sub.h
    └── 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

    说明

    -DCMAKE_INSTALL_PREFIX:指定安装目录,需要是绝对路径。

    4. 项目安装基本语法

    4.1 安装target

    语法

    INSTALL(TARGETS targets...
    [[ARCHIVE|LIBRARY|RUNTIME]
    [DESTINATION <dir>]
    [PERMISSIONS permissions...]
    [CONFIGURATIONS
    [Debug|Release|...]]
    [COMPONENT <component>]
    [OPTIONAL]
    ] [...])

    targets: 一般填执行文件、动态库、静态库。

    ARCHIVE: 特指静态库。

    LIBRARY: 特指动态库。

    RUNTIME: 特指执行文件。

    dir: 安装路径,一般配合CMAKE_INSTALL_PREFIX使用,即表示为${CMAKE_INSTALL_PREFIX}/dir。若是dir/开头,表示绝对路径,即不使用CMAKE_INSTALL_PREFIX变量。

    一个例子

    #安装动态库和静态库
    INSTALL(TARGETS sub_lib_shared sub_lib_static
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)
        
    
    # 安装执行文件
    INSTALL(TARGETS test_add test_sub
        RUNTIME DESTINATION bin)

    4.2 安装普通文件

    语法

    INSTALL(FILES files... DESTINATION <dir>
    [PERMISSIONS permissions...]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [RENAME <name>] [OPTIONAL])

    使用方法和上述方法类似,举个简单的例子,就大概知道怎么用了。

    一个例子

    #安装头文件
    INSTALL(FILES ${h_files}  DESTINATION include)

    4.3 安装目录和脚本

    语法

    INSTALL(DIRECTORY dirs... DESTINATION <dir>
    [FILE_PERMISSIONS permissions...]
    [DIRECTORY_PERMISSIONS permissions...]
    [USE_SOURCE_PERMISSIONS]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [[PATTERN <pattern> | REGEX <regex>]
    [EXCLUDE] [PERMISSIONS permissions...]] [...])

    说明

    dirs:DIRECTORY 后面连接的路径是所在Source目录的相对路径; 但务必注意: abcabc/有很大的区别: 如果目录名不以/结尾,那么这个目录将被安装为目标路径下的abc,如果目录名以/结尾,代表将这个目录中的内容安装到目标路径,但不包括这个目录本身。

    pattern: 使用正则表达式进行过滤.

    permissions: 用于指定pattern过滤后的文件权限。

    举例说明

    INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj
    PATTERN "CVS" EXCLUDE
    PATTERN "scripts/*"
    PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
    GROUP_EXECUTE GROUP_READ)

    这条指令的执行结果是:将icons 目录安装到 <prefix>/share/myproj
    scripts/中的内容安装到<prefix>/share/myproj不包含目录名为CVS
    的目录,对于scripts/*文件指定权限为OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ

    出处:https://www.cnblogs.com/standardzero/p/10793746.html
  • 相关阅读:
    关于GaussDB(DWS)的正则表达式知多少?人人都能看得懂的详解来了!
    前端面试常考题:JS垃圾回收机制
    先收藏!关于Java类、接口、枚举的知识点大汇总
    一文带你熟悉Pytorch->Caffe->om模型转换流程
    详解SSH 框架中对象调用流程
    Golang代码测试:一点到面用测试驱动开发
    构建万物可信互联的基石,带你深度剖析区块链跨链的关键技术,满满是干货!
    数据库的两个好帮手:pagehack和pg_xlogdump
    什么是OpenMAX技术分析OpenMAX
    OpenMAX概述
  • 原文地址:https://www.cnblogs.com/jingsupo/p/12194170.html
Copyright © 2020-2023  润新知