当所有需要的库和引用都被考虑在内时,为什么我会收到 `undefined reference to xxx` 错误?
Why am I getting `undefined reference to xxx` errors when all libraries and references needed are accounted for?
本质上,我正在尝试使用 redland rdf 库,但我无法对它们进行 link。当我尝试使用 redland 库的简单基本程序时,出现以下错误:
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_free_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:671: undefined reference to `raptor_free_memory'
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_alloc_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:689: undefined reference to `raptor_alloc_memory'
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_calloc_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:707: undefined reference to `raptor_calloc_memory'
乍一看,您可能只是认为我丢失了一个 link 库,在我进一步检查之前我是这么想的(见下文),但是,这些库都已计算在内。
在这种情况下,一个适当的最小工作示例很困难,因为它需要获取和构建我正在尝试使用的库。但是,我创建了一个 GitHub repository
$ git clone git@github.com:CiaranWelsh/RedlandBuildTest.git
其中包含构建 Redland 库所需的源文件以及我正在使用的示例代码(中断)。
为了构建库,您还需要
$ sudo apt install automake autoconf libtool gtk-doc-tools
$ sudo apt install libxml2 libxml2-dev libxslt libxslt-dev libcurl4-openssl-dev libltdl-dev
请注意,我正在为 Linux 开发 windows 子系统上的 Ubuntu-18.04。
要获取、构建和安装我正在使用这些终端命令的库:
#raptor2
wget "http://download.librdf.org/source/raptor2-2.0.15.tar.gz"
tar -xvf raptor2-2.0.15.tar.gz
cd raptor2-2.0.15
./autogen.sh
make
sudo make install
# redland (librdf)
wget "http://download.librdf.org/source/redland-1.0.17.tar.gz"
tar -xvf redland-1.0.17.tar.gz
cd redland-1.0.17
./autogen.sh
make
sudo make install
# rasqal
wget "http://download.librdf.org/source/rasqal-0.9.33.tar.gz"
tar -xvf rasqal-0.9.33.tar.gz
cd rasqal-0.9.33
./autogen.sh
make
sudo make install
在 github 存储库中作为 shell 脚本可用(get-raptor.sh
、get-rasqal.sh
和 get-librdf.sh
)。
还有我的最小 CMake 脚本(也在存储库中):
cmake_minimum_required(VERSION 3.15)
project(RedlandBuildTest)
set(CMAKE_CXX_STANDARD 14)
find_library(RAPTOR2_STATIC_LIBRARY
NAMES libraptor2.a
PATHS /usr/local/lib
)
find_path(RAPTOR2_INCLUDE_DIR
NAMES raptor2.h
PATHS /usr/local/include/raptor2
)
find_library(RASQAL_STATIC_LIBRARY
NAMES librasqal.a
PATHS /usr/local/lib
)
find_path(RASQAL_INCLUDE_DIR
NAMES rasqal.h
PATHS /usr/local/include/rasqal
)
find_library(LIBRDF_STATIC_LIBRARY
NAMES librdf.a
PATHS /usr/local/lib
)
find_path(LIBRDF_INCLUDE_DIR
NAMES librdf.h
PATHS /usr/local/include
)
add_executable(RedlandBuildTest main.c)
target_include_directories(RedlandBuildTest PRIVATE
${RAPTOR2_INCLUDE_DIR}
${RASQAL_INCLUDE_DIR}
${LIBRDF_INCLUDE_DIR}
)
target_link_libraries(RedlandBuildTest PRIVATE
${RAPTOR2_STATIC_LIBRARY}
${RASQAL_STATIC_LIBRARY}
${LIBRDF_STATIC_LIBRARY}
curl
xml2
xslt
ltdl
)
get_target_property(LINK_LIBRARIES RedlandBuildTest LINK_LIBRARIES)
get_target_property(INCLUDE_DIRECTORIES RedlandBuildTest INCLUDE_DIRECTORIES)
message(STATUS "
LINK_LIBRARIES ${LINK_LIBRARIES}
INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES}
")
message(STATUS "
RAPTOR2_STATIC_LIBRARY ${RAPTOR2_STATIC_LIBRARY}
RAPTOR2_INCLUDE_DIR ${RAPTOR2_INCLUDE_DIR}
RASQAL_STATIC_LIBRARY ${RASQAL_STATIC_LIBRARY}
RASQAL_INCLUDE_DIR ${RASQAL_INCLUDE_DIR}
LIBRDF_STATIC_LIBRARY ${LIBRDF_STATIC_LIBRARY}
LIBRDF_INCLUDE_DIR ${LIBRDF_INCLUDE_DIR}
")
CMake 命令的输出:
#(looks good)
LINK_LIBRARIES /usr/local/lib/libraptor2.a;/usr/local/lib/librasqal.a;/usr/local/lib/librdf.a;curl;xml2;xslt;ltdl
INCLUDE_DIRECTORIES /usr/local/include/raptor2;/usr/local/include/rasqal;/usr/local/include
RAPTOR2_STATIC_LIBRARY /usr/local/lib/libraptor2.a
RAPTOR2_INCLUDE_DIR /usr/local/include/raptor2
RASQAL_STATIC_LIBRARY /usr/local/lib/librasqal.a
RASQAL_INCLUDE_DIR /usr/local/include/rasqal
LIBRDF_STATIC_LIBRARY /usr/local/lib/librdf.a
LIBRDF_INCLUDE_DIR /usr/local/include
为了构建,我使用的是 CLion,它只是在后台执行此操作:
mkdir build && cd build
CMake ..
make
因此给我 linker 错误。通过使用 nm
检查 Redland 库的内容,我进行了更深入的挖掘。
$nm -A librdf.a > librdf.a.nmoutput.txt
$nm -A libraptor2.a > libraptor2.a.nmoutput.txt
$nm -A librasqal.a > librasqal.a.nmoutput.txt
第一次冒犯undfined reference
错误
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_free_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:671: undefined reference to `raptor_free_memory'
在函数librdf_free_memory
里面,是librdf.a
里面定义的引用
# librdf.a.nmoutput.txt
...
librdf.a:rdf_init.o:0000000000000740 T librdf_free_memory
...
当我们查找对raptor_free_memory
的未定义引用时,我们发现它在librdf.a.
.
中确实是未定义的
#librdf.a.nmoutput.txt
...
librdf.a:rdf_init.o: U raptor_free_memory
...
但这无论如何都应该在 libraptor2.a
中,如果我们看一下,我们会发现它确实存在并且应该被定义为:
# libraptor2.a.nmoutput.txt
...
libraptor2.a:raptor_general.o:0000000000000863 T raptor_free_memory
...
我的理解是 linking 的过程本质上应该用 libraptor.a
中的定义填充 librdf.a
中的未定义引用,但这显然没有发生。
为什么会这样?
当您的静态库相互依赖时,link 命令很重要(参见this 回复)。
如果 librdf
依赖于 libraptor
库(如 link 错误所示),libraptor
库应列在 [之后] librdf
当指定给 linker 时。尝试根据您的库依赖项重新排列 target_link_libraries()
命令中的库列表以遵守此顺序。
本质上,我正在尝试使用 redland rdf 库,但我无法对它们进行 link。当我尝试使用 redland 库的简单基本程序时,出现以下错误:
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_free_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:671: undefined reference to `raptor_free_memory'
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_alloc_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:689: undefined reference to `raptor_alloc_memory'
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_calloc_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:707: undefined reference to `raptor_calloc_memory'
乍一看,您可能只是认为我丢失了一个 link 库,在我进一步检查之前我是这么想的(见下文),但是,这些库都已计算在内。
在这种情况下,一个适当的最小工作示例很困难,因为它需要获取和构建我正在尝试使用的库。但是,我创建了一个 GitHub repository
$ git clone git@github.com:CiaranWelsh/RedlandBuildTest.git
其中包含构建 Redland 库所需的源文件以及我正在使用的示例代码(中断)。
为了构建库,您还需要
$ sudo apt install automake autoconf libtool gtk-doc-tools
$ sudo apt install libxml2 libxml2-dev libxslt libxslt-dev libcurl4-openssl-dev libltdl-dev
请注意,我正在为 Linux 开发 windows 子系统上的 Ubuntu-18.04。
要获取、构建和安装我正在使用这些终端命令的库:
#raptor2
wget "http://download.librdf.org/source/raptor2-2.0.15.tar.gz"
tar -xvf raptor2-2.0.15.tar.gz
cd raptor2-2.0.15
./autogen.sh
make
sudo make install
# redland (librdf)
wget "http://download.librdf.org/source/redland-1.0.17.tar.gz"
tar -xvf redland-1.0.17.tar.gz
cd redland-1.0.17
./autogen.sh
make
sudo make install
# rasqal
wget "http://download.librdf.org/source/rasqal-0.9.33.tar.gz"
tar -xvf rasqal-0.9.33.tar.gz
cd rasqal-0.9.33
./autogen.sh
make
sudo make install
在 github 存储库中作为 shell 脚本可用(get-raptor.sh
、get-rasqal.sh
和 get-librdf.sh
)。
还有我的最小 CMake 脚本(也在存储库中):
cmake_minimum_required(VERSION 3.15)
project(RedlandBuildTest)
set(CMAKE_CXX_STANDARD 14)
find_library(RAPTOR2_STATIC_LIBRARY
NAMES libraptor2.a
PATHS /usr/local/lib
)
find_path(RAPTOR2_INCLUDE_DIR
NAMES raptor2.h
PATHS /usr/local/include/raptor2
)
find_library(RASQAL_STATIC_LIBRARY
NAMES librasqal.a
PATHS /usr/local/lib
)
find_path(RASQAL_INCLUDE_DIR
NAMES rasqal.h
PATHS /usr/local/include/rasqal
)
find_library(LIBRDF_STATIC_LIBRARY
NAMES librdf.a
PATHS /usr/local/lib
)
find_path(LIBRDF_INCLUDE_DIR
NAMES librdf.h
PATHS /usr/local/include
)
add_executable(RedlandBuildTest main.c)
target_include_directories(RedlandBuildTest PRIVATE
${RAPTOR2_INCLUDE_DIR}
${RASQAL_INCLUDE_DIR}
${LIBRDF_INCLUDE_DIR}
)
target_link_libraries(RedlandBuildTest PRIVATE
${RAPTOR2_STATIC_LIBRARY}
${RASQAL_STATIC_LIBRARY}
${LIBRDF_STATIC_LIBRARY}
curl
xml2
xslt
ltdl
)
get_target_property(LINK_LIBRARIES RedlandBuildTest LINK_LIBRARIES)
get_target_property(INCLUDE_DIRECTORIES RedlandBuildTest INCLUDE_DIRECTORIES)
message(STATUS "
LINK_LIBRARIES ${LINK_LIBRARIES}
INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES}
")
message(STATUS "
RAPTOR2_STATIC_LIBRARY ${RAPTOR2_STATIC_LIBRARY}
RAPTOR2_INCLUDE_DIR ${RAPTOR2_INCLUDE_DIR}
RASQAL_STATIC_LIBRARY ${RASQAL_STATIC_LIBRARY}
RASQAL_INCLUDE_DIR ${RASQAL_INCLUDE_DIR}
LIBRDF_STATIC_LIBRARY ${LIBRDF_STATIC_LIBRARY}
LIBRDF_INCLUDE_DIR ${LIBRDF_INCLUDE_DIR}
")
CMake 命令的输出:
#(looks good)
LINK_LIBRARIES /usr/local/lib/libraptor2.a;/usr/local/lib/librasqal.a;/usr/local/lib/librdf.a;curl;xml2;xslt;ltdl
INCLUDE_DIRECTORIES /usr/local/include/raptor2;/usr/local/include/rasqal;/usr/local/include
RAPTOR2_STATIC_LIBRARY /usr/local/lib/libraptor2.a
RAPTOR2_INCLUDE_DIR /usr/local/include/raptor2
RASQAL_STATIC_LIBRARY /usr/local/lib/librasqal.a
RASQAL_INCLUDE_DIR /usr/local/include/rasqal
LIBRDF_STATIC_LIBRARY /usr/local/lib/librdf.a
LIBRDF_INCLUDE_DIR /usr/local/include
为了构建,我使用的是 CLion,它只是在后台执行此操作:
mkdir build && cd build
CMake ..
make
因此给我 linker 错误。通过使用 nm
检查 Redland 库的内容,我进行了更深入的挖掘。
$nm -A librdf.a > librdf.a.nmoutput.txt
$nm -A libraptor2.a > libraptor2.a.nmoutput.txt
$nm -A librasqal.a > librasqal.a.nmoutput.txt
第一次冒犯undfined reference
错误
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_free_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:671: undefined reference to `raptor_free_memory'
在函数librdf_free_memory
里面,是librdf.a
里面定义的引用
# librdf.a.nmoutput.txt
...
librdf.a:rdf_init.o:0000000000000740 T librdf_free_memory
...
当我们查找对raptor_free_memory
的未定义引用时,我们发现它在librdf.a.
.
#librdf.a.nmoutput.txt
...
librdf.a:rdf_init.o: U raptor_free_memory
...
但这无论如何都应该在 libraptor2.a
中,如果我们看一下,我们会发现它确实存在并且应该被定义为:
# libraptor2.a.nmoutput.txt
...
libraptor2.a:raptor_general.o:0000000000000863 T raptor_free_memory
...
我的理解是 linking 的过程本质上应该用 libraptor.a
中的定义填充 librdf.a
中的未定义引用,但这显然没有发生。
为什么会这样?
当您的静态库相互依赖时,link 命令很重要(参见this 回复)。
如果 librdf
依赖于 libraptor
库(如 link 错误所示),libraptor
库应列在 [之后] librdf
当指定给 linker 时。尝试根据您的库依赖项重新排列 target_link_libraries()
命令中的库列表以遵守此顺序。