【问题标题】:CMake command target_link_libraries in Visual StudioVisual Studio 中的 CMake 命令 target_link_libraries
【发布时间】:2019-07-26 07:16:38
【问题描述】:

我正在尝试使用 CMake 和 Visual C++ 2017 工具链构建一个跨平台项目。

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)

project(CMakeLibTest)

add_executable(mainApp App.cpp)

target_include_directories(mainApp PRIVATE ${PROJECT_SOURCE_DIR}/../Lib)
target_link_libraries(mainApp -L${PROJECT_SOURCE_DIR}/../Win32/Debug -lLib)

Lib.lib 是一些静态库。它位于文件夹../Win32/Debug 相对于CMakeLists.txt 和App.cpp 的位置。

当我开始项目构建时,我在链接器命令行中看到奇怪的选项:

-LC:/Users/UserName/source/repos/CMakeLibTest/App/../Win32/Debug -lLib.lib

链接器无法识别这些选项并显示警告:

warning LNK4044: unrecognized option '/LC:/Users/UserName/source/repos/CMakeLibTest/App/../Win32/Debug'; ignored
warning LNK4044: unrecognized option '/lLib.lib'; ignored

最后还是失败了:

error LNK2019: unresolved external symbol "void __cdecl f(void)" (?f@@YAXXZ) referenced in function main

预期正确的链接器命令行选项:

/LIBPATH:"C:\Users\UserName\source\repos\CMakeLibTest\Win32\Debug\" "Lib.lib"

我做错了什么?在与 Visual Studio 兼容的 CMake 中链接库的正确方法是什么?或者可能是 CMake 中的错误?

【问题讨论】:

  • 无需在target_link_libraries 中指定-l 标志,尤其是对于选项-l(和/l)毫无意义的Visual Studio。只需使用target_link_libraries(mainApp lib)。与链接目录类似:选项-L/L 对Visual Studio 没有意义。请改用link_directories(${PROJECT_SOURCE_DIR}/../Win32/Debug)。有关在 CMake 中链接到外部库的可能方式,请参阅 that question
  • link_directories 不推荐使用:“注意这个命令很少需要,在有其他选择的地方应该避免使用。” cmake.org/cmake/help/v3.13/command/link_directories.html

标签: visual-studio visual-c++ cmake visual-studio-2017 linker


【解决方案1】:

@Tsyvarev 是正确的;在 CMake 中使用 target_link_libraries 时,无需担心 -l-L 标志。此处的另一个链接问题建议将另一个 DLL 依赖项设为导入库。这是您的示例的样子:

# Add the static library 'Lib.lib', marking it as an IMPORT.
add_library(MyLib STATIC IMPORTED)
# Define the location of the library dependency.
set(MYLIB_FILE_PATH "C:/Users/UserName/source/repos/CMakeLibTest/Win32/Debug/Lib.lib")
# Tell CMake where to find the library.
set_target_properties(MyLib PROPERTIES IMPORTED_LOCATION ${MYLIB_FILE_PATH})

请注意,如果 Win32 是您的 CMake 构建目录,您可以使用 CMAKE_BINARY_DIRCMAKE_CURRENT_BINARY_DIR 获取 Lib.lib 的位置。

# Add the static library 'Lib.lib', marking it as an IMPORT.
add_library(MyLib STATIC IMPORTED)
# Tell CMake where to find the library.
set_target_properties(MyLib PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/Debug/Lib.lib)

我鼓励您查看IMPORTED_LOCATION 的调试/发布选项,因为您使用的是 Visual Studio。

现在,您可以使用target_link_libraries 链接导入的库:

target_link_libraries(mainApp MyLib)

重要提示:如果您使用 CMake 在与 mainApp 相同的源代码树中配置和构建 Lib.lib,则可以跳过 IMPORTED 步骤,只需调用 target_link_libraries如上图。

【讨论】:

  • 3 个命令添加 1 个 .lib 文件?如果这个库包含几个 .lib 文件,我需要为每个文件重复这 3 个命令吗?在使用 link_directories 和 target_link_libraries 的情况下,对于所有文件来说 2 个命令就足够了:第一个添加库的路径,第二个添加所有文件。
  • 是的,您需要单独导入每个库,但您可以列出库并使用 CMake 的 foreach 迭代每个库。此外,您可以使用 target_link_libraries(mainApp MyLib1 MyLib2 ... ) 将所有这些链接到您的应用程序。
  • @AndreyEpifantsev 您可以将其缩短为两个命令,如我在答案中所示。关于link_directorieslink_directories 的 CMake 文档警告不要使用它,因为它使用了相对路径,他们建议使用add_library 方法(如我所述),或者改用find_library。如果您想尝试find_library 方法,请查看此response
  • 与大多数问题一样,有多种解决方案。有些只是比其他的更安全。在这种情况下,使用add_library 比使用link_directories 更安全。
猜你喜欢
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-12
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多