How can I generate completely static binaries with clang? I have used the following command:
clang -flto <source files> -o <executable output> -fuse-ld=lld -static-libgcc -lc -Bstatic -m32
And yet, the generated output depends on a certain .so file:
$ ldd <executable output file>
linux-gate.so.1 => (0xf77dd000)
libc.so.6 => /lib/libc.so.6 (0xf75f0000)
/lib/ld-linux.so.2 (0x5663b000)
The following answer tries to answer the question but doesn't directly address the problem.
Is it even possible, to generate completely independent binaries? Or should I have resort to using other different C library implementations other than libgcc?
If yes, then how do I link it with clang if I have the source code, of for example newlib?
Just compile it using the clang's -static flag.
On your case, try:
clang -flto <source files> -o <executable output> -static -m32
The results on my test program show:
[root#interserver ogrerobot.com]# ldd ./CppUtilsSpikes
not a dynamic executable
Related
The C HelloWorld.so (shared object) is created by linking in a C++ myatomic library. That C++ library uses a Boost Header:
myatomic.cpp
...
#include <boost/system/error_code.hpp>
...
Loading HelloWorld.so with dlopen() returns error: _ZTVN10__cxxabiv117__class_type_infoE
If that Boost header is commented-out, then dlopen() succeeds?
HelloWorld.yaml
...
Common:
Sources:
- Folder: src
Files:
- HelloWorld.h
- HelloWorld.c
ConanLibs:
- CONAN_PKG::myatomic
Linux:
CompilerOptions:
- -fPIC
LinkerOptions:
- -lstdc++
Does Boost C++ under linux need to built with specific options? Maybe gcc vs g++ issues?
Added -lstdc++ to HelloWorld linker options but to no avail. :(
A co-worker discovered this fix
If we're interacting with C++ materials (in this case Boost C++), we
need to be using g++. The gcc tool, even if supplied with a bunch of
-lstdc++ args - does not fill the shoes of the g++ compiler, in terms of things like 'linker/loader hints'
The reason for the error _ZTVN10__cxxabiv117__class_type_infoE is the HelloWorld.so (C program) was not loading a runtime dependent (C++ shared object) libstdc++.so.6. For example,
$ ldd HelloWorldBAD.so
linux-vdso.so.1 (0x00007ffc8a5c5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f78cf21f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f78cf431000)
$ ldd HelloWorldGOOD.so
linux-vdso.so.1 (0x00007ffd53bba000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f2540003000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f253fe11000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f253fcc2000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2540205000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f253fca7000)
Edit
It was also found that the ordering of the -lstdc++ option is important. (see also this link)
This command correctly includes the C++ runtime dependencies by placing the -lstdc++ option at the END of the build command
/usr/bin/cc -fPIC -O2 -g -DNDEBUG -shared -Wl,-soname,HelloWorld.so ...Lots of Boost Libraries... -lstdc++
whereas putting the option BEFORE the Boost libraries does not
/usr/bin/cc -fPIC -O2 -g -DNDEBUG -lstdc++ -shared -Wl,-soname,HelloWorld.so ...Lots of Boost Libraries...
I have read this thread on llvm-dev and is faced with the same problem: I cannot link the llvm-ar archieve library with other bitcode files into another single bitcode file with the help of llvm-link.
clang -emit-llvm -g -c -o main.bc main.c
clang -emit-llvm -g -c -o calc.bc calc.c
llvm-ar rcs libcalc.la calc.bc
llvm-link libcalc.la main.bc -o test
the problem is the same: llvm-link complains
llvm-link: libcalc.la:1:2: error: expected integer
!<arch>
^
And after reading How to link object to libraries with LLVM >= 3.1 ? ( no GNU ld ), I also tried a llvm2.9 version of llvm-ld.
llvm-ld --disable-opt libcalc.la main.bc -o test
however libcalc.la is not linked into the module correctly and lli reports:
LLVM ERROR: Program used external function 'Square' which could not be resolved!
So what should i do?
UPDATE
I then read Can't link against static library when compiling objects from LLVM bitcode. and find that llvm-ld WORKS when changing the order:
llvm-ld --disable-opt main.bc libcalc.la -o test
But llvm-link still fails.
llvm-link does not support bitcode archives, AFAIK. It simply goes over the input files it was provided, and tries to parse each one as a bitcode file (either binary or textual LLVM IR).
llvm-ld doesn't exist in the newer LLVMs, so I would suggest to stay away from it completely.
Just link the separate .bc files together with llvm-link. The archiving of bitcode files doesn't have the same benefits for the linker as in native linking anyway.
You don't need archivers to link your bitcode files:
clang -emit-llvm -g -c -o main.bc main.c
clang -emit-llvm -g -c -o calc.bc calc.c
clang main.bc calc.bc -o test
I want to compile C code into one monolithic executable file (include every dependencies in this file) using GCC.
Usually I can compile the code with this command:
gcc -o server ex-serv-x509.c -lgnutls
But when I try to compile it with this -static argument I get this error:
[root#localhost test]# gcc -static -o server ex-serv-x509.c -lgnutls
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
[root#localhost test]#
How I can solve the problem?
Best wishes
Try using the ldd command to see what it's linking in without the -static option. Here's what I get for a silly program I have.
~$ gcc so.o -lm -o so
~$ ldd so
linux-gate.so.1 => (0x00db7000)
libm.so.6 => /lib/libm.so.6 (0x00c7f000)
libc.so.6 => /lib/libc.so.6 (0x0037f000)
/lib/ld-linux.so.2 (0x002da000)
~$ gcc so.o -static -lm -o so
~$ ldd so
not a dynamic executable
So without the static I automagically get the shared version of libc, which surprised me even though it should not have. I imagine you have the shared version but not the static, so you'll need to get the static library from somewhere if you have decided that 1986 is the year for you :-).
To make sure you can do: gcc -print-search-dirs and search through them and make sure that libc.a is not to be found.
I want clang to compile my C/C++ code to LLVM bitcode rather than a binary executable. How can I achieve that?
And if I have the LLVM bitcode, how can I further compile it to a binary executable?
I want to add some of my own code to the LLVM bitcode before compiling to a binary executable.
Given some C/C++ file foo.c:
> clang -S -emit-llvm foo.c
Produces foo.ll which is an LLVM IR file.
The -emit-llvm option can also be passed to the compiler front-end directly, and not the driver by means of -cc1:
> clang -cc1 foo.c -emit-llvm
Produces foo.ll with the IR. -cc1 adds some cool options like -ast-print. Check out -cc1 --help for more details.
To compile LLVM IR further to assembly, use the llc tool:
> llc foo.ll
Produces foo.s with assembly (defaulting to the machine architecture you run it on). llc is one of the LLVM tools - here is its documentation.
Use
clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
If you have multiple source files, you probably actually want to use link-time-optimization to output one bitcode file for the entire program. The other answers given will cause you to end up with a bitcode file for every source file.
Instead, you want to compile with link-time-optimization
clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o
and for the final linking step, add the argument -Wl,-plugin-opt=also-emit-llvm
clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program
This gives you both a compiled program and the bitcode corresponding to it (program.bc). You can then modify program.bc in any way you like, and recompile the modified program at any time by doing
clang program.bc -o program
although be aware that you need to include any necessary linker flags (for external libraries, etc) at this step again.
Note that you need to be using the gold linker for this to work. If you want to force clang to use a specific linker, create a symlink to that linker named "ld" in a special directory called "fakebin" somewhere on your computer, and add the option
-B/home/jeremy/fakebin
to any linking steps above.
If you have multiple files and you don't want to have to type each file, I would recommend that you follow these simple steps (I am using clang-3.8 but you can use any other version):
generate all .ll files
clang-3.8 -S -emit-llvm *.c
link them into a single one
llvm-link-3.8 -S -v -o single.ll *.ll
(Optional) Optimise your code (maybe some alias analysis)
opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
Generate assembly (generates a optimised.s file)
llc-3.8 optimised.ll
Create executable (named a.out)
clang-3.8 optimised.s
Did you read clang documentation ? You're probably looking for -emit-llvm.
I have some scenario like this:
Product-> Platform-> mylibs(version-1)
Product-> mylibs(version-2)
i.e Product uses mylibs (version-2) directly. Product also uses platform (which is also a dynamic lib) and platform uses my libs (version-1).
The names of the libs used by product and platform are same. Only versions are different and both these versions are not compatible.
Is there a way with ".so" libs in linux that Platform can link to one version and product can link to another version of the same libs having the same name?
Note, even changing the names of the libs won't be enough by default, as symbol names would conflict.
Your libs should use soname and versioned symbols, in which case they can even be called the same.
$ make
gcc -shared -fpic -Wl,-soname -Wl,libmylibs.so.1 -Wl,--default-symver -o libmylibs.so.1 mylibs1.c
gcc -shared -fpic -Wl,-soname -Wl,libmylibs.so.2 -Wl,--default-symver -o libmylibs.so.2 mylibs2.c
gcc -shared -fpic -Wl,-soname -Wl,libplatform.so.1 -Wl,--default-symver -Wl,--default-imported-symver -o libplatform.so.1 platform.c libmylibs.so.1
gcc -Wl,-rpath-link -Wl,. -Wl,--default-imported-symver -o program program.c libplatform.so.1 libmylibs.so.2
/usr/bin/ld: warning: libmylibs.so.1, needed by libplatform.so.1, may conflict with libmylibs.so.2
$ LD_LIBRARY_PATH=$PWD ldd ./program
linux-vdso.so.1 => (0x00007fff1e3ff000)
libplatform.so.1 => /tmp/so-4539442/libplatform.so.1 (0x00007f6dc3ba0000)
libmylibs.so.2 => /tmp/so-4539442/libmylibs.so.2 (0x00007f6dc399f000)
libc.so.6 => /lib/libc.so.6 (0x00007f6dc364c000)
libmylibs.so.1 => /tmp/so-4539442/libmylibs.so.1 (0x00007f6dc344b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6dc3da1000)
$ LD_LIBRARY_PATH=$PWD ./program
lib version 2, platform lib version 1