Undefined symbol in a Hackage package `double-conversion` - gcc

I'm trying to build the double-conversion package from Hackage. It builds OK but ghci can't load it. The complaint is:
Loading package double-conversion-0.2.0.0 ... linking ... <interactive>:
/home/me/.cabal/lib/double-conversion-0.2.0.0/ghc-7.0.4/HSdouble-conversion-0.2.0.0.o:
unknown symbol `_ZNK17double_conversion6Double5valueEv'
The nm output shows that the symbol is weak:
nm /home/me/.cabal/lib/double-conversion-0.2.0.0/ghc-7.0.4/HSdouble-conversion-0.2.0.0.o \
| grep _ZNK17double_conversion6Double5valueEv
00000000 W _ZNK17double_conversion6Double5valueEv
This is the only weak symbol in the file, and indeed, as far as I can tell, in the entire world of GHC-compiled packages.
The problematic function is apparently a FFI one, written in C++ and defined inline in double-conversion/src/double.h. It's not the only inline function there, but only this one gets labelled weak.
As a stopgap measure I have moved the function out-of-line, and the package now loads. But there's obviously some problem somewhere in there. Why this function is weak? Why other functions are not? Should ghc complain at weak symbols? Should I file a bug, and if so, who should get it (double-conversion, gcc, ghc, someone else?)
System data: Gentoo Linux, gcc-4.4.5, ghc-7.0.4, cabal-1.10.2.0.

This ticket on GHC Trac looks relevant: Can't use ghci with a library linked against libstdc++. This looks like a Gentoo (or possibly GCC 4.4)-specific problem - the .o file in question doesn't contain any weak symbols on my system (I tested on Ubuntu Natty with GCC 4.5.2 & GHC 7.0.3/7.0.4). I suggest you file a ticket on GHC Trac. Incidentally, I can reproduce #5289.

Related

Why do I get linker errors when I build a CMake project using Drake, but I can clearly see the symbols?

I have followed the Installation and Quickstart instructions, and am writing a CMake project to use Drake.
I'm looking at a unittest that builds in Drake, run it, and it builds, runs, and passes. However, when I try to use some of that functionality in my CMake project, I get a linker error, such as:
undefined reference to `RigidBodyTree<double>::get_position_name(int) const'
If I look at symbols in the Drake shared library (e.g. nm -C or objdump -TC with grep), I see the signature RigidBodyTree<double>::get_position_name[abi:cxx11](int). However, if I look in the produced object code (which causes the linking to fail), I see RigidBodyTree<double>::get_position_name(int).
(Note: This post is a means to migrate from http://drake.mit.edu/faq.html to StackOverflow for user-based questions.)
This is most likely due to an incompatibilty between the compiler used to produce Drake (e.g. clang) and the compiler that CMake has selected (e.g. gcc-4.9). Specifically, gcc-4.9 or before does not tend to handle the DualABI well when linking against clang-compiled code (ref). You may be able to use other functions, because only functions that return an ABI-dependent class (e.g. std::string) are tagged with the ABI that they are using (since they cannot be distinguished in the function signature).
The fix is to change the compiler CMake is using. One way to do this is to set the CC and CXX environment variables to use a supported compiler. For a list of supported compilers, see Supported Configurations. If you are using pre-compiled binaries, please refer to Binary Packages for the compilers used.
WARNING: Do NOT change the compiler using update-alternatives in Ubuntu, as this may affect your DKMS module compatibility with the kernel (among other things) (ref).

Why is it possible to override symbols from some static libraries but not others?

I'm working on a tool that links against Clang, and I need to implement a small number of changes to some operations. To improve development times, instead of rebuilding Clang, I decided to redefine the symbols of interest in my program code, and let the linker take care of the rest: in most cases, the program version of a symbol that is defined in both program code and a static library takes precedence at link-time without a fuss. (The linked answer relates to Linux, but I found that to work on macOS too–usually.)
This worked great when I was using the stock Clang build for macOS that can be downloaded from the LLVM website. However, I am currently trying to switch to my company's customized Clang (which I built once from source, and hoped to further modify in the same way), and now I get duplicate symbol errors.
I don't know what is causing this issue. My project's linker flags have remained unchanged (save for one new static library): importantly, they do not contain -all_load or its -force_load cousin, which tell the linker to try to include every symbol defined in static libraries. The symbols that I'm trying to override look defined the same way when I check them with nm in the stock archive and in the custom archive. The difference has to be with how I built LLVM, but just knowing that doesn't really help me figure out what I need to change.
For instance, say that I want to redefine clang::Qualifiers::getAsString() const. I could do that just fine using the stock LLVM libraries, but now I would get a duplicate symbol error:
duplicate symbol __ZNK5clang10Qualifiers11getAsStringEv in:
.../Objects-normal/x86_64/TypePrinter.o
clang+llvm-internal/lib/libclangAST.a(TypePrinter.cpp.o)
Using nm -f darwin to inspect both archives, I would get very similar results for __ZNK5clang10Qualifiers11getAsStringEv:
# clang+llvm-6.0.0/lib/libclangAST.a
(undefined) external __ZNK5clang10Qualifiers11getAsStringEv
0000000000000bb0 (__TEXT,__text) external __ZNK5clang10Qualifiers11getAsStringEv
# clang+llvm-internal/lib/libclangAST.a
(undefined) external __ZNK5clang10Qualifiers11getAsStringEv
0000000000000d00 (__TEXT,__text) external __ZNK5clang10Qualifiers11getAsStringEv
So, assuming more or less identical symbol definitions, and identical linker flags, why was I able to override static library symbols this way before, and why am I no longer able to?
This part of the premise isn't quite correct:
In most cases, the program version of a symbol that is defined in both program code and a static library takes precedence at link-time without a fuss. (The linked answer relates to Linux, but I found that to work on macOS too–usually.)
The linked answer appears correct, but I originally misunderstood it. The actual behavior, as evidenced by passing -Wl,-why_load to Clang (or -why_load to the linker), goes as follow:
if a symbol is referenced, try to find its definition in the program code.
if it is defined in the program code, you're done; do not search static libraries.
if it is not defined in the program code, look up the .__SYMDEF file in the static library to know which object file has it.
use all the definitions from that object file.
The issue was that switching to the custom Clang, I accidentally pulled in references to symbols that were defined in the same object file as symbols that I am redefining, causing the linker to see both definitions. I was able to solve the problem by using the -why_load argument to the linker, and then looking for which symbol caused the problem object file to be loaded. I then duplicated the definition of that symbol to my program, and now the linker doesn't complain anymore.
The morale of the story is that this technique isn't as reliable on macOS as it is on Linux, and that if you do it, you kind of have to go all in. It's better to take the entire source file and copy it to your project than to try to pick symbols piecewise.
Actually this behavior is the same for Linux, see this reproducer:
First case: build library where symbols are in different object files:
//val.cpp - contains needed symbol
int val=42;
//wrong_main.cpp - contains duplicate symbol
int main(){
return 21;
}
>>> g++ -c val.cpp -o val.o
>>> g++ -c wrong_main.cpp -o wrong.o
>>> ar rcs libsingle.a val.o wrong.o
Linking against this library works, no multiple definition of main-error is issued, because no symbols at all are used from the object file wrong_main.o at all:
//main.cpp
extern int val;
int main(){
return val;
}
>>> g++ main.cpp -L. -lsingle -o works
Second case: both symbols are in the same object file:
//together.cpp - contains both, needed and duplicate, symbols
#include "val.cpp"
#include "wrong_main.cpp"
>>> g++ -c together.cpp -o together.o
>>> ar rcs libtogether.a all.o
Linking against libtogether.a doesn't work:
>>> g++ main.cpp -L. -ltogether -o doesntwork
./libtogether.a(all.o): In function `main':
all.cpp:(.text+0x0): multiple definition of `main'
/tmp/cc38isDb.o:main.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
The linker takes either the whole object file from a static library or nothing. In this case val is needed and so the object file together.o will be taken, but it also contains the duplicate symbol main and thus the linker issues an error.
A great description how the linker works on Linux (and very very similar on MacOS) is this article.

Boost logging - getting unresolved symbol

I am a novice to cmake and boost so this question might be missing something obvious:
I am building a project with cmake on linux (ubuntu) and I am trying to use boost logging in that project. Here is what I do to generate the Makefile:
rm CMakeCache.txt
cmake ../ -DCMAKE_EXE_LINKER_FLAGS="-lboost_log -lboost_log_setup -lpthread -std=c++11" -DCMAKE_SHARED_LINKER_FLAGS="-lboost_log_setup -lboost_log -lpthread" -DCMAKE_MODULE_LINKER_FLAGS="-lboost_log_setup -lboost_log -lpthread" -DCMAKE_CXX_FLAGS="-DBOOST_LOG_DYN_LINK -std=c++11"
Compile goes through fine. (Some of these flags may be overkill -- I should only need the CMAKE_EXE_LINKER_FLAGS).
When I run the executable, I get the following unresolved reference:
-- ImportError: /home/mranga/gr-msod-sensor/gr-msod_sensor/build/lib/libgnuradio-msod_sensor.so: undefined symbol: _ZN5boost3log11v2_mt_posix3aux25unhandled_exception_countEv
What flags am I missing? My boost library is set up and LD_LIBRARY_PATH points to the right location.
When I manually built a test program using the same linker flags, it compiles and runs fine so boost is installed correctly. I hope I have not missed the obvious.
(Moved question from the GNU Radio mailing list -- sorry if you are reading this post for a second time).
I believe the order of libraries in the linker command line in -DCMAKE_EXE_LINKER_FLAGS is incorrect. boost_log_setup depends on boost_log, so boost_log_setup should go first.
You seem to be linking against the non-multithreaded version:
-lboost_log
but the run-time linker seems to explicitely look for the multithreaded variant (the Boost doc site on that):
_ZN5boost3log11v2_mt_posix3aux25unhandled_exception_countEv
^^
My guess hence is that you should try linking with
-lboost_log_mt
but the question whether that is right or not depends too much on your individual project to make it possible for me to clearly answer this.

Haskell package missing c library

I'm having trouble building the hmatrix library on OS X Lion. Looking at the .cabal file, it requires the gsl library, so I installed it with macports. The .a files are in /opt/local/lib and the .h files are in /opt/local/include/gsl
As suggested here I changed the built-type from Custom to Simple. (without that change I get a similar error).
When I use cabal configure I get the following output:
* Missing C library: gsl
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
So I tried cabal --extra-include-dirs=/opt/local/include --extra-lib-dirs=/opt/local/lib configure, but I still get the same error. I can compile and link a c program that includes gsl. What files is cabal looking for? If I have the right files, how do I tell it how to find them?
libgsl.a is a universal binary:
$ file /opt/local/lib/libgsl.a
/opt/local/lib/libgsl.a: Mach-O universal binary with 2 architectures
/opt/local/lib/libgsl.a (for architecture x86_64): current ar archive random library
/opt/local/lib/libgsl.a (for architecture i386): current ar archive random library
ghc looks like it's 64-bit:
$ ghc --info
[("Project name","The Glorious Glasgow Haskell Compilation System")
,("GCC extra via C opts"," -fwrapv")
,("C compiler command","/usr/bin/llvm-gcc")
,("C compiler flags"," -m64 -fno-stack-protector -m64")
,("ar command","/usr/bin/ar")
,("ar flags","clqs")
,("ar supports at file","NO")
,("touch command","touch")
,("dllwrap command","/bin/false")
,("windres command","/bin/false")
,("perl command","/usr/bin/perl")
,("target os","OSDarwin")
,("target arch","ArchX86_64")
,("target word size","8")
,("target has GNU nonexec stack","False")
,("target has subsections via symbols","True")
,("Project version","7.4.2")
,("Booter version","7.4.2")
,("Stage","2")
,("Build platform","x86_64-apple-darwin")
,("Host platform","x86_64-apple-darwin")
,("Target platform","x86_64-apple-darwin")
,("Have interpreter","YES")
,("Object splitting supported","NO")
,("Have native code generator","YES")
,("Support SMP","YES")
,("Unregisterised","NO")
,("Tables next to code","YES")
,("RTS ways","l debug thr thr_debug thr_l thr_p dyn debug_dyn thr_dyn thr_debug_dyn")
,("Leading underscore","YES")
,("Debug on","False")
,("LibDir","/usr/local/Cellar/ghc/7.4.2/lib/ghc-7.4.2")
,("Global Package DB","/usr/local/Cellar/ghc/7.4.2/lib/ghc-7.4.2/package.conf.d")
,("Gcc Linker flags","[\"-m64\"]")
,("Ld Linker flags","[\"-arch\",\"x86_64\"]")
]
As an alternative to mac-ports you can use the nix package manager for mac. It does a pretty good job of taking care of the c dependancies for for the libraries available through it. In general I have been more happy with it then any other package manager on mac.
Unfortunately mac(darwin) unlike for linux does not have as many binaries available through nix so installing ghc often means waiting for it to compile.
The commands to install ghc and hmatrix after installation of nix are:
nix-env -iA nixpkgs-unstable.haskellPackages.ghc
nix-env -iA nixpkgs-unstable.haskellPackages.hmatrix
All of the needed dependencies will be taken care of for you.
I just tried it on my macbook pro and hmatrix seems to be working correctly in ghci after trying commands from the first few pages of the tutorial.
I'm not a mac person, but it really sounds like you haven't installed the "-dev" version. For a mac, I suspect you need to install gsl-devel in addition to gsl. If the problem persists, verify that you have libgsl0-dev on your library path.

Why does the mingw g++ compiler result in wrong linking result?

I have some (larger) code developped under linux. Once I realized I would need it under windows I installed a cross compiler under linux and all went well.
Now the code should be managed futher without the need of the virtual machine. Therefore I installed mingw and tried to compile the code under windows.
I get a DLL without any warnings or similar.
But:
As soon as I tried to use the DLL (bind it in Matlab) I get an error about a module that could not be found. Using Dependency walker I get an error about
At least one module has an unresolved import due to a missing export function in an implicitly dependent module.
I saw, that e.g. the function InterlockedDecrement from the kernel32.dll is red (missing). In the mingw installation I find a libkernel32.a that has two functions according to this function (output from nm):
00000000 T _InterlockedDecrement#4
00000000 I __imp__InterlockedDecrement#4
That looks quite good so far. In c:\Windows\System32\kernel32.dll there is a function InterlockedDecrement according to pexport.
So my question is: Where is this error coming from? What do I do wrong?

Resources