使用CMake构建库

7
很抱歉打扰了大家,但我在使用cmake时遇到了一些编译问题。
我有一个CMakeLists.txt文件,用于构建测试可执行文件和共享库。它们都依赖于另一个库(SFML)。
我在Windows上使用MinGW的cmake。
我知道我正在构建的库名与SFML相当混淆,但它应该是一个SFML的包装器,所以我没有找到更好的名称!
以下是CMakeLists.txt内容:
cmake_minimum_required(VERSION 2.6)
project(projectName)

set(EXECUTABLE_NAME testSFML)
set(LIBRARY_NAME    SFMLwindow)

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin/)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include /
${CMAKE_CURRENT_SOURCE_DIR}/../../include
)

link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../lib/)

file(
    GLOB_RECURSE
    SRC_FILES
    src/*
)

file(
    GLOB_RECURSE
    INCLUDE_FILES
    include/*
)

add_executable(
${EXECUTABLE_NAME}
main.cpp
${SRC_FILES}
${INCLUDE_FILES}
)

target_link_libraries(
    ${EXECUTABLE_NAME}
    sfml-main
    sfml-system
    sfml-window
)


add_library(
${LIBRARY_NAME}
SHARED
${SRC_FILES}
)

我在终端中得到的内容:

"C:\MinGW\bin\mingw32-make.exe" 
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/iksemel/docs/WorkBench/programming/projets/TestSFML/cmake
Linking CXX shared library libSFMLwindow.dll
Creating library file: libSFMLwindow.dll.a
CMakeFiles\SFMLwindow.dir/objects.a(SFMLWindow.cpp.obj):SFMLWindow.cpp:(.text+0x59):undefined reference to `_imp___ZN2sf9VideoModeC1Ejjj'
CMakeFiles\SFMLwindow.dir/objects.a(SFMLWindow.cpp.obj):SFMLWindow.cpp:(.text+0xda): undefined reference to `_imp___ZN2sf6WindowC1ENS_9VideoModeERKSsjRKNS_15ContextSettingsE'
CMakeFiles\SFMLwindow.dir/objects.a(SFMLWindow.cpp.obj):SFMLWindow.cpp:(.text+0x163): undefined reference to `_imp___ZN2sf6Window5closeEv'
CMakeFiles\SFMLwindow.dir/objects.a(SFMLWindow.cpp.obj):SFMLWindow.cpp:(.text+0x1bd): undefined reference to `_imp___ZN2sf6Window9pollEventERNS_5EventE'
CMakeFiles\SFMLwindow.dir/objects.a(SFMLWindow.cpp.obj):SFMLWindow.cpp:(.text+0x1d8): undefined reference to `_imp___ZN2sf6Window7displayEv'
collect2: ld a retourné 1 code d'état d'exécution
mingw32-make.exe[2]: *** [libSFMLwindow.dll] Error 1
mingw32-make.exe[1]: *** [CMakeFiles/SFMLwindow.dir/all] Error 2
mingw32-make.exe: *** [all] Error 2

如果有人知道发生了什么事情,我会非常感激!
1个回答

14

根据猜测,你的SFMLwindow库需要链接至sfml-main、sfml-system、sfml-window中的一些或全部。

你可以尝试将CMakeLists.txt的末尾更改为:

add_library(
    ${LIBRARY_NAME}
    SHARED
    ${SRC_FILES}
    ${INCLUDE_FILES}
)

add_executable(
    ${EXECUTABLE_NAME}
    main.cpp
)

target_link_libraries(
    ${LIBRARY_NAME}
    sfml-main
    sfml-system
    sfml-window
)

target_link_libraries(
    ${EXECUTABLE_NAME}
    ${LIBRARY_NAME}
)


顺便提一下,file(GLOB_RECURSE... 通常不被视为收集源文件列表的好方法。来自于file文档的描述:

我们不建议使用GLOB从源树中收集源文件列表。如果没有CMakeLists.txt文件在添加或删除源文件时发生更改,则生成的构建系统无法知道何时要求CMake重新生成。


此外,在这种情况下应该首选find_library而不是link_directories。来自于link_directories文档的描述:

请注意,此命令很少必要。 find_package()和find_library()返回的库位置是绝对路径。将这些绝对库文件路径直接传递给target_link_libraries()命令。 CMake将确保链接器找到它们。


感谢您的帮助,我已经编辑了我的CMakeLists.txt文件,但似乎还没有生效。但奇怪的是,如果我只构建可执行文件,它可以正常工作,只有在构建库时才遇到问题。而且.o文件似乎也按照预期创建了。这是我的CMakeLists.txt文件:http://pastebin.com/hLux8Lvi - Cuthalion
我找到问题了!你关于链接问题的说法是正确的,但为了纠正它,我不得不使用2个target_link_libraries。一个用于可执行文件,另一个用于库。我遇到的另一个问题是命令顺序。似乎target_link_libraries必须出现在add_executable和add_library之后。这是我的当前cmake,再次感谢您提供有关cmake的一般信息并帮助我!http://pastebin.com/ErgbGir0 - Cuthalion
好的,很高兴它能正常工作。我们解决方案的主要区别在于,您将源代码编译成库和可执行文件。对于小型项目来说这是可以的,但如果有很多源文件,这将变得非常麻烦。通常,您只需将源代码编译一次成为库,然后将该库链接到测试可执行文件中。使用CMake,如果您指定库A依赖于库B,而可执行文件Z依赖于库A,则它会自动将库B添加为Z的依赖项。这就是为什么我只指定${EXECUTABLE_NAME}的依赖项为${LIBRARY_NAME}。不过这没什么大不了的 :-) - Fraser
再次感谢您的经验!我现在清楚地理解了您想让我做什么,我必须承认您的解决方案非常高效!我根据您的建议编辑了我的CMakeLists.txt:http://pastebin.com/xL5FATsL - Cuthalion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接