Why does gcc want me to link to libgcc_ext.10.5.dylib? - c++

I've built GCC 4.9.2 on Mac OS X from source statically (using --disable-shared), for C language only (not C++), with the static version of libgcc (libgcc.a). Of course, since I only built the static version of libgcc, there's no such thing as libgcc*.dylib. GCC has built and installed libgcc.a (as expected) and that's all fine. Now when I invoke this newly-built copy of GCC using the following command (using a simple hello, world! example):
gcc -v test.c -o test
it shows these compiler flags as default:
-no_compact_unwind -lSystem -lgcc_ext.10.5 -lgcc -lSystem
No, no no! I don't want you to try to link to a shared version of libgcc! Don't you remember I told you that at the configuration step? And if I use the -static-libgcc option, I get this:
-no_compact_unwind -lgcc_eh -lgcc -lSystem
libgcc_eh? HUH? When was that built during GCC compilation? Oh right, it wasn't, hence why it can't find libgcc_eh.a.
What's going on here? I specifically told GCC I didn't want shared libraries, so why is it trying to link to them by default? I can, of course, remedy all this by using -nodefaultlibs and specifying -lgcc and -lSystem manually, but why should I have to do that?
Furthermore, the GCC documentation has this to say:
-shared-libgcc
-static-libgcc
On systems that provide libgcc as a shared library, these options force the use of either the shared or static version, respectively. If no shared version of libgcc was built when the compiler was configured, these options have no effect.
So, based on this, I take it that if I did not specifically ask GCC to build a shared version of libgcc, it should not assume I would want to link to anything but a static version. But, for some reason, it does anyway. I haven't been able to find a configure option that would prevent this, nor an option that lets me specify which "default libs" get linked to by default. It seems GCC is forcing me to link to a shared version of libgcc that isn't there unless I suppress this using -nodefaultlibs. This seems backwards.

I figured out how to fix this. I had to edit /gcc/config/darwin.h in GCC's source and comment out where the macro REAL_LIBGCC_SPEC is defined. By leaving this macro undefined, it ensures GCC will only pass the -lgcc and -lSystem library flags during linking, which is what I wanted.
The GCC docs for the compilation driver explain what this and other macros do:
https://gcc.gnu.org/onlinedocs/gccint/Driver.html
— Macro: LIBGCC_SPEC
Another C string constant that tells the GCC driver program how and when to place a reference to libgcc.a into the linker command line. This constant is placed both before and after the value of LIB_SPEC.
If this macro is not defined, the GCC driver provides a default that passes the string -lgcc to the linker.
— Macro: REAL_LIBGCC_SPEC
By default, if ENABLE_SHARED_LIBGCC is defined, the LIBGCC_SPEC is not directly used by the driver program but is instead modified to refer to different versions of libgcc.a depending on the values of the command line flags -static, -shared, -static-libgcc, and -shared-libgcc. On targets where these modifications are inappropriate, define REAL_LIBGCC_SPEC instead. REAL_LIBGCC_SPEC tells the driver how to place a reference to libgcc on the link command line, but, unlike LIBGCC_SPEC, it is used unmodified.

Related

Use compiled LLVM/clang without gcc

I have been trying to compile LLVM/clang from source, both by myself and using this script. I am compiling clang using gcc 11.2, which itself was also built from source, and hence resides in a non-default location on my system (/scratch/opt/gcc-ml-11.2). Note that it only works with a gcc that was compiled with multilib enabled.
The problem is that I can use the compiled clang and clang++ binaries only if I supply the gcc location as follows: --gcc-toolchain=/scratch/opt/gcc-ml-11.2.0. Without that flag, I run into linker errors:
clang test.c -o test
/usr/bin/ld: cannot find crtbeginS.o: No such file or directory
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: cannot find -lgcc_s
I do not understand why a clang compiled binary needs to link against some kind of gcc library and why clang does not supply the crtbeginS.O file.
I have also tried using the LLVM linker as well as the LLVM standard library for C++ test applications, i.e., "-fuse-ld=lld -stdlib=libc++. This did not help either.
While I could just export CXXFLAGS=--gcc-toolchain=/scratch/opt/gcc-ml-11.2.0, I am not sure whether this is the right approach. Shouldn't clang/LLVM be able to function without a gcc installation?
I have also tried using my clang installation with the --gcc-toolchain=/scratch/opt/gcc-ml-11.2.0 flag to compile clang again, but the new binary also requires the gcc-toolchain flag.
Should I just globally export the path to my gcc toolchain? Why is this necessary? Isn't clang a standalone compiler that - if supplied with the option to use its own standard library - does not require gcc?
Thank you very much for your help!
Best,
Maxbit

