CMake:将可执行文件链接到多个库(*.so)

cod*_*ver 3 c++ cmake

我是使用 CMake 构建的新手。我正在使用 Ubuntu,并且有一个 .cpp 文件(比如位于 ~/mydir 中的 xyz.cpp),它链接到三个自定义共享库(libA.so、libB.so 和 libC.so 库)。这三个 *.so 文件位于/usr/local/lib.

我想创建一个 CMakeLists.txt 来编译它。下面的脚本会抛出如下错误:

cmake_minimum_required(VERSION 3.11)
project(xyz VERSION 1.0.0 LANGUAGES C CXX)

# Set C standard to C11
set(CMAKE_C_STANDARD 11)

set(SOURCES src/xyz.cpp)

include_directories(/usr/local/include)

#For the shared library:

target_link_libraries(libA -L/usr/local/lib/)
target_link_libraries(libB -L/usr/local/lib/)
target_link_libraries(libC -L/usr/local/lib/)

target_link_libraries(xyz libA libB libC )
add_executable(xyz src/xyz.cpp)
Run Code Online (Sandbox Code Playgroud)

错误:

CMake Error at CMakeLists.txt: (target_link_libraries):

   Cannot specify link libraries for target "libA" which is not built
   by this project.


 -- Configuring incomplete, errors occurred!
Run Code Online (Sandbox Code Playgroud)

squ*_*les 5

一些重要的注意事项:

  1. 第一个参数target_link_libraries()应该是一个有效的 CMake目标add_library(),由或创建add_executable()。因此,任何调用target_link_libraries()都应该add_executable()代码中的调用
  2. 您只需调用一次target_link_libraries()即可将所有*.so库链接到可执行文件。前三个调用是不必要的(并且无效,因为libAlibB、 和libC均未定义)。您应该提供完整的每个库的
  3. 最好在target_*调用中包含作用域参数,例如target_link_libraries(). 这指定库是链接到 ( PRIVATE)、添加到链接接口 ( INTERFACE) 还是两者都添加 ( PUBLIC)。随着您的 CMake 项目逐渐包含更多目标,这种区别变得更加重要。

有了这些注释以及下面的其他一些注释,您的 CMake 文件可能如下所示:

cmake_minimum_required(VERSION 3.11)

# No need to specify C and CXX for LANGUAGES here, these are enabled by default!
project(xyz VERSION 1.0.0)

# Set C standard to C11
set(CMAKE_C_STANDARD 11)

set(SOURCES src/xyz.cpp)

include_directories(/usr/local/include)

# Define your executable target. You can pass in the SOURCES variable defined above.
add_executable(xyz ${SOURCES})

# Link the other libraries to your executable, using their full path.
# Note, the '-L' flag is not necessary.
target_link_libraries(xyz PRIVATE 
    /usr/local/lib/libA.so
    /usr/local/lib/libB.so
    /usr/local/lib/libC.so
)
Run Code Online (Sandbox Code Playgroud)