Why explicite -L flag breaks linking on gcc - gcc

If this works as expected:
Lenovo#Lenovo-Komputer MINGW64 ~/source/hft (master)
$ gcc.exe main.c -o main.exe -lmsvcr110 && ldd ./main.exe # main.exe links to /c/WINDOWS/SYSTEM32
ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff8d6130000)
KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ff8d3a30000)
KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ff8d2030000)
msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7ff8d5e70000)
MSVCR110.dll => /c/WINDOWS/SYSTEM32/MSVCR110.dll (0x7ff8c3980000)
then why issuing this command in following manner ends up with this error?
Lenovo#Lenovo-Komputer MINGW64 ~/source/hft (master)
$ gcc.exe main.c -o main -lmsvcr110 -L /c/WINDOWS/SYSTEM32/ && ldd ./main.exe # so why explicit path makes linking error?
d000027.o:(.idata$5+0x0): multiple definition of `__imp___C_specific_handler'
d000024.o:(.idata$5+0x0): first defined here
d000057.o:(.idata$5+0x0): multiple definition of `__imp___iob_func'
d000031.o:(.idata$5+0x0): first defined here
d000057.o:(.idata$6+0x0): multiple definition of `__nm___iob_func'
d000031.o:(.idata$6+0x0): first defined here
d000058.o:(.idata$5+0x0): multiple definition of `__imp___setusermatherr'
d000034.o:(.idata$5+0x0): first defined here
d000058.o:(.idata$6+0x0): multiple definition of `__nm___setusermatherr'
d000034.o:(.idata$6+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

Related

Unable to link ".so" shared library to main ".c" file while compiling

I am trying to make a shared library for a particular problem I was working on. It has "point_sense.c" as the main file which uses functions defined in "createPolygon.c." The functions are declared in a header file "createPolygon.h."
To compile them, I used a makefile which looks like the following
all:point_sense
createPolygon.o:createPolygon.c
g++ -c -fpic createPolygon.c
libcreatePolygon.so:createPolygon.o
g++ -shared -o libcreatePolygon.so createPolygon.o
point_sense:point_sense.c libcreatePolygon.so
g++ -o point_sense -L~Desktop/Summer_2020_linux/tutorials/cpp_practise point_sense.c -lcreatePolygon
clean:
rm point_sense createPolygon.o libcreatePolygon.so
but when I make the file, it gives an output as
g++ -c -fpic createPolygon.c
g++ -shared -o libcreatePolygon.so createPolygon.o
g++ -o point_sense -L~Desktop/Summer_2020_linux/tutorials/cpp_practise point_sense.c -lcreatePolygon
/usr/bin/ld: cannot find -lcreatePolygon
collect2: error: ld returned 1 exit status
make: *** [makefile:10: point_sense] Error 1
Initially I thought this was some silly mistake, and to check I used
ld -L~/Desktop/Summer_2020_linux/tutorials/cpp_practise -lcreatePolygon -verbose
and after a long output I got (a few unimportant lines in the code are skipped in between)
ld: mode elf_x86_64
attempt to open ~/Desktop/Summer_2020_linux/tutorials/cpp_practise/libcreatePolygon.so failed
attempt to open ~/Desktop/Summer_2020_linux/tutorials/cpp_practise/libcreatePolygon.a failed
attempt to open /usr/local/lib/x86_64-linux-gnu/libcreatePolygon.so failed
attempt to open /usr/local/lib/x86_64-linux-gnu/libcreatePolygon.a failed
.
.
.
ld: cannot find -lcreatePolygon
But when I try to open 'libcreatePolygon.so' directly, I am able to open it.
$ nano ~/Desktop/Summer_2020_linux/tutorials/cpp_practise/libcreatePolygon.so
There are several threads which explain the process of doing this, but I don't see what it is that I am doing wrong. Any help is appreciated.
I am using Ubuntu 20.04.1 LTS and g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0 .
I tried to reproduce the problem here, and this error message goes away if you put a space between the -L flag and the tilde character.
The reason is: if there is no space between -L and ~, the tilde character cannot be expanded to the home directory.

Does GNU linker (ld) fail when files are in different directories?

When I run the following command,
ld -m elf_i386 -T kernel.ld -o img/kernel bin/entry.o bin/bio.o bin/console.o ... bin/main.o ... bin/proc.o ... bin/vm.o -b binary img/initcode img/entryother
I get the following errors:
bin/main.o: In function `startothers':
main.c:75: undefined reference to `_binary_entryother_size'
main.c:75: undefined reference to `_binary_entryother_start'
bin/proc.o: In function `userinit':
proc.c:131: undefined reference to `_binary_initcode_size'
proc.c:131: undefined reference to `_binary_initcode_start'
However, if kernel.ld, and all the binary files are in the same directory, the link completes with no errors:
ld -m elf_i386 -T kernel.ld -o kernel entry.o bio.o console.o ... main.o ... proc.o ... vm.o -b binary initcode entryother
Is GNU linker the problem, or is this a red herring?
When create *_start, *_end and _size symbols, corresponded to the binary data, the linker produces the prefix from its command-line argument as it is.
That is, the linker uses:
a prefix _binary_initcode_ for argument initcode and
a prefix _binary_img_initcode_ for argument img/initcode.
As far as I know, it is impossible to redefine this prefix when calling the linker.
With objcopy one may create an object file with a specific section, containing the binary data from other file:
objcopy -I binary -O <output-format> -B <architecture> --rename-section .data=.initcode,alloc,load,readonly,data,contents img/initcode <output-obj-file>
Resulted object file then can be used for linking with. In the linker's command-line one need to use a custom linker srcipt, which specifies the placement of the binary section and creates symbols denoted its start and end:
...
SECTIONS
{
...
<output-section-name>:
{
...
initcode_start = .;
*(.initcode);
initcode_end = .;
...
}
}

Linking shared library absolute vs. relative path

I've been trying to link a shared library into my program and I want its path to be relative to my RPATH.
However, when I ran ldd, I noticed that the absolute path of the shared library was linked. Any ideas why?
Edit:
/home/projects/my_files/winter_fresh.so
libgcc_s.so.1 => /home/tomo/anaconda3/lib/libgcc_s.so.1 (0x00007f0a3bf64000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0a3bd47000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a3b97d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a3e369000)
libstdc++.so.6 => /home/tomo/anaconda3/lib/libstdc++.so.6 (0x00007f0a3b643000)
The issue is the first file. I don't want the library for winter_fresh to be an absolute path, since I have an RPATH that contains it.
The issue is the first file. I don't want the library for winter_fresh to be an absolute path
This most usually happens when you link against your library like so:
gcc ... /home/projects/my_files/winter_fresh.so ...
and your library does not have SONAME (you didn't use -soname linker option when building it).
To fix this, either add SONAME to winter_fresh.so (a good practice in general), or link against it like so:
gcc ... -L /home/projects/my_files -l:winter_fresh.so
An even better approach might be to rename winter_fresh.so to libwinter_fresh.so, and then link against it like so:
gcc ... -L /home/projects/my_files -lwinter_fresh
My guess is, you compiled your program using winter_fresh.so as source file, not by linking against it.
If you encoded the path to shared library/executable as /home/projects/my_files/winter_fresh.so, you can put your shared library inside RPATH directory, like this:
$ mkdir some_dir
$ mkdir -p some_dir/home/projects/my_files
$ cp /home/projects/my_files/winter_fresh.so some_dir/home/projects/my_files
$ RPATH=$(pwd)/some_dir ./executable
The linker searches for library named /home/projects/my_files/winter_fresh.so under RPATH.
Now a simple test:
// main.c
int main() {
int external_function(void);
return external_function();
}
// exlib.c
#include <stdio.h>
int external_function(void) {
return printf("%s\n", __func__);
}
Now, let's create bad.out compiled with exlib.so shared library used as source:
$ gcc -shared -fPIC -o exlib.so exlib.c
$ gcc /tmp/exlib.so main.c -o bad.out
$ ldd bad.out
linux-vdso.so.1 (0x00007ffd921db000)
/tmp/exlib.so (0x00007fe4470f7000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fe446d3b000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fe4474fb000)
As you see the string /tmp/exlib.so points to the shared library. I can run the program, using RPATH to point the linker to exlib.so location. I need to create subtree /tmp/exlib.so inside RPATH, like this:
$ mkdir -p lib/tmp
$ mv exlib.so lib/tmp
$ RPATH=$(pwd)/lib ./bad.out
external_function
When running bad.out, linker searches for a file named /tmp/exlib.so inside RPATH.
Linux uses a convention for naming shared libraries. Now let's link against good.out:
$ gcc -shared -fPIC -o libexlib.so exlib.c
$ gcc -I /tmp -lexlib main.c -o good.out
$ ldd good.out
linux-vdso.so.1 (0x00007ffcb01bf000)
libexlib.so => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007fc1230ef000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fc1236ad000)
Now you see that good.out is linked against libexlib.so. gcc searched for alibrary named libexlib.so inside /tmp directory when linking. I can run good.out by specyfing LD_LIBRARY_PATH to the path libexlib.so resides:
$ LD_LIBRARY_PATH=/tmp ldd ./good.out
external_function

Makefile deleted my fortran program

Hi I've never written a makefile before, but I tried my hand at it with my fortran90 final project and the makefile seems to have delete my main program. here's my makefile
# Sample makefile for several modules
#
FC = gfortran
final.x: subs.o func.o maina.o
gfortran -o final.x subs.o func.o maina.o
subs.o: subs.f90
gfortran -c subs.f90
func.o: func.f90
gfortran -c func.f90
maina.o: maina.f90
gfortran -c maina.f90
after running this, my maina.f90 was deleted and the I did not have a copy. this was what it showed when it was running. (The first output is when I ran it and found an error in subs, and after fixing these errors, I got the second output)
$ make
gfortran -o final.x subs.o func.o maina.o
subs.o: In function `__subs_MOD_gauss':
subs.f90:(.text+0x350): undefined reference to `f_'
subs.f90:(.text+0x366): undefined reference to `f_'
subs.o: In function `__subs_MOD_simp':
subs.f90:(.text+0x434): undefined reference to `f_'
subs.f90:(.text+0x4a2): undefined reference to `f_'
subs.f90:(.text+0x51b): undefined reference to `f_'
subs.o:subs.f90:(.text+0x571): more undefined references to `f_' follow
collect2: ld returned 1 exit status
make: *** [final.x] Error 1
$ make
gfortran -c subs.f90
gfortran -o final.x subs.o func.o maina.o
does anyone know why this file deleted my maina.f90, or (though it's probably unlikely) how to get my work back?
EDIT- I should add that I do not have admin or sudo privileges on this computer

Force solib dependency to have relative path of non-standard named shared library under a directory using gcc

I have an issue regarding the linking of a shared library with a non-standard naming convention under several directories. I need the generated executable to search for the shared library within the executables current location, but cannot find a command line parameter to force this behavior.
To demonstrate this behavior all that is required is a shared library that is under a directory.
gcc -shared mylib.c -o some/dir/mylib.so
gcc main.c -o main -Lsome/dir -l:mylib.so
The executable main gives the following ldd output:
ldd main
some/dir/mylib.so (0xf76e2000)
The output that I require is:
ldd main
mylib.so => some/dir/mylib.so (0xf7700000)
This output can be created if the library is named conventionally as libmylib.so rather than mylib.so like so:
mv some/dir/mylib.so some/dir/libmylib.so
gcc main.c -o main -Lsome/dir -lmylib
This also drops the path some/dir in the ldd listing as required.
I have investigated the use of rpath, and command line options for both the ld and gcc but I am unable to find a satisfactory solution. The strict requirements of a non-standard name and directory structure cannot be changed easily in this case.
My question is how can I force the dependency of the library to be relative to the current directory rather than absolute as in the second ldd through gcc command line options.
Thank you for your time, I hope I have explained the problem reasonably.
Jon.
Try to add soname in your shared library:
$ gcc -shared mylib.c -o some/dir/mylib.so -Wl,-soname=mylib.so
$ gcc main.c -o main -Lsome/dir -l:mylib.so
$ LD_LIBRARY_PATH=some/dir:$LD_LIBRARY_PATH ldd main
mylib.so => some/dir/mylib.so (0x00007fa7a4fd6000)
There's a magic variable you can pass to rpath to do this: $ORIGIN. See man ld.so for details.
I think in your case, the command should look like this (untested):
gcc main.c -o main -Lsome/dir -lmylib -Wl,-rpath,'$ORIGIN/some/path'
Note that you mustn't let the shell expand $ORIGIN as a shell variable.
BTW, this was the first Google hit for "rpath relative".

Resources