ld - environment variable for dynamic linker? - linker

When using GNU ld, it is possible specify a dynamic linker other than the default by using the -dynamic-linker or -I flag. ie,
ld something.o otherthing.o -lc -I /path/to/ld.so.1
Is it possible to accomplish this with an environment variable instead?
ie, something along the lines of
export LD_DYNAMIC_LINKER=/path/to/ld.so.1
ld something.o otherthing.o -lc

Related

ld cannot find -lz in an empty environment even with LIBRARY_PATH, LD_LIBRARY_PATH and LD_PRELOAD

I am trying to create a conda package that includes c code that have to compile with -lz. However, when the package is building, ld cannot find zlib even though I provide it with any paths possible.
As I understand, conda creates almost empty environment, and then fills it with necessary libraries and tools. It also installs zlib, so that there is zlib.h in $BUILD_PREFIX/include/ and libz.so, libz.a in $BUILD_PREFIX/lib.
Compilation itself looks like
$BUILD_PREFIX/bin/x86_64-conda_cos6-linux-gnu-cc -fPIC -g -Wall -O2 -Wc++-compat main.o -o <name> -L. -l<name> -lm -lz -lpthread
x86_64-conda_cos6-linux-gnu-cc is gcc version 7.3.0, and it calls ld defined here as $BUILD_PREFIX/bin/x86_64-conda_cos6-linux-gnu-ld. Then ld falls with an error cannot find -lz.
I tried using
export C_INCLUDE_PATH="$BUILD_PREFIX/include"
export LIBRARY_PATH="$BUILD_PREFIX/lib"
export LD_LIBRARY_PATH="$BUILD_PREFIX/lib"
export LD_PRELOAD="$BUILD_PREFIX/lib/libz.so"
in any combinations, but that did not work.
Are there any other ways to show ld path to the library?

why can my gcc command not have -static parameter

I usually use gcc to compile my C program, it works ok, but when I tried to compile static library with -static parameter it always failed.
Although I tried some solutions on google, but it still didn't get fixed.
My command is as follows:
gcc mycode.c -static -L . -lurl -lcap -o mycode
The error message is:
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
but when I remove -static it works very well.
GCC's -static linkage option directs the linker to ignore shared libraries
during the linkage. So it must find static versions of all the libraries required
by the linkage, including those that are linked by default, such as libc.
You have not installed the static version of libc (which would be /usr/lib/???/libc.a), so:
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
libc.a is installed by the libc development package. The name of the libc
development package and how to install it depends on your distro. E.g. On Debian
or Ubuntu, the package to install is libc6-dev; on Fedora it is glibc-develop.
But before you go to do that, hang on a tick. You said:
I tried to compile static library with -static parameter it always failed.
gcc mycode.c -static -L . -lurl -lcap -o mycode
That sounds rather as if you just wanted to link your program with one or both
static libraries liburl.a, libcap.a, located in ./, and thought you should
do it by passing -static to the linkage.
There is no need to pass -static to link your program with ./liburl.a and/or
./libcap.a. The options:
-L . -lurl -lcap
will direct the linker to search in ./ for either of the files liburl.so (shared library)
or liburl.a (static library) and if it finds one or other of them it will link your
program with that library. If it finds both of them in ./, then it will choose the
shared library liburl.so. So unless you have ./liburl.so as well as ./liburl.a
then:
-L . -lurl
by itself will link your program against ./liburl.a.
And likewise for -lcap. No need for -static. The default shared library libc.so
will be linked automatically. The linker has no problem at all linking your program
with some static libraries and some shared ones. That is what is already happening
with your successful linkage:
gcc mycode.c -L . -lurl -lcap -o mycode
assuming that liburl.a and libcap.a are the only candidates for resolving
-lurl and -lcap in ./.
And even if you do have both ./liburl.a and ./liburl.so - and/or ./libcap.a and ./libcap.so - there is still no
need for a solution as drastic as a fully static linkage. You can just explicitly
tell the linker to find a particular static library if that's what you want, like:
gcc mycode.c -L . -l:liburl.a -l:libcap.a -o mycode

How to compile gcc with static library?

I have static library lib.a and in all tutorials using:
gcc -o main main.o -L. -lib
But I cant, I have errors:
/usr/bin/ld: cannot find -lib
collect2: error: ld returned 1 exit status
I need to use:
gcc -o main main.o -L. -lib.a
Why? What should I do to repair it ?
From the documentation of gcc -l:
-llibrary:
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
...
The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories.
So you cannot use -l with a library named 'lib.a'. Use 'lib.a' without the -l to include it. Of course, you cannot use -L then to set the directories to be searched for this particular library.
Do you have the error with this line ?
gcc -o main main.o -L. -llib
As MicroVirus found in the documentation, you will have to rename your library in liblib.a to use my previous line or just pass your library to gcc like a simple file.

