[C/C++] CMake使用方法(詳細)


cmake使用方法(詳細)

 

 


幫助文檔

  1. cmake官方新手tutorial
  2. cmake 添加頭文件目錄,鏈接動態、靜態庫
  3. 官方文檔
  4. cmake 語法

技巧

  1. cmake命令是不區分大小寫的,但是變量區分。
  2. 判斷編譯器類型

cmake if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") MESSAGE("Clang") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") MESSAGE("GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") MESSAGE("Intel") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") MESSAGE("MSVC") endif()

命令行選項

-D

  1. -D 相當於就是定義, -D 可以理解為告訴cmake 后邊我要定義一些參數了, 你每定義一個就在前邊加上-D就是了
  2. CMAKE_BUILD_TYPE 這種東西往往是在CMakeList.txt 中定義的, 這個是你要編譯的類型, 一般的選擇有debug,release, 但是不確定
  3. CMAKE_INSTALL_PREFIX 這個是安裝路徑.

例子

cmake -DCMAKE_BUILD_TYPE=Debug

編譯選項

cmake腳本中,設置編譯選項可以通過add_compile_options命令,也可以通過set命令修改CMAKE_CXX_FLAGSCMAKE_C_FLAGS。 使用這兩種方式在有的情況下效果是一樣的,但請注意它們還是有區別的:

  1. add_compile_options命令添加的編譯選項是針對所有編譯器的(包括c和c++編譯器),
  2. 而set命令設置CMAKE_C_FLAGSCMAKE_CXX_FLAGS變量則是分別只針對c和c++編譯器的。

例子

#判斷編譯器類型,如果是gcc編譯器,則在編譯選項中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX)  set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")  message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX)

add_compile_options

語法

add_compile_options(<option> ...)  # 例子  add_compile_options(-Wall -Wextra -pedantic -Werror -g)

add_compile_definition

待補充

option & add_definition

語法

# Provides an option for the user to select as ON or OFF. If no initial <value> is provided, OFF is used. If <variable> is already set as a normal variable then the command does nothing option(<variable> "<help_text>" [value])  # Add -D define flags to the compilation of source files. add_definitions(-DFOO -DBAR ...)

使用方法

  1. 首先在CMakeList.txt中增加選項
    cmake option(TEST_DEBUG "option for debug" OFF) if (TEST_DEBUG) add_definitions(-DTEST_DEBUG) endif()
  2. 在cmake構造makefile的時候輸入想要的參數
    bash cmake -DTEST_DEBUG=ON ..
  3. 源碼中使用該定義
    ```cmake // test.cpp
    include "test.h"
    ifdef TEST_DEBUG
    ...
    endif
    ```

語法說明

列表和字符串

在CMake中基礎的數據形式是字符串。CMake也支持字符串列表。

列表通過分號分隔。譬如兩個聲明給變量VAR設同樣的值:

set(VAR a;b;c) set(VAR a b c)

字符串列表可以通過foreach命令迭代或直接操控列表命令。

變量

CMake 支持簡單的變量可以是字符串也可以是字符串列表。變量參考使用${VAR}語法。多參數可以使用set命令組合到一個列表中。所有其他的命令

通過空白分隔符傳遞命令來擴展列表,例如

set(Foo a b c) # 將 變量 Foo 設為 a b c, 並且如果Foo 傳遞給另一個命令 command(${Foo}) # 等同於 command(a b c)  # 如果要把參數列表傳遞給一個命令,且它是一個簡單的參數只要加一個雙引號就可以。例如 command("${Foo}") # 等價於 command("a b c")

控制流

像大多數語言一樣,Cmake 提供了控制流結構。Cmake提供了三中控制流:

  1. 條件控制流 if
    ```cmake
    some_command will be called if the variable's value is not:
    empty, 0, N, NO, OFF, FALSE, NOTFOUND, or -NOTFOUND.
    if(var) some_command(...) endif(var) ```
  2. 循環結構: foreach 和 while
    ```cmake set(VAR a b c)
    loop over a, b,c with the variable f
    foreach(f ${VAR}) message(${f}) endforeach(f) ```
  3. 過程定義 宏和函數(函數在2.6及更高的版本中有效)。函數對變量局部有效,宏是全局有效。
    ```cmake
    define a macro hello
    macro(hello MESSAGE) message(${MESSAGE}) endmacro(hello)
    call the macro with the string "hello world"
    hello("hello world")
    define a function hello
    function(hello MESSAGE) message(${MESSAGE}) endfunction(hello) ```

更多控制流信息參見命令 if,while,foreach,macro,function文檔。

引號,字符串和轉義

在CMake中原義字符串用雙引號括起來。字符串可以是多行字符串,並在其中嵌入新的行。例如

set(MY_STRING "this is a string with a   newline in  it")

也可以在一個字符串中轉義字符和使用變量

set(VAR "   hello   world  ")  message("\${VAR}= ${VAR}")  # prints out  ${VAR}=  hello  world

同樣支持標准C中的轉義

message("\n\thello world")  #prints out  hello world

如果字符在引號之前是空格則原義字符串只是原義字符串。但是引號必須成對,例如