Why do clang++ and gcc/g++ produce differently linked executables

When compiling and linking with g++ and clang++ there is an expectation that the resulting executable will be linked equal with respect to their linkage.
However in certain cases it appears that clang++ executables are linked to more libraries than g++ despite the same arguments passed in.
This can cause functional differences especially with respect to dynamically linked libraries that have automatic execution on load and unload.
Why does this happen?
It turns out gcc has a feature enabled by default in ubuntu --as-needed which causes gcc to effectively ignore any library for which none of it's symbols are referenced in the chain of linked items
This can be disabled in gcc with --no-as-needed flag. Or alternatively you can issue -Wl,--as-needed as the first option to clang++ to behave the way gcc does.

lstd++ & extern - calling C++ from C

I have wrapped my C++ header file in an extern "C" block to allow calling C++ functions from C. I have included the proper header files in the proper places. It works if I do something like the following:
g++ -c cpp_src.cc
gcc -c c_src.c
gcc -o c_exe c_src.o cpp_src.o -lstdc++
But if I remove the -lstdc++ from the last line, I get a bunch of errors. Because of reasons beyond my control, I cannot add the -lstdc++ flag. Is there a way to get the above to work without -lstdc++? What exactly is lstdc++, as in how does the gcc use it while linking with g++ compiled code?
Also, cpp_src.cc uses STL, if that makes a difference.
If you really need to have an object file that you can link with gcc without using -lstdc++, you can do an incremental link of your C++ object file with -lstdc++ and then use the result of that on your gcc link line. Something like:
ld -i -static cpp_src.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -lstdc++ -o cpp_withstdlib.o
This will link your C++ object file with the standard C++ library and produce a new object file (cpp_withstdlib.o) that contains all the standard C++ library stuff you need, so can be linked on the gcc command line without needing -lstdc++
The tricky part is the -L option -- you need to figure out where g++ has stashed its standard library, as it generally doesn't put it in the standard /usr/lib location. The above is for an Ubuntu 14.04 machine. On most Linux machines, you can find it with locate libstdc++.a
You're generally just better off using g++ to link C++ code, as it knows all the right paths and won't make little mistakes that result in a binary that superficially appears to work, but is actually incorrect.
Using Josh's suggestion, you can do:
ld -i -static cpp_src.o `g++ -print-file-name=libstdc++.a` -o cpp_withstdlib.o
which is a bit cleaner, and could readily be done in a Makefile.
-lstdc++ causes the linker to link to libstdc++, which is gcc's implementation of the C++ standard library. If your code uses any symbols from the standard library (it uses the standard library, and not all code is inlined from headers), it must link libstdc++ (or whichever standard library implementation you use).
You can avoid the standard library, or you can link against the system standard library, or you can statically link a copy of the standard library into your program.

Error when static linking g++