How to generate an c function directly to excutable machine code?

My file is bootpack.c and it has a function void f() { while(1); } in it.
I want to generate it directly to excutable machine code. So I compile it like this:
gcc -c -nostdinc -fno-builtin bootpack.c
ld -nostdlib file.o -o bootpack.bin
But I find that bootpack.bin is 3.84KB. It is should only be a few bytes, I thought, because it is just a loop. What is wrong? And how to generate this file correctly?
You can use binary as output format for the GNU (BFD-based) linker:
ld -nostdlib file.o --oformat=binary -o bootpack.bin
You can then disassemble that with:
objdump -b binary -m i386 -D bootpack.bin
(substitute your target architecture in place of i386).
Because it contain symbol table information ,to reduce the size of executable you can use strip command .
Use it as "strip --strip-all executable-file-name" so it will remove extra information such as symbol table etc. Even in gcc option -s can be used , there are more option in gcc which can be used .

How can I force gcc to use custom implementations of newlibc implemented functions?

I am working on embedded software for a ARM microcontroller (SAM7) and using Yagarto toolchain.
My code currently links libc.a. However I'd like to use a custom implementation of the builtin function memcpy that my code already has.
I have tried using -fno-builtin and/or -fno-builtin-memcpy as specified in the GCC Manual but the linker still complains will the following warning:
contiki-crazy-horse.a(flashd_efc.o): In function `memcpy':
C:\Users\Melvin\GitRepo\projects\Amatis_Project\SAM7_Contiki\examples\er-rest-example/../../cpu/arm//at91sam7s-x/./flashd_efc.c:669: multiple definition of `memcpy'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-memcpy.o):C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\string/../../../../../newlib-1.19.0/newlib/libc/string/memcpy.c:78: first defined here
collect2: ld returned 1 exit status
make: *** [rest-server-example-nosyms.crazy-horse] Error 1
../../cpu/arm/at91sam7s-x/Makefile.at91sam7s-x:181: recipe for target `rest-server-example-nosyms.crazy-horse' failed
What is the correct way to use custom implementations of certain gcc built-in functions?
Edit 1: Adding the linking command I am using. In the code below Porject.a is an archive file created with all the project's object files.
CC = arm-none-eabi-gcc
CFLAGSNO = -I. -I$(CONTIKI)/core -I$(CONTIKI_CPU) -I$(CONTIKI_CPU)/loader \
-I$(CONTIKI_CPU)/dbg-io \
-I$(CONTIKI)/platform/$(TARGET) \
${addprefix -I,$(APPDIRS)} \
-DWITH_UIP -DWITH_ASCII -DMCK=$(MCK) \
-Wall $(ARCH_FLAGS) -g -D SUBTARGET=$(SUBTARGET)
CFLAGS += $(CFLAGSNO) -O -DRUN_AS_SYSTEM -DROM_RUN -ffunction-sections
LDFLAGS += -L $(CONTIKI_CPU) --verbose -T $(LINKERSCRIPT) -nostartfiles -Wl,-Map,$(TARGET).map
$(CC) $(LDFLAGS) $(CFLAGS) -nostartfiles -o project.elf -lc Project.a
If it is finding memcpy() in libc.a, then it is not conflicting with any "built-in", but rather with the newlib implementation. You may need also to specify -nostdlibs option and explicitly link libc.a and libm.a as necessary.
Object (.o) files are linked before library archives (.a) files are searched, so if a symbol is resolved by an object file, it will not be searched for in the archives. If you place your overrides in an static-link library, then you simply list it ahead of the standard library (or any other libraries that use the standard library) on the linker command line.
[Added] The following was originally a "comment" but should probably be in the answer; it is in response to "Edit 1" in the question, and the comment below about link order:
Change -nostartfiles -o project.elf -lc Project.a to -nostdlib -o project.elf -start-group Project.a -lc -end-group. The switch -nostdlib disables default linking of both start-up files (i.e. -nostartfiles) and standard libraries. The library grouping causes the libraries in the group to be searched iteratively until no further symbols can be resolved, allowing out-of-order and circular dependencies like yours to be resolved. An alternative form for the grouping switches is -( Project.a -lc -).

Resources