【问题标题】:CMake Imported Library Target giving undefined giving undefined symbols on WindowsCMake 导入的库目标在 Windows 上给出未定义的未定义符号
【发布时间】:2017-06-12 19:59:31
【问题描述】:

我正在尝试将 libuv 导入到我的 CMake 项目中,以便可以链接它。我从here 安装了libuv 1.12.0,并将其放在C:\Program Files\libuv\ 中。

project(tls-server LANGUAGES C)
set(LIBUV_ROOT_DIR "C:\\Program Files\\libuv")
add_library(libuv SHARED IMPORTED)
set_property(TARGET libuv PROPERTY IMPORTED_LOCATION "${LIBUV_ROOT_DIR}\\libuv.dll")
set_property(TARGET libuv PROPERTY IMPORTED_IMPLIB "${LIBUV_ROOT_DIR}\\libuv.lib")
add_executable(tls-server "${CMAKE_SOURCE_DIR}/src/main.c")
target_link_libraries(tls-server libuv)

但是,鉴于上述代码,我仍然在 Visual Studio 中遇到未定义符号错误:

我该如何解决这个问题?我相信这些路径都是正确的。我也在使用 Windows 10。

【问题讨论】:

  • 不能在 MinGW 上使用 .lib 文件。 .lib 用于 Visual Studio 编译器和链接器,但 MinGW 及其 gcc 需要 .a(或 .dll.a)。使用纯 C 语言可以从 .def 文件创建 .a
  • @Tsyvarev 我明白了。但是,我在使用 Visual Studio 生成器时遇到了同样的错误。

标签: windows cmake libuv


【解决方案1】:

永远不要在 CMake 中硬编码这样的库路径或名称。

改为使用find_library 命令,如果提供的库出现问题,该命令可以尽早通知您。

特别是在 Windows 上,由于系统上没有库所在的默认位置(类似于 *nix 系统上的 /usr/local/lib),您可能需要为库的位置提供额外的自定义点。我个人喜欢为此使用环境变量,但普通的 CMake 选项也可以:

project(tls-server LANGUAGES C)

find_library(LIBUV_LIBRARIES NAMES uv libuv 
     HINTS $ENV{LIBUV_ROOT})

add_executable(tls-server ${PROJECT_SOURCE_DIR}/src/main.c)
target_link_libraries(tls-server ${LIBUV_LIBRARIES})

请注意,CMake 通常从不负责将运行时依赖项复制到正确的位置!也就是说,如果libuv 被构建为.dll,则在运行程序时必须确保.dll 在正确的路径中。

您当然可以在 CMake 中手动插入复制命令以将所有 dll 就位,但这可能非常麻烦。不幸的是,目前没有更合适的解决方案来解决这个问题。

在此处使用导入的目标是可能的,但实际上只有在您需要将更复杂的属性传递给依赖目标时才会得到回报。根据我的经验,如果依赖项提供了fully-fledged package config file,则导入的目标效果最好。就额外的复杂性而言,手动编写导入的目标通常不值得。

【讨论】:

  • 这篇文章如何帮助解决问题(“未定义的引用”)? 改进问题中的代码是好意,但这不是回答帖子的主要目的。我最近在 meta 上看到过相关问题。
  • @Tsyvarev 未定义的引用未被检测到,因为 CMake 不检查硬编码路径。通过改进代码,潜在的问题作为副作用得到了解决,恕我直言,这比痛苦地调试问题要好得多,同时让损坏的 CMake 保持原样。 StackOverflow 不是免费的调试服务。
  • 有效地您的代码与问题帖子中的代码相同(至少对于 Visual Studio)。指定 HINTSPATHS 只是硬编码路径的跨平台方式:这只允许自动选择库的前缀/后缀。 (假设您没有系统安装库)。 StackOverflow is not a free debugging service. - 这是针对“一堆没有任何注释的代码”的情况。实际上,我猜关于 SO 的更多 90% 问题是关于检测现有代码中的问题。
  • @Tsyvarev 好吧,它确实消除了我们不小心混合 MinGW 和 VS 工具链的情况,以及库文件不存在于硬编码位置的情况。在那之后,就没有太多可能出错的地方了,当然也没有什么可以在不依靠一些猜测的情况下解决的。
  • ... nothing that can be solved without resorting to some amount of guesswork. - 您可以在问题帖子的 cmets 中请求更多信息。当然,有些问题无法要求提供更多信息,因此我们将其关闭。但是在给定的问题中,作者能够(他在某种程度上熟悉他使用的工具)并且想要(已经有一些额外的信息)提供当前缺失的信息。顺便说一句,某些问题的许多有效答案实际上是“猜测”的结果。
【解决方案2】:

我终于设法解决了这个问题。

首先,我从目标库 (libuv) 重新安装了二进制文件。然后,我确保我的cmake 正在使用cmake -G "Visual Studio 14 2015 Win64" 生成x64 项目文件。这足以摆脱未定义的符号错误。然后我需要做的就是将libuv.dll文件复制到与可执行文件相同的目录下,一切正常。

如果有人知道为什么会发生此错误,请发表评论,以便将来帮助其他人更好地定位错误原因。

【讨论】:

    猜你喜欢
    • 2014-09-20
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多