[英]CMake compile dependencies with settings
我想知道如何為我的項目編譯依賴項,同時為這些依賴項啟用特定設置,例如將依賴項編譯為靜態或動態庫或使用x64或x86設置或作為另一個示例,當項目定義變量以確定如何構建項目(與Wayland或X.Org支持一樣)。
我目前的設置如下:
root_project
|─── CMakeLists.txt
|─── Project 1
| |─── .h and .cpp files
| └─── CMakeLists.txt
|─── Dependency 1 (GLFW)
| |─── include directory
| |─── source directory
| |─── ...
| └─── CMakeLists.txt
└─── Dependency 2 (GLEW)
|─── build
| └─── cmake
| └─── CMakeLists.txt
|─── source directory
|─── include directory
└─── ...
我的root cmake文件:
cmake_minimum_required (VERSION 3.8)
project ("EbsiStaller")
add_subdirectory ("EbsiStaller")
# Adds the CMakeLists.txt file located in the specified directory
# as a build dependency.
add_subdirectory ("glfw")
include_directories("glfw/include")
add_subdirectory ("glew/build/cmake")
include_directories("glew/include")
我的項目cmake文件:
cmake_minimum_required (VERSION 3.8)
add_executable (EbsiStaller
"....cpp"
"....h"
)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
# Links the CMake build output against glfw.
target_link_libraries(EbsiStaller glfw ${GLFW_LIBRARIES} glew ${GLEW_LIBRARIES})
我在Windows下使用Visual Studio 2017進行此項目,而項目應該與平台無關。 因為我對CMake沒有太多經驗,所以我總是對我的CMake文件的任何建議更改開放。
在為依賴項定義特定於編譯器的設置時,我不想編輯它們的CMake文件來執行此操作。
在CMake中這樣做有很多困難,但我會盡我所能回答它。
通常,通過add_subdirectory
添加的任何項目都將繼承當前作用域中當前定義的所有設置。 更改單個依賴項設置的最簡單方法(IMO)是將ExternalProject_Add
與以下宏一起使用:
include(ExternalProject)
#
# Add external project.
#
# \param name Name of external project
# \param path Path to source directory
# \param external Name of the external target
#
macro(add_external_project name path)
# Create external project
set(${name}_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${path})
set(${name}_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${path})
ExternalProject_Add(${name}
SOURCE_DIR "${${name}_SOURCE_DIR}"
BINARY_DIR "${${name}_BINARY_DIR}"
CMAKE_ARGS "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}"
# These are only useful if you're cross-compiling.
# They, however, will not hurt regardless.
"-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}"
"-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}"
"-DCMAKE_AR=${CMAKE_AR}"
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_RC_COMPILER=${CMAKE_RC_COMPILER}"
"-DCMAKE_COMPILER_PREFIX=${CMAKE_COMPILER_PREFIX}"
"-DCMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}"
INSTALL_COMMAND ""
)
endmacro(add_external_project)
#
# Add external target to external project.
#
# \param name Name of external project
# \param includedir Path to include directory
# \param libdir Path to library directory
# \param build_type Build type {STATIC, SHARED}
# \param external Name of the external target
#
macro(add_external_target name includedir libdir build_type external)
# Configurations
set(${name}_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${libdir})
# Create external library
add_library(${name} ${build_type} IMPORTED)
set(${name}_LIBRARY "${${name}_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_${build_type}_LIBRARY_PREFIX}${name}${CMAKE_${build_type}_LIBRARY_SUFFIX}")
# Find paths and set dependencies
add_dependencies(${name} ${external})
set(${name}_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${includedir}")
# Set interface properties
set_target_properties(${name} PROPERTIES IMPORTED_LOCATION ${${name}_LIBRARY})
set_target_properties(${name} PROPERTIES INCLUDE_DIRECTORIES ${${name}_INCLUDE_DIR})
endmacro(add_external_target)
這些宏基本上配置了一個具有非常相似的CMake變量定義的CMake新實例。
第一個宏, ExternalProject_Add
,通知那些自定義CMake參數,源目錄和輸出二進制目錄需要構建一次的外部項目。 特別是,像"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
這樣的選項告訴CMake使用與當前構建類型相同的構建類型(Debug,Release等),而"-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}"
指示CMake使用構建共享庫時的相同偏好(默認情況下,如果BUILD_SHARED_LIBS
設置為OFF
,則項目應構建靜態依賴項)。
第二個宏然后創建導入的目標CMake可以鏈接與類似於本機CMake庫的屬性。
要默認使用這些宏,您可以執行以下操作:
add_external_project(googletest_external googletest)
add_external_target(gtest googletest/googletest/include googletest/googlemock/gtest STATIC googletest_external)
add_external_target(gtest_main googletest/googletest/include googletest/googlemock/gtest STATIC googletest_external)
在這個例子中,我配置外部項目googletest
,然后創建目標gtest
和gtest_main
,它們應該是靜態庫(由於Googletest如何強制靜態鏈接),它可以像任何普通的CMake庫一樣鏈接。
現在您已經粗略地了解了這些宏的功能,修改它們以允許每個依賴項的自定義配置非常容易。 比如說,無論我的實際項目設置如何,我都想要一個靜態版本的glew。 讓我們假設我想要將GLEW_OSMESA
設置為ON
。
#
# Add external project.
#
macro(add_release_osmesa_glew)
# Create external project
set(${name}_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/glew)
set(${name}_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/glew)
ExternalProject_Add(glew_external
SOURCE_DIR "${${name}_SOURCE_DIR}"
BINARY_DIR "${${name}_BINARY_DIR}"
CMAKE_ARGS "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
"-DCMAKE_BUILD_TYPE=Release"
"-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}"
# These are only useful if you're cross-compiling.
# They, however, will not hurt regardless.
"-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}"
"-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}"
"-DCMAKE_AR=${CMAKE_AR}"
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_RC_COMPILER=${CMAKE_RC_COMPILER}"
"-DCMAKE_COMPILER_PREFIX=${CMAKE_COMPILER_PREFIX}"
"-DCMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}"
"-DGLEW_OSMESA=ON"
INSTALL_COMMAND ""
)
然后,要使用使用這些配置選項構建的glew,我可以執行以下操作:
add_release_osmesa_glew()
add_external_target(
glew
glew/include
glew
SHARED
glew_external
)
add_external_target(
glew_s
glew/include
glew
STATIC
glew_external
)
最后,我可以使用以下選項鏈接它:
target_link_libraries(my_target
glew_s
...
)
正確的方法是直接對目標進行操作。 例如(猜測目標名稱,原諒我):
add_subdirectory ("glfw")
set_target_properties(glfw PROPERTIES
COMPILE_FLAGS "-m32 -O2" # Adjust as needed
)
target_link_libraries(glew INTERFACE
${GLFW_LIBRARIES}
)
add_subdirectory ("glew/build/cmake")
target_include_directories(glew PUBLIC
"glfw/include"
)
target_link_libraries(glew INTERFACE
${GLEW_LIBRARIES}
)
這使您可以按目標而不是全局調整內容(這是現代CMake使用的基礎)。 你可以使用這些函數和他們的朋友調整你喜歡的關於目標的任何東西,包括調整編譯器標志甚至添加新文件。
您正在使用的方法有效,但是您正在影響之后聲明的每個目標,包括稍后添加的子目錄。
您的主項目的CMakeLists.txt
可能如下所示:
add_executable (EbsiStaller
"....cpp"
"....h"
)
target_compile_features(EbsiStaller PUBLIC
cxx_std_17 # might actually be a cmake 3.9 thing, but you get the idea
)
# Links the CMake build output against glfw.
target_link_libraries(EbsiStaller
glfw
glew
)
這里有太多的內容,但這一切都歸結為你的CMake的現代化。 在線文檔太棒了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.