yaml-cpp 的编译器错误 - 对`YAML::detail::node_data::convert_to_map` 的未定义引用
Compiler error with yaml-cpp - undefined reference to `YAML::detail::node_data::convert_to_map`
完整日志如下:
/tmp/ccCvErNZ.o: In function `YAML::detail::node& YAML::detail::node_data::get<std::string>(std::string const&, std::shared_ptr<YAML::detail::memory_holder>)':
cricket.cpp:(.text._ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE[_ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE]+0x94): undefined reference to `YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)'
collect2: error: ld returned 1 exit status
我要编译的代码很简单
#include <iostream>
#include <yaml-cpp/yaml.h>
using namespace std;
int main() {
YAML::Node test = YAML::LoadFile("test.yaml");
if (test["date"]) {
cout << "HELLO";
}
return 0;
}
我使用的 YAML 是来自 http://www.yaml.org/start.html
的示例
如果我只是尝试加载 YAML,它可以正常加载。但是如果我尝试访问任何数据,我会得到同样的错误。所以这不是链接问题。
编辑:我可以执行 cout << test
和 cout << test.type()
之类的操作以及其他功能。我认为问题在于使用基于字符串的映射来访问内部节点。
我尝试在 Debian 系统上编译 OpenXcom 时遇到了类似的情况。事实证明,我混合使用了测试包和稳定包,yaml 包来自稳定包,如果初始函数不止几个,这种组合会以某种方式使 linking 失败。
如果这是您遇到的情况(并且您也在使用 Debian),请尝试使用
从稳定版编译源码包
apt-get --build source libyaml-cpp0.5/stable
此命令将为 libyaml 构建 .deb 包,然后您可以像这样使用 dpkg 插入它们:
dpkg -i libyaml-cpp0.5*.deb
作为根用户。
从源代码编译 libyaml 将使它 link 成为您已有的测试库,而不是期望稳定的库,因此应该可以解决上述问题。至少对我有用。
即使您不使用 Debian,从源代码(例如 tarball)编译 yaml-cpp 也可能出于类似原因工作。
您似乎没有正确链接 yaml-cpp
库。编译时加入参数-lyaml-cpp
。例如:
g++ -I/usr/local/include -L/usr/local/lib -lyaml-cpp -o test main.cpp
编辑
另一种选择是将此 cmake 添加到您的 CMakeLists.txt:
# attempt to find static library first if this is set
if(YAMLCPP_STATIC_LIBRARY)
set(YAMLCPP_STATIC libyaml-cpp.a)
endif()
# find the yaml-cpp include directory
find_path(YAMLCPP_INCLUDE_DIR yaml-cpp/yaml.h
PATH_SUFFIXES include
PATHS
~/Library/Frameworks/yaml-cpp/include/
/Library/Frameworks/yaml-cpp/include/
/usr/local/include/
/usr/include/
/sw/yaml-cpp/ # Fink
/opt/local/yaml-cpp/ # DarwinPorts
/opt/csw/yaml-cpp/ # Blastwave
/opt/yaml-cpp/
${YAMLCPP_DIR}/include/)
# find the yaml-cpp library
find_library(YAMLCPP_LIBRARY
NAMES ${YAMLCPP_STATIC} yaml-cpp
PATH_SUFFIXES lib64 lib
PATHS ~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt
${YAMLCPP_DIR}/lib)
# handle the QUIETLY and REQUIRED arguments and set YAMLCPP_FOUND to TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(YAMLCPP DEFAULT_MSG YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
mark_as_advanced(YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
确保这两个文件存在:
/usr/local/lib/libyaml-cpp.a
/usr/local/include/yaml-cpp/yaml.h
我的CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
FIND_PACKAGE(yaml-cpp REQUIRED)
ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
yaml_cpp_test.cpp的内容与问题中提到的相同。
我尝试在 vps (Ubuntu 14.04.1 LTS)
上重现该问题
wget -c https://github.com/jbeder/yaml-cpp/archive/release-0.5.1.tar.gz
tar xvf release-0.5.1.tar.gz yaml-cpp-release-0.5.1/
cd yaml-cpp-release-0.5.1/
sudo apt-get install cmake
sudo apt-get install libboost-dev
cmake .
make
make install
之后,yaml-cpp 安装到 /usr/local/lib 和 /usr/local/include
我工作目录中的文件:
fqlgy@li407-86:~/yaml-cpp$ ll
total 12
-rw-r--r-- 1 fqlgy fqlgy 162 May 8 03:29 CMakeLists.txt
-rw-r--r-- 1 fqlgy fqlgy 10 May 8 03:11 test.yaml
-rw-r--r-- 1 fqlgy fqlgy 240 May 8 03:11 yaml_cpp_test.cpp
因为我尝试运行 "cmake .",有一些错误,所以我删除了行CMakeFiles/CMakeOutput.log
,CMakeLists.txt的内容是:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
以下输出符合预期:
fqlgy@li407-86:~/yaml-cpp$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/fqlgy/yaml-cpp
fqlgy@li407-86:~/yaml-cpp$ make
Scanning dependencies of target yaml_cpp_test
[100%] Building CXX object CMakeFiles/yaml_cpp_test.dir/yaml_cpp_test.cpp.o
Linking CXX executable yaml_cpp_test
[100%] Built target yaml_cpp_test
fqlgy@li407-86:~/yaml-cpp$ ./yaml_cpp_test
HELLO
我确认某些版本的 yaml-cpp 库包含此问题(这与不正确的链接无关)。
它相当脏,但我已经通过在我的代码中定义空函数解决了它,它看起来像
YAML::BadConversion::~BadConversion()
{
}
void YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}
该方法并不完美(例如,如果使用另一个库版本,它会导致重复)。
就我而言,我 运行 在两台计算机上使用完全相同的代码,只在其中一台计算机上出错,这几乎让我发疯。这不是编译错误,链接错误什么的,我认为代码有问题。
我尝试了所有选项:
- 从源代码进行常规构建并使用
cmake ..
=> make
=> make install
安装
- 同1,
CC=$(which gcc) CXX=$(which g++) cmake -DBUILD_SHARED_LIBS=ON ..
- 正在卸载 apt 的默认包(我使用 ubuntu 16.04)
全部失败,直到我找到 Ilya Golshtein 的答案,然后在我将使用 yaml-cpp 的代码中,我在 YAML::LoadFIle
行
之前添加了这段代码
YAML::BadConversion::~BadConversion()
{
}
void YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}
这是唯一有效的解决方案
完整日志如下:
/tmp/ccCvErNZ.o: In function `YAML::detail::node& YAML::detail::node_data::get<std::string>(std::string const&, std::shared_ptr<YAML::detail::memory_holder>)':
cricket.cpp:(.text._ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE[_ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE]+0x94): undefined reference to `YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)'
collect2: error: ld returned 1 exit status
我要编译的代码很简单
#include <iostream>
#include <yaml-cpp/yaml.h>
using namespace std;
int main() {
YAML::Node test = YAML::LoadFile("test.yaml");
if (test["date"]) {
cout << "HELLO";
}
return 0;
}
我使用的 YAML 是来自 http://www.yaml.org/start.html
的示例如果我只是尝试加载 YAML,它可以正常加载。但是如果我尝试访问任何数据,我会得到同样的错误。所以这不是链接问题。
编辑:我可以执行 cout << test
和 cout << test.type()
之类的操作以及其他功能。我认为问题在于使用基于字符串的映射来访问内部节点。
我尝试在 Debian 系统上编译 OpenXcom 时遇到了类似的情况。事实证明,我混合使用了测试包和稳定包,yaml 包来自稳定包,如果初始函数不止几个,这种组合会以某种方式使 linking 失败。
如果这是您遇到的情况(并且您也在使用 Debian),请尝试使用
从稳定版编译源码包apt-get --build source libyaml-cpp0.5/stable
此命令将为 libyaml 构建 .deb 包,然后您可以像这样使用 dpkg 插入它们:
dpkg -i libyaml-cpp0.5*.deb
作为根用户。
从源代码编译 libyaml 将使它 link 成为您已有的测试库,而不是期望稳定的库,因此应该可以解决上述问题。至少对我有用。
即使您不使用 Debian,从源代码(例如 tarball)编译 yaml-cpp 也可能出于类似原因工作。
您似乎没有正确链接 yaml-cpp
库。编译时加入参数-lyaml-cpp
。例如:
g++ -I/usr/local/include -L/usr/local/lib -lyaml-cpp -o test main.cpp
编辑
另一种选择是将此 cmake 添加到您的 CMakeLists.txt:
# attempt to find static library first if this is set
if(YAMLCPP_STATIC_LIBRARY)
set(YAMLCPP_STATIC libyaml-cpp.a)
endif()
# find the yaml-cpp include directory
find_path(YAMLCPP_INCLUDE_DIR yaml-cpp/yaml.h
PATH_SUFFIXES include
PATHS
~/Library/Frameworks/yaml-cpp/include/
/Library/Frameworks/yaml-cpp/include/
/usr/local/include/
/usr/include/
/sw/yaml-cpp/ # Fink
/opt/local/yaml-cpp/ # DarwinPorts
/opt/csw/yaml-cpp/ # Blastwave
/opt/yaml-cpp/
${YAMLCPP_DIR}/include/)
# find the yaml-cpp library
find_library(YAMLCPP_LIBRARY
NAMES ${YAMLCPP_STATIC} yaml-cpp
PATH_SUFFIXES lib64 lib
PATHS ~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt
${YAMLCPP_DIR}/lib)
# handle the QUIETLY and REQUIRED arguments and set YAMLCPP_FOUND to TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(YAMLCPP DEFAULT_MSG YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
mark_as_advanced(YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
确保这两个文件存在:
/usr/local/lib/libyaml-cpp.a
/usr/local/include/yaml-cpp/yaml.h
我的CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
FIND_PACKAGE(yaml-cpp REQUIRED)
ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
yaml_cpp_test.cpp的内容与问题中提到的相同。
我尝试在 vps (Ubuntu 14.04.1 LTS)
上重现该问题wget -c https://github.com/jbeder/yaml-cpp/archive/release-0.5.1.tar.gz
tar xvf release-0.5.1.tar.gz yaml-cpp-release-0.5.1/
cd yaml-cpp-release-0.5.1/
sudo apt-get install cmake
sudo apt-get install libboost-dev
cmake .
make
make install
之后,yaml-cpp 安装到 /usr/local/lib 和 /usr/local/include
我工作目录中的文件:
fqlgy@li407-86:~/yaml-cpp$ ll
total 12
-rw-r--r-- 1 fqlgy fqlgy 162 May 8 03:29 CMakeLists.txt
-rw-r--r-- 1 fqlgy fqlgy 10 May 8 03:11 test.yaml
-rw-r--r-- 1 fqlgy fqlgy 240 May 8 03:11 yaml_cpp_test.cpp
因为我尝试运行 "cmake .",有一些错误,所以我删除了行CMakeFiles/CMakeOutput.log
,CMakeLists.txt的内容是:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
以下输出符合预期:
fqlgy@li407-86:~/yaml-cpp$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/fqlgy/yaml-cpp
fqlgy@li407-86:~/yaml-cpp$ make
Scanning dependencies of target yaml_cpp_test
[100%] Building CXX object CMakeFiles/yaml_cpp_test.dir/yaml_cpp_test.cpp.o
Linking CXX executable yaml_cpp_test
[100%] Built target yaml_cpp_test
fqlgy@li407-86:~/yaml-cpp$ ./yaml_cpp_test
HELLO
我确认某些版本的 yaml-cpp 库包含此问题(这与不正确的链接无关)。 它相当脏,但我已经通过在我的代码中定义空函数解决了它,它看起来像
YAML::BadConversion::~BadConversion()
{
}
void YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}
该方法并不完美(例如,如果使用另一个库版本,它会导致重复)。
就我而言,我 运行 在两台计算机上使用完全相同的代码,只在其中一台计算机上出错,这几乎让我发疯。这不是编译错误,链接错误什么的,我认为代码有问题。
我尝试了所有选项:
- 从源代码进行常规构建并使用
cmake ..
=>make
=>make install
安装
- 同1,
CC=$(which gcc) CXX=$(which g++) cmake -DBUILD_SHARED_LIBS=ON ..
- 正在卸载 apt 的默认包(我使用 ubuntu 16.04)
全部失败,直到我找到 Ilya Golshtein 的答案,然后在我将使用 yaml-cpp 的代码中,我在 YAML::LoadFIle
行
YAML::BadConversion::~BadConversion()
{
}
void YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}
这是唯一有效的解决方案