This question already has answers here:
How to link to a shared library without lib* prefix in a different directory? [duplicate]
(2 answers)
Closed 2 years ago.
I compiled a few libraries using Eclipse-CDT on windows. However, when I tried to compile them under linux gcc keeps giving me the error /usr/bin/ld: cannot find -lrequestedLib. I'm using the exact same build settings between the two environments (namely I made sure to add the directories that contain the libraries i need to link to). I'm sure the system has read access rights to the files as well. I'm not sure what to make of this. Please help.
Edit: These are the commands that ecplise runs to build the library:
gcc -I/home/me/lib/ -O3 -Wall -c -fmessage-length=0 -olibToMake.o ../libToMake.c
gcc -L/home/me/lib/ -shared -olibToMake.so libToMake.o -lrequestedLib
Edit 2: The command that renders the error is the second of the two, resulting in the /usr/bin/ld: cannot find -lrequestedLib being output.
Edit 3: I've confirmed that requestedLib.so is a x86_64 binary.
If you don't want to pass -L command line options to gcc(1), be sure to add the path containing the libraries to /etc/ld.so.conf or /etc/ld.so.cond.d/<something>.
Once you've installed your libraries you also need to run ldconfig(8) by hand. (Most new users forget this step because typical package managers take care of this for you when installing new libraries.)
gcc -I/home/me/lib/ -O3 -Wall -c -fmessage-length=0 -olibToMake.o ../libToMake.c
gcc -L/home/me/lib/ -shared -olibToMake.so libToMake.o -lrequestedLib
When building 64-bit shared libraries on x86_64, the -fPIC flag is usually required, or you get a recompile with -fPIC error at shared library link time.
Since you didn't use -fPIC, yet your link succeeded, you are likely using (non-default) gcc that targets i*86 (that is, produces 32-bit output). You can confirm that by running file libToMake.so.
You didn't show that command that actually fails (the one that produces cannot find -lrequestedLib error). I am guessing that that command is using a different gcc (default one?), that targets x86_64. If it looks something like
gcc main.c -L/home/me/lib -lrequestedLib
that command will ignore /home/me/lib/librequestedLib.so (because you can't link together 32-bit and 64-bit code), and will continue searching for librequestedLib elsewhere. When it can't find a 64-bit version of librequestedLib, it will produce the error message you are gettiing.
Related
For example, consider that I wrote a Fortran program in one computer and want to run it on another computer which may not have required libraries and/or has a different compiler (or even better, no Fortran compiler at all). Is it possible to create an executable with all its dependencies?
I am using gfortran (7.2.1) in Fedora 26 and sometimes use LAPACK routines in my code.
Using -static option with the program
program main
write (*,*) 'Hello'
end
I get the output
gfortran -static a.f90
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
There is no error with gfortran -static-libgfortran a.f90
In Fedora, gcc does not ship by default with static libraries.
You need to install the package glibc-static for the -static option to work, as hinted in this related question.
Note that -static-libgfortran will only do static linking of the libgfortran library and that you must have static versions of your dependencies as well.
The best option is to use Alpine Linux that uses musl libc. I highly recommend using the docker image (only 5 Mb).
I have 3 classes - I denote those by firstClass,secondClass,thirdClass.
My headers - firstClass.h, secondClass.h, thirdClass.h and sources firstClass.cpp, secondClass.cpp, thirdClass.cpp.
In class thirdClass I create instance of firstClass and two instance of secondClass.
In main.cpp I deamonize and create instance thirdClass.
I want to create static library of thirdclass and linking to main.cpp.
firstClass and thirdClass used the same library libm.a
I created library step by step as following:
g++ -c -I-/usr/include/ -I-/usr/lib/ -I-/home/projects/Learninig firstClass.cpp -lstdc++ -lm-o WsChannel.o -w -m32
g++ -c -I-/usr/include/ -I-/usr/lib/ --I-/home/projects/Learninig secondClass -lstdc++ -o secondClass.o -w -m32
g++ -c -I-/usr/include/ -I-/usr/lib/ --I-/home/projects/Learninig thirdClass.cpp -lstdc++ -lm -o thirdClass.o -w -m32
ar rcs libLearning.a firstClass.o secondClass.o thirdClass.o
g++ main.cpp -L. -lLearning -lm -o MnLearning.o -m32
Compiling was maked correctly without any errors, but when I execute program I have same error. I spent some hours on checking code, but I don't find bugs. So then maybe compiling was incorrect. I did this using some tutorial in web.
If whatever was unclearly I am ready to more explain my question.
Edit: My error:
segfault at 557400000045 ip 00005574bd509dcd sp 00007ffd9e887900 error 4 in MnLearning[5574bd4f2000+26000]
The error is surely inside your own source code. Avoid undefined behavior in it, and be scared of UB.
Your use of -I- is strange, and probably wrong. I recommend removing it (and also, at first, remove the -m32 flag if your computer and distribution is 64 bits; work first to have your program run correctly on your laptop, then port it later to 32 bits Linux by adding the -m32 flag). You might use preprocessor options like -H to be shown what files are included.
I recommend building your library and your program with some build automation tool, such as GNU make or ninja.
Configure your build to compile with all warnings and debug info, i.e. using g++ -Wall -Wextra -g with GCC. Improve your source code to get no warnings. Then use the gdb debugger to understand the behavior of your program (and library).
So then maybe compiling was incorrect.
No, the compiler is probably good, and you should trust it.
The bug is very likely to be in your own code.
My error: segfault at 557400000045 ip 00005574bd509dcd sp 00007ffd9e887900 error 4 in MnLearning[5574bd4f2000+26000]
Segmentation fault is a symptom of some error in your own code (e.g. some buffer overflow, some bad pointer dereference, etc; or other kind of UB).
You might also use valgrind.
I spent some hours on checking code, but I don't find bugs.
You did not spend enough time (some bugs may take you weeks of work to be found), and you forgot to use the debugger, a very handy tool to help you understand the behavior of your program and find bugs in it. Be aware that programming is difficult, and don't be discouraged.
I'm using the Visual C++ for Linux plugin. I can run a basic Hello world without problems. My actual project uses a .lib. It compiles fine but I get an error during linking (this is copied from Visual Studio's output pane):
ClCompile:
Starting remote build
Compiling sources:
Invoking g++
g++ -c -x c++ /home/devbox/projects/LinuxProgServ/LinuxProgServ/main.cpp -I /home/devbox/projects/LinuxProgServ/include/libuv -I /home/devbox/projects/LinuxProgServ/../include/lubuntu -I "/home/devbox/projects/LinuxProgServ/../include/lubuntu/x86_64-linux-gnu" -g2 -gdwarf-2 -o "/home/devbox/projects/LinuxProgServ/obj/x64/Debug/main.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O0 -fno-strict-aliasing -fno-omit-frame-pointer -fthreadsafe-statics -fexceptions -frtti -std=c++11
main.cpp
Done compiling '/home/devbox/projects/LinuxProgServ/LinuxProgServ/main.cpp'
Link:
Linking objects
Invoking ld
g++ -o "/home/devbox/projects/LinuxProgServ/bin/x64/Debug/LinuxProgServ.out" -Wl,--no-undefined /home/devbox/projects/LinuxProgServ/obj/x64/Debug/main.o -llibuv.lib
/usr/bin/ld: cannot find -llibuv.lib
collect2: error: ld returned 1 exit status
libuv.lib is specified in Project Properties>Linker>Input>Library Dependencies. I tried the following without success:
Copy the lib to /home/devbox/projects/lib and add that directory to
the linker command with -L, both using Visual Studio's additional
library folder field and directly in the Additional command line
options field. This results in the same final command.
Copy the lib to the output directory and set it to be copied
Add the local Windows path to Visual Studio's additional library folders
Add the linux path from #1 to Visual Studio's additional library folders
Try with another library
I made the same project but for Windows just to be sure and it works.
Am I missing something? Obviously I could just run the commands myself or use any variant of *make but that's not the point.
When you pass a library to g++ with -l, g++ helpfully prefixes the name you give with lib then looks for a file of that name with a .so or .a extension on the library search path. By convention, shared libraries (dlls) have the .so extension and static libraries the .a extension.
The route of least resistance would be to build your library with the .a extension, i.e. libuv.a then specify it to the VCLinux project library dependencies as uv. And specify the library search path with -L, as you do in your step 1.
Alternatively, you can put the full path of the library on the g++ link command line, without -l prefix, i.e. /home/devbox/projects/lib/libuv.lib and g++ will use it in the same way it uses other object files. Set via Linker/All Options/Additional Options.
Update: on reflection, this second approach won't work. Although g++ (gcc) will accept the library as an input when specified with its fully qualified path, the library must appear after the program object files for references to be resolved. Unfortunately there is no control over positioning of Additional Options in VCLinux which always puts them at the front of the parameter list on the g++ command line, i.e. before the object file(s). :(
And, at the risk of stating the obvious, the library must be built on Linux with g++ and be located on a path visible to g++ when linking your program.
I am developing and testing some code on 2 different machines: my own *buntu laptop and a remote linux machine configured by someone else.
My code uses a library, let's say libfoo, that in turn depends on, say, libbase.
I would like to keep a single makefile across both the machines, but I found out things works differently when I build my project (with GCC):
On my laptop, I need to specify -lfoo -lbase for the code to link
correctly.
On the remote machine, I only need the -lfoo flag, and the linker
somehow picks up the base library automagically.
Anyone knows what is going on? Is there any flag that might have been passed when building libfoo from source that made this automatical "depencency detection" possible?
PS: I know I could just specify every library in the make file, but keeping the list of flags to the minimum looks interesting, and I would like to know what's going on under the hood.
Yes. Both -lfoo and -lbase refer to some shared libraries libfoo.so and libbase.so (perhaps with some version number).
On the remote machine, libfoo.so was built and linked to libbase.so, perhaps from some foo1.c and foo2.c like
gcc -Wall -O -fPIC foo1.c -o foo1.pic.o
gcc -Wall -O -fPIC foo2.c -o foo2.pic.o
gcc -shared -O foo1.pic.o foo2.pic.o -lbase -o libfoo.so
(of course, probably some Makefile did run above commands thru make)
On your own laptop, you (or your distribution maker) did not link -lbase inside libfoo.so
Read Drepper's how to write shared library (long) paper (and the program library howto)
It is possible to link a shared (low-level) library inside another (higher-level) shared library (and that is not possible with static libraries libfoo.a).
You could use ldd on (the absolute path of) your libraries libfoo.so and libbase.so to find out how they have been linked.
I am trying to cross-compile linux for an ARM architecture.
The host is an X86 machine running ubuntu-jaunty. I downloaded a cross-compile toolchain for ARM from http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/. I downloaded the 2.95.3 version of the toolchain.
The problem I am having is that GCC is passing in some default flags by itself that is causing GCC to then output error:
/usr/local/arm/2.95.3/bin/arm-linux-gcc -specs=/home/feroze/wnr834m/marvell_WNR834M/gcc_specs -D__KERNEL__ -I/home/feroze/wnr834m/marvell_WNR834M/linux-88fxx81-1_1_3_gtk/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -DLED_DUAL_COLOR -DFOR_ROUTER -I/home/feroze/wnr834m/marvell_WNR834M/linux-88fxx81-1_1_3_gtk/arch/arm/mach-mv88fxx81/Soc/gpp/ -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=5 -march=armv5 -mtune=arm9tdmi -mshort-load-bytes -msoft-float -Uarm -march=strongarm -DKBUILD_BASENAME=main -c -o init/main.o init/main.c
cc1: bad value (strongarm) for -march= switch
make[1]: *** [init/main.o] Error 1
make[1]: Leaving directory `/home/feroze/wnr834m/marvell_WNR834M/linux-88fxx81-1_1_3_gtk'
I checked the whole makefile, and could not find any place where LINUX_ARM_ARCH_5 and -march=armv5 are being defined. I am defining -march=strongarm in the makefile, but then it gets appended by theh ARMv5 defines.
So, I created a defs file from gcc, modified it to only have options for ARMv4, and then used it by specifying the -specs= option. However, that still doesnt solve the problem.
Can somemone help? How do I resolve this?
Thanks!
feroze
The -march flag is set in arch/ARM/Makefile, and depends on the machine you selected in your config file. If you don't want the armv5 flag, be sure to select the correct architecture in the config file.
You should assume the kernel appended CFLAGS are right (provided your config is ok) and if your toolchain does not support one of them, then you have no choice but to cross compile a toolchain by yourself, using the original crosstol script that should work with 2.95.3
Edit : original answer
What are you trying to build ?
a 2.95.3 toolchain is fairly ancient. You should try a more recent toolchain. You can find a precompiled one here
Pick the EABI one to start.
This is not a direct answer to your problem, but if you are building the linux kernel, you should not need to mess with the Makefiles. You will get more help if you can get a more "standard" toolchain.
This won't strictly help you eliminate the issue, but you can do gcc -dM -E <empty_file.c> or gcc -dM -E -x c /dev/null to print out a listing of all the predefined #defines for gcc. Combine -dM with another flag like your -march and you might be able to track down what's causing your #define issue.
Be sure to check your environment variables, as they can persuade make to do unexpected things.
If the Makefile includes another file, it could be modifying CFLAGS before CC is called. Can you print the contents of CFLAGS just before the CC call?