Static linking against external library - go

I'm trying to understand how to build static executable in Go and I need to link it against external library, in my case ORACLE, but the use case is generic. I do the following:
go build -x --ldflags '-s -w -extldflags "-static -L$ORACLE_HOME/lib -lclntsh"'
The compilation phase is fine, but linking part fails to find external lib(s):
/path/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/path/x86_64-redhat-linux-gnu/bin/ld: cannot find -lclntsh
I'm skipping here full path for better readability.
The gcc linker can't see passed -L path and library (in my case -L$ORACLE_HOME/lib -lclntsh).
So, the question is how for any generic case to pass external library path and libs to linker using go build command.

Related

Flags needed to create static binaries in golang

I was building a Docker image using scratch as base.
The following build command:
RUN go build -o /go/bin/myapp
created a binary that kept failing when executed:
standard_init_linux.go:211: exec user process caused "no such file or directory"
By trial and error I found out that I needed to build as follows:
RUN CGO_ENABLED=0 go build -o /go/bin/myapp -a -ldflags '-extldflags "-static"' .
Why are both CGO_ENABLED=0 and -ldflags '-extldflags "-static"' necessary?
Don't both options create static binaries? (i.e. binaries that will need absolutely nothing in terms of libraries from the environments they will run on?)
Just before we start, a heads up by Russ Cox's: Comment
Read this as well: Comment
Yes, I agree with Volker's comment that some systems don't really allow static binaries.
Read on: Compile packages and dependencies
-a
force rebuilding of packages that are already up-to-date.
-ldflags '[pattern=]arg list'
arguments to pass on each go tool link invocation.
Read: go tool link
-extldflags flags
Set space-separated flags to pass to the external linker.
Hence, it tries to rebuild all the packages (dependencies as well) with CGO disabled and also -static means do not link against shared libraries.
Some of the points related to static linking are explained well: Linking golang statically

OpenELEC: Bootstrap GCC with libatomic

I am trying to bootstrap GCC during OpenELEC compilation. I need to add libatomic for the target system so as to compile some packages.
When I try to add libatomic for the target system, I get a compilation error with:
/home/mathieu/tmp/OpenELEC.tv/build.OpenELEC-ci20.mips-8.0-devel/toolchain/mipsel-openelec-linux-gnu/bin/ld: cannot find crti.o: No such file or directory
/home/mathieu/tmp/OpenELEC.tv/build.OpenELEC-ci20.mips-8.0-devel/toolchain/mipsel-openelec-linux-gnu/bin/ld: cannot find -lc
/home/mathieu/tmp/OpenELEC.tv/build.OpenELEC-ci20.mips-8.0-devel/toolchain/mipsel-openelec-linux-gnu/bin/ld: cannot find crtn.o: No such file or directory
collect2: error: ld returned 1 exit status
Using the following package.mk file:
https://github.com/malaterre/OpenELEC.tv/blob/fd5a5558104ed38aee1c53bb6d31ba73e8eb6e57/packages/lang/gcc/package.mk
If that matter I am targetting a MIPS system, specifically the Creator CI20:
https://github.com/malaterre/OpenELEC.tv/blob/master/config/arch.mips
I am not clear about the OpenELEC build system, but it seems as if the host compiler and target compiler are build at the same time, while I would need to build binutils in between:
http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/
You might need to have a GCC built without libatomic to build one with libatomic. The intermediary compiler will serve to build your CRT (if you do not have it already) and libatomic, so that a second compiler can use these "prebuilt" things.
That was not hard at all. Basically one need to create first a minimal gcc (bootstrap) and then build the full one with libatomic:
https://github.com/malaterre/OpenELEC.tv/blob/70dbe25c1647f01eb83c108939c470437a2db259/packages/lang/gcc/package.mk

How to find actual location of library used by linker (gcc)

I have this compile command
qcc -Vgcc_ntoarmv7le -lang-c++ -Wl,-rpath-link,\
C:\Users\mureadr\Desktop\A\QNX_SDK\target\qnx6/armle-v7/lib -Wl,-rpath-link,\
C:\Users\mureadr\Desktop\A\QNX_SDK\target\qnx6/armle-v7/usr/lib -Wl,-O1 -Wl,-rpath,\
C:/fs/mp/qt5/lib -Wl,-rpath,C:/fs/mp/fordhmi/lib -shared -Wl,-soname,libHmiLogging.so.1\
-o libHmiLogging.so.1.0.0 .obj/hmiloggingcategory.o .obj/hmiloggingcategoryregistry.o\
.obj/hmiperformancelogging.o .obj/hmitracelogging.o\
-LC:\Users\mureadr\Desktop\A\QNX_SDK\target\qnx6/armle-v7/lib \
-LC:\Users\mureadr\Desktop\A\QNX_SDK\target\qnx6/armle-v7/usr/lib \
-LC:/Users/mureadr/Desktop/A/HMI_FORGF/qt5binaries/lib -lQt5Core \
-LC:/QNX650/target/qnx6/armle-v7/lib -LC:/QNX650/target/qnx6/armle-v7/usr/lib -lm
When I run it under make, it runs fine but using another build system, I get the error
C:\Users\mureadr\Desktop\A\QNX_SDK\host\win32\x86\usr\bin\ntoarm-ld: cannot find -lQt5Core
cc: C:/Users/mureadr/Desktop/A/QNX_SDK/host/win32/x86/usr/bin/ntoarm-ld caught signal 1
Obviously the other build system doesn't have access to all the included directories.
Question
How can I find out which directory Qt5Core was pulled from?
Is there a linker option that will make it say I got Qt5Core from directory X?
I ran make with --debug=a but I didn't get any info about Qt5Core.
Is there a linker option that will make it say I got Qt5Core from directory X?
Yes. It is -trace. To pass it via gcc, use gcc ... -Wl,-trace....
This will cause the linker to print the name of each input (object file or library) that
it receives from the commandline together with the absolute path where it located
the same.
BTW, passing debug options to make will produce debugging info from make
but none from tools that are invoked by make.

