c++ cmakelist 詳解


基本元素

首先cmaklist必須包括以下幾個部分:

#工程名

project(study_case)

#cmake最低版本需求

cmake_minimum_required(VERSION 2.8.3)

 

#添加添加需要的庫

set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/share/OpenCV")

find_package(OpenCV 3.2.0 REQUIRED)

 

#確定需要的頭文件

include_directories(

    include

)

 

#確定編譯語言

#1

set(CMAKE_CXX_STANDARD 11)

#2. or

add_definitions(-std=c++11)

 

#設置二進制文件目錄

SET(BIN_DESTINATION ${PROJECT_SOURCE_DIR}/bin)

SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_DESTINATION})

 

#如果多個文件相關,則添加源代碼(可選)

set(SRC 

    ${PROJECT_SOURCE_DIR}/src/detector.cpp

    ${PROJECT_SOURCE_DIR}/src/demo.cpp

    ${PROJECT_SOURCE_DIR}/src/test.cpp

)

#如果需要編譯動態庫並鏈接庫文件(可選)

link_directories(${PROJECT_SOURCE_DIR})

add_library(overload SHARED ${SRC})

target_link_libraries(overload -llianghao  -lpthread -lm -lstdc++)

 

#生成可執行文件

link_directories(${PROJECT_SOURCE_DIR})

#添加可執行文件

#1. 如果文件之間沒有關聯

add_executable(overload src/overload.cpp)

#2. or 如果多個文件相關

add_executable(overload src/overload.cpp ${SRC})

 

#如果有依賴外部庫則需要添加以下命令(可選)

target_link_libraries(overload -llianghao  -lpthread -lm -lstdc++)

其他功能

1. 使其包含c++11特性-std=c++11如何寫進cmakeList.txt

#1

set(CMAKE_CXX_STANDARD 11)

#2. or

add_definitions(-std=c++11)

#3. or

include(CheckCXXCompilerFlag)

CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)

CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)

if(COMPILER_SUPPORTS_CXX11)

        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

elseif(COMPILER_SUPPORTS_CXX0X)

        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")

else()

     message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")

endif()

2. 設定可執行文件的輸出目錄

SET(BIN_DESTINATION ${PROJECT_SOURCE_DIR}/bin)

SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_DESTINATION})

3. 生成so

3.1 想生成多個so

# 設置構建本地庫所需的最小版本的cbuild。

cmake_minimum_required(VERSION 3.4.1)

# 創建並命名一個庫,將其設置為靜態

#  或者共享,並提供其源代碼的相對路徑。

# 您可以定義多個庫,而cbuild為您構建它們。

#  Gradle自動將共享庫與你的APK打包。

add_library( hello-lib  #設置庫的名稱。即SO文件的名稱,生產的so文件為“libhello-lib.so”,在加載的時候“System.loadLibrary("hello-lib");”

                SHARED  # 將庫設置為共享庫。

                src/main/jni/hello.cpp    # 提供一個源文件的相對路徑

                src/main/jni/helloJni.cpp    # 提供同一個SO文件中的另一個源文件的相對路徑

              )

#搜索指定的預構建庫,並將該路徑存儲為一個變量。因為cbuild默認包含了搜索路徑中的系統庫,所以您只需要指定您想要添加的公共NDK庫的名稱。cbuild在完成構建之前驗證這個庫是否存在。

find_library(log-lib  # 設置path變量的名稱。

              log   #  指定NDK庫的名稱 你想讓CMake來定位。

               )

#指定庫的庫應該鏈接到你的目標庫。您可以鏈接多個庫,比如在這個構建腳本中定義的庫、預構建的第三方庫或系統庫。

target_link_libraries( hello-lib     #指定目標庫中。與 add_library的庫名稱一定要相同

                       ${log-lib}    # 將目標庫鏈接到日志庫包含在NDK。

                        )

#如果需要生產多個SO文件的話,寫法如下

add_library( natave-lib  #設置庫的名稱。另一個so文件的名稱

                SHARED  # 將庫設置為共享庫。

                src/main/jni/nataveJni.cpp    # 提供一個源文件的相對路徑

              )

target_link_libraries( natave-lib     #指定目標庫中。與 add_library的庫名稱一定要相同

                       ${log-lib}    # 將目標庫鏈接到日志庫包含在NDK。

                        )

