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\n", 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\n", 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


免責聲明!

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



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