How to link a shared library to a makefile - makefile

Hello everyone I have the following makefile:
LHAPDFldflag = -L "/home/user/local/lib -lLHAPDF"
LHAPDFincdir = -I "/home/user/local/include/"
demo: demo.o vegas.o ranlxd.o
g++ -o demo demo.o vegas.o ranlxd.o -lgfortran ${LHAPDFldflag}
demo.o: demo.cpp
g++ ${LHAPDFincdir} -c demo.cpp
vegas.o: vegas.F
gfortran -c vegas.F
ranlxd.o: ranlxd.c
gcc -c ranlxd.c
clean:
rm -f vegas.o ranlxd.o
distclean: clean
rm -f demo
In my demo.cpp I call a function from the library. After trying 'make' I receive the following error:
g++ -o demo demo.o vegas.o ranlxd.o -lgfortran -L "/home/user/local/lib -lLHAPDF"
/usr/bin/ld: demo.o: in function `main':
demo.cpp:(.text+0x13ca): undefined reference to `LHAPDF::initPDFSet(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
collect2: error: ld returned 1 exit status
make: *** [makefile:6: demo] Error 1
As far as I know an undefined reference error originates from a problem in the linker stage which is also indicated by the last line of the error. But I am wondering that in the fourth line of the error code it seems to know the function that I want to call. Is the problem here really in the linking? I donĀ“t see whats wrong with the line 6 of my makefile which is refered to in the error code. Could there be another explanation? I highly appreciate any kind of help!

Related

Raylib Makefile Issue

I've install raylib according to this wiki page.
My Project Folder is look like this:
[this][1]
> ..\build>mingw32-make
g++ ../main.cpp -o test.exe -O2 -Wall -Wno-missing-braces -I ../include/ -L ../lib/ -lraylib -lopeng132 -lgdi32 -lwinmm
D:/Software/raylib/mingw/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lopeng132
collect2.exe: error: ld returned 1 exit status
mingw32-make: *** [Makefile:2: default] Error 1```
[1]: https://i.stack.imgur.com/QK2X3.png
It seems you have typed openg132 instead of opengl132. You have mistaken the letter l for the number 1

How to change the structure of this makefile

I am new to handling makefiles and was provided with this one:
demo: demo.cpp vegas.o ranlxd.o
g++ -o demo demo.cpp vegas.o ranlxd.o -lgfortran
vegas.o: vegas.F
gfortran -c vegas.F
ranlxd.o: ranlxd.c
gcc -c ranlxd.c
clean:
rm -f vegas.o ranlxd.o
distclean: clean
rm -f demo
I use functions defined in the vegas and ranlxd files within the demo file. Now I want to change this so that all the codefiles are converted to object files first and then linked in the end so I tried the following:
demo: demo.o vegas.o ranlxd.o
demo.o vegas.o ranlxd.o -lgfortran
demo.o: demo.cpp
g++ -c demo.cpp
vegas.o: vegas.F
gfortran -c vegas.F
ranlxd.o: ranlxd.c
gcc -c ranlxd.c
clean:
rm -f vegas.o ranlxd.o
distclean: clean
rm -f demo
This resulted in the error
demo.o vegas.o ranlxd.o -lgfortran
make: demo.o: Command not found
make: *** [makefile:9: demo] Error 127
What am I doing wrong and what do I have to change in order to compile all the codefiles first? I highly appreciate any kind of help!
With your link command you forgot to actually call a program for the linker
demo: demo.o vegas.o ranlxd.o
demo.o vegas.o ranlxd.o -lgfortran
should be:
demo: demo.o vegas.o ranlxd.o
g++ -o demo demo.o vegas.o ranlxd.o -lgfortran
Samuel is right, you just forgot the link command (g++ -o demo). Make passed demo.o vegas.o ranlxd.o -lgfortran to the shell and the shell complained that demo.o is not a command it knows.
I am just adding this answer to let you know about GNU make Built-In Rules. If you use GNU make you could also rely on them and replace your compilation and link rules by a single demo: demo.o vegas.o ranlxd.o. Yes, just that. GNU make knows how to build the .o files form your source files and how to assemble them to create the executable. Modify the standard variables, if needed (e.g. FC := gfortran and CC := gcc). Your Makefile could be as simple as, for example:
FC := gfortran
CC := gcc
LDLIBS := -lgfortran
demo: demo.o vegas.o ranlxd.o
.PHONY: clean distclean
clean:
rm -f *.o
distclean: clean
rm -f demo
But of course, if your goal is to learn make, it is probably better to write all these rules yourself.

How do you compile the occi demo on ubuntu?

It's 2021, does Oracle not support modern operating systems that use compiler ABIs released over 6 years ago?
$ make -f demo.mk
rm -rf SunWS_cache
rm -rf cdemo81 cdemo81.o occidml occidml.o occiobj occiobj.o occiobjo* occiobjm* occiobj.h occiobjout.type
/usr/bin/gcc -c -I../include -DLINUX -D_GNU_SOURCE -D_REENTRANT -g cdemo81.c
/usr/bin/g++ -o cdemo81 -g cdemo81.o -L../../ -locci -lclntsh -lpthread
make -f demo.mk buildocci OBJS=occidml.o EXE=occidml
rm -rf SunWS_cache
/usr/bin/g++ -c -I../include -DLINUX -D_GNU_SOURCE -D_REENTRANT -g occidml.cpp
/usr/bin/g++ -o occidml -g occidml.o -L../../ -locci -lclntsh -lpthread
occidml.cpp:291: error: undefined reference to 'oracle::occi::SQLException::getMessage[abi:cxx11]() const'
occidml.cpp:63: error: undefined reference to 'oracle::occi::SQLException::getMessage[abi:cxx11]() const'
occidml.cpp:83: error: undefined reference to 'oracle::occi::SQLException::getMessage[abi:cxx11]() const'
occidml.cpp:106: error: undefined reference to 'oracle::occi::SQLException::getMessage[abi:cxx11]() const'
collect2: error: ld returned 1 exit status
The default libocci.so.19.1 is not compatible with g++ versions 5 and above. Please contact Oracle support to get the specially built libocci to work with g++ 5 and above.
For the supported Linux platforms, please try
make -f demo_rdbms.mk occidemos (for building all OCCI demos)
make -f demo_rdbms.mk occidml (for building just one demo like occidml)
make -f demo_rdbms.mk buildocci EXE=myapp OBJS=myapp.o (for a custom .cpp program)
The above is with a regular installation. You didn't mention which version of OCCI you are trying and the version of g++.

How to run manually produce an elf executable using ld?

I'm trying to get my head around how the linking process works when producing an executable. To do that I'm reading Ian Taylor's blog series about it, but a lot of it is beyond me at the moment - so I'd like to see how it works in practice.
At the moment I produce some object files and link them via gcc with:
gcc -m32 -o test.o -c test.c
gcc -m32 -o main.o -c main.c
gcc -m32 -o test main.o test.o
How do I replicate the gcc -m32 -o test main.o test.o stage using ld?
I've tried a very naive: ld -A i386 ./test.o ./main.o
But that returns me these errors:
ld: i386 architecture of input file `./test.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `./main.o' is incompatible with i386:x86-64 output
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
./test.o: In function `print_hello':
test.c:(.text+0xd): undefined reference to `_GLOBAL_OFFSET_TABLE_'
test.c:(.text+0x1e): undefined reference to `puts'
./main.o: In function `main':
main.c:(.text+0x15): undefined reference to `_GLOBAL_OFFSET_TABLE_
I'm most confused by _start and _GLOBAL_OFFSET_TABLE_ being missing - what additional info does gcc give to ld to add them?
Here are the files:
main.c
#include "test.h"
void main()
{
print_hello();
}
test.h
void print_hello();
test.c
#include <stdio.h>
void print_hello()
{
puts("Hello, world");
}
#sam : I am not the best people to answer your question because I am a beginner in compilation. I know how to compile programs but I do not really understand all the details (https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)
So, I decided this year to try to understand how compilation works and I tried to do, more or less, the same things as you tried a few days ago. As nobody has answered, I am going to expose what I have done but I hope an expert will supplement my answer.
Short answer : It is recommended to not use ld directly but to use gcc directly instead. Nevertheless, it is, as you write, interesting to know how the linking process works. This command works on my computer :
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o /usr/lib/crtn.o
Very Long answer :
How did I find the command above ?
As n.m suggested, run gcc with -v option.
gcc -v -m32 -o test main.o test.o
... /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 ... (many
options and parameters)....
If you run ld with these options and parameters (copy and paste), it should work.
Try your command with -m elf_i386 (cf. collect2 parameters)
ld -m elf_i386 test.o main.o
ld: warning: cannot find entry symbol _start; ....
Look for symbol _start in object files used in the full ld command.
readelf -s /usr/lib/crt1.o (or objdump -t)
Symbol table '.symtab' contains 18 entries: Num: Value Size
Type Bind Vis Ndx Name... 11: 00000000 0 FUNC
GLOBAL DEFAULT 2 _start
Add this object to your ld command :ld -m elf_i386 test.o main.o /usr/lib/crt1.o
... undefined reference to `__libc_csu_fini'...
Look for this new reference in object files. It is not so obvious to know which library/object files are used because of -L, -l options and some .so include other libraries. For example, cat /usr/lib/libc.so. But, ld with --trace option helps. Try this commandld --trace ... (collect2 parameters)At the end, you should findld -m elf_i386 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc_nonshared.a /lib/libc.so.6 /usr/lib/crti.oor shorter (cf. cat /usr/lib/libc.so) ld -m elf_i386 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o
It compiles but it does not run (Try to run ./test). It needs the right -dynamic-linker option because it is a dynamically linked ELF executable. (cf collect2 parameters to find it) ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o But, it does not run (Segmentation fault (core dumped)) because you need the epilogue of the _init and _fini functions (https://gcc.gnu.org/onlinedocs/gccint/Initialization.html). Add the ctrn.o object. ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o /usr/lib/crtn.o./test
Hello, world

Gcc /usr/bin/ld compiler error

I got this error when I do make
gcc -o tests/simple_test tests/simple_test.o -L. libtraceback.a -Wall -Werror -gdwarf-2 -O0 -m32 -fno-stack-protector -fno-omit-frame-pointer -Itraceback/ -mpreferred-stack-boundary=2 -static
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_eh.a when searching for -lgcc_eh
/usr/bin/ld: cannot find -lgcc_eh
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
I read one post and tried
sudo ln -s /usr/lib/x86_64-linux-gnu /usr/lib64
But it doesn't help, is there any reason for this?
Im running on a surface pro 2 using vmware running 64bits ubuntu 13.10.
If you do not have any parcticular reason to build a 32bit application on a 64bit machine just do not use the option -m32.
In case you are following this tutorial then fixed make file code is below working on Ubuntu 20
# $# = target file
# $< = first dependency
# $^ = all dependencies
# First rule is the one executed when no parameters are fed to the Makefile
all: run
kernel.bin: kernel-entry.o kernel.o
ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary --entry main
kernel-entry.o: kernel-entry.asm
nasm $< -f elf -o $#
kernel.o: kernel.c
gcc -m32 -ffreestanding -c $< -o $# -fno-pie
mbr.bin: mbr.asm
nasm $< -f bin -o $#
os-image.bin: mbr.bin kernel.bin
cat $^ > $#
run: os-image.bin
qemu-system-i386 -fda $<
clean:
$(RM) *.bin *.o *.dis
To run make file
make run
to clean all output files
make clean

Resources