【问题标题】:Link external library CMakeLists.txt on Windows在 Windows 上链接外部库 CMakeLists.txt
【发布时间】:2018-01-10 12:05:06
【问题描述】:

我正在尝试实现一个 CMakeLists.txt 来在 Linux 和 Windows 下编译我的项目。我使用两个库:SFML 和 boost。但是,我希望我的项目可以在 Linux 或 Windows 下构建,而无需用户安装库。

我解释一下。库 SFML 和 boost 被编译并放置在我的文件夹项目中,我希望无论我在哪台计算机上下载我的项目,我都可以构建它。

这是我的问题,我无法从我的文件夹项目、SFML 和 boost 库中的库文件夹进行外部链接。

这是我的 CMakeLists.txt :

cmake_minimum_required(VERSION 3.0)

project(r-type_client CXX)

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

include_directories(./boost/include
        ./SFML/include
        ./include
        )

if(UNIX)

set(BOOST_LIBRARY
-L./boost/linux
-lboost_regex
)

set(SFML_LIBRARY
-L./SFML/linux
-lsfml-graphics
-lsfml-window
-lsfml-system
)

add_executable(r-type_client
       srcs/Main.cpp
       )

target_link_libraries(r-type_client
          ${BOOST_LIBRARY}
          ${SFML_LIBRARY}
          )

elseif(WIN32)

add_library(bar SHARED IMPORTED)
set_property(TARGET bar PROPERTY IMPORTED_LOCATION        
C:/Users/Hugo/Downloads/Old/client/SFML/windows/sfml-graphics.dll)
set_property(TARGET bar PROPERTY IMPORTED_IMPLIB         
C:/Users/Hugo/Downloads/Old/client/SFML/windows/sfml-graphics.lib)
add_library(bor SHARED IMPORTED)
set_property(TARGET bor PROPERTY IMPORTED_LOCATION 
C:/Users/Hugo/Downloads/Old/client/SFML/windows/sfml-window.dll)
set_property(TARGET bor PROPERTY IMPORTED_IMPLIB 
C:/Users/Hugo/Downloads/Old/client/SFML/windows/sfml-window.lib)
add_library(bur SHARED IMPORTED)
set_property(TARGET bur PROPERTY IMPORTED_LOCATION 
C:/Users/Hugo/Downloads/Old/client/SFML/windows/sfml-system.dll)
set_property(TARGET bur PROPERTY IMPORTED_IMPLIB 
C:/Users/Hugo/Downloads/Old/client/SFML/windows/sfml-system.lib)
add_executable(r-type_client srcs/Main.cpp)
target_link_libraries(r-type_client bar bor bur)

endif(UNIX)

【问题讨论】:

  • SFML_LIBRARY 应该只是要链接的库的名称。
  • BOOST_LIBRARY cmake 已经支持 boost。使用它。
  • 你应该在 target_link_libraries 之前做 IMPORTED 的东西
  • @drescherjm 我的问题是针对 Windows 而不是 Linux
  • 您应该使用find_package() 正确定位所有内容,以正确的方式设置您的CMake 项目。你现在的做法很容易出错(正如你所经历的那样)并且不是真正可移植的。如果您对所有内容都进行硬编码,那么例如设置一个 MSVC 项目会容易得多。您正在使用 CMake,但您基本上是在完全解决它。

标签: c++ boost cmake sfml


【解决方案1】:

正如我在 cmets 中提到的,您应该通过使用 find_package() 正确定位所有内容,以正确的方式设置您的 CMake 项目。

CMake 是一种工具,它允许人们在运行中创建编译所需的文件,无论主机系统如何。通过硬编码路径和(不需要的)每个平台分支,您基本上否定了 CMake 的全部目的。

要在 CMake 中包含第三方库,您通常需要使用 find_package(),其中包括正确定位库和设置变量的必要逻辑(它基本上完成了到目前为止您手动完成的工作) .

让我们为 SFML 做,因为它与 Boost 基本相同(而且我并没有真正准备好 Boost 来测试所有内容,因为变量名称可能因项目而异)。

首先,您将告诉 CMake 您的项目想要使用 SFML:

find_package(SFML)

根据实际的“包”,您可以扩展它。在 SFML 的情况下,我们甚至可以定义我们想要的最低版本以及我们实际想要使用的子库:

find_package(SFML 2.3 COMPONENTS graphics window system REQUIRED)

REQUIRED 标志使整个事情成为强制性的,即如果找不到,CMake 将出错。

一旦这一行成功,它将设置一些具有正确路径和库的变量,然后我们可以在定义目标时使用它们:

include_directories(${SFML_INCLUDE_DIR})
add_executable(myprogram ${MY_SOURCE_FILES})
target_link_libraries(myprogram ${SFML_LIBRARIES} ${SFML_DEPENDENCIES})

你就完成了。如您所见,我可以在不到 10 行的时间内设置一个 CMake 项目,而无需任何特定于平台的路径、代码或知识。

但是,在运行此程序时,您很可能会遇到一个错误:

默认情况下,CMake 可能无法找到 FindSFML.cmake 文件并抱怨。

您可以在cmake 路径下的SFML 目录中找到此文件。将其复制到您的项目中并告诉 CMake 在哪里查找它,例如:

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

完成此操作后,CMake 可能无法找到实际的 SFML 文件,尤其是在 Windows 上。为了告诉它在哪里寻找它,您可以在调用 CMake 时定义 SFML_ROOT

cmake -DSFML_ROOT=C:/Users/Hugo/Downloads/Old/client/SFML path/to/source

这为您提供了一个很大的优势,即您不必对 SFML(或任何其他库,如 Boost)的路径进行硬编码。在您的 linux 机器上,您通常甚至不必提供任何路径,一切都应该开箱即用。

【讨论】:

  • 我刚刚尝试了你所说的,但我得到了其他错误:未定义引用 `__imp__ZN2sf6StringC1EPKcRKSt6locale'
  • 您是否为编译器使用了正确的二进制文件?
  • @drescherjm 是的,我使用的是 32 位版本,但它不起作用。我尝试添加 #define SFML_STATIC 并且错误发生了变化:未定义引用 `sf::String::String(char const*, std::locale const&)'
  • 我用32位VS2017的命令提示符编译,已经出现同样的错误
  • @Meugiwara 你确定你没有忘记 SFML-System 并且你的顺序是正确的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-27
相关资源
最近更新 更多