I have a problem, i want to compile my application with static linking of mysql connector.
My command line:
g++ -o newserver stdafx.cpp ... -lboost_system -lboost_thread
-lpthread -lmysqlcppconn -static /usr/lib/libmysqlcppconn-static.a -std=c++0x
But i have error:
/usr/bin/ld: cannot find -lmysqlcppconn
/tmp/ccxpOfdZ.o: In function `IsEqualsDns(unsigned long, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
Server.cpp:(.text+0x356e): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
collect2: ld returned 1 exit status
How can i fix this?
Thanks!
Where is the library libsqlcppconn.a or libsqucppconn.so
(static or dynamic)? The compiler is looking for it, and
doesn't find it.
Presumably, this is the same library as
/usr/lib/mysqlcppconn-static.a. If so, just drop the
-lmysqlcppconn. Or just use -lmysqlcppconn-static (no
spaces), and forget about the /usr/lib/libmysqlconn-static.a.
With a name like that, there shouldn't be a corresponding .so,
which means that g++ will link it statically, even without the
-static. You only need the -static if there is both
a libmysqlconn-static.so and a libmysqlconn-static.a in the
same directory.
With regards to the second error (which is just a warning, but
will cause problems if you try to run the linked program on
other machines, or even after an upgrade of your machine): if
you use -static anywhere in your command line (as you
currently do), then it applies to all files linked afterwards.
Including the system libraries, which you don't want to link
statically. My guess is that the -static isn't necessary (see
above); if it is, place it immediately before the library you
want to link statically, and place a -dynamic immediately
after (so that any following libraries, including the system
libraries, will be dynamically linked).
You could try g++ -static YOUR ARGUMENTS.
If you are coming from a Windows platform, linking against Boost can give a few surprises. The typicall Boost installation (e.g. after ./b2 install) will make both dynamic and static libraries and put them in the same directory. Typically, the two library forms only differ in their extension (.so or .a).
Windows supports auto-linking, which basically means that library files contain some flags in their first few bytes indicating whether they are for dynamic or for static linking. On Linux platforms, this is not the case and the linker gets confused which file to load (since you don't provide the extension of the library name). Therefore, you need to tell your linker which form of linking you want.

how to do static linking of libwinpthread-1.dll in mingw?

I use mingw from here: http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev2.7z/download
And I've sucessfully managed to link statically libstdc++-6.dll and libgcc_s_sjlj-1.dll by using -static-libgcc -static-libstdc++ parameters, but I cannot find a command for doing the same with libwinpthread-1.dll.
If your toolchain includes the static winpthreads, adding the option
-static
Will pull in static versions of all libraries it can.
Alternatively, you can remove libwinpthread.dll.a and the DLL itself from the toolchain directories. This might mess up programs linking with libstdc++ and libgcc DLLs though, so be careful.
A third option is to use -Wl,-Bdynamic and -Wl,-Bstatic to select which version you want linked in (which is what -static internally does when ld is called). An example:
gcc -o someexec someobject.o -Wl,-Bdynamic -lsomelibIwantshared -Wl,-Bstatic -lsomelibIwantstatic
If you run your link command with -v added, you should see these options appearing in the ld/collect2 invocation when you use -static-libgcc and -static-libstdc++.
Try this:
-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic
Notice the -lstdc++ before -lpthread. It worked for me.
Make sure to add this to the very end of your g++ command line.
You should probably check command line options documentation for GCC.
These's no '-static-something' command, only standard libraries (libgcc and libstdc++) can be set to static linking with one command. For other libraries, you first switch to static linking with "-static" and then list the libraries to include with separate commands, ie "-lpthread".
To statically link winpthread even if threading isn't used in the program, pass the -Bstatic and --whole-archive parameters to the linker:
g++ -o hello.exe hello.cpp -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive
Note the following:
The "whole archive" option should be disabled immediately afterwards.
You don't need to do this hack if your program actually uses symbols from the library (i.e. you use <thread> from C++11), in which case the library won't get dropped when you statically link it.
This hack is intended for MinGW-w64, to fix the libwinpthread-1.dll dependencies.
For anyone working in CMake, this solution is readily implemented in your CMakeLists.txt file as follows...
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
Apparently, CMake does some weird stuff with how the -Wl compiler flags are handled, making the -Wl,-Bstatic -lstdc++ -lwinpthread -Wl,-Bdynamic solution not work, with only two other options seemingly left: the bad compiler flag -static and the ugly compiler flag -Wl,--whole-archive.
Meanwhile, the good option that actually works in CMake, yet seems rather undocumented, is to directly use the linker flags. Hence, in CMake, this seems to be the best way to statically link to all the mingw-w64 C++ dependencies:
target_link_libraries (MyVeryAwesomeApp -static gcc stdc++ winpthread -dynamic)
It should be noted that even if there isn't a library explicitly following -dynamic, it should still be applied in order to ensure that the standard, implicitly linked libraries get linked correctly.
I circumvented this problem by using win32 variant of the mingw toolchain instead of the posix variant. With the win32 variant, -static-libgcc -static-libstdc++ is sufficient for an independent build.
If you are using toolchains from MSys2 (tested with gcc version 12) ,the only way to use winpthread statically is standard -static (forces all library to be static) or simply delete/rename the libwinpthread.dll.a && libpthread.dll.a imp libs.
Other methods like "Bstatic", "-l:libwinpthread.a" will no longer work (due to dependency hell, especially in CMake). The one with whole archive still works but it overrides the program properties.
You may also want static link libgcc and libstdc++ if the dependency comes from them.
Just link with -l:libwinpthread.a
Just add -static to your CFLAGS.
For example: ./configure CFLAGS="-static".
This will link all static libraries to your executable file.