如何用CMake将可执行文件链接到ExternalProject构建的共享库?
问题:CMake链接ExternalProject构建的LuaJIT共享库失败
我尝试构建依赖LuaJIT(通过Makefile构建的第三方共享库)的可执行文件,使用CMake的ExternalProject集成,但链接时出现未定义引用错误。
我的CMakeLists.txt:
cmake_minimum_required(VERSION 3.28) project(untitled2 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) include(ExternalProject) set(LUAJIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/LuaJIT) set(LUAJIT_INSTALL_DIR ${CMAKE_BINARY_DIR}/luajit) # this is to avoid having a leading space in the quotes if(CMAKE_C_FLAGS) set(LUAJIT_CFLAGS "${CMAKE_C_FLAGS} -DLUAJIT_ENABLE_LUA52COMPAT") else () set(LUAJIT_CFLAGS "-DLUAJIT_ENABLE_LUA52COMPAT") endif() ExternalProject_Add( luajit_proj PREFIX ${LUAJIT_INSTALL_DIR} SOURCE_DIR ${LUAJIT_SOURCE_DIR} CONFIGURE_COMMAND "" # LuaJIT does not have a CMake configure step BUILD_COMMAND make -C ${LUAJIT_SOURCE_DIR} install CC=${CMAKE_C_COMPILER} PREFIX=${LUAJIT_INSTALL_DIR} CFLAGS=${LUAJIT_CFLAGS} SHARED=1 INSTALL_COMMAND "" # the `make install` step already did it UPDATE_DISCONNECTED 1 ) set(LUAJIT_LIB_PATH ${LUAJIT_INSTALL_DIR}/lib) set(LUAJIT_INCLUDE_PATH ${LUAJIT_INSTALL_DIR}/include) # main executable add_executable(untitled2 main.cpp) add_dependencies(untitled2 luajit_proj) target_include_directories(untitled2 PRIVATE ${LUAJIT_INCLUDE_PATH}) target_link_libraries(untitled2 PRIVATE ${LUAJIT_LIB_PATH}/libluajit-5.1.so)
main.cpp代码:
#include <iostream> #include <luajit-2.1/lua.h> #include <luajit-2.1/lualib.h> #include <luajit-2.1/lauxlib.h> int main() { lua_State* L = luaL_newstate(); luaL_openlibs(L); return 0; }
错误信息:
main.cpp:(.text+0xd): undefined reference to `luaL_newstate()' /usr/bin/ld: main.cpp:(.text+0x1d): undefined reference to `luaL_openlibs(lua_State*)' collect2: error: ld returned 1 exit status
LuaJIT已正常构建,头文件在builddir/luajit/include/luajit-2.1,共享库在builddir/luajit/lib(含libluajit-5.1.so符号链接),但链接失败,请问如何解决?
解决方案
1. 修复C++调用C库的符号修饰问题
LuaJIT是C语言库,C++会对函数名进行名字修饰,导致链接器无法匹配C语言符号。修改main.cpp,用extern "C"包裹LuaJIT头文件:
#include <iostream> extern "C" { #include <luajit-2.1/lua.h> #include <luajit-2.1/lualib.h> #include <luajit-2.1/lauxlib.h> } int main() { lua_State* L = luaL_newstate(); luaL_openlibs(L); return 0; }
2. 优化CMake链接方式
直接指定.so文件路径不够稳妥,建议先设置链接目录,再通过库名链接:
# 替换原target_link_libraries行 target_link_directories(untitled2 PRIVATE ${LUAJIT_LIB_PATH}) target_link_libraries(untitled2 PRIVATE luajit-5.1)
或用find_library定位库,更符合CMake规范:
find_library(LUAJIT_LIB NAMES luajit-5.1 PATHS ${LUAJIT_LIB_PATH} NO_DEFAULT_PATH) target_link_libraries(untitled2 PRIVATE ${LUAJIT_LIB})
3. 核对库的实际安装路径
LuaJIT的make install可能将库安装到架构相关子目录(如lib/x86_64-linux-gnu),检查${LUAJIT_INSTALL_DIR}/lib下的实际结构,调整LUAJIT_LIB_PATH:
# 示例:如果库在lib/x86_64-linux-gnu下 set(LUAJIT_LIB_PATH ${LUAJIT_INSTALL_DIR}/lib/x86_64-linux-gnu)
4. 配置运行时库路径(可选)
运行可执行文件时可能找不到共享库,通过设置INSTALL_RPATH让运行时定位到库:
set_target_properties(untitled2 PROPERTIES INSTALL_RPATH ${LUAJIT_LIB_PATH} BUILD_WITH_INSTALL_RPATH ON )
内容的提问来源于stack exchange,提问作者Andrew Sokolov
相关产品推荐
相关产品推荐

