Why can't ld called from MSYS find (existing static) library when arguments are read from a response #file containing backslashes? - path

This is basically the same issue as in mingw ld cannot find some library which is exist in the search path, MinGW linker can't find MPICH2 libraries - and I'm aware that there are heaps of posts on StackOverflow regarding the issue of static and dynamic linking with MinGW - but I couldn't find anything that explains how I can troubleshoot.
I am building a project with a huge linker command like (via g++) on MinGW, in a MSYS2 shell (git-bash.exe). The process fails with, among others:
/z/path/to/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lssl
I add -Wl,--verbose to the g++ linker call (to be passed to ld), and I can see for the -L/z/path/to/libs/openssl/lib/mingw -lssl:
...
attempt to open /z/path/to/libs/openssl/lib/mingw/libssl.a failed
...
/z/path/to/libs/openssl/lib/mingw/ssl.dll failed
attempt to open /z/path/to/libs/openssl/lib/mingw\libssl.a failed
...
But this is weird, because the file exists?
$ file /z/path/to/libs/openssl/lib/mingw/libssl.a
/z/path/to/libs/openssl/lib/mingw/libssl.a: current ar archive
(... and it was built with the same compiler on the same machine)?
Weirdly, once it attempts to open with forward slash .../libssl.a, once with backslash ...\libssl.a - but at least the first path checks out in a bash shell, as shown above?
It gets even worse if I try to specify -l:libssl.a -- or if I specify -L/z/path/to/libs/openssl/lib/mingw -Wl,-Bstatic -lssl -- instead; then all attempts to open are with a backslash:
...
attempt to open /z/path/to/scripts/other/build/openssl/build/mingw/lib\libssl.a failed
attempt to open /z/path/to/libs/openssl/lib/mingw\libssl.a failed
...
To top it all off, if I look it up manually through the command line using ld, it is found ?!:
$ ld -L/z/path/to/libs/openssl/lib/mingw -lssl --verbose
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.dll.a failed
attempt to open Z:/path/to/libs/openssl/lib/mingw/ssl.dll.a failed
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
Does anyone have an idea why this happens, and how can I get ld to finally find these libraries? Or rather - how can I troubleshoot, and understand why these libraries are not found, when they exist at the paths where ld tries to open them?
OK, found something more - not sure if this is a bug; but my problem is that I'm actually reading arguments from a file (otherwise I get g++: Argument list too long). So, to simulate that:
$ echo " -Wl,--verbose -L/z/path/to/libs/openssl/lib/mingw -lssl -lcrypto " > tmcd3
$ g++ #tcmd3 2>&1 | grep succeeded | grep ssl
# nothing
$ g++ `cat tcmd3` 2>&1 | grep succeeded | grep ssl
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
attempt to open Z:/path/to/libs/openssl/lib/mingw/libcrypto.a succeeded
... it turns out, if the very same arguments are fed on the command line, then static library lookup succeeds - but if the arguments are read from file through the # at-sign, then static library lookup fails?! Unfortunately, I cannot use on my actual project, since even with cat, I'd still get g++: Argument list too long ... So how can I fix this?

MSYS has special handling of directories as arguments when they are used in the shell. This translates e.g. /<drive_letter>/blabla to the proper Windows style paths. This is to accomodate Unix programs that don't handle Z: style directory root.
What you see here is that MSYS isn't performing this interpretation for string read from a file. When you think about it, it's very logical, but as you have experienced first-hand, also sometimes annoying.
Long story short: don't put Unix style paths in files with command arguments. Instead, pass them through e.g. cygpath -w, which works in MSYS2 (which should be the MSYS that Git for Windows 2+ comes with).

Ok, with some more experiments, I noticed that:
-L/z/path/to/libs/openssl/lib/mingw, the Unix path specification, tends to fail - while if we specify the same, except starting with a Windows drive letter, that is:
-LZ:/path/to/libs/openssl/lib/mingw, then things work - also from an arguments file with # at-sign:
$ echo " -Wl,--verbose -LZ:/path/to/libs/openssl/lib/mingw -lssl -lcrypto " > tmcd3
$ g++ #tcmd3 2>&1 | grep succeeded | grep ssl
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
attempt to open Z:/path/to/libs/openssl/lib/mingw/libcrypto.a succeeded
I guess, since the shell is MSYS2/git-bash.exe, entering full POSIX paths on the shell with /z/... is not a problem, because the shell will convert them - but in a file, there is nothing to convert them, so we must use Windows/MingW convention to specify them...

Related

stat method not found in libc.so.6