這里還有一個坑在里面,就是如果你的庫的名字起得不是叫xx-lib的話,編譯是通不過的,親測,比如起個so庫名叫test,cpp文件叫做test.cpp,這樣是編譯不過的,不會生成多個so庫。

3.1 生成一個so庫,多個cpp文件

# 查找cpp目錄下的所有源文件

# 並將名稱保存到 DIR_LIB_SRCS 變量

aux_source_directory(src/main/cpp/ DIR_LIB_SRCS)

# 生成鏈接庫

add_library (native-lib SHARED ${DIR_LIB_SRCS})

 

# 導入cpp目錄下的所有頭文件

include_directories(src/main/cpp/)

替換原有的add_library命令就可以了,其實就是生成一個變量,指定cpp的文件路徑

4. 設置編譯類型

#set release

if (NOT CMAKE_BUILD_TYPE)

    message("not defined Build Type:auto define it to Debug" )

    set (CMAKE_BUILD_TYPE Debug)

endif (NOT CMAKE_BUILD_TYPE)

 

if (CMAKE_BUILD_TYPE MATCHES "Debug" )

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")

    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")

elseif (CMAKE_BUILD_TYPE MATCHES "Release" )

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 ")

    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 ")

elseif (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 ")

    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O2 ")

else()

    message("unkown defined Build Type:same handle with Debug" )

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")

    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")

endif (CMAKE_BUILD_TYPE MATCHES "Debug")

5. 外部庫FIND_PACKAGE

格式: 

FIND_PACKAGE(<name> [version] [EXACT] [QUIET] [NO_MODULE] [ [ REQUIRED | COMPONENTS ] [ componets... ] ] )

5.1 查找*.cmake的順序

1 find_package(<Name>)命令首先會在模塊路徑中尋找Find<name>.cmake

這是查找庫的一個典型方式,具體查找路徑依次為CMake: 

變量${CMAKE_MODULE_PATH}中的所有目錄。

如果沒有, 然后再查看它自己的模塊目錄: /share/cmake-x.y/Modules/ 。

這稱為模塊模式。

2如果沒找到這樣的文件:

find_package()會在:

~/.cmake/packages/

或/usr/local/share/

中的各個包目錄中查找,尋找:

<庫名字的大寫>Config.cmake 

或 <庫名字的小寫>-config.cmake

(比如庫Opencv,它會查找/usr/local/share/OpenCV中的OpenCVConfig.cmake或opencv-config.cmake)。**這稱為配置模式。

不管使用哪一種模式,只要找到.cmake.cmake里面都會定義下面這些變量:

例子<NAME>: OpenCVConfig.cmake

<NAME>_FOUND

<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES

<NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS

<NAME>_DEFINITIONS

注意大部分包的這些變量中的包名是全大寫的,如 LIBFOO_FOUND ,有些包則使用包的實際大小寫,如 LibFoo_FOUND

  如果找到這個包,則可以通過在工程的頂層目錄中的CMakeLists.txt 文件添加 include_directories(_INCLUDE_DIRS) 來包含庫的頭文件,添加target_link_libraries(源文件 _LIBRARIES)命令將源文件與庫文件鏈接起來。

5.2 使用外部庫的方式

為了能支持各種常見的庫和包,CMake自帶了很多模塊。可以通過命令cmake --help-module-list得到你的CMake支持的模塊的列表,或者直接查看模塊路徑。比如Ubuntu上,模塊的路徑是: 

/usr/share/cmake/Modules/

讓我們以bzip2庫為例。CMake中有個FindBZip2.cmake 模塊。只要使用 find_package(BZip2) 調用這個模塊,cmake會自動給一些變量賦值,然后就可以在CMakelists.txt中使用它們了。變量的列表可以查看cmake模塊文件,或者使用命令 cmake –help-module FindBZip2 。

比如一個使用bzip2的簡單程序,編譯器需要知道 bzlib.h 的位置,鏈接器需要找到bzip2庫(動態鏈接的話,Unix上是 libbz2.so 類似的文件,Windows上是 libbz2.dll )。

cmake_minimum_required(VERSION 2.8)

project(helloworld)

add_executable(helloworld hello.c)

find_package(BZip2)

if (BZIP2_FOUND)

  include_directories(${BZIP_INCLUDE_DIRS})

  target_link_libraries (helloworld ${BZIP2_LIBRARIES})

endif (BZIP2_FOUND)

5.3 find_package中的參數定義

FIND_PACKAGE(<name> [version] [EXACT] [QUIET] [[REQUIRED|COMPONENTS] [ componets... ] ] )

1 version參數 

需要一個版本號,它是正在查找的包應該兼容的版本號。 

eg: 

find_package(Boost ${boost_version})

2 EXACT選項 

要求版本號必須精確匹配。如果在find-module內部對該命令的遞歸調用沒有給定[version]參數,那么[version]和EXACT選項會自動地從外部調用前向繼承。對版本的支持目前只存在於包和包之間。 

eg: 

find_package(Boost ${boost_version} EXACT REQUIRED)

3 QUIET 參數: 

會禁掉包沒有被發現時的警告信息。對應於Find.cmake模塊中的 NAME_FIND_QUIETLY。 

eg: 

find_package(Boost ${boost_version} EXACT QUIET)

4 REQUIRED 參數 

其含義是指是工程必須的,表示如果報沒有找到的話,cmake的過程會終止,並輸出警告信息。對應於Find.cmake模塊中的 NAME_FIND_REQUIRED 變量。 

eg: 

find_package(Boost REQUIRED COMPONENTS system)

COMPONENTS參數 

在REQUIRED選項之后,或者如果沒有指定REQUIRED選項但是指定了COMPONENTS選項,在它們的后面可以列出一些與包相關(依賴)的部件清單(components list) 

eg: 

find_package(Boost REQUIRED COMPONENTS system)

6. 其他

cmake中一些預定義變量

  • PROJECT_SOURCE_DIR 工程的根目錄
  • PROJECT_BINARY_DIR 運行cmake命令的目錄,通常是${PROJECT_SOURCE_DIR}/build
  • CMAKE_INCLUDE_PATH 環境變量,非cmake變量
  • CMAKE_LIBRARY_PATH 環境變量
  • CMAKE_CURRENT_SOURCE_DIR 當前處理的CMakeLists.txt所在的路徑
  • CMAKE_CURRENT_BINARY_DIR target編譯目錄 
  • 使用ADD_SURDIRECTORY(src bin)可以更改此變量的值 
  • SET(EXECUTABLE_OUTPUT_PATH <新路徑>)並不會對此變量有影響,只是改變了最終目標文件的存儲路徑
  • CMAKE_CURRENT_LIST_FILE 輸出調用這個變量的CMakeLists.txt的完整路徑
  • CMAKE_CURRENT_LIST_LINE 輸出這個變量所在的行
  • CMAKE_MODULE_PATH 定義自己的cmake模塊所在的路徑 
  • SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令來調用自己的模塊
  • EXECUTABLE_OUTPUT_PATH 重新定義目標二進制可執行文件的存放位置
  • LIBRARY_OUTPUT_PATH 重新定義目標鏈接庫文件的存放位置
  • PROJECT_NAME 返回通過PROJECT指令定義的項目名稱
  • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 用來控制IF ELSE語句的書寫方式

系統信息

  • CMAKE_MAJOR_VERSION cmake主版本號,如2.8.6中的2
  • CMAKE_MINOR_VERSION cmake次版本號,如2.8.6中的8
  • CMAKE_PATCH_VERSION cmake補丁等級,如2.8.6中的6
  • CMAKE_SYSTEM 系統名稱,例如Linux-2.6.22
  • CAMKE_SYSTEM_NAME 不包含版本的系統名,如Linux
  • CMAKE_SYSTEM_VERSION 系統版本,如2.6.22
  • CMAKE_SYSTEM_PROCESSOR 處理器名稱,如i686
  • UNIX 在所有的類UNIX平台為TRUE,包括OS X和cygwin
  • WIN32 在所有的win32平台為TRUE,包括cygwin

開關選項

  • BUILD_SHARED_LIBS 控制默認的庫編譯方式。如果未進行設置,使用ADD_LIBRARY時又沒有指定庫類型,默認編譯生成的庫都是靜態庫 (可在t3中稍加修改進行驗證)
  • CMAKE_C_FLAGS 設置C編譯選項
  • CMAKE_CXX_FLAGS 設置C++編譯選項

運行

cmake .

make

 


免責聲明!

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



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