linker option order causing opencv undefined references [duplicate] - opencv

I'm writing a small C program that uses librt. I'm quite surprised that the program won't compile if I place the link flag at the start instead of at the end:
At the moment, to compile the program I do:
gcc -o prog prog.c -lrt -std=gnu99
If I were to do the following, it will fail to find the functions in librt:
gcc -std=gnu99 -lrt -o prog prog.c
Yet, this works with other libraries. I found the issue when attempting to use a simple Makefile. make actually compiled prog.c without liking first (using -c flag) and then did the linking.
This is the Makefile:
CC = gcc
CFLAGS = -std=gnu99
LIBS= -lrt
LDFLAGS := -lrt
prog: prog.o
$(CC) -o prog prog.c -lrt -std=gnu99
The output I would get when typing make would be:
gcc -std=gnu99 -c -o prog.o prog.c
gcc -lrt prog.o -o prog
prog.o: In function `main':
prog.c:(.text+0xe6): undefined reference to `clock_gettime'
prog.c:(.text+0x2fc): undefined reference to `clock_gettime'
collect2: ld returned 1 exit status
make: *** [buff] Error 1
I have now crafted a Makefile that puts the linking at the end of the gcc line, however I'm puzzled why it doesn't work if the linking flag is at the start.
I would appreciate if anybody can explain this to me. Thanks.

As the linker processes each module (be it a library or a object file), it attempts to resolve each undefined symbol while potentially adding to its list of undefined symbols. When it gets to the end of the list of modules, it either has resolved all undefined symbols and is successful or it reports undefined symbols.
In your case, when it processed librt, it had no undefined symbols. Processing proc resulted in clock_gettime being an undefined symbol. gcc will not go back and look in librt for the undefined symbols.
For that reason, you should always have your code first, followed by your libraries, followed by platform provided libraries.
Hope this helps.

From the ld (the GNU linker) documentation (http://sourceware.org/binutils/docs/ld/Options.html#Options):
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
So if you specify the library too early, the linker will scan it, but not find anything of interest. Then the linker moves on to the object file produced by the compiler and finds references that need to be resolved, but it has already scanned the library and won't bother looking there again.

Related

Problems linking FFTW with gfortran (symbol(s) not found for architecture x86_64)

I am on macOS Catalina (10.15.5) and I have installed FFTW using brew install fftw. I also have GCC (version 10.2.0) installed which is symlinked to the commands I am using below.
I am able to compile and run a simple C++ program like so:
g++-10 test.cpp -L/usr/local/lib -I/usr/local/include -lfftw3 -lm
But, I had to modify the environment variable CPATH to make this work.
I am unable to get a simple Fortran FFTW example to work (I am using this one). The command I am using to compile is:
gfortran-10 test.f90 -L/usr/local/lib -I/usr/local/include -lfftw3 -lm
The error I get is as follows:
Undefined symbols for architecture x86_64:
"__gfortran_os_error_at", referenced from:
_MAIN__ in ccRvJaEQ.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
If I understand correctly, the linking step fails. Any inputs on how I might find the relevant paths that I may have to pass to the compiler would be very helpful. I searched for solutions and I wasn't able to find one. But, in case I missed something obvious, I apologise.
Thanks to msi_gerva's helpful hints through comments, I was able to solve the issue by downloading FFTW and compiling it to a custom directory following the installation directions.
Now, the linking doesn't fail if I pass the new locations of the libraries to gfortran like so:
gfortran-10 test.f90 -L/new/path/to/lib -I/new/path/to/include -lfftw3 -lm
Since /usr/local/ is the default installation path, it's possible that there is a mixing up of the FFTW library files from previous installations.

what does clang command option -lm mean?

I found someone says that -lm means linking to the math library.
I want to figure out the meaning by using build-in help in the terminal.
So I run the $ clang --help
I don't find any stuff related to -l or -m
How can I get the meaning of -lm with the self-help terminal?
The -l{name} flag tells the linker to link against lib{name}. So -lm links against libm, the c math library.
This isn't a flag to the clang compiler but passed to the linker, which is why you won't find it with clang --help or man clang.
If you run clang with the --verbose flag you will see the invocation of the linker (in my case /usr/bin/ld) as the last step.By running man ld or ld --help (or whichever linker your clang version is using) you will find the documentation.
Keep in mind that not all flags are passed to the linker in this way (-l is probably passed for compatibility with the gcc compiler as melpomene said). To make sure an option is passed, use the -Wl option of clang.

Building ARM code on OS X

I am targeting the Cortex-A7 (ARMv7-A)
As a test:
bootstrap.s
.globl _start
_start:
mov sp,#0x00010000
bl main
hang: b hang
main.c
int main(void) { return 0; }
Trying:
$ as -arch armv7 -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 bootstrap.s -o bootstrap.o
$ file bootstrap.o
bootstrap.o: Mach-O object arm
$ clang -c -arch armv7 -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 main.c -o main.o
$ file main.o
notmain.o: Mach-O object arm
Confirms the compilation of Mach-O arm object files (also verified using hexdump, otool, gobjdump)
But now we try to link them together:
$ ld -e _start -arch armv7 bootstrap.o main.o -o foo
ld: warning: -ios_version_min not specified, assuming 6.0
ld: building for iOS, but linking in object file built for OSX, file 'bootstrap.o' for architecture armv7
And we have some issues. Not sure what's going on here. I haven't asked to link-in any iOS-related stuff. Using the -t linker flag confirms that no other objects are being linked in. Not sure why it thinks bootstrap.o is built for OS X when it clearly is a Mach-O arm file. Not sure if I'm passing the right flags to the assembler (pretty much all of them are undocumented?) or the linker
Note that this is for a bare-metal mini-project running on RPi2. I'm going to gobjcopy the linked executable object to a flat binary anyways. I'm just working with Mach-O since that's the only object type the system linker on OS X is capable of working with (and fat Mach-O). If I built a separate cross-compiler, I would be doing the exact same thing, instead I'd be linking ELF files before converting them to flat binary (I can output ELF32 files using clang/llvm anyways, I just cant link them). Seems silly to build a separate cross-compiler when clang/llvm is a perfectly suitable cross-compiler that's able to target my microarchitecture

Symbols not found in libusb

Note that I am new to iOS (actually, iDevices) internals.
I'm trying to compile iRecovery,
a tool used to communicate with iBoot, iOS's bootloader. Sadly... I'm getting errors about libusb while compiling :
./configure: line 15323: syntax error near unexpected token `libusb,'
./configure: line 15323: `PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.3)'
libusb is installed :
$> pkg-config --libs libusb
-L/opt/local/lib -lusb
$> pkg-config --libs libusb-1.0
-L/opt/local/lib -lusb-1.0
I tried to comment out the line that checks for libusb, but then I get a bunch of not found symbols, such as :
"_libusb_set_configuration", referenced from:
_irecv_open_with_ecid in libirecovery_la-libirecovery.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
My simple question is... WHY ?!
Thanks for any help...
Okay, so here's a dirty workaround :
open (NOT RUN) autogen.sh file, and comment out the "PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.3)" line
save
run autogen.sh modified file provided
open the makefile located in /src : add "-lusb-1.0 -L/usr/local/lib/ -I /usr/local/include/ - I /usr/local/include/libusb-1.0" to the "GLOBAL_CFLAGS" variable
save
cd to main directory (parent of /src)
make
make install
Once done, your should be able to run irecovery from your shell.
Please note that it is not really clean, and that it is only confirmed to work for iRecovery.
But - It Works !

Compile Link LUA5.1 Lib. Error in dev-cpp

this is my dev-cpp compiler log:
rm -f main.o luaTest.exe'
gcc.exe -c main.c -o main.o -I"E:/Dev-Cpp/include" -I"E:/Lua/5.1/include"'
gcc.exe main.o -o "luaTest.exe" -L"E:/Dev-Cpp/lib" -L "E:/lua/5.1/lua5.1.lib"'
main.o(.text+0x34):main.c: undefined reference to 'luaL_newstate'
main.o(.text+0x48):main.c: undefined reference to 'luaL_openlibs'
main.o(.text+0xab):main.c: undefined reference to 'luaL_loadbuffer'
main.o(.text+0xd5):main.c: undefined reference to 'lua_pcall'
main.o(.text+0x11c):main.c: undefined reference to 'lua_tolstring'
main.o(.text+0x14e):main.c: undefined reference to 'lua_settop'
main.o(.text+0x161):main.c: undefined reference to 'lua_close'
collect2: ld returned 1 exit status'
make.exe: *** [luaTest.exe] Error 1'
I can compiling & linking my code success with code::blocks. I can't figure out what's wrong with dev-cpp.
The linking step looks off. The option -L (uppercase L) sets a search directory for libs referenced via -l (lowercase L). The last step tries to link to lua5.1.lib using -L instead of the correct -l.
I have found out what's wrong with dev-cpp.when you want to link lib file you must shut down the makefile generation in the compiler option

Resources