Using Dart FFI I'm trying to dynamically load the linux/posix 'stat' function.
I've assumed that the function is in the libc.so.6 library but when I attempt to load it I get the error:
Invalid argument(s): Failed to lookup symbol (/lib/x86_64-linux-gnu/libc.so.6: undefined symbol: stat)
I'm successfully loading other functions from the libc.so.6 library so my dynamic loading technique is working correctly.
I have two theories:
stat is a macro for xstat and as such stat no longer exists.
stat is in another library that I've not been able to groc.
Ideally I want to use stat rather than xstat as I need this code to also work on osx which as far as I can tell doesn't support xstat.
Help?
I have two theories:
There is no need to theorize: you can just look:
echo "#include <sys/stat.h>" | gcc -xc - -E -dD | less
nm -AD /lib/x86_64-linux/gnu/*.so* | grep ' stat$'
will tell you everything you need to know (your first theory is correct).
I want to use stat rather than xstat
You can't: it doesn't exist (when using GLIBC).
I need this code to also work on osx which as far as I can tell doesn't support xstat.
Your code can detect the platform it's running on and adjust. This is the price of using non-portable mechanisms, such as FFI.

libtool error: only absolute run-paths are allowed

Getting this error during "make" in mpich
GEN lib/libmpi.la
libtool: error: only absolute run-paths are allowed
Compiler being used is clang (the code builds fine with gcc). Any idea what this error could be due to?
Here is the configure command:
./configure '--prefix=$PWD/BIN' '--with-device=ch3:nemesis:mxm' '--with-mxm=/home/xyz/software/hpcx-v1.9.5-gcc-inbox-redhat7.3-x86_64/mxm' '--disable-spawn' '--disable-ft-tests' '--enable-g=all' '--enable-nemesis-dbg-localoddeven' '--enable-large-tests' '--disable-perftest' 'CC=clang' 'CXX=clang++' 'FC=gfortran' 'F77=gfortran' --cache-file=/dev/null --disable-fortran
I think the issue is the evaluation of $PWD within the quotes. If you replace
./configure '--prefix=$PWD/BIN' ...
with
./configure --prefix=$PWD/BIN ...
you should be good.
I ran into this error as well when building a different piece of software. The solution for me was to enclose the shell variable in --prefix= with {}:
./configure --prefix=${PWD}/BIN

ld cannot find OCCI libraries even if they exist in LD_LIBRARY_PATH

I am just doing some simple OCCI thing, however it compiles a bit strangely
Environment:
Oracle VM: Centos7 64bit on Windows 8 64bit
gcc-c++.x86_64
Simply installed Oracle XE by double clicking the rpm (download pages says
linux 64bit)
echo $LD_LIBRARY_PATH yields:
/usr/local/lib64/:/u01/app/oracle/product/11.2.0/xe/lib/
I also tried export LD_LIBRARY_PATH=/u01/app/oracle/product/11.2.0/xe/lib/
so that it yields
/u01/app/oracle/product/11.2.0/xe/lib/
some listing command:
find /u01/app/oracle/product/11.2.0/xe/lib/ -name lib*
yields the following:
/u01/app/oracle/product/11.2.0/xe/lib/
/u01/app/oracle/product/11.2.0/xe/lib/libagtsh.so.1.0
/u01/app/oracle/product/11.2.0/xe/lib/libcell11.so
/u01/app/oracle/product/11.2.0/xe/lib/libclntsh.so.11.1
/u01/app/oracle/product/11.2.0/xe/lib/libnnz11.so
/u01/app/oracle/product/11.2.0/xe/lib/libocci.so.11.1
/u01/app/oracle/product/11.2.0/xe/lib/libclntsh.so
/u01/app/oracle/product/11.2.0/xe/lib/libocci.so
/u01/app/oracle/product/11.2.0/xe/lib/libagtsh.so
and some others....
however the compile command says ld cannot find some libraries:
g++ -o ab -I/u01/app/oracle/product/11.2.0/xe/rdbms/public/ -lnnz11 -lclntsh -locci a.cpp
/usr/bin/ld: cannot find -lnnz11
/usr/bin/ld: cannot find -lclntsh
/usr/bin/ld: cannot find -locci
collect2: error: ld returned 1 exit status
I have tried adding -L/u01/app/oracle/product/11.2.0/xe/lib/, it successfully compiles however running the program will cause it silently crashes / blocks at the simple line
Environment *env = Environment::createEnvironment();
no exceptions caught.
Does anyone know some part I did wrong? or are the two issues related?
And by the way, it USED to work like 5 hours ago, when it suddenly stopped working I reinstalled the whole VM and now it still doesn't work.
however the compile command says ld cannot find some libraries: g++ -o ab -I/u01/app/oracle/product/11.2.0/xe/rdbms/public/ -lnnz11 -lclntsh -locci a.cpp
Your command is incorrect (and the linker is right to complain). You need to tell the linker where to find the library, and you do that with -L flag:
ORACLE=/u01/app/oracle/product/11.2.0/xe
g++ -I ${ORACLE}/rdbms/public -L ${ORACLE}/lib a.cpp -lnnz11 -lclntsh -locci
(Note that your placement of source after library is also incorrect, and I fixed it above. Placement of libraries and sources on link command line matters.)

ERROR while code coverage report using lcov

I am trying to run coverage on my project, after updating to Ubuntu 16.04.
I get
Deleted 665 files
Writing data to coverage.info.cleaned
lcov: ERROR: cannot write to coverage.info.cleaned!
CMakeFiles/coverage.dir/build.make:57: recipe for target 'CMakeFiles/coverage' failed
make[3]: *** [CMakeFiles/coverage] Error 13
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/coverage.dir/all' failed
make[2]: *** [CMakeFiles/coverage.dir/all] Error 2
CMakeFiles/Makefile2:74: recipe for target 'CMakeFiles/coverage.dir/rule' failed
make[1]: *** [CMakeFiles/coverage.dir/rule] Error 2
Makefile:129: recipe for target 'coverage' failed
make: *** [coverage] Error 2
enter code here
Before the update I had no problem running the coverage
Does it help if you use absolute paths instead of relative paths when passing files to lcov?
I ran into a similiar problem where lcov also failed to write the file.
Not sure if it is a bug in lcov, but the problem was that it got confused with relative paths:
lcov -a test_fast_cxxtest_gcov__base.info -a test_fast_cxxtest_gcov__test.info \
-o test_fast_cxxtest_gcov__total.info
Combining tracefiles.
Reading tracefile test_fast_cxxtest_gcov__base.info
Reading tracefile test_fast_cxxtest_gcov__test.info
lcov: WARNING: function data mismatch at /home/phil/ghost/constants.h:1862
Writing data to test_fast_cxxtest_gcov__total.info
lcov: ERROR: cannot write to test_fast_cxxtest_gcov__total.info!
Running it with strace revealed that it executes chdir("/") on several locations, which changes the working directory to /. That explains why it cannot write the file.
One workaround is to use absolute paths. For instance, if you are using GNU make, you can use the abspath command:
lcov -a $(abspath test_fast_cxxtest_gcov__base.info) \
-a $(abspath test_fast_cxxtest_gcov__test.info) \
-o $(abspath test_fast_cxxtest_gcov__total.info)
After that change, it was finally able to write the file.
(Other options like trying to set the directories using the --base-directory or --directory option did not have an effect, as far as I saw.
The version of lcov that I tested with is 1.12.)
The problem is not limited to Ubuntu, as I ran into it on Arch Linux. It could be a regression introduced in 1.12, however, so I reported it (see issue #77630).
Update: Lcov is not part of GCC, so my original bug report was closed, but I got an answer from the Lcov mailing list. The problem is already fixed in commit 632c25. Users of Arch Linux based distros can try the latest snapshot with aur/lcov-git.

Enabling the gold linker on Freebsd

I have been trying to enable the gold linker on FreeBSD to use the link time optimizations. I made gold from the binutils under /usr/ports. After building binutils using make -k install clean i got ld under /usr/bin and in the directory /usr/local/bin i got ld, ld.gold and ld.bfd.
Now while trying to use link time optimization for the simple example programs here http://llvm.org/docs/GoldPlugin.html (a.c and b.c under the heading 'Examples of Link Time Optimization') i entered the four commands as follows:
clang -flto a.c -c -o a.o
ar q a.a a.o
clang b.c -c -o b.o
clang -flto a.a b.o -o main
I got the following error:
usr/bin/ld: unrecogonized option '-plugin'
usr/bin/ld: use the --help option for usage information
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Is there the problem with the linker that ld.gold is not being called. Should I replace the ld with ld.gold? Does the linker looks in the right directiry for the .so plugins?
The LLVMgold.so and libLTO.so shared objects are in the directory /usr/local/llvm-devel/lib/.
I cannot find the directory where clang is installed. I am not sure where to make the bfd-plugins directory and add the symlinks to LLVMgold.so and libLTO.so.
I am using freebsd 10.1 release. How to enable the gold linker for link time optimizations?
also how can I enable it to be the default linker?
You may want to use ld.gold instead of ld. It is installed at /usr/local/bin/ld.gold. If you are using a Makefile, it would work by setting LD variable to ld.gold, either by modifying your Makefile or specifying it on command line. Example in case you are using lang/clang37:
gmake all CC=clang37 LD=ld.gold
EDIT:
It would be even more neat if you add -fuse-ld=gold to your LDFLAGS:
LDFLAGS=-fuse-ld=gold
I'm not sure ld.bfd allows plugins, but I could be wrong.
Your /usr/bin/ld should be a symlink to whatever linker you want. You can change which linker is used by using binutils-config. Check the man-page here: http://www.linuxhowtos.org/manpages/8/binutils-config.htm. I realise this is a Linux link, but it's directed at binutils itself rather than linux-specifically.
It should be something along the lines binutils-config --gold.
On my Gentoo box it is binutils --linker=gold
EDIT: As pointed out, binutils-config doesn't work on BSD it seems. You can still manually update the symlinks though, the downside is that there might be a few of them.
You can find out which ld is used by your compiler by using gcc -print-prog-name=ld or clang -print-prog-name=ld. The file printed should be a symlink you can re-create to point to ld.gold as oposed to ld.bfd.

Resources