cmake學習-2

似懂非懂,一定要搞懂基礎的,剩下的邊做邊學,從案例中入手。

有關cmake的介紹,請參考:
1、https://www.cnblogs.com/pam-sh/p/13885959.html
2、https://www.cnblogs.com/pam-sh/p/14800154.html

基礎

A-hello-cmake(單文件)

1、文件結構
image

2、CMakeLists文件

#該項目所支持cmake的最低版本號
cmake_minimum_required(VERSION 3.5)

#項目名稱
project (hello_cmake)

#指定從源文件生成可執行文件
add_executable(hello_cmake main.cpp)

註釋:
(1)一般將項目名稱作爲可執行文件名

add_executable(${PROJECT_NAME} main.cpp)

B-hello-headers(多文件)

1、文件結構
image
2、CMakeLists文件

cmake_minimum_required(VERSION 3.5)
project (hello_headers)

# 創建一個源文件變量,表示多個源文件(cpp)
set(SOURCES
    src/Hello.cpp
    src/main.cpp
)

add_executable(hello_headers ${SOURCES})

# 存在不同文件夾(頭文件)時,使用該命令讓編譯器知道,其中PRIVATE表示include文件的使用範圍target_include_directories(hello_headers
    PRIVATE 
        ${PROJECT_SOURCE_DIR}/include
)

註釋:
1、變量說明
CMake語法指定了許多變量,可用於幫助在項目或源代碼樹中查找有用的目錄。其中包括:
(1)CMAKE_SOURCE_DIR:項目根目錄
(2)CMAKE_CURRENT_SOURCE_DIR:當前項目原目錄(若存在子項目)
(3)PROJECT_SOURCE_DIR:當前cmake項目的源目錄。
(4)CMAKE_BINARY_DIR:binary / build的目錄,即運行cmake的目錄
(5)CMAKE_CURRENT_BINARY_DIR:當前所在的build目錄
(6)PROJECT_BINARY_DIR:當前項目的build目錄

2、在創建源文件變量時可以使用通配符

#利用GLOB命令,識別通配符,
file(GLOB SOURCES "src/*.cpp")

3、target_include_directories() 中的權限
(1)PRIVATE:被添加到目標include目錄
(2)INTERFACE:被添加到任何鏈接此庫的目錄中
(3)PUBLIC:此庫和其他目標都有鏈接

這裏include中的頭文件,正好對應着文件中過的引用。

C-static-library(靜態庫)

1、文件結構
image
2、CMakeLists文件

cmake_minimum_required(VERSION 3.5)
project(hello_library)

############################################################
# Create a library
############################################################

#從源文件中生成一個靜態庫(libhello_library.a)
add_library(hello_library STATIC 
    src/Hello.cpp
)

target_include_directories(hello_library
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)

############################################################
# Create an executable
############################################################

# Add an executable with the above sources
add_executable(hello_binary 
    src/main.cpp
)

# 鏈接靜態庫,即將該靜態庫告知編譯器
target_link_libraries( hello_binary
    PRIVATE 
        hello_library
)

註釋:
1、使用add_library()將源文件轉換爲靜態庫
2、使用target_link_libraries()函數導入靜態庫

D-shared-library(動態庫)

1、文件結構
image

2、CMakeLists文件

cmake_minimum_required(VERSION 3.5)
project(hello_library)

############################################################
# Create a library
############################################################

#從源文件中生成一個分析庫/動態庫(libhello_library.so/libhello_library.dylib)
add_library(hello_library SHARED 
    src/Hello.cpp
)
# 給動態庫取一個別名,可以代替該庫使用
add_library(hello::library ALIAS hello_library)

target_include_directories(hello_library
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)

############################################################
# Create an executable
############################################################

# Add an executable with the above sources
add_executable(hello_binary
    src/main.cpp
)

# 鏈接此動態庫
target_link_libraries( hello_binary
    PRIVATE 
        hello::library
)

E-installing(make install)

1、文件結構
image

2、CMakeLists文件

cmake_minimum_required(VERSION 3.5)
project(cmake_examples_install)

############################################################
# Create a library
############################################################

#創建一個動態庫
add_library(cmake_examples_inst SHARED
    src/Hello.cpp
)

# 引入頭文件
target_include_directories(cmake_examples_inst
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)

############################################################
# Create an executable
############################################################

# Add an executable with the above sources
add_executable(cmake_examples_inst_bin
    src/main.cpp
)

#鏈接動態庫
# link the new hello_library target with the hello_binary target
target_link_libraries( cmake_examples_inst_bin
    PRIVATE 
        cmake_examples_inst
)

############################################################
# Install
#${CMAKE_INSTALL_PREFIX}默認是/usr/local
############################################################

# 將生成的可執行文件(cmake_examples_inst_bin)下載到${CMAKE_INSTALL_PREFIX}/bin文件夾下,
install (TARGETS cmake_examples_inst_bin
    DESTINATION bin)

# 將生成的動態庫(libcmake_examples_inst.dylib)下載到${CMAKE_INSTALL_PREFIX}/lib文件夾下
# Note: may not work on windows
install (TARGETS cmake_examples_inst
    LIBRARY DESTINATION lib)

# 將該庫的頭文件下載到${CMAKE_INSTALL_PREFIX}/include文件夾下
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ 
    DESTINATION include)

