musl fails to link libc.a into shared library - linux

I have a C99 shared library that I want to link in a few statically static libraries (via --whole-archive). Note: All the static libs are built with -fPIC
I also would like to build a universal linux binary and thus have decided to use musl. When I try to link in the static libc.a from musl I get the following error:
# Building shared library tgt/Linux-x86_64/mylib/lib/mylib.so
/root/mylib/./tgt/Linux-x86_64/libmusl/bin/musl-gcc -Wl,-whole-archive -L./tgt/Linux-x86_64/libmusl/lib -L./tgt/Linux-x86_64/libz/lib -L./tgt/Linux-x86_64/libssl/lib -L./tgt/Linux-x86_64/libsasl/lib -L./tgt/Linux-x86_64/librdkafka/lib -L./tgt/Linux-x86_64/libcurl/lib -L./tgt/Linux-x86_64/libgjalloc/lib -L./tgt/Linux-x86_64/libavro/lib -L./tgt/Linux-x86_64/libunwind/lib -l:libc.a -l:libpthread.a -l:libz.a -l:libssl.a -l:libcrypto.a -l:libsasl2.a -l:libm.a -l:librt.a -l:libcrypt.a -l:libunwind-x86_64.a -l:librdkafka.a -l:libcurl.a -l:libgjalloc.a -l:libavro.a -Wl,-no-whole-archive -shared -fPIC -o tgt/Linux-x86_64/mylib/lib/mylib.so ./tgt/Linux-x86_64/mylib/obj/myfile.o ./tgt/Linux-x86_64/mylib/obj/myotherfile.o ./tgt/Linux-x86_64/mylib/obj/cJSON.o
/usr/bin/ld: ./tgt/Linux-x86_64/libmusl/lib/libc.a(exit.lo): relocation R_X86_64_PC32 against undefined hidden symbol `__fini_array_start' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [tgt/Linux-x86_64/mylib/lib/mylib.so] Error 1
My musl build looks like:
cd mystatic_libs_build_dir/musl; \
./configure CFLAGS='-fPIC' \
--enable-shared \
--enable-static \
--prefix=/root/mylib/tgt/Linux-x86_64/libmusl; \
make; make install;
# libmusl is available

exit.lo will be written in assembler which is why your CFLAGS='-fPIC' is not having the effect you intend. This is either 1. a bug in 'musl' or 2. intentional and they do not support statically linking into .so's.
I would assume that it is unintentional and file a bug against 'musl'
You could also edit the asm yourself if you need a fix quickly.
Finally you might be able to configure musl to build with no asm?
Slightly off topic, but other options for a universal binary are:
Simply linking against glibc on the oldest version of Linux that you support.
Rather than struggling with a dependency on 'musl', simply use the Linux kernel api's directly.

Recompile musl as long as your own code with CFLAGS="-fPIC -Wa,-mrelax-relocations=no" (your binutils version must be >=2.27).

Related

Is it possible to compile a standalone Fortran executable in Linux?

For example, consider that I wrote a Fortran program in one computer and want to run it on another computer which may not have required libraries and/or has a different compiler (or even better, no Fortran compiler at all). Is it possible to create an executable with all its dependencies?
I am using gfortran (7.2.1) in Fedora 26 and sometimes use LAPACK routines in my code.
Using -static option with the program
program main
write (*,*) 'Hello'
end
I get the output
gfortran -static a.f90
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
There is no error with gfortran -static-libgfortran a.f90
In Fedora, gcc does not ship by default with static libraries.
You need to install the package glibc-static for the -static option to work, as hinted in this related question.
Note that -static-libgfortran will only do static linking of the libgfortran library and that you must have static versions of your dependencies as well.
The best option is to use Alpine Linux that uses musl libc. I highly recommend using the docker image (only 5 Mb).

DMD2 fails to compile shared library on Linux, amd64

I've been programming on a 32 bit machine, until recently, I upgraded to a 64 bit one. I'm using the latest version of DMD (amd64), on xubuntu 16.04 (amd64).
Before the upgrade, I could easily compile shared libs using dmd -shared 'FILES', but now, it gives an error.
I have a file named q.d:
module q;
export extern(C) int abcd(){
return 4;
}
And now when I do dmd -shared 'q.d', I get this:
nafees#OptiPlex-755:~/Desktop/temp$ dmd -shared q.d
/usr/bin/ld: q.o: relocation R_X86_64_32 against `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC
q.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
--- errorlevel 1
and when I do dmd -shared -fPIC q.d:
nafees#OptiPlex-755:~/Desktop/temp$ dmd -shared -fPIC q.d
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(exception_224_3b4.o): relocation R_X86_64_32 against `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC
/usr/lib/x86_64-linux-gnu/libphobos2.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
--- errorlevel 1
How can I get it to compile?
EDIT: The library compiles fine if I use the -m32 flag.
Oh, I just realized I know this problem, sorry it took me so long to realize it though.
You just need to compile against the shared lib Phobos as well to make the shared lib on 64 bit.
dmd -shared q -m64 -fPIC -defaultlib=libphobos2.so
The -defaultlib switch tells it to use an alternate library. By specifying the .so (as opposed to the default static link with a .a file), it uses the shared lib - which happens to be compiled with -fPIC too, so it is all compatible.
Among other advantages here is that one runtime can be shared across all the shared objects and D executables, which means a lot of things just work when you distribute them all (though note you may also need to compile the program that loads this so with the -defaultlib switch too). On 32 bit, the library isn't built with these options regardless... but the result is you can see link errors for multiple definitions in some circumstances.
The one thing to be careful though is that libphobos2.so file is now a runtime dependency too, be sure to distribute it with your own library builds together. You might need to set the LD_LIBRARY_PATH or install it globally for the program to start up correctly, just like any other library (and you might want to version it too btw)

boost coroutine and asio test build failed on linux x64 platform with gcc4.7

I try to build the example code provide by boost asio example:
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp
I copy all the code and put it into a cpp file, compile it on linux with gcc4.7 and cmake, link with boost coroutine and boost context library, but the link is failed.
The output is list below:
Linking CXX executable ../../../output/bin/unit_test
cd /home/watson/ID_project/build/server_linux_makefile_gcc/abc/test/unit/abc_async && /usr/local/bin/cmake -E cmake_link_script CMakeFiles/unit_test.dir/link.txt --verbose=1
/usr/bin/c++ -std=c++11 -O3 -DNDEBUG -pthread -lrt -ltcmalloc -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free CMakeFiles/unit_test.dir/TestFileChannel.cpp.o CMakeFiles/unit_test.dir/TestStreamBuffer.cpp.o CMakeFiles/unit_test.dir/TestTimer.cpp.o CMakeFiles/unit_test.dir/TestThreadPool.cpp.o CMakeFiles/unit_test.dir/TestScheduler.cpp.o CMakeFiles/unit_test.dir/PCH.cpp.o CMakeFiles/unit_test.dir/main.cpp.o CMakeFiles/unit_test.dir/TestUDPNetwork.cpp.o CMakeFiles/unit_test.dir/TestTCPNetwork.cpp.o -o ../../../output/bin/unit_test -rdynamic ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_unit_test_framework-gcc47-mt-1_54.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_context-gcc47-mt-1_54.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_coroutine-gcc47-mt-1_54.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_thread-gcc47-mt-1_54.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_filesystem-gcc47-mt-1_54.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libyaml-cpp.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libmongoc.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_system-gcc47-mt-1_54.a ../../../../../../install/thirdparty_linux_makefile_gcc/lib/libprotobuf.a
../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_coroutine-gcc47-mt-1_54.a(coroutine_context.o): In function `boost::coroutines::detail::coroutine_context::coroutine_context(void (*)(long), boost::coroutines::stack_context*)':
coroutine_context.cpp:(.text+0x103): undefined reference to `make_fcontext'
../../../../../../install/thirdparty_linux_makefile_gcc/lib/libboost_coroutine-gcc47-mt-1_54.a(coroutine_context.o): In function `boost::coroutines::detail::coroutine_context::jump(boost::coroutines::detail::coroutine_context&, long, bool)':
coroutine_context.cpp:(.text+0x1bc): undefined reference to `jump_fcontext'
collect2: error: ld returned 1 exit status
make[2]: *** [abc/output/bin/unit_test] Error 1
I print the symbol table from the .a file, and find the symbol jump_fcontext' andmake_fcontext' is existed:
nm libboost_context-gcc47-mt-1_54.a
make_x86_64_sysv_elf_gas.o:
U _GLOBAL_OFFSET_TABLE_
U _exit
000000000000002e t finish
0000000000000000 T make_fcontext
jump_x86_64_sysv_elf_gas.o:
0000000000000000 T jump_fcontext
Someone can give me any tips about it? I try google every place but without information.
Try swapping the linking order of boost_context and boost_coroutine.
The linker documentation states:
[...] the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
In this case
Boost.Coroutine depends on Boost.Context. As such, boost_coroutine should appear before boost_context when linking. For more linker ordering details, consider reading this answer.
Just to add another possibility for this (specifically with the Boost Context library) - if building under MinGW on Windows, using an earlier version of MASM can produce static libraries that contain no linkable symbols due to the way the symbols are exported.
The solution is to rebuild Boost Context with MASM 8.
See the answer at https://stackoverflow.com/a/26874113/1678468 for more about this.

create position independent object file from LLVM bit code

I have a llvm module that i've dumped as bitcode file with llvm::WriteBitcodeToFile. I want to turn this bitcode file into an native dynamically loadable library that contains the functions in the module.
How do i do this? i tried using llc for this, but this produces code that apparently is not relocatable, since after doing the following steps:
llc -enable-pie -cppgen=functions -filetype=asm executableModule -o em.s
then, assemblying with gnu as into an object file:
as -o mylib.o em.s
finally, trying to produce a shared library with:
gcc -shared -o libmyfile.so -fPIC mylib.o
fails with the error:
/usr/bin/ld: error: mylib.o: requires dynamic R_X86_64_PC32 reloc against 'X.foo' which may overflow at runtime; recompile with -fPIC
collect2: ld returned 1 exit status
You need to setup relocation model. Something like -llc -relocation-model=pic. Do not use PIE, because it's for executables, not for libraries. Also, -cppgen does not make any sense here, it's for cpp backend only.

error Compile shared libraries with -fPIC

While I run snmpd daemon on powerpc board(a.p.) I am getting this error:
R_PPC_REL24: Compile shared libraries with -fPIC!
/usr/local/sbin/snmpd: symbol 'strlen': can't handle reloc type 0xa in lib
/lib/libnetsnmpmibs.so.15'
sh: you need to specify whom to kill
I googled and found that the -fPIC flag should be there while compiling and its place should be right after gcc, so I changed my Makefie accordingly. Here is a snippet of my makefile:
$(Q)cd $(PROJECT_BUILD_DIR)/$(NET_SNMP_PKG) && ./configure --target=$(TARGET_TRIPLET) \
--host=$(HOST_TRIPLET) \
--build=$(BUILD_TRIPLET) \
--with-cc="$(CR_COMPLR)gcc -fPIC" \`
--with-cflags="-Os -I$(RFS)/lib -I$(NMS_DIR)/include" \`
--with-linkcc="$(CR_COMPLR)gcc -fPIC" \`
As you can see I embedded -fPIC right after gcc, but I am still getting an error. I have cross compiled for powerpc platform and I am using latest buildroot-2011.11 and gcc 4.3.6 and uClibc version 0.9.32. What may be the cause of error?
P.S. When I do nm libnetsnmpmibs.so.15 | grep strlen then I get output as U strlen. Does this mean it is undefined?
I got the problem. actually the main thing is to compile with -fPIC only.
In my case I was compiling snmp libraries with -fPIC correctly but some of the functions were dependent on libraries of other packages (nms). As I am working on firmware development there are more than 20 packages involved. So I compiled nms libraries with -fPIC and error is resolved.

Resources