4. CMake 系列 - 項目添加編譯選項


[TOC]

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\n", a, b, add(a, b));
#endif

#ifdef ENABLE_SUB
    printf("%d - %d = %d\n", 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: 幫助


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM