scylladb / seastar

High performance server-side application framework
http://seastar.io
Apache License 2.0
8.3k stars 1.54k forks source link

Failed to link on Ubuntu 19 #635

Open kostja opened 5 years ago

kostja commented 5 years ago
 % cat /etc/os-release| grep VERS
VERSION="19.04 (Disco Dingo)"
VERSION_ID="19.04"
VERSION_CODENAME=disco
kostja@atlas ~/work/scylla/scylla/seastar
 % uname -a
Linux atlas 5.0.0-13-generic #14-Ubuntu SMP Mon Apr 15 14:59:14 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
kostja@atlas ~/work/scylla/scylla/seastar
 % gcc --version
gcc (Ubuntu 8.3.0-6ubuntu1) 8.3.0

I'm using the latest master branch downloaded today, e031d3d2f61f54ed4d3641477c116370eee18da9

kostja@atlas ~/work/scylla/scylla/seastar
 % cmake .

succeeds with the following message:

-- Performing Test StdFilesystem_NO_EXPLICIT_LINK
-- Performing Test StdFilesystem_NO_EXPLICIT_LINK - Success

Linking, however, fails:

cd /home/kostja/work/scylla/scylla/seastar/tests/unit && /usr/bin/c++  -DSEASTAR_HAS_MEMBARRIER -DSEASTAR_HAVE_ASAN_FIBER_SUPPORT -DSEASTAR_HAVE_GCC6_CONCEPTS -DSEASTAR_HAVE_HWLOC -DSEASTAR_HAVE_LZ4_COMPRESS_DEFAULT -DSEASTAR_HAVE_NUMA -DSEASTAR_TESTING_MAIN -I/home/kostja/work/scylla/scylla/seastar/tests/unit -I/home/kostja/work/scylla/scylla/seastar/src -I/home/kostja/work/scylla/scylla/seastar/include -I/home/kostja/work/scylla/scylla/seastar/gen/include  -O3 -DNDEBUG   -fvisibility=hidden -UNDEBUG -Wall -Werror -Wno-error=deprecated-declarations -gz -std=gnu++17 -U_FORTIFY_SOURCE -Wno-maybe-uninitialized -fconcepts -o CMakeFiles/test_unit_noncopyable_function.dir/noncopyable_function_test.cc.o -c /home/kostja/work/scylla/scylla/seastar/tests/unit/noncopyable_function_test.cc
/usr/bin/ld: ../../libseastar.a(reactor.cc.o): in function `seastar::syscall_result<int>::throw_fs_exception(seastar::basic_sstring<char, unsigned int, 15u, true> const&, std::filesystem::__cxx11::path const&) const':
reactor.cc:(.text._ZNK7seastar14syscall_resultIiE18throw_fs_exceptionERKNS_13basic_sstringIcjLj15ELb1EEERKNSt10filesystem7__cxx114pathE[_ZNK7seastar14syscall_resultIiE18throw_fs_exceptionERKNS_13basic_sstringIcjLj15ELb1EEERKNSt10filesystem7__cxx114pathE]+0xb4): undefined reference to `std::filesystem::__cxx11::filesystem_error::_M_gen_what()'

The root cause of the problem is that for some reason adding flag -std=gnu++17 affects linker behavior in a way that the test in FindStdFilesystem passes without -lstdc++fs in the link flags:

kostja@atlas ~ % cat foo.cxx 
#if __cplusplus >= 201703L && __has_include(<filesystem>)
#include <filesystem>
namespace filesystem = std::filesystem;
#else
#include <experimental/filesystem>
namespace filesystem = std::experimental::filesystem;
#endif

int main() {
    filesystem::path path("/root");
    (void)path;
}

kostja@atlas ~ % g++ foo.cxx -lstdc++fs
kostja@atlas ~ % g++ -std=gnu++17 foo.cxx
kostja@atlas ~ % g++ foo.cxx             
/usr/bin/ld: /tmp/ccUPtXRW.o: in function `std::experimental::filesystem::v1::__cxx11::path::path<char [6], std::experimental::filesystem::v1::__cxx11::path>(char const (&) [6])':
foo.cxx:(.text._ZNSt12experimental10filesystem2v17__cxx114pathC2IA6_cS3_EERKT_[_ZNSt12experimental10filesystem2v17__cxx114pathC5IA6_cS3_EERKT_]+0x6a): undefined reference to `std::experimental::filesystem::v1::__cxx11::path::_M_split_cmpts()'
collect2: error: ld returned 1 exit status
hakuch commented 5 years ago

Thanks for the information.

I wasn't able to reproduce this on an Ubuntu 18.10 virtual machine, but I'll try with an Ubuntu 19 one.

hakuch commented 5 years ago

I was able to reproduce this, and the results of some experiments are a little confusing.

