Selecting correct multilib version for linker automatically - gcc

I am using GCC to compile a program for an Atmel Cortex M4 SAM4S Processor. I need to link the standard libraries libgcc.a and libc.a, and to do so I am currently using the following makefile commands
LIBDIR1=C:/Program\ Files\ \(x86\)/GNU\ Arm\ Embedded\ Toolchain/10\ 2020-q4-major/arm-none-eabi/lib/thumb/v7e-m/nofp
LIBDIR2=C:/Program\ Files\ \(x86\)/GNU\ Arm\ Embedded\ Toolchain/10\ 2020-q4-major/lib/gcc/arm-none-eabi/10.2.1/thumb/v7e-m/nofp
ld_input=linker.ld startup.o main.o syscalls.o
ld_flags=-L$(LIBDIR1) -L$(LIBDIR2) -lm -lc -lgcc
out.elf: $(ld_input)
arm-none-eabi-ld -o out.elf -T $(ld_input) $(ld_flags)
However, to link to the correct multilib, I need to specify the subdirectories /thumb/v7e-m/nofp explicitly, which I determined via
arm-none-eabi-gcc -mcpu=cortex-m4 --print-multi-dir
Is there a way to link to the correct subdirectories automatically, based on the -mcpu=cortex-m4 option?

It seems everything works by using gcc instead of ld for linking. gcc then calls the linker with all the correct options, including all the standard librarier automatically.
The code shown in the question can be replaced by
ld_input=linker.ld startup.o main.o syscalls.o
out.elf: $(ld_input)
arm-none-eabi-gcc -mcpu=cortex-m4 -o out.elf -T $(ld_input)

Related

GCC: include math.h function in bare-metal software on ARM (arm-none-eabi-gcc)

I am working on a bare-metal free standing software on a STM32H753. I'm not using neither the libc nor the crt.
Here is the link command line:
arm-none-eabi-gcc -T"xxx.ld" -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -ffreestanding -nostdlib -nostartfiles --specs=nosys.specs -Wl,--start-group -lc -lm -Wl,--end-group -Wl,-Map=xxx.map -o xxx.elf <list of .o>
Now I need to include math library since I am using sqrt function. i thought the link command line would be sufficient but I get a "sqrt undefined" error.
I tried to add the path to the libm.a: (also tried without -Wl)
arm-none-eabi-gcc -T"xxx.ld" -Wl,-L/opt/gcc-arm-none-eabi-10-2020-q4-major/arm-none-eabi/lib/ -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -ffreestanding -nostdlib -nostartfiles --specs=nosys.specs -Wl,--start-group -lc -lm -Wl,--end-group -Wl,-Map=build_uP1/base_gen_uP1.map -o build_uP1/base_gen_uP1.elf <list of .o>
But I still get the same error.
I don't understand what options to choose to link with the correct library
Sorry for this self answer but I think I 've found the solution.
my first mistake is that the library must be put at the end of the command line. the order of arguments does matter.
then there are many versions of libm.a in the gcc install so I had to pick the right one
The following line is working:
arm-none-eabi-gcc -T"xxx.ld" -L/opt/gcc-arm-none-eabi-10-2020-q4-major/arm-none-eabi/lib/thumb/v7+fp/hard/ -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -ffreestanding -nostdlib -nostartfiles --specs=nosys.specs -Wl,-Map=xxx.map -o xxx.elf <list of .o> -lm -lc
I've noticed that one symbol and some data from libc.a are needed: __errno, and impure_data

gfortran linking flag for openmp

I'm trying to link multiple .o files using gfortran. I've compiled the files like so (in a makefile):
gfortran -c -fopenmp file1.f
gfortran -c -fopenmp file2.f
Now I'd like to link the files with an option for OpenMP. I know with the Intel compiler the linking flag is -liomp5, so to link the files with the Intel compiler one would call:
ifort -o a.out file1.o file2.o -liomp5
This is obviously not the correct flag for the GNU compiler. What is the correct OpenMP linking flag for gfortran?
It is -fopenmp as well:
gfortran -fopenmp -o a.out file1.o file2.o

What's the Difference between linking by GCC and LD?

Recently I was creating a loadable module and found that both
gcc -fPIC --shared -o foo.so.1 foo.c
and
gcc -fPIC --shared -c foo.c
ld --shared -o foo.so.2 foo.o
can achieve the same effect.
I also discovered that foo.so.1 is larger than foo.so.2 by about 3KB, and
gcc -### -fPIC --shared -o foo.so.1 foo.c
revealed that GCC added stuffs other than foo.c into foo.so.1 (e.g, crtendS.o and crtn.o):
/usr/lib/gcc/x86_64-linux-gnu/4.7/collect2 "--sysroot=/" --build-id --no-add-needed --eh-frame-hdr -m elf_x86_64 "--hash-style=both" -shared -o foo.so.1 /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/4.7 -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../.. /tmp/cc3JBdCJ.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crtn.o
Since both foo.so.1 and foo.so.2 can be loaded via dlopen, I was wondering:
What's the difference between these 2 linking methods?
Do crtendS.o and crtn.o make any difference to functions in created libraries?
There's no difference in principle. When you "link by gcc" it actually calls ld. If you get a message at the linking stage when "linking by gcc" you'll immediately see that it is actually from ld. If you want to pass some ld-specific command-line options to ld, gcc's command-line interface has features intended specifically for that purpose (-Xlinker and -Wl options).
As for the additional objects files... they probably contain global load-time library initialization/de-initialization code implicitly added by the compiler. (Requested by the standard library?) You can find some information about it here: https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

GCC equivalent of llvm-link

I use the following LLVM tools to convert a cpp project which is written in multiple files into "ONE" single assembly file.
clang *.cpp -S -emit-llvm
llvm-link *.s -S -o all.s
llc all.s -march=mips
Is there any way of doing this in GCC? In particular, is there any way of linking GCC generated assembly files into one assembly file? i.e., what is the equivalent of LLVM-LINK?
Perhaps LTO (Link Time Optimization) is what you want.
Then, compile each compilation unit with gcc -flto e.g.
gcc -flto -O -Wall -c src1.c
g++ -flto -O -Wall -c src2.cc
and use also -flto (and the same optimizations) to link them:
g++ -flto -O src1.o src2.o -lsomething
LTO works in GCC by putting, in each generated assembly file and object file, some representation of the internal GCC representations (like Gimple). See its documentation
You might want to use MELT to customize GCC (or simply use its probe to understand the Gimple, or try just gcc -fdump-tree-all).

GCC suppress flags

I'm trying to create a shared library with my gcc. It's a gcc for vxworks (thats probably the problem...).
I use the gcc as following:
./gcc -shared -B/path/to/gnutools/bin -o test.so test.c
Result:
/path/to/ld: -r and -shared may not be used together
collect2: ld returned 1 exit status
If I try the same with the linux gcc, there's no problem. So i guess the gcc for VxWorks automatically passes the -r (or -i, which is the same and results in the same) flag to the linker. Is there a way to suppress this?
Greetz
marty
PS: making it static is not really an alternative...
Try compile object file separately with -fPIC and then link:
gcc -Wall -fPIC -c -o test.o test.c
gcc -Wall -shared -o test.so test.o
Another suggestion is to use libtool (at least to figure out the correct flags).
A workaround may be to go directly with ld:
ld -shared -o test.so test.o -lc

Resources