I'm using the apple gcc to compile a dylib that I'm going to redistribute. For various reasons I'm using some libraries, let's say libz to keep it simple.
Since this library is not typically found on a Mac system I wish to static link in used symbols into the dylib by passing the path to the .a-file to simplify deployment.
Now, the linker links in all symbols from the lib into the resulting dylib although I only reference a subset. On linux I've never encountered this problem, the linker happily discards all unreferenced symbols and creates a very slim executable, so it should be possible. The dylib file I have now is ~10 times larger than it should.
I've tried fiddle around with the -dead_code linker flag, but to no avail. Perhaps I just don't understand it?
Does anyone know the solution to this?
Try -Wl,--gc-sections.
As regards -dead_strip (what you probably meant by -dead_code):
Before turning on the -dead_strip
option your project will first have to
be "ported" to work with dead code
stripping. This will include changing
from -gused (the default for -g) to
-gfull and re-compiling all of the objects files being linked into your
program with the new compiler from the
Mac OS X June 2004 release. Also if
your building an executable that loads
plugins, which uses symbols from the
executable, you will have to make sure
the symbols the plugins use are not
stripped (by using
attribute((used)) or the -exported_symbols_list option). If you are using an export list and building
a shared library, or an executable
that will be used with ld(1)'s
-bundle_loader flag, you need to include the symbols for exception
frame information in the export list
for your exported C++ symbols. These
symbols end with .eh and can be seen
with the nm(1) tool.
and:
To enable dead-code stripping from the
command line, pass the -dead_strip
option to ld. You should also pass the
-gfull option to GCC to generate a complete set of debugging symbols for
your code. The linker uses this extra
debugging information to dead strip
the executable.
Hope this helps.
All content in this answer was located within the first few Google search results for "apple ld static link unused symbols". :)
Related
I use c++11, but also some libraries that are not configured for it, and need some type conversion. In particular I need a way to convert std::__cxx11::string to regular std::string, but googling I can't find a way to do this and putting (string) in front does not work.
If I do not convert I get linker errors like this:
undefined reference to `H5::CompType::insertMember(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, H5::DataType const&) const'
Is it possible that you are using GCC 5?
If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.
Source: GCC 5 Release Notes/Dual ABI
Defining the following macro before including any standard library headers should fix your problem: #define _GLIBCXX_USE_CXX11_ABI 0
If you can recompile all incompatible libs you use, do it with compiler option
-D_GLIBCXX_USE_CXX11_ABI=1
and then rebuild your project. If you can't do so, add to your project's makefile compiler option
-D_GLIBCXX_USE_CXX11_ABI=0
The define
#define _GLIBCXX_USE_CXX11_ABI 0/1
is also good but you probably need to add it to all your files while compiler option do it for all files at once.
When I had similar issue it's happened because my lib was build using clang++, and it's linked to libstdc++.so by default on my system. While app binary was build using clang and linked with -lc++ option.
Easiest way to check dependencies is to perform ldd libName.so
To fix it you should use the same library on in app and library.
Easiest way. Build library using clang++ and compile app using clang++. Without extra linking options on both steps. Default stdlib will be used.
Build library with -stdlib=c++ and compile app with -lc++. In this case both library and app will use libc++.so.
Build library without extra options and link binary to -lstdc++. In this case both library and app will use libstdc++.so.
Answers here mostly focus on short way to fix it, but if that does not help, I'll give some steps to check, that helped me (Linux only):
If the linker errors happen when linking other libraries, build those libs with debug symbols ("-g" GCC flag)
List the symbols in the library and grep the symbols that linker complains about (enter the commands in command line):
nm lib_your_problem_library.a | grep functionNameLinkerComplainsAbout
If you got the method signature, proceed to the next step, if you got no symbols instead, mostlikely you stripped off all the symbols from the library and that is why linker can't find them when linking the library. Rebuild the library without stripping ALL the symbols, you can strip debug (strip -S option) symbols if you need.
Use a c++ demangler to understand the method signature, for example, this one
Compare the method signature in the library that you just got with the one you are using in code (check header file as well), if they are different, use the proper header or the proper library or whatever other way you now know to fix it
I got this, the only way I found to fix this was to update all of mingw-64 (I did this using pacman on msys2 for your information).
For me -D_GLIBCXX_USE_CXX11_ABI=0 didn't help.
It works after I linked to C++ libs version instead of gnustl.
I had a similar issue recently while trying to link with the pre-built binaries of hdf5 version 1.10.5 on Ubuntu 16.04. None of the solutions suggested here worked for me, and I was using g++ version 9.1. I found that the best solution is to build the hdf5 library from source. Do not use the pre-built binaries since these were built using gcc 4.9! Instead, download the source code archives from the hdf website for your particular distribution and build the library. It is very easy.
You will also need the compression libraries zlib and szip from here and here, respectively, if you do not already have them on your system.
In my case, I was having a similar problem:
/usr/bin/ld: Bank.cpp:(.text+0x19c): undefined reference to 'Account::SetBank(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: error: ld returned 1 exit status
After some researches, I realized that the problem was being generated by the way that Visual Studio Code was compiling the Bank.cpp file. So, to solve that, I just prompted the follow command in order to compile the c++ file sucessful:
g++ Bank.cpp Account.cpp -o Bank
With the command above, It was able to linkage correctly the Header, Implementations and Main c++ files.
OBS: My g++ version: 9.3.0 on Ubuntu 20.04
I've encountered similar problems
It turns out my project was using gcc 7 and g++ 9 and tried to link together object files compiled by those two and it all messed up.
Make sure you use the same compiler versions in all your project.
I use c++11, but also some libraries that are not configured for it, and need some type conversion. In particular I need a way to convert std::__cxx11::string to regular std::string, but googling I can't find a way to do this and putting (string) in front does not work.
If I do not convert I get linker errors like this:
undefined reference to `H5::CompType::insertMember(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, H5::DataType const&) const'
Is it possible that you are using GCC 5?
If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.
Source: GCC 5 Release Notes/Dual ABI
Defining the following macro before including any standard library headers should fix your problem: #define _GLIBCXX_USE_CXX11_ABI 0
If you can recompile all incompatible libs you use, do it with compiler option
-D_GLIBCXX_USE_CXX11_ABI=1
and then rebuild your project. If you can't do so, add to your project's makefile compiler option
-D_GLIBCXX_USE_CXX11_ABI=0
The define
#define _GLIBCXX_USE_CXX11_ABI 0/1
is also good but you probably need to add it to all your files while compiler option do it for all files at once.
When I had similar issue it's happened because my lib was build using clang++, and it's linked to libstdc++.so by default on my system. While app binary was build using clang and linked with -lc++ option.
Easiest way to check dependencies is to perform ldd libName.so
To fix it you should use the same library on in app and library.
Easiest way. Build library using clang++ and compile app using clang++. Without extra linking options on both steps. Default stdlib will be used.
Build library with -stdlib=c++ and compile app with -lc++. In this case both library and app will use libc++.so.
Build library without extra options and link binary to -lstdc++. In this case both library and app will use libstdc++.so.
Answers here mostly focus on short way to fix it, but if that does not help, I'll give some steps to check, that helped me (Linux only):
If the linker errors happen when linking other libraries, build those libs with debug symbols ("-g" GCC flag)
List the symbols in the library and grep the symbols that linker complains about (enter the commands in command line):
nm lib_your_problem_library.a | grep functionNameLinkerComplainsAbout
If you got the method signature, proceed to the next step, if you got no symbols instead, mostlikely you stripped off all the symbols from the library and that is why linker can't find them when linking the library. Rebuild the library without stripping ALL the symbols, you can strip debug (strip -S option) symbols if you need.
Use a c++ demangler to understand the method signature, for example, this one
Compare the method signature in the library that you just got with the one you are using in code (check header file as well), if they are different, use the proper header or the proper library or whatever other way you now know to fix it
I got this, the only way I found to fix this was to update all of mingw-64 (I did this using pacman on msys2 for your information).
For me -D_GLIBCXX_USE_CXX11_ABI=0 didn't help.
It works after I linked to C++ libs version instead of gnustl.
I had a similar issue recently while trying to link with the pre-built binaries of hdf5 version 1.10.5 on Ubuntu 16.04. None of the solutions suggested here worked for me, and I was using g++ version 9.1. I found that the best solution is to build the hdf5 library from source. Do not use the pre-built binaries since these were built using gcc 4.9! Instead, download the source code archives from the hdf website for your particular distribution and build the library. It is very easy.
You will also need the compression libraries zlib and szip from here and here, respectively, if you do not already have them on your system.
In my case, I was having a similar problem:
/usr/bin/ld: Bank.cpp:(.text+0x19c): undefined reference to 'Account::SetBank(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: error: ld returned 1 exit status
After some researches, I realized that the problem was being generated by the way that Visual Studio Code was compiling the Bank.cpp file. So, to solve that, I just prompted the follow command in order to compile the c++ file sucessful:
g++ Bank.cpp Account.cpp -o Bank
With the command above, It was able to linkage correctly the Header, Implementations and Main c++ files.
OBS: My g++ version: 9.3.0 on Ubuntu 20.04
I've encountered similar problems
It turns out my project was using gcc 7 and g++ 9 and tried to link together object files compiled by those two and it all messed up.
Make sure you use the same compiler versions in all your project.
I am recently writing a kernel module for osx 10.9, and found out that every symbol in the final binary I compiled is undefined by nm tool.
How is it done by specifying flags in build settings? I mean, when you are building a user mode application, it cant be linked correctly when it has symbols unresolved. I cant find any related flags in command line of building the kext binary.
Just out of cuirosity, where is this flag that tells linker any undefined symbols are ok? I know the --unresolved-symbols flag but it is not found in the build command line.
Moreover, how do I link directly against mach_kernel? Cause I just saw a driver of osx 10.5 which links to macho. Or is it only possible in the old days?
The flag that accomplishes this for a kext is the -Xlinker -kext, it also includes the option -nostdlib because the base standard library is not available to a kext. These rules tell the OSX linker that it doesn't need to resolve all the symbols in the resulting binary.
You don't link directly to the kernel, you rely on the undefined symbols being connected up at kext load time rather than at any other time.
I'm creating an application specifically for the Nintendo Wii using devKitPro. I wanted to make my application modular by offering the ability to load code passed though objcopy -O binary. My problem is, I want the modules to be able to use symbols from the main ELF that is loaded into memory. I have tried various things and I have not come up with any solutions.
I tried use -Map, as I thought that would let me use a linker map with it, but that idea failed.
I also tried compilation into a shared library, but that did not work for me, as the linker complained about "read-only segments with dynamic relocations".
I really need help with this, as I am in neither a Windows or Linux environment.
You may consider doing this using libdl which is made precisely to load symbols by name at runtime. Using libdl you can get handles to all of the functions you want to call as part of an initialization subroutine and then have them available to you when your program needs them. best of all, you dont need to have the library you are linking against at compile time so you can replace it with any elf that has those symbols defined without recompiling.
I am trying to link a number of dynamic libraries into an application and running into problems with g++.
Consider:
libA.so
libB.so depends on libA.so
libC.so depends on libB.so
Application D depends directly on libC.so
If I try to link application D just to libC.so, I get unresolved symbols for the symbols in A and B. I feel as if the compiler should be able to figure it out, and when I use the intel compiler, it does. G++, however, can't figure out the linking. I would like my libraries and executables to only have to link to the things they directly need, not try to anticipate what the libraries they are using need.
I have also had problems when libA.so links to a static library, and when I try to compile the executable I get unresolved symbols from the static library that libA.so was supposed to be using.
I have seen a number of other people ask this and similar questions and get a variety of answers (Linking with dynamic library with dependencies), but the answers are all rather vague, often conflicting, and very much along the lines of "keep on trucking and RTFM".
I get the impression that link order matters. How so, and how do I know what order to link in?
Update
I believe that what is happening is something along the lines of libA.so contains two functions (AA and AB). libB.so needs AA and libC.so needs AB. When libB.so gets linked, g++ gets libA.so, sees that only AA is used, and drops AB. Then when libC.so is linked in, g++ sees that libA.so was already linked and doesn't revisit it, resulting in AB being undefined. I have seen documentation indicating that static libraries work this way, but would the compiler treat dynamic libraries the same way? If so, is there a way to work around it?
(You haven't shown the actual linker error, or provided nearly enough information about the problem, so what follows is partly guesswork...)
If I try to link application D just to libC.so, I get unresolved symbols for the symbols in A and B.
When linking an executable the GNU linker checks that all symbols are available. You can turn that off with --allow-shlib-undefined (to tell GCC to pass that to the linker use -Wl,--allow-shlib-undefined)
It is better not to use that option, but in that case the linker needs to know where to find libA.so and libB.so so it can check that the symbols needed by libC.so will be found. You can do that with the -rpath-link linker option
When using ELF or SunOS, one shared library may require another. This happens when an "ld -shared" link includes a shared library as one of the input files.
When the linker encounters such a dependency when doing a non-shared, non-relocatable link, it will automatically try to locate the required shared library and include it in the link, if it is not included explicitly.
So you should be able to fix the problem by using -Wl,-rpath-link,. to tell the linker to look in the current directory (.) for the libraries libC.so depends on.
I get the impression that link order matters. How so, and how do I know what order to link in?
Yes, link order matters. You should link in the obvious order ;-) If a file foo.cc depends on a library then put the library later in the linker line, so it will be found after processing foo.cc, and if that library depends on another library put that even later, so it will be processed after the earlier library that needs it. If you put a library at the start of the link line then the linker doesn't have any unresolved symbols to look up, so doesn't need to link to that library.
You need to explicitly specify all libraries that you directly use.
During static linking, the dependencies of the loaded .so are not used; when linking the main program, all symbols have to be found in either the main program itself, in a static library specified on the command line, or in a shared library specified on the command line.
This is where you get an error.
When the program is executed, the dependencies of dynamic libraries are loaded so that references from within other shared libraries can be resolved.
By the time the program runs, it might actually be linked (dynamically) against a different version of the shared library. This different version might have different dependencies, so the main program MUST NOT rely on the set of additional libraries that get loaded as dependencies.
This is why the static linker stops you early.