Ubuntu下使用CMake编译共享库时出现链接器错误
Ubuntu下CMake构建共享库出现链接器错误
我在Ubuntu系统上使用CMake和GCC(G++)构建共享库时,每次都会出现链接器错误。编译静态库可正常构建,Windows系统下静态库和共享库均能正常编译。
链接器错误信息
usr/bin/ld: Dependencies/GLAD/libGLAD.a(gl.c.o): warning: relocation against glad_glNamedFramebufferReadBuffer' in read-only section .text' /usr/bin/ld: CMakeFiles/Soul-Byte-Engine-Core-Window-Manager-obj.dir/Sources/WindowManager.cpp.o: relocation R_X86_64_PC32 against symbol `_ZSt4cout@@GLIBCXX_3.4' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: bad value collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/Soul-Byte-Engine-Core-Window-Manager.dir/build.make:89: libSoul-Byte-Engine-Core-Window-Manager.so] Error 1 make[1]: *** [CMakeFiles/Makefile2:164: CMakeFiles/Soul-Byte-Engine-Core-Window-Manager.dir/all] Error 2 make: *** [Makefile:91: all] Error 2
我的CMakeLists.txt内容
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) project(Soul-Byte-Engine-Core-Window-Manager VERSION 1.0.0 LANGUAGES CXX) option(BUILD_WINDOW_MANAGER_AS_STATIC "" OFF) option(BUILD_WINDOW_MANAGER_WITH_GLFW_SOURCES "" OFF) option(INCLUDE_LOGGING_SYSTEM_SUPPORT "" OFF) string(TIMESTAMP BuildDate "%Y-%m-%d") set(BUILT_BY "Unknown" CACHE STRING "The name of build author") get_directory_property(hasParent PARENT_DIRECTORY) if(hasParent) set(WINDOW_MANAGER_MAJOR_VERSION PARENT_SCOPE) set(WINDOW_MANAGER_MINOR_VERSION PARENT_SCOPE) set(WINDOW_MANAGER_PATCH_VERSION PARENT_SCOPE) else() set(WINDOW_MANAGER_MAJOR_VERSION 1) set(WINDOW_MANAGER_MINOR_VERSION 0) set(WINDOW_MANAGER_PATCH_VERSION 0) endif() include_directories(Include) add_library(${PROJECT_NAME}-obj OBJECT Sources/WindowManager.cpp Sources/META.cpp Include/WindowManager/WindowManager.hpp Include/WindowManager/META.hpp ) add_subdirectory(Dependencies/GLAD) target_include_directories(${PROJECT_NAME}-obj PUBLIC Dependencies/GLAD/include) if(BUILD_WINDOW_MANAGER_AS_STATIC) add_library(${PROJECT_NAME} STATIC $<TARGET_OBJECTS:${PROJECT_NAME}-obj> ) else() if(WIN32) set ( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) endif() add_library(${PROJECT_NAME} SHARED $<TARGET_OBJECTS:${PROJECT_NAME}-obj> ) endif() if(WIN32) if(NOT BUILD_WINDOW_MANAGER_WITH_GLFW_SOURCES) message(WARNING "When using Windows OS Window Manager will be built with GLFW sources regardless of options !") set(BUILD_WINDOW_MANAGER_WITH_GLFW_SOURCES ON) endif() endif() if(BUILD_WINDOW_MANAGER_WITH_GLFW_SOURCES) set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) add_subdirectory(Dependencies/GLFW) target_include_directories(${PROJECT_NAME}-obj PUBLIC Dependencies/GLFW/include) else() find_package(glfw3 REQUIRED) target_include_directories(${PROJECT_NAME}-obj PUBLIC ${GLFW_INCLUDE_DIRS}) endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}/META) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(BUILT_FOR "${CMAKE_SYSTEM_NAME} x86_64") elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) set(BUILT_FOR "${CMAKE_SYSTEM_NAME} x86") endif() configure_file( "META/BuildInfo.h.in" "${CMAKE_CURRENT_BINARY_DIR}/META/BuildInfo.h" ) target_link_libraries(${PROJECT_NAME} GLAD glfw)
解决方案
1. 为OBJECT目标添加-fPIC编译选项
Ubuntu下构建共享库要求所有参与链接的目标文件都使用位置无关代码(PIC),但CMake默认不会为OBJECT目标启用该选项。在定义${PROJECT_NAME}-obj库后添加以下代码:
target_compile_options(${PROJECT_NAME}-obj PRIVATE -fPIC)
2. 确保依赖库GLAD也编译为PIC
GLAD静态库同样需要PIC才能被共享库链接。在add_subdirectory(Dependencies/GLAD)之前,全局启用位置无关代码编译:
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
该设置会让后续所有构建的目标(包括GLAD)自动使用-fPIC编译。
3. 优化后的关键CMake代码片段
修改后的OBJECT库定义和GLAD构建部分:
add_library(${PROJECT_NAME}-obj OBJECT Sources/WindowManager.cpp Sources/META.cpp Include/WindowManager/WindowManager.hpp Include/WindowManager/META.hpp ) # 添加PIC编译选项 target_compile_options(${PROJECT_NAME}-obj PRIVATE -fPIC) # 全局启用PIC,确保依赖库也符合要求 set(CMAKE_POSITION_INDEPENDENT_CODE ON) add_subdirectory(Dependencies/GLAD) target_include_directories(${PROJECT_NAME}-obj PUBLIC Dependencies/GLAD/include)
完成以上修改后,重新运行CMake和make即可正常构建共享库。
内容的提问来源于stack exchange,提问作者Allen
相关产品推荐
相关产品推荐

