How to link libcxx application to a C++ library compiled with gcc - c++

I am trying to link an application that is compiled with clang/libc++ to the v8-devel system library on Fedora. However the latter is compiled with gcc/libstdc++ which leads to a linking error for std::unique_ptr, I think due to inlining.
Is there anything I can change in eiher my application code, or the compiler/linker flags (other than -stdlib) , such that my program can be linked to v8-devel while being still compiled with clang+libcxx?
Below a minimal toy example to reproduce the problem on Fedora (in reality, the only compiler that I have available is a custom clang version with libcxx, so switching to libstdc++ is not an option):
#include <libplatform/libplatform.h>
#include <v8.h>
using namespace v8;
int main(){
std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
}
Then on Fedora we do:
# Install dependencies
yum install -y clang libcxx-devel v8-devel
# Try to compile test program
clang++ test.cpp -std=gnu++17 -stdlib=libc++ -lv8 -lv8_libplatform
Which gives the following linker error:
/usr/bin/ld: /tmp/test-9925a1.o: in function `main':
test.cpp:(.text+0x24): undefined reference to `v8::platform::NewDefaultPlatform(int, v8::platform::IdleTaskSupport, v8::platform::InProcessStackDumping, std::__1::unique_ptr<v8::TracingController, std::__1::default_delete<v8::TracingController> >)'
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
You can automatically run the steps above using this Dockerfile.

Related

Clang compilation into sysroot with newer glibc

