【问题标题】:Cannot link local libraries in CMake无法在 CMake 中链接本地库
【发布时间】:2020-11-02 09:15:22
【问题描述】:

我正在 Visual Studio 上开发一个将部署在 linux 上的 c++ 程序,并通过 ssh 在 linux 上进行调试。目前,这是我的文件夹的结构:

ANT
-xscommon
--xscommon_config.h
-xscontroller
-xstypes
ANT.cpp
ANT.h
CMakeLists.txt
CMakeSettings.json
hashes.h
quaternionic.h
stars.h

目前,我认为我必须链接到的所有.h, .cpp, .o, .cpp.o, .a 文件都保存在三个 xs------- 目录中。我对 cmake 很陌生,链接到这些库给我带来了麻烦;我能够正确链接到包含,但是当我不进行链接时会抛出未定义的引用错误,当我尝试链接时,它会抛出错误。这是我当前的 CMakeLists.txt 文件:

# CMakeList.txt : CMake project for ANT, include source and define
# project specific logic h"ere.
#
cmake_minimum_required (VERSION 3.8)

project ("ANT")

link_directories(${ANT_SOURCE_DIR}/xscommon xscontroller xstypes)

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
    "quaternionic.h" 
    "stars.h"
    "hashes.h"
)

target_include_directories(ANT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(ANT PUBLIC xscommon_config)

当我运行它时,构建器会说以下内容:

/usr/bin/ld: cannot find -lxscommon_config

我需要在 ANT.cpp 所在的目录中查找这些库,因为这是保存它们的位置,但是我所做的任何事情(我已经搞砸了几个小时的配置)都不会告诉 camke 去寻找这些库在 src 文件夹中。它总是转到/usr/bin/ld

我真的只需要知道告诉 CMake 什么,这样它就会在每个文件的正确位置查找,也就是说,如果我告诉它查找正确的文件(我很确定我是)。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

更新

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

所以我将 CMakeLists.txt 文件重新制作为:

# CMakeList.txt : CMake project for ANT, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.15)

project ("ANT")

#[STATIC | SHARED | MODULE]
#[STATIC | SHARED | MODULE]
#[STATIC | SHARED | MODULE]


add_library(xscommon SHARED IMPORTED)
add_library(xscontroller SHARED IMPORTED)
add_library(xstypes SHARED IMPORTED)

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
)

target_include_directories(ANT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

并且仍然得到未定义的引用。我将尝试构建库。此外,我已经联系了使用此 SDK 的 IMU 制造商,因为同事也无法解决此问题。

【问题讨论】:

  • 欢迎来到 Stack Overflow!如果您尝试将预构建的外部库链接到您的 ANT 可执行文件,请参阅 this 问题及其响应以了解完成此操作的正确方法。

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


【解决方案1】:

假设你的目录是这样的:

ANT
-xscommon
--xscommon_config.h
--xscommon_config.cpp
...

首先将CMakeLists.txt文件添加到xscommon/

ANT
-xscommon
--CMakeLists.txt
--xscommon_config.h
--xscommon_config.cpp
...

现在在xscommon/CMakeLists.txt 中,我们将创建一个库,该库将被导入并链接到主 CMakeLists.txt 文件中:

xscommon/CMakeLists.txt

#define another target, let's name it 'xscommon'
add_library(xscommon
   xscommon_config.h
   xscommon_config.cpp
   #more sources if you want
   )

现在在主CMakeLists.txt 文件中:

cmake_minimum_required (VERSION 3.8)

project ("ANT")

#remove this line
#link_directories(${ANT_SOURCE_DIR}/xscommon xscontroller xstypes)

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
    "quaternionic.h" 
    "stars.h"
    "hashes.h"
)

# add the xscommon directory, this will make the library target defined there available here
add_subdirectory(xscommon)

# link to this directory
target_link_libraries(ANT PRIVATE xscommon)
# use PUBLIC if the xscommon library will be part of the public interface of your
# library. But since it is an executable, PRIVATE is better here.

