![](/img/trans.png)
[英]Compile c++ project without makefile neither CMakeLists.txt
[英]How to link and compile a C++ project for Linux using CMake? (Adapting CMakeLists.txt)
上下文:我想為 Linux、Windows 和 MacOS 制作跨平台的 GameClient、GameServer 和自定義庫(客戶端和服務器都使用)。 服務器和客戶端都依賴於我更喜歡靜態鏈接的各種庫和標頭。 我聽說我可以通過將我當前由 VisualStudio 開發的 3 個項目包裝到 CMake 環境中來做到這一點,所以我首先為 Server 和 Shared lib 創建了 CMakeLists.txt,它們是最簡單的,並且具有較少的庫依賴項。
問題:我如何調整這些 CMakeLists.txt(目前在 Windows 上構建),以便我可以選擇是為 Windows 還是 Linux(最好是從 Windows)編譯?
共享庫 CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(MORPH_Server VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(SFML_STATIC_LIBRARIES TRUE) #Link to statically
set(SFML_DIR "C:/libraries/SFML/SFMLx64SourceAndCompile")
find_package(SFML 2.5.1 COMPONENTS system network REQUIRED)
add_library(MORPH_Shared_Functions)
target_sources(MORPH_Shared_Functions
PRIVATE Transform.cpp
PRIVATE World.cpp
PRIVATE Player.cpp
PRIVATE PropsData.cpp
PRIVATE Prop.cpp
PRIVATE udp_network_manager.cpp
PRIVATE utility_functions.cpp
)
target_link_libraries(MORPH_Shared_Functions
sfml-system #Basically already found sfml modules and their dependencies (find-package)
sfml-network
)
target_include_directories(MORPH_Shared_Functions
PRIVATE C:/libraries/SFML/SFML-2.5.1/include
PRIVATE C:/libraries/GLM/glm
PRIVATE C:/libraries/CEREAL
)
服務器 CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(MORPH_Server VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
configure_file(CmakeConfig.h.in CmakeConfig.h)
set(SFML_STATIC_LIBRARIES TRUE) #Link to statically
set(SFML_DIR "C:/libraries/SFML/SFMLx64SourceAndCompile")
find_package(SFML 2.5.1 COMPONENTS system network REQUIRED)
add_executable(MORPH_Server)
target_sources(MORPH_Server
PRIVATE Main.cpp
PRIVATE Game.cpp
PRIVATE CommandManager.cpp
PRIVATE ServerPlayer.cpp
PRIVATE ServerProp.cpp
PRIVATE ServerWorldState.cpp
PRIVATE UDP_Server_CS.cpp
)
add_library(MORPH_Shared_Functions STATIC IMPORTED)
set_target_properties(MORPH_Shared_Functions PROPERTIES IMPORTED_LOCATION C:/Users/dylan/Desktop/MORPH/MORPH_Shared_Functions/Build/Debug/MORPH_Shared_Functions.lib)
target_link_libraries(MORPH_Server
MORPH_Shared_Functions
sfml-system
sfml-network
)
target_include_directories(MORPH_Server
PRIVATE C:/Users/dylan/Desktop/MORPH/MORPH_Shared_Functions
PRIVATE C:/libraries/SFML/SFML-2.5.1/include
PRIVATE C:/libraries/GLM/glm
PRIVATE C:/libraries/CEREAL
)
您很幸運,因為您使用的三個庫都正確導出了它們的包。
在 linux 上,我假設庫安裝在~/workspace/libraries
。
訣竅是對所有依賴項使用find_package
,並且您必須刪除每個自定義Findxyz.cmake
文件。
然后,您必須刪除目錄名稱的 ALL_CAPS。 這對於 CMake 正確找到包很重要。 在 Windows 上這可能無關緊要,因為文件系統不區分大小寫,但在 linux 上是。
因此,首先,為了讓您的 CMakeLists 完全不知道在哪里可以找到包,我們將創建一個名為linux-dependencies.cmake
的新文件,其中包含以下內容:
list(APPEND CMAKE_PREFIX_PATH "$ENV{HOME}/workspace/libraries")
list(APPEND CMAKE_PREFIX_PATH "path/to/morph/build") # can be relative
和windows-dependencies.cmake
:
list(APPEND CMAKE_PREFIX_PATH "C:/libraries/")
list(APPEND CMAKE_PREFIX_PATH "$ENV{HOMEPATH}/Desktop/MORPH/build")
當然,如果你設置了庫安裝目錄相對於項目或者兩個平台都相對於home目錄,則可以只有一個dependencies.cmake
文件。
然后,在您下一次 cmake 調用時,只需告訴 cmake 包含該文件:
cmake .. -DCMAKE_PROJECT_INCLUDE=linux-dependencies.cmake
請注意, CMAKE_PROJECT_INCLUDE
僅自 CMake 3.15 起可用。 如果您不想升級 CMake 或只是提供默認值,您始終可以手動包含該文件。
您的 CMakeLists 文件應如下所示:
cmake_minimum_required(VERSION 3.15)
project(MORPH_Server VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
configure_file(CmakeConfig.h.in CmakeConfig.h)
find_package(SFML 2.5.1 COMPONENTS system network REQUIRED)
find_package(glm 0.9.9 REQUIRED)
find_package(cereal REQUIRED) # cereal don't export version info as far as I know
# You will have to export your target or write a MORPH-config.cmake file
find_package(MORPH REQUIRED)
add_executable(MORPH_Server)
target_sources(MORPH_Server
PRIVATE Main.cpp
PRIVATE Game.cpp
PRIVATE CommandManager.cpp
PRIVATE ServerPlayer.cpp
PRIVATE ServerProp.cpp
PRIVATE ServerWorldState.cpp
PRIVATE UDP_Server_CS.cpp
)
# this take care of both linking and include dirs
target_link_libraries(MORPH_Server
MORPH_Shared_Functions
sfml-system
sfml-network
glm
cereal
)
另一件事可以提供幫助:在安裝庫時設置與CMAKE_INSTALL_PREFIX
或CMAKE_INSTALL_PREFIX/libname
相同的CMAKE_PREFIX_PATH
。
如果你想在 Windows 上編譯 linux 可執行文件,我建議簡單地使用 WSL 或在 Docker 中運行編譯器。 VSCode 實際上有一個很好的擴展,可以使用 docker 作為構建環境,而且據我所知,還可以使用 WSL 作為構建和運行環境。
我的 2 美分,
根據find_package()
搜索過程文檔:
在所有情況下,
<name>
都被視為不區分大小寫,並對應於指定的任何名稱(<PackageName>
或NAMES
給出的NAMES
)。
參考: https : //cmake.org/cmake/help/latest/command/find_package.html#search-procedure
注意:我個人更喜歡使用PackageNameConfig.cmake
不是package-name-config.cmake
...
為什么CMAKE_PREFIX_PATH
地在配置命令行上添加CMAKE_PREFIX_PATH
而不是通過您的dependencies.cmake
文件?
對於靜態鏈接,我將使用FetchContent()
方法來控制“靜態性”,因為大多數 Linux 發行版傾向於將庫構建為共享庫,然后將它們放在FHS之后的目錄中。
您還可以使用標志來允許用戶根據需要使用系統范圍的庫(因此發行版維護人員很高興,並且您可以輕松創建獨立的工件)。
警告:大多數庫不打算在超級構建中使用,因此您可能需要修補它們(即PATCH_COMMAND git apply ...
)
# enable CMP0077 so superbuild can set it.
option(BUILD_THIRDPARTY "Build the third party" ON)
...
# to allow recursive superbuild (add_subdirectory(morph_server) etc...)
# first check if third party target is not already present
# see: https://gitlab.kitware.com/cmake/cmake/-/issues/17735
if(NOT TARGET ThirdParty::ThirdParty)
if(BUILD_THIRDPARTY)
FetchContent_Declare(...)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_EXAMPLES OFF) ...
FetchContent_MakeAvailable(third_party)
set(BUILD_SHARED_LIBS ${BUILD_SHARED_BCKP})
else()
find_package(ThirdParty REQUIRED)
endif()
endif()
您還可以提供默認的FindThirdParty.cmake
。
if(UNIX)
list(APPEND CMAKE_PREFIX_PATH "$ENV{HOME}/workspace/libraries")
list(APPEND CMAKE_PREFIX_PATH "path/to/morph/build") # can be relative
else()
list(APPEND CMAKE_PREFIX_PATH "C:/libraries/")
list(APPEND CMAKE_PREFIX_PATH "$ENV{HOMEPATH}/Desktop/MORPH/build")
endif()
find_package(ThirdParty CONFIG REQUIRED)
因此,您不必使用CMAKE_PREFIX_PATH
或dependencies.cmake
等,並且用戶仍然可以提供他們自己的FindThirdParty.cmake
並在CMAKE_PREFIX_PATH
如果他們想更改...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.