I'm trying to compile with a sysroot for Ubuntu 22.04 from a Ubuntu 20.04 image, and I'm having quite a bit of trouble, getting linker errors like these:
/usr/bin/ld: ../build_rootfs/x86_64_jammy/lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_audit_symbind_alt#GLIBC_PRIVATE'
/usr/bin/ld: ../build_rootfs/x86_64_jammy/lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_audit_preinit#GLIBC_PRIVATE'
/usr/bin/ld: ../build_rootfs/x86_64_jammy/lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_fatal_printf#GLIBC_PRIVATE'
/usr/bin/ld: ../build_rootfs/x86_64_jammy/lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__nptl_change_stack_perm#GLIBC_PRIVATE'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The exact same invocation works fine from a Ubuntu 22.04, using the exact same compiler and exact same sysroot.
Here's my setup:
// test.cpp
int main(){}
Compile command:
clang++ --sysroot ../build_rootfs/x86_64_jammy test.cpp
Where ../build_rootfs/x86_64_jammy is a sysroot created with multistrap (I can share a minimized multistrap config if it's relevant, but considering the same sysroot works fine from Ubuntu 22.04, the sysroot seems to not be the issue.
Things I have tried:
Using lld--same result
Using clang 14, both from apt.llvm.org and from the binary tarball
Notably, GCC is able to compile it by passing -L/usr/lib/x86_64-linux-gnu/9 -L/usr/lib/x86_64-linux-gnu (yes, even when compiling with --sysroot), but this seems strange as this is linking to libraries on the host system. Adding these flags does let the compilation succeed, but compiling from clang on 22.04 works fine without loading any of the system libraries (allegedly).
I assume this is an issue with glibc verisons, but I can't see how the host glibc version would matter when compiling from a sysroot, and it doesn't seem like any of the linker inputs are actually from the host system, so what's going wrong?
This gist has the verbose logs from clang on focal, gcc on focal, and clang on jammy for reference.

GoogleTest: CLang error compiling ASSERT_FALSE(false)

I downloaded googletest and built it in a subdirectory named build.
Then, I wrote the following code in a file named main.cpp:
#include <gtest/gtest.h>
TEST(FOO, BAR) { ASSERT_FALSE(false); }
Quite simple indeed.
It relies on the fact that a main function is already provided with googletest if you link the libgtestmain.a library.
GCC (v5.3.1) compiles it using the following command:
g++ -L./googletest/build/googlemock/gtest -L./googletest/build/googlemock -I./googletest/googletest/include/ -lgmock -lgtest -lgtest_main -lgmock_main -pthread -std=c++11 main.cpp
Anyway, clang (v3.6.2) does not compile using the same command:
clang++ -L./googletest/build/googlemock/gtest -L./googletest/build/googlemock -I./googletest/googletest/include/ -lgmock -lgtest -lgtest_main -lgmock_main -pthread -std=c++11 main.cpp
The error is the following one:
/tmp/main-4127ae.o: In function 'FOO_BAR_Test::TestBody()':
main.cpp:(.text+0x7b): undefined reference to `testing::internal::GetBoolAssertionFailureMessage(testing::AssertionResult const&, char const*, char const*, char const*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The code contains almost the sole ASSERT_FALSE(false) statement (that's a minimal, complete example and still it doesn't compile), so I'd say that the problem is not in the code itself.
The same problem arises also from the following statement:
TEST(FOO, BAR) { ASSERT_TRUE(true); }
Is that an issue due to googletest, to clang or whatever?
I'm trying to figure it out, but I'm a little bit in trouble while looking at the code of googletest.
NOTE
I've not been able to find neither an open nor a closed issue for googletest, so I'm to open also a ticket for it on github.
In a while I'll probably post the link to the issue.
As of GCC 5.1, g++ is not ABI-compatible with clang++. Some
bug reports: clang++ no longer ABI-compatible with g++
and Add support for gcc's attribute abi_tag (needed for compatibility with gcc 5's libstdc++).
Till this is fixed you need to link googletest-ing projects
with googletest libraries built with the same compiler.

Undefined reference to boost::random::random_device constructor and destructor on MinGW-w64 gcc

My OS is Windows 7 64-bit and C++ compiler I'm using is:
g++ (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 5.3.0
And I installed Boost version 1.60 using:
bootstrap.bat mingw
b2 install target=gcc
Then I tested is it working, using examples from Boost.Random tutorial.
With the first two everything was fine, but the third one gave linker errors about boost::random::random_device. I minimized the code to have only this:
// Compiled with:
// g++ -IC:/Boost/include/boost-1_60
// -LC:/Boost/lib -lboost_random-mgw53-mt-1_60
// main.cpp
#include "boost/random/random_device.hpp"
int main() {
boost::random::random_device rng;
}
And I get the following errors:
C:\Users\Daniel\AppData\Local\Temp\cc5DfdjZ.o:main.cpp:(.text+0x15):
undefined reference to `boost::random::random_device::random_device()'
C:\Users\Daniel\AppData\Local\Temp\cc5DfdjZ.o:main.cpp:(.text+0x20):
undefined reference to `boost::random::random_device::~random_device()'
collect2.exe: error: ld returned 1 exit status
Here, on SO, I found that someone with similar problem added -lboost_system to flags, but for me it didn't helped.
Does anyone have any idea, why it isn't working? I checked, and I have random_device.hpp header in my Boost folder, with declarations of random_device() and ~random_device() in it.
I found what was wrong - the g++ command syntax, that I wanted to use to compile and link my code.
As I wrote in my question, I do this that way:
g++ -IC:/Boost/include/boost-1_60 -LC:/Boost/lib -lboost_random-mgw53-mt-1_60 main.cpp
While the correct one is with main.cpp (or any other source code file(s), that we want to include in compiling process) before the -L and -l flags.
For example:
g++ -IC:/Boost/include/boost-1_60 main.cpp -LC:/Boost/lib -lboost_random-mgw53-mt-1_60
or even
g++ main.cpp -IC:/Boost/include/boost-1_60 -LC:/Boost/lib -lboost_random-mgw53-mt-1_60
Hope it will help anyone, who will make such silly mistake too.

How to compile boost unit test module with clang++?

I'm trying to compile a boost unit test module with cmake and clang but ran into a linker error. I was able to produce the following minimal test case:
$ cat boost_test_test.cc
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE scanio
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(foo) { BOOST_CHECK(1); }
This compiles fine with g++:
$ g++ boost_test_test.cc -lboost_unit_test_framework
$ echo $?
0
But it does not with clang++:
$ /usr/bin/clang++-3.7 boost_test_test.cc -lboost_unit_test_framework
/tmp/boost_test_test-7e4892.o: In function `boost::unit_test::make_test_case(boost::unit_test::callback0<boost::unit_test::ut_detail::unused> const&, boost::unit_test::basic_cstring<char const>)':
boost_test_test.cc:(.text._ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x58): undefined reference to `boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring<char const>)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
So during the linker stage I get an undefined reference error and this problem persists no matter the order of arguments to clang++.
Since it works fine with g++ I suppose there is something clang++ specific going on here?
This is with g++ 5.2.1, clang++ 3.7 and boost 1.58 on Debian Sid.
In Ubuntu Willy, Boost 1.58 Unit Test library is compiled with GCC 5.0. The library file libboost_unit_test_framework.a contains the mangled function _ZN5boost9unit_test9ut_detail24normalize_test_case_nameB5cxx11ENS0_13basic_cstringIKcEE that resolves to boost::unit_test::ut_detail::normalize_test_case_name[abi:cxx11](boost::unit_test::basic_cstring<char const>)
However, CLang does not seem to use the new ABI, so it searches for _ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE, which is boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring<char const>).
In order to overcome this, define your own function in the test file:
namespace boost { namespace unit_test { namespace ut_detail {
std::string normalize_test_case_name(const_string name) {
return ( name[0] == '&' ? std::string(name.begin()+1, name.size()-1) : std::string(name.begin(), name.size() ));
}
}}}
This should resolve the issue. If compiled with the same version of the compiler as Boost, it should be no problem, as the linker will simply ignore the library version of the function.

What library do I need to link to use std::list in clang++?

I am trying to use the std::list class in C++, and I need to use clang++ to compile the program. g++ compiles the following program just fine, but I can't figure out how to compile/link it with clang++:
#include <iostream>
#include <list>
int main(){
std::list<int> L;
L.push_back(10);
std::cout << L.back() << std::endl;
return 0;
}
I've tried clang++ -lstdc++ listTest.cpp but still get the following error:
/tmp/listTest-3175a9.o: In function `std::list<int, std::allocator<int> >::_M_insert(std::_List_iterator<int>, int const&)':
listTest.cpp:(.text._ZNSt4listIiSaIiEE9_M_insertESt14_List_iteratorIiERKi[_ZNSt4listIiSaIiEE9_M_insertESt14_List_iteratorIiERKi]+0x31): undefined reference to `std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Clang version:
clang version 3.4 (tags/RELEASE_34/final)
linux version:
LSB_VERSION=base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Red Hat Enterprise Linux Server release 6.5 (Santiago)
You should provide library arguments after the translation unit that uses them:
clang++ listTest.cpp -lstdc++
I should note that I couldn't reproduce your issue, but that could easily be down to differences in version/configuration (particularly w.r.t. a stdlib implementation selected for use by default).
I solved it on mine (redhat, clang 3.4, gcc 4.7.2).
By default this project was linking against /usr/lib/libstdc++. I have a build of gcc 4.7.2 installed in a separate location; when I add lines analogous to the following to the link step it works fine
-L${GCC_PATH}/lib -Wl,-R${GCC_PATH}/lib
... provided they appear in the link step before analogous statements for /usr/lib.
edit
You can use strace to help diagnose this problem; I did something like the following:
// copy the link step into a temp shell script
strace -f ./temp.sh |& grep -P 'lib(std)?c\+\+'
... which is when I realized I probably needed a different build of the C++ runtime because I saw it was finding and linking against the one in /usr/lib.