# 將該庫的設置文件下載到${CMAKE_INSTALL_PREFIX}/etc文件夾下
install (FILES cmake-examples.conf
    DESTINATION etc)

註釋:
1、在make install時,若在Windows平臺中:

install (TARGETS cmake_examples_inst
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION bin)

2、在make install 後,會生成install_manifest.txt文件,記錄下載的信息
3、下載位置默認爲:/usr/local,可以通過該方式指定下載位置:
(1)在cmake時每次手動指定

cmake .. -DCMAKE_INSTALL_PREFIX=/install/location

(2)在CMakeLists文件中指定

if( CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT )
  message(STATUS "Setting default CMAKE_INSTALL_PREFIX path to ${CMAKE_BINARY_DIR}/install")
  set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "The path to use for make install" FORCE)
endif()

(3)在make時手動指定

make install DESTDIR=指定安裝位置

F-build-type(調試類型)

1、文件結構
image

2、CMakeLists文件

# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.5)

# 設置默認調試類型(RelWithDebInfo)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message("Setting build type to 'RelWithDebInfo' as none was specified.")
  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()

# Set the project name
project (build_type)

# Add an executable
add_executable(cmake_examples_build_type main.cpp)

註釋:
1、在調試build時,可以指定調試類型:
(1)Release:命令參數 -O3 -DNDEBUG
(2)Debug:命令參數 -g
(3)MinSizeRel:命令參數 -Os -DNDEBUG
(4)RelWithDebInfo:命令參數 -O2 -g -DNDEBUG
可以手動設置:

cmake .. -DCMAKE_BUILD_TYPE=Release/Debug/MinSizeRel/RelWithDebInfo

也可以設置爲默認:

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message("Setting build type to 'RelWithDebInfo' as none was specified.")
  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()

也可以在cmake中設置:
image

G-compile-flags(不太懂)

1、文件結構
image
2、CMakeLists文件


註釋:
1、使用target_compile_definitions()函數

2、使用CMAKE_C_FLAGS 和 CMAKE_CXX_FLAGS變量

H-third-party-library(第三方庫)

在cmake中,使用find_package()函數引入第三方庫,它能找到CMAKE_MODULE_PATH(默認爲/usr/share/cmake/Modules)目錄下的FindXXX.cmake文件。
這裏以Boost庫爲例,boost更多可參考:https://www.cnblogs.com/pam-sh/p/16107753.html

1、文件結構
image

2、CMakeLists文件

cmake_minimum_required(VERSION 3.5)
# Set the project name
project (third_party_include)


# 使用庫文件系統和系統查找boost庫的.cmake文件
find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)

# 檢查是否找到boost
if(Boost_FOUND)
    message ("boost found")
else()
    message (FATAL_ERROR "Cannot find Boost")
endif()

# Add an executable
add_executable(third_party_include main.cpp)

# 鏈接boost庫
target_link_libraries( third_party_include
    PRIVATE
        Boost::filesystem
)

註釋:
1、find_package()
可以在CMAKE_MODULE_PATH目錄下查找類似FindXXX.cmake的文件。
解釋一下:find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)

  • Boost:表示引入的第三方庫的名字,找的就是FindBoost.cmake
  • 1.46.1:表示支持的boost最低版本
  • REQUIRED:表示這庫是必要要有的,不然會出錯
  • COMPONENTS:表示會在哪找這個庫,filesystem和system表示。。

2、Checking if the package is found
很多庫中都會設置一個變量“XXX_FOUND”,能夠檢查系統中是否存在對應的庫,以boost爲例:

if(Boost_FOUND)
    message ("boost found")
    include_directories(${Boost_INCLUDE_DIRS})
else()
    message (FATAL_ERROR "Cannot find Boost")
endif()

在找到包後,通常會導出一些變量,告知庫的頭文件、靜態文件、可執行文件在哪個位置,這些信息通暢裏記錄在FindXXX.cmake文件中。
上面例子中的:Boost_INCLUDE_DIRS就表示boost庫的頭文件。
可以使用ccmakecmake-gui在緩存中檢查這些變量。

3、別名
當前很多庫會使用別名,更加方便的表示,比如boost庫,會使用Boost::導出別名:

  • Boost::boost:僅表示庫的頭文件
  • Boost::system:表示boost系統庫
  • Boost::filesystem :表示文件系統

並且會有依賴關係,當使用Boost::filesystem時,會依賴於Boost::boost 和 Boost::system
如果要有針對的導入,可以使用:

target_link_libraries( third_party_include
      PRIVATE
          Boost::filesystem
  )

而不使用別名時,則會單獨指出:

# Include the boost headers
target_include_directories( third_party_include
    PRIVATE ${Boost_INCLUDE_DIRS}
)

# link against the boost libraries
target_link_libraries( third_party_include
    PRIVATE
    ${Boost_SYSTEM_LIBRARY}
    ${Boost_FILESYSTEM_LIBRARY}
)

其中:
target_include_directories:指向庫的include目錄,即表示庫的頭文件
target_link_libraries:表示庫的路徑

參考

1、https://github.com/ttroy50/cmake-examples
這是一個學習cmake的地方,有很多案例可以學習,從淺入深
2、https://pan.baidu.com/s/1Bvzy0gK4O5vEYti3VV2A5g
提取碼:0un9,別人總結的筆記
3、CmakeList入門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章