On Fedora 28 with GCC 9 from Git, I can configure Seastar and build a target with a dependency on libseastar.a:

$ ./configure.py --mode=dev
$ ninja -C build/dev test_unit_futures

On Ubuntu 19.04, I observe the same error that you do.

Consider the following snippet (test.cc):

#include <filesystem>

int main() {
    std::filesystem::path p{"/opt"};
    (void)p;
}

On Ubuntu 19.04:

$ g++ -std=gnu++17 test.cc
$ g++ -c test.cc
test.cc: In function 'int main()':
test.cc:4:10: error: 'std::filesystem' has not been declared
$ g++ -std=gnu++17 -c test.cc
$ g++ test.o -o test

The same invocations fail and succeed in the same way on Fedora 28 with GCC 9.

The difference between these examples and the compilation process for test_unit_futures is that we're linking against a library (libseastar.a) which depends on the filesystem features:

/usr/bin/g++  -O1   tests/unit/CMakeFiles/test_unit_futures.dir/futures_test.cc.o  -o tests/unit/futures_test  libseastar_testing.a /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so libseastar.a /usr/lib/x86_64-linux-gnu/libboost_program_options.so /usr/lib/x86_64-linux-gnu/libboost_thread.so /usr/lib/x86_64-linux-gnu/libboost_chrono.so /usr/lib/x86_64-linux-gnu/libboost_date_time.so /usr/lib/x86_64-linux-gnu/libboost_atomic.so -lpthread /usr/lib/x86_64-linux-gnu/libcares.so /usr/lib/x86_64-linux-gnu/libcryptopp.so /usr/lib/x86_64-linux-gnu/libfmt.a /usr/lib/x86_64-linux-gnu/liblz4.so -ldl /usr/lib/x86_64-linux-gnu/libboost_filesystem.so /usr/lib/x86_64-linux-gnu/libboost_system.so /usr/lib/x86_64-linux-gnu/libgnutls.so -latomic /usr/lib/x86_64-linux-gnu/libsctp.so /usr/lib/x86_64-linux-gnu/libprotobuf.so -lrt /usr/lib/x86_64-linux-gnu/libyaml-cpp.so /usr/lib/x86_64-linux-gnu/libhwloc.so -std=gnu++17 /usr/lib/x86_64-linux-gnu/libnuma.so && :
/usr/bin/ld: libseastar.a(reactor.cc.o): in function `seastar::syscall_result<int>::throw_fs_exception(seastar::basic_sstring<char, unsigned int, 15u, true> const&, std::filesystem::__cxx11::path const&) const':
reactor.cc:(.text._ZNK7seastar14syscall_resultIiE18throw_fs_exceptionERKNS_13basic_sstringIcjLj15ELb1EEERKNSt10filesystem7__cxx114pathE[_ZNK7seastar14syscall_resultIiE18throw_fs_exceptionERKNS_13basic_sstringIcjLj15ELb1EEERKNSt10filesystem7__cxx114pathE]+0xb8): undefined reference to `std::filesystem::__cxx11::filesystem_error::_M_gen_what()'
/usr/bin/ld: libseastar.a(reactor.cc.o): in function `seastar::syscall_result<int>::throw_fs_exception(seastar::basic_sstring<char, unsigned int, 15u, true> const&, std::filesystem::__cxx11::path const&, std::filesystem::__cxx11::path const&) const':
reactor.cc:(.text._ZNK7seastar14syscall_resultIiE18throw_fs_exceptionERKNS_13basic_sstringIcjLj15ELb1EEERKNSt10filesystem7__cxx114pathESA_[_ZNK7seastar14syscall_resultIiE18throw_fs_exceptionERKNS_13basic_sstringIcjLj15ELb1EEERKNSt10filesystem7__cxx114pathESA_]+0x90): undefined reference to `std::filesystem::__cxx11::filesystem_error::_M_gen_what()'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

GCC 9 continues to support explicit linking with -lstdc++fs (see this discussion), and so I propose modifying FindStdFilesystem.cmake to explicitly check for GCC so that we always explicitly link in libstdc++fs.

Does that sound reasonable?

kostja commented 5 years ago

Yes. I think generally FindStdFilesystem.cmake could win if it is more explicit about what compiler each check is added for. BTW, it's pretty easy to add .travis.yaml to seastar to be able to quickly see which patch breaks which build/platform.

niekbouman commented 5 years ago

I also experienced this problem on Ubuntu 19.04.

As a temporary fix, I commented out the line

_stdfilesystem_check_compiles (StdFilesystem_NO_EXPLICIT_LINK)

from FindStdFilesystem.cmake in the cmake/ folder

emaxerrno commented 5 years ago

related https://github.com/scylladb/seastar/issues/648