message(hell"o") -> prints hell"o" message(hell\"o\") -> prints hello"o"

正則表達式

cmake可以使用正則表達式

常用命令

cmake_minimum_required

cmake project 頭文件必須存在這行命令, 例如cmake_minimum_required(VERSION 3.10)

project

設置項目名稱project(Tutorial)

set

語法

# Set Normal Variable set(<variable> <value>... [PARENT_SCOPE])  # Set Environment Variable # 這個環境變量只對當前cmake工程有效,對外界是無效的。 set(ENV{<variable>} [<value>])

例子

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -Wall -Wl,-rpath=/tools/lib64 -Wl,--dynamic-linker=/tools/lib/ld-2.17.so")

message

語法

message([<mode>] "message to display" ...)

mode關鍵字

The optional <mode> keyword determines the type of message:

|mode | explaination| |--|--:| |FATAL_ERROR|CMake Error, stop processing and generation. |SEND_ERROR|CMake Error, continue processing, but skip generation. |WARNING|CMake Warning, continue processing. |AUTHOR_WARNING|CMake Warning (dev), continue processing. |DEPRECATION|CMake Deprecation Error or Warning if variable CMAKE_ERROR_DEPRECATED or CMAKE_WARN_DEPRECATED is enabled, respectively, else no message. |(none) or NOTICE|Important message printed to stderr to attract user’s attention. |STATUS|一般就用這個,Ideally these should be concise, no more than a single line, but still informative. |VERBOSE|Detailed informational messages intended for project users. These messages should provide additional details that won’t be of interest in most cases, but which may be useful to those building the project when they want deeper insight into what’s happening. |DEBUG|Detailed informational messages intended for developers working on the project itself as opposed to users who just want to build it. These messages will not typically be of interest to other users building the project and will often be closely related to internal implementation details. |TRACE|Fine-grained messages with very low-level implementation details. Messages using this log level would normally only be temporary and would expect to be removed before releasing the project, packaging up the files, etc.

aux_source_directory 查找源文件

# 找到所有dir目錄下的源文件(不會遞歸遍歷子文件夾),源文件是.c文件(也就是makefile中可以生成.o的文件) aux_source_directory(<dir> <variable>)

add_library

將指定的源文件(CPP文件)生成鏈接文件,然后添加到工程中去。

語法

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [source1] [source2 ...])

其中<name>表示庫文件的名字,該庫文件會根據命令里列出的源文件來創建。而STATICSHAREDMODULE的作用是指定生成的庫文件的類型。

  1. STATIC庫是目標文件的歸檔文件,在鏈接其它目標的時候使用。
  2. SHARED庫會被動態鏈接(動態鏈接庫),在運行時會被加載。
  3. MODULE庫是一種不會被鏈接到其它目標中的插件,但是可能會在運行時使用dlopen-系列的函數。
  4. 默認狀態下,庫文件將會在於源文件目錄樹的構建目錄樹的位置被創建(默認static),該命令也會在這里被調用。

例子

add_library(roland_pb CreateUDiskRequest.pb.cc) add_executable(echo_client echo_client.cc) target_link_libraries(echo_client uevent event uevent_base pthread roland_pb protobuf)

add_subdirectory

在子文件夾添加了library或者executable之后,在上層目錄添加subdirectory, 也可以在同一個CMakeList.txt中使用

include_directories 添加頭文件目錄

它相當於g++選項中的-I參數的作用,也相當於環境變量中增加路徑到CPLUS_INCLUDE_PATH變量的作用。

語法:

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]) # 例子 include_directories(../../../thirdparty/comm/include)

link_directories 添加需要鏈接的庫文件目錄

它相當於g++命令的-L選項的作用,也相當於環境變量中增加LD_LIBRARY_PATH的路徑的作用。 語法:

`link_directories(directory1 directory2 ...)` # 例子 `link_directories("/home/server/third/lib")`

find_library 查找庫所在目錄

語法:

# A short-hand signature is: find_library (<VAR> name1 [path1 path2 ...])  # The general signature is: find_library ( <VAR> name | NAMES name1 [name2 ...] [NAMES_PER_DIR] [HINTS path1 [path2 ... ENV var]] [PATHS path1 [path2 ... ENV var]] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [NO_DEFAULT_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [NO_CMAKE_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_SYSTEM_PATH] [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | NO_CMAKE_FIND_ROOT_PATH] )  # 例子如下 FIND_LIBRARY(RUNTIME_LIB rt /usr/lib /usr/local/lib NO_DEFAULT_PATH) cmake會在目錄中查找,如果所有目錄中都沒有,值RUNTIME_LIB就會被賦為NO_DEFAULT_PATH

link_libraries 添加需要鏈接的庫文件路徑

該指令的作用主要是指定要鏈接的庫文件的路徑,該指令有時候不一定需要。因為find_package和find_library指令可以得到庫文件的絕對路徑。不過你自己寫的動態庫文件放在自己新建的目錄下時,可以用該指令指定該目錄的路徑以便工程能夠找到。

語法:

link_libraries(library1 <debug | optimized> library2 ...)

# 直接是全路徑 link_libraries(“/home/server/third/lib/libcommon.a”) # 下面的例子,只有庫名,cmake會自動去所包含的目錄搜索 link_libraries(iconv)  # 傳入變量 link_libraries(${RUNTIME_LIB}) # 也可以鏈接多個 link_libraries("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

可以鏈接一個,也可以多個,中間使用空格分隔.

target_link_libraries 設置要鏈接的庫文件的名稱

語法:

target_link_libraries(<target> [item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)  # 以下寫法都可以: target_link_libraries(myProject comm) # 連接libhello.so庫,默認優先鏈接動態庫 target_link_libraries(myProject libcomm.a) # 顯示指定鏈接靜態庫 target_link_libraries(myProject libcomm.so) # 顯示指定鏈接動態庫  # 再如: target_link_libraries(myProject libcomm.so)  #這些庫名寫法都可以。 target_link_libraries(myProject comm) target_link_libraries(myProject -lcomm)

add_executable 為工程生成目標文件

語法:

add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...])

簡單的例子如下:

add_executable(demo main.cpp) add_executable(echo_client echo_client.cc CreateUDiskRequest.pb.cc)
本篇文章由一文多發平台 ArtiPub自動發布


免責聲明!

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



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