首页 > 解决方案 > 从项目 CMakeLists.txt 链接相互依赖的库?

问题描述

我对 CMake 有很大的误解,我无法按照 StackOverflow 上的常见建议来解决。我有以下项目:

# SDL2
add_subdirectory(vendor/SDL2-2.0.16)
set(SDL2_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/vendor/SDL2-2.0.16/include")
set(SDL2_LIBRARY "SDL2")
set(SDL2_LIBDIR "${PROJECT_SOURCE_DIR}/vendor/SDL2-2.0.16")

# ogg
add_subdirectory(vendor/libogg-1.3.5)
set(OGG_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/vendor/libogg-1.3.5/include")
set(OGG_LIBRARY "ogg")

# vorbis
add_subdirectory(vendor/libvorbis-1.3.7)
set(OGG_VORBIS_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/vendor/libvorbis-1.3.7/include")
set(OGG_VORBIS_LIBRARY "vorbis")

# SDL2 Mixer
add_subdirectory(vendor/SDL2_mixer-2.0.4)
set(SDL2_MIXER_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/vendor/SDL2_mixer-2.0.4")
set(SDL2_MIXER_LIBRARY "SDL_mixer")

add_executable(myProject ${MY_PROJECT_SOURCES})
target_include_directories(myProject PRIVATE ${MY_PROJECT_INCLUDE_DIRS} PUBLIC ${SDL2_INCLUDE_DIR} ${SDL2_MIXER_INCLUDE_DIR})
target_link_libraries(myProject PUBLIC ${SDL2_LIBRARY} ${SDL2_MIXER_LIBRARY})

这个想法是提供构建 SDL2 和 SDL2_mixer 所需的所有依赖项。到目前为止,这意味着 ogg 和 vorbis。我为 ogg 创建了一个非常简单的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.2)
project(libogg)

configure_file(include/ogg/config_types.h.in include/ogg/config_types.h @ONLY)

set(OGG_HEADERS
    ${CMAKE_CURRENT_BINARY_DIR}/include/ogg/config_types.h
    include/ogg/ogg.h
    include/ogg/os_types.h
)

set(OGG_SOURCES
    src/bitwise.c
    src/framing.c
    src/crctable.h
)

if(WIN32 AND BUILD_SHARED_LIBS)
    list(APPEND OGG_SOURCES win32/ogg.def)
endif()

add_library(ogg ${OGG_HEADERS} ${OGG_SOURCES})
target_include_directories(ogg PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

vorbis 也有类似的情况。SDL_mixer 的那个也很简单:

cmake_minimum_required(VERSION 3.2)
project(SDL_mixer VERSION 2.0.4)
set(ENABLE_DEFS "MUSIC_OGG")

set(SRC_C_FILES bla bla bla)
set(SRC_H_FILES bla bla bla)

add_library(SDL_mixer ${SRC_C_FILES} ${SRC_H_FILES})
target_link_libraries(SDL_mixer PUBLIC ${SDL2_LIBRARY} ${OGG_LIBRARY} ${OGG_VORBIS_LIBRARY})
target_include_directories(SDL_mixer PUBLIC ${SDL2_INCLUDE_DIR} ${OGG_INCLUDE_DIR} ${OGG_VORBIS_INCLUDE_DIR})
target_compile_definitions(SDL_mixer PUBLIC "${ENABLE_DEFS}")

但是,不幸的是,我仍然无法链接。奇怪的是,在我的项目中,我的来源可以看到 ogg。但 SDL_mixer 不能:

/usr/bin/cmake -E cmake_link_script CMakeFiles/myProject.dir/link.txt --verbose=1
/bin/c++ -rdynamic MY_SOURCES -o ../bin/myProject  -Wl,-rpath:/var/dev/qube/build/vendor/SDL2-2.0.16 vendor/SDL2_mixer-2.0.4/libSDL_mixer.a -lrt vendor/SDL2-2.0.16/libSDL2-2.0.so.0.16.0 vendor/libvorbis-1.3.7/libvorbis.a vendor/libogg-1.3.5/libogg.a -lm
/bin/ld: vendor/SDL2_mixer-2.0.4/libSDL_mixer.a(music_ogg.c.o): in function `OGG_Load':
music_ogg.c:(.text+0x11): undefined reference to `ov_clear'

标签: c++cmakeg++

解决方案


但是,不幸的是,我仍然无法链接。奇怪的是,在我的项目中,我的来源可以看到 ogg。但 SDL_mixer 不能:

我可以看到为什么 ogg 可以看到您的源而 SDL_mixer 不能看到的唯一原因是由于您的链接命令中库的顺序。

 vendor/libvorbis-1.3.7/libvorbis.a vendor/libogg-1.3.5/libogg.a 

在链接 ogg 对象时,vorbis 符号已经包含在符号表中。

尝试这个:

target_link_libraries(SDL_mixer PUBLIC  ${OGG_VORBIS_LIBRARY} ${OGG_LIBRARY} ${SDL2_LIBRARY})

推荐阅读