target_include_directories(ANT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

使用上述方法,您可以创建更多的库并链接到它们。

请注意,需要为每个子目录创建单独的 cmake 文件,但它被认为是一种很好的做法,并且可以模块化您的代码。如果您想在主 cmake 文件中执行此操作而不是创建子目录,请将其添加到主 cmake:

add_library(xscommon
   xscommon/xscommon_config.h
   xscommon/xscommon_config.cpp
   #more sources if you want
   )

根据问题的变化更新

您当前的CMakeLists.txt

下面这三行没有做任何事情,绝对不是你想的那样。 add_library() 命令里面有“add”这个词,我知道,但它没有添加任何库,就像add_executable 没有添加任何可执行文件一样。它创建一个库。

add_library(xscommon SHARED IMPORTED)
add_library(xscontroller SHARED IMPORTED)
add_library(xstypes SHARED IMPORTED)

如何在 cmake 中从两个文件 a.cppa.h 创建一个库:

add_library(myALib "a.cpp")

就是这样。如果您有更多来源,您当然会相应地包括它们。在您的情况下,您必须相应地添加 xscommon 和其他来源。

创建库后,您需要将它们链接到您的可执行文件。如果你不这样做,你会得到 undefined reference 错误,因为编译器可以找到头文件中的声明,但不能找到 .cpp 文件中存在的代码定义。

那么,你如何链接?简单:

target_link_libraries(TARGET_NAME PUBLIC | PRIVATE LIBRARY_NAME)
# TARGET_NAME: can be `executable` or `library`
# PUBLIC or PRIVATE (for exe, it is usually private)
# LIBRARY_NAME: Name of library you want to link to TARGET_NAME

# So if you wanted to link "myALib" which I created above to ANT, you would do:
target_link_libraries(ANT PRIVATE myALib)

# Note: You need to add this line **after** add_executable() because target "ANT" will be created after that. You can do the linking after the "target_include_directories" command.

【讨论】:

  • 对于每个带有新 CMakeLists.txt 的文件夹,它会显示:``` 1> [CMake] CMake 错误:无法确定目标“ixscommon”的链接语言。 1> [CMake] CMake 错误:CMake 无法确定目标的链接器语言:xscommon ``` 或某些变体。它似乎将库名称视为链接。如果我从 CMakeLists.txt 中删除链接,它会说同样的话,但对于 xscommon_config.h
  • 您在xscommon 中有.cpp 文件吗?如果没有,那么用它来做图书馆是徒劳的。
  • 您能否更新问题,以添加您所做的更改(单独),以便我可以看到您到底做了什么?如果可能的话,也许显示xscommon中的文件?
  • 会的。我已经使用了下面评论中的建议,尽管它似乎也不想那样工作。
  • 刚看到你更新的cmake,肯定不行。我会更新答案
【解决方案2】:

问题是您正在链接到尚未构建的库。 这个

# link to this directory
target_link_libraries(ANT PRIVATE xscommon)

尝试将名为 xscommon 的库链接到目标 ANT,但您尚未在项目中的任何位置构建 xscommon。

如果 xscommon 是预构建库并且您只想导入它,则添加该库并设置 IMPORTED 目标属性:

add_library(xscommon [STATIC | SHARED | MODULE] IMPORTED)

如果你想在你的根 CMakeLists.txt 中构建 xscommon。将 xscommon 添加为库并包含标题的位置。

add_library(xscommon [STATIC | SHARED | MODULE]
    xxx/xxx.cpp #list all source files that build the library - use relative path
)
target_include_directories(xscommon PRIVATE
   xxx/xxx #path to the location of library header files
)

另外,添加可执行文件时不需要添加头文件。所以这个

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
    "quaternionic.h" 
    "stars.h"
    "hashes.h"
)

可以简化为

add_executable(
    ANT
    "ANT.cpp" 
)

【讨论】:

  • 我尝试了第一个选项,但运气不佳,仍然未定义引用。我正在尝试构建选项。
猜你喜欢
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-31
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多