Boost::filesystem::directory_iterator 升级到 v1.78.0 后导致链接器错误
Boost::filesystem::directory_iterator causes linker error after upgrade to v1.78.0
我想在我的项目中使用 boost::filesystem,直到最近这都是可能的 (v1.65.1)。几天前,我不得不将我的 boost 安装升级到 1.78.0,并按照网站上的说明从源代码构建库。我执行了以下几行:
wget https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.tar.gz
tar xzvf boost_1_78_0.tar.gz
cd boost_1_78_0/
./bootstrap.sh --prefix=/usr/
./b2
sudo ./b2 install
boost 中的测试代码利用了 boost 的文件系统函数。编译没问题,但链接器抛出错误(见下文)。
代码
#include <iostream>
#include <boost/filesystem.hpp>
using std::cout;
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "Usage: tut3 path\n";
return 1;
}
path p(argv[1]);
try
{
if (exists(p))
{
if (is_regular_file(p))
{
cout << p << " size is " << file_size(p) << '\n';
}
else if (is_directory(p))
{
cout << p << " is a directory containing:\n";
for (directory_entry const& x : directory_iterator(p))
cout << " " << x.path() << '\n';
}
else
cout << p << " exists, but is not a regular file or directory\n";
}
else
cout << p << " does not exist\n";
}
catch (filesystem_error& ex)
{
cout << ex.what() << '\n';
}
return 0;
}
编译和链接器命令(由eclipse生成)
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/main.d" -MT"src/main.d" -o "src/main.o" "../src/main.cpp"
g++ -o "test" ./src/main.o -lboost_system -lboost_filesystem
错误
./src/main.o: In function »boost::filesystem::directory_iterator::directory_iterator(boost::filesystem::path const&, boost::filesystem::directory_options)«:
/usr/include/boost/filesystem/directory.hpp:326: Warning: undefined reference to »boost::filesystem::detail::directory_iterator_construct(boost::filesystem::directory_iterator&, boost::filesystem::path const&, unsigned int, boost::system::error_code*)«
makefile:45: recipe for target 'test' failed
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
如果我删除包含 boost::filesystem::directory_iterator
的行,则链接有效。我不确定如何解决这个问题。我最初认为旧版本的 boost 可能会干扰,因为它仍然驻留在 /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1
中,但是当检查文件中包含的版本时,它显示了较新的版本。
这里发生了什么?
解决方案
最后我把原装和新版都删了,重新安装了/usr/local
下的包。帮助遇到相同问题的人的快速演练:
// remove the dirs under <prefix>/lib/libboost* and <prefix>/include/boost* first
sudo apt purge -y libboost-all-dev libboost*
sudo apt autoremove
// then either install the package via the manager or copy the sources to /usr/local/ or another suitable place
sudo apt install libboost-all-dev // option with aptitude
包含的是编译时。共享库在 link 时间 link 编辑。
您没有明确告诉 headers 找到 headers,也没有告诉编译器在哪里找到这些库。这意味着使用标准位置。
根据您的包管理器,可能会有类似 link 的符号:
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so -> libboost_filesystem.so.1.65.1
用您的文件覆盖部分已安装软件包通常是一个坏主意。不在最后,因为例如这样的 symlinks 可能不会更新,或者如果它们更新了,它们可能会破坏您安装的许多依赖项。
一般来说,更喜欢使用安全前缀(例如 /usr/local
)或在本地构建并在构建工具(如 Eclipse)或命令行中指明 include/library 目录,如:
-I ~/custom/boost_1_77_0/ -L ~/custom/boost_1_77_0/stage/libs
选择 /usr/local
的一个优点是许多发行版都支持它,并且可能将它添加到运行时加载程序的路径中(参见 ldconfig
)。
我想在我的项目中使用 boost::filesystem,直到最近这都是可能的 (v1.65.1)。几天前,我不得不将我的 boost 安装升级到 1.78.0,并按照网站上的说明从源代码构建库。我执行了以下几行:
wget https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.tar.gz
tar xzvf boost_1_78_0.tar.gz
cd boost_1_78_0/
./bootstrap.sh --prefix=/usr/
./b2
sudo ./b2 install
boost 中的测试代码利用了 boost 的文件系统函数。编译没问题,但链接器抛出错误(见下文)。
代码
#include <iostream>
#include <boost/filesystem.hpp>
using std::cout;
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "Usage: tut3 path\n";
return 1;
}
path p(argv[1]);
try
{
if (exists(p))
{
if (is_regular_file(p))
{
cout << p << " size is " << file_size(p) << '\n';
}
else if (is_directory(p))
{
cout << p << " is a directory containing:\n";
for (directory_entry const& x : directory_iterator(p))
cout << " " << x.path() << '\n';
}
else
cout << p << " exists, but is not a regular file or directory\n";
}
else
cout << p << " does not exist\n";
}
catch (filesystem_error& ex)
{
cout << ex.what() << '\n';
}
return 0;
}
编译和链接器命令(由eclipse生成)
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/main.d" -MT"src/main.d" -o "src/main.o" "../src/main.cpp"
g++ -o "test" ./src/main.o -lboost_system -lboost_filesystem
错误
./src/main.o: In function »boost::filesystem::directory_iterator::directory_iterator(boost::filesystem::path const&, boost::filesystem::directory_options)«:
/usr/include/boost/filesystem/directory.hpp:326: Warning: undefined reference to »boost::filesystem::detail::directory_iterator_construct(boost::filesystem::directory_iterator&, boost::filesystem::path const&, unsigned int, boost::system::error_code*)«
makefile:45: recipe for target 'test' failed
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
如果我删除包含 boost::filesystem::directory_iterator
的行,则链接有效。我不确定如何解决这个问题。我最初认为旧版本的 boost 可能会干扰,因为它仍然驻留在 /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1
中,但是当检查文件中包含的版本时,它显示了较新的版本。
这里发生了什么?
解决方案
最后我把原装和新版都删了,重新安装了/usr/local
下的包。帮助遇到相同问题的人的快速演练:
// remove the dirs under <prefix>/lib/libboost* and <prefix>/include/boost* first
sudo apt purge -y libboost-all-dev libboost*
sudo apt autoremove
// then either install the package via the manager or copy the sources to /usr/local/ or another suitable place
sudo apt install libboost-all-dev // option with aptitude
包含的是编译时。共享库在 link 时间 link 编辑。
您没有明确告诉 headers 找到 headers,也没有告诉编译器在哪里找到这些库。这意味着使用标准位置。
根据您的包管理器,可能会有类似 link 的符号:
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so -> libboost_filesystem.so.1.65.1
用您的文件覆盖部分已安装软件包通常是一个坏主意。不在最后,因为例如这样的 symlinks 可能不会更新,或者如果它们更新了,它们可能会破坏您安装的许多依赖项。
一般来说,更喜欢使用安全前缀(例如 /usr/local
)或在本地构建并在构建工具(如 Eclipse)或命令行中指明 include/library 目录,如:
-I ~/custom/boost_1_77_0/ -L ~/custom/boost_1_77_0/stage/libs
选择 /usr/local
的一个优点是许多发行版都支持它,并且可能将它添加到运行时加载程序的路径中(参见 ldconfig
)。