无法链接 CMake 中的本地库

Cannot link local libraries in CMake

本文关键字:链接 CMake      更新时间:2023-10-16

我正在Visual Studio上开发一个C++程序,该程序将部署在Linux上,并通过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制造商,因为同事也无法解决此问题。

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

# link to this directory
target_link_libraries(ANT PRIVATE xscommon)

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

如果 xscommon 是一个预构建库,而你只想导入它,那么添加库并设置 IMPORTED 的目标属性:

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

如果你想在你的根CMakeList中构建xscommon.txt。将 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" 
)

假设你的目录是这样的:

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和其他来源。

创建库后,需要将它们链接到可执行文件。否则,将出现未定义的引用错误,因为编译器可以在头文件中找到声明,但不能找到存在于.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.