lib specified by LD_PRELOAD can not be loaded

I met some trouble when using LD_PRELOAD to load my so.
The steps are as following:
libtest.c:
void fun()
{
return
}
gcc -o libtest.so libtest.c -fPIC --shared
export LD_PRELOAD=pwd/libtest.so
main.c
extern void fun();
void main()
{
fun()
}
gcc -o main -L. main.c -ltest
Then ldd main
ldd main
linux-vdso.so.1=>(0x00007ffff7ffd000)
/home/shiyanlou/Code/libtest.so(0x00007ffff7df9000)
libtest.so=>not found
libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6 (0x00007ffffa29000)
/lib64/ld-linux-x86-64.so.2 (0x0000555555554000)
execute main ./main
it promotes:
error while loading shared library:libtest.so. cannot open shared object file:No such file or directory.
I wonder that why it prompts that libtest.so cannot be found After I exported LD_PRELOAD variable. However, I also tried to use LD_PRELOAD to specify a different shared lib(not "libc.so") to inject malloc function, it works!
Why LD_PRELOAD only works for the shared lib that was not used when linking???
You need to create 2 versions of the *.so. One which has default behavior and is loaded and hard linked via "-ltest".
Now build your default libtest.so and prove with nm -B the symbol you are expecting to intercept is dynamically linked.
Now build main.c into main.o, then check main.o with nm to also see it has an extern unsatisfied linkage requirement on the symbol.
Now link ./main with main.o and libtest.so and then run it.
The ./main needs to run with this copy by default, demonstrate the default behavior and also show the correct path to the correct DSO via ldd command.
...
Now you take the step to create the LD_PRELOAD version.
You shall call this libtest2.so. You do not use the -ltest2
The point is that whoever built ./main does not know about libtest2.so at all, there is no hard linkage dependency.
libtest2.so has alternative behavior, like make foo() returns a different string/number) and the goal now is to intercept this 2nd version at runtime, so the 1st version is not called by default (or at all). By using the LD_PRELOAD environment.
LD_PRELOAD=./libtest2.so ./main
...
Good luck.
I copied and rename the DSO as libtest2.so and reset LD_PRELOAD to the renamed DSO(with absolute path), It also prompt that libtest.so could not be found.
I think that the reason why it prompt so is that the libtest.so which is used for hard dependency could not be loaded.
That is to say while LD_PRELOAD has been loaded, but hard dependency could not be satisfied, so it could not execute ./main either.
Now I can conclude that when execute ./main, hard dependency DSO must be satisfied because every hard dependency DSO also must be loaded(although this DSO shall be totally replaced!), otherwise it will prompt that the DSO could not be found!
Thanks for your help #Darryl Miles
I think the reason why your example not working is that your libtest.so does not have the correct soname.
If you compile your libtest.c with the following command
$ gcc -o libtest.so libtest.c -fPIC -shared -Wl,-soname,libtest.so
then you should be able to execute your main with PRELOAD.

g++ library search failure

I have a directory structure as below:
/
|
+--- /lib
| libsomething.a
| libsomething.so
|
+----/obj
anObjFile.o
When I run the following command from within the obj directory:
g++ -L../lib -lsomething anObjFile.o
I get undefined reference errors. Apparently gcc is failing to locate libsomething.a.
But now if I delete libsomething.so and then rerun the command, linking succeeds.
As per gcc documentation -lsomething should expand to libsomething.a. Then why is presence of libsomething.so causing the library search to fail? Also, how can I resolve this problem?
I'm on Linux Mint 12 with gcc version 4.6.1.
The .so file is a dynamic library, meaning it is used each time you run your program. In that case you need to tell your OS (Mint in this case) where that dynamic library is located so your prgramm can find it at run time.
The .a file is a static library, meaning functions needed from it will be copied into your prgramm while linking. So your prgramm can run without the library file.
If nothing else is said gcc will assume you want to use the dynamic lib. If it can find a .so file it will use it instead of a .a file. If you want to tell gcc to make your programm static (use the .a file) you can add -static to your gcc call.
However the reason why the linking fails when the dynamic library is used is not clear. How did you install/build the library?

Resources