I am looking at a Makefile written by someone else and I see that (after variable expansion) he calls gcc with a sequential list of -L paths followed by -l libraries.
For example:
gcc file.o -Lpath_1 -la -lb -c -Lpath_2 -ld -le -lf ... -o binary_file
My questions are:
Does this call guarantee that gcc:
only looks into path1 when searching for -la, -lb and -lc,
and only looks into path2 when searching for -ld, -le, and -lf?
Is this "proper" (recommended) gcc syntax?
Related
I am attempting to compile a .adb file with gnatmake, and the -o flag isn't producing the object file name I want:
$ gnatmake --GCC=g++ -D bin/src/ghdl_grt/ -f -u -c src/ghdl_grt/grt-vstrings_io.adb -o bin/src/ghdl_grt/grt-vstrings_io.adb.o
g++ -c -Isrc/ghdl_grt/ -I- -o /home/jon/controlix-code/bin/src/ghdl_grt/grt-vstrings_io.o src/ghdl_grt/grt-vstrings_io.adb
As you can see, it gets the path correct, but the filename should end with .adb.o and it only ends with .o. Any ideas?
For gnatmake, -o 'chooses an alternate executable name'. But even using gcc (or g++) on its own fails, at any rate on macOS, because gnat1: incorrect object file name.
I found that you can compile to assembler and then compile that. Using a local file I happened to have lying about,
$ g++ -D $PWD -c gator2.adb -S -o gator2.adb.s
$ g++ -D $PWD -c gator2.adb.s
Well, that's a weird naming scheme, but...
gnatmake only allows you to specify alternate executable names with -o:
-o name Choose an alternate executable name
You can, however, tell gnatmake to pass on options to the compiler:
-cargs opts opts are passed to the compiler
And similarly, to the binder and linker:
-bargs opts opts are passed to the binder
-largs opts opts are passed to the linker
Thus,
$ gnatmake --GCC=g++ -D bin/src/ghdl_grt/ -f -u -c src/ghdl_grt/grt-vstrings_io.adb -cargs -o bin/src/ghdl_grt/grt-vstrings_io.adb.o
I want to compile a program main that uses two different modules m1 and m2, each of which uses a different version of the library ./f1/libfa and `./f2/libf.a. I cannot change the source in the libf libraries, I only have access to main, m1, and m2 sources.
gfortran -o main main.F90 -L./f1 -lf m1.o -L./f2 -lf m2.o && ./main
Linker defaults result in ./f1/libf being used by both m1and m2. How can I make m1 use the library from ./f1 and m2 use the library from ./f2
Ideas (all of which have failed so far)
Manipulation link library path (but I can only add to path not remove from path with -L
use --exclude-libs, hide symbols ...
Rename symbols during linking stage
A minimal example is available https://github.com/platipodium/multisymbol. Any help greatly appreciated.
I tried objcopy
objcopy --redefine-sym __f_MOD_g=_f1_f_MOD_g f1/libf.a objcopy --redefine-sym __f_MOD_g=_f1_f_MOD_g f1/f.o objcopy --redefine-sym __f_MOD_g=_f1_f_MOD_g m1.o
Now the symbols seem correct and different, but I get
gfortran -o main main.F90 -Lf1 -lf m1.o -Lf2 -lf m2.o && ./main m2.o: In function __m2_MOD_b':
m2.F90:(.text+0x5): undefined reference to __f_MOD_g'
Directly using the object files now works.
gfortran -o main main.F90 f1/f.o m1.o f2/f.o m2.o && ./main I am first I am second
So what's the necessary steps to make it from the above working command with obj files into an archive/library command?
Linker defaults result in ./f1/libf being used by both m1and m2.
That is expected: that's just how UNIX linkers work.
How can I make m1 use the library from ./f1 and m2 use the library from ./f2
You'll have to rename any conflicting symbols (objcopy can do that).
Update:
I tried objcopy ...
gfortran -o main main.F90 -Lf1 -lf m1.o -Lf2 -lf m2.o
This command line is wrong, for the reasons explained in "how UNIX linkers work" above.
You want:
gfortran -o main main.F90 m1.o m2.o -Lf1 -lf -Lf2 -lf
Actually, that's not likely to work either: you also want to rename f2/libf.a -> f2/libf2.a and then:
gfortran -o main main.F90 m1.o m2.o -Lf1 -lf -Lf2 -lf2
I have the following makefile:-
all:
find | grep -E "\.c\$" | xargs gcc -c -I src -I include -w
gcc -o main *.o -lm -pthread
On running make I get the following error:-
find | grep -E "\.c\ | xargs gcc -c -I src -I include -w
/bin/sh: 1: Syntax error: Unterminated quoted string
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 2
I tried answers to similar questions, but adding a SHEBANG line did not help. Also, I have already escaped the $ character. What am I doing wrong here?
make already does most of what you are trying to do. Assuming you aren't expecting find to look recursively in subdirectories, all you really need is
# Rule for building a c file
.c:
gcc -c -I src -I include -w -o $# $<
# Make sure all C files are compiled, then link the resulting object files
all: *.c
gcc -o main *.o -lm -pthread
If you were expecting to find C source files in subdirectories, you might want to restructure your project slightly, by adding Makefiles to each subdirectory and calling make recursively in those directories.
Here I am compiling a C code with the following Makefile.
MAIN:
g++ -c -o td.o -I/home/user/dp/pro/include td.c
g++ -c -o disk.o -I/home/user/dp/pro/include disk.c
g++ -o disk disk.o tds2.o -L ${DP_LIB} -L ${LIPN_LIB} -lgnb -lgtd -lnbl -lpin
./disk.exe RUN.dat
What is the purpose of -L ${DP_LIB} here? Precisely, I wish to know the function of ${}.
If it is linking a library, how is it different from -llib?
This makefile is by far very crude (I have seen bigger and better ones). I am new to makefiles, but atleast this one works.
The -L options is telling the linker to add a path to the list it uses to search for libraries. The ${DP_LIB} thing is how variables are used in makefiles. Presumably DP_LIB is a path to somewhere.
All this should be very clear if you just read the documentation and the actual makefile.
With -Ldir you specify a directory where the linker searches for libs. The lib files themselves are specified with the -llib argument.
Example:
-L/usr/X11R6/lib -lX11
means that the linker will look for libX11.so in /usr/X11R6/lib
(...and in other default places.)
Is this syntax incorrect?
C:\Users\Brett\Compilers>gcc -I MinGW\include -l MinGW\lib\libgdi32.a -o hello
world helloworld.c
The directory's are all fine, I mist be including and linking in the wrong order or something?
Here is the output:
c:/users/Brett/compilers/mingw/bin/../lib/gcc/mingw32/4.6.2/../../../../mingw
2/bin/ld.exe: cannot find -lMinGW\lib\libgdi32.a
collect2: ld returned 1 exit status
The syntax for -l switch is the library name without lib prefix and without the extension. If it cannot be found, it's directory should be given with -L option. So I would write:
gcc -I MinGW\include -L MinGW\lib -lgdi32 -o helloworld helloworld.c
Maybe -L is not needed, maybe you also need -mwindows to tell the linker you want windows app. To specify a library file explicitly, give it without any letter option, like this:
gcc -I MinGW\include MinGW\lib\libgdi32.a -o helloworld helloworld.c
Here is the gcc reference: linking options.