How to link static library with cmake in 64bit linux? - linux

I build my project with cmake in linux.
I link some static libraries by using
set(BUILD_SHARED_LIBS FALSE)
set(CMAKE_EXE_LINKER_FLAGS "-static")
target_link_libraries(MyProject /usr/lib/libImlib2.a)
It work perfectly in 32bit linux(In my case, Ubuntu), not in 64bit Ubuntu
This error message appears.
/usr/bin/ld: /usr/lib64/libImlib2.a(api.o) : relocation R_X86_64_32 againts '.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/lib64/libImlib2.a : could not read symbols: Bad value
collect2:ld returned 1 exit status
Some document what I found says it's problem about 64bit linux, need to set flags.
So I add
set(CMAKE_CXX_FLAGS_DEBUG "-fPIC")
set(CMAKE_CXX_FLAGS_RELEASE "-fPIC")
but nothing is changed.
Could you give me some advice about what I should do?
Thank you very much for reading this question.

You need to build Imlib2 (~all shared libraries, in fact) yourself with -fPIC on. Take a look at this article for an explanation of why this is happening.

The fix that issue you need to recompile with -fPIC for x86_64 architecture.
More information about that is available at:
http://www.technovelty.org/c/position-independent-code-and-x86-64-libraries.html
https://en.wikipedia.org/wiki/Position-independent_code
Add following lines into your main CMakeLists.txt
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
ADD_DEFINITIONS(-fPIC)
ENDIF()

Related

Is it possible to compile a standalone Fortran executable in Linux?

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).

DMD2 fails to compile shared library on Linux, amd64

I've been programming on a 32 bit machine, until recently, I upgraded to a 64 bit one. I'm using the latest version of DMD (amd64), on xubuntu 16.04 (amd64).
Before the upgrade, I could easily compile shared libs using dmd -shared 'FILES', but now, it gives an error.
I have a file named q.d:
module q;
export extern(C) int abcd(){
return 4;
}
And now when I do dmd -shared 'q.d', I get this:
nafees#OptiPlex-755:~/Desktop/temp$ dmd -shared q.d
/usr/bin/ld: q.o: relocation R_X86_64_32 against `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC
q.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
--- errorlevel 1
and when I do dmd -shared -fPIC q.d:
nafees#OptiPlex-755:~/Desktop/temp$ dmd -shared -fPIC q.d
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(exception_224_3b4.o): relocation R_X86_64_32 against `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC
/usr/lib/x86_64-linux-gnu/libphobos2.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
--- errorlevel 1
How can I get it to compile?
EDIT: The library compiles fine if I use the -m32 flag.
Oh, I just realized I know this problem, sorry it took me so long to realize it though.
You just need to compile against the shared lib Phobos as well to make the shared lib on 64 bit.
dmd -shared q -m64 -fPIC -defaultlib=libphobos2.so
The -defaultlib switch tells it to use an alternate library. By specifying the .so (as opposed to the default static link with a .a file), it uses the shared lib - which happens to be compiled with -fPIC too, so it is all compatible.
Among other advantages here is that one runtime can be shared across all the shared objects and D executables, which means a lot of things just work when you distribute them all (though note you may also need to compile the program that loads this so with the -defaultlib switch too). On 32 bit, the library isn't built with these options regardless... but the result is you can see link errors for multiple definitions in some circumstances.
The one thing to be careful though is that libphobos2.so file is now a runtime dependency too, be sure to distribute it with your own library builds together. You might need to set the LD_LIBRARY_PATH or install it globally for the program to start up correctly, just like any other library (and you might want to version it too btw)

musl fails to link libc.a into shared library

I have a C99 shared library that I want to link in a few statically static libraries (via --whole-archive). Note: All the static libs are built with -fPIC
I also would like to build a universal linux binary and thus have decided to use musl. When I try to link in the static libc.a from musl I get the following error:
# Building shared library tgt/Linux-x86_64/mylib/lib/mylib.so
/root/mylib/./tgt/Linux-x86_64/libmusl/bin/musl-gcc -Wl,-whole-archive -L./tgt/Linux-x86_64/libmusl/lib -L./tgt/Linux-x86_64/libz/lib -L./tgt/Linux-x86_64/libssl/lib -L./tgt/Linux-x86_64/libsasl/lib -L./tgt/Linux-x86_64/librdkafka/lib -L./tgt/Linux-x86_64/libcurl/lib -L./tgt/Linux-x86_64/libgjalloc/lib -L./tgt/Linux-x86_64/libavro/lib -L./tgt/Linux-x86_64/libunwind/lib -l:libc.a -l:libpthread.a -l:libz.a -l:libssl.a -l:libcrypto.a -l:libsasl2.a -l:libm.a -l:librt.a -l:libcrypt.a -l:libunwind-x86_64.a -l:librdkafka.a -l:libcurl.a -l:libgjalloc.a -l:libavro.a -Wl,-no-whole-archive -shared -fPIC -o tgt/Linux-x86_64/mylib/lib/mylib.so ./tgt/Linux-x86_64/mylib/obj/myfile.o ./tgt/Linux-x86_64/mylib/obj/myotherfile.o ./tgt/Linux-x86_64/mylib/obj/cJSON.o
/usr/bin/ld: ./tgt/Linux-x86_64/libmusl/lib/libc.a(exit.lo): relocation R_X86_64_PC32 against undefined hidden symbol `__fini_array_start' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [tgt/Linux-x86_64/mylib/lib/mylib.so] Error 1
My musl build looks like:
cd mystatic_libs_build_dir/musl; \
./configure CFLAGS='-fPIC' \
--enable-shared \
--enable-static \
--prefix=/root/mylib/tgt/Linux-x86_64/libmusl; \
make; make install;
# libmusl is available
exit.lo will be written in assembler which is why your CFLAGS='-fPIC' is not having the effect you intend. This is either 1. a bug in 'musl' or 2. intentional and they do not support statically linking into .so's.
I would assume that it is unintentional and file a bug against 'musl'
You could also edit the asm yourself if you need a fix quickly.
Finally you might be able to configure musl to build with no asm?
Slightly off topic, but other options for a universal binary are:
Simply linking against glibc on the oldest version of Linux that you support.
Rather than struggling with a dependency on 'musl', simply use the Linux kernel api's directly.
Recompile musl as long as your own code with CFLAGS="-fPIC -Wa,-mrelax-relocations=no" (your binutils version must be >=2.27).

makefile recompile with -fPIC

So, I'm trying to build something in make. I produced the files via cmake, went to the appropriate folder for the build file, and:
make
Scanning dependencies of target Spenvis
[ 33%] Building CXX object source/CMakeFiles/Spenvis.dir/pySpenvisCSV.cc.o
[ 66%] Building CXX object source/CMakeFiles/Spenvis.dir/SpenvisCSV.cc.o
[100%] Building CXX object source/CMakeFiles/Spenvis.dir/SpenvisCSVCollection.cc.o
Linking CXX shared library libSpenvis.so
/usr/bin/ld: /usr/local/lib64/libpython2.7.a(abstract.o): relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib64/libpython2.7.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make[2]: *** [source/libSpenvis.so] Error 1
make[1]: *** [source/CMakeFiles/Spenvis.dir/all] Error 2
make: *** [all] Error 2
I'm a bit of a novice as far as make/cmake goes. I'm uncertain where to go from here. I've looked at several suggestions, but I'm uncertain which are relevant to my particular problem and how to implement the suggested fixes in the first place.
Halp!
There are two CMakeLists.txt files within the python_utilities directory. I'll include both. One from spenvis_csv/source:
# Make sure the compiler can find include files
include_directories (${PYSPENVIS_SOURCE_DIR})
# get boost
set(Boost_USE_STATIC_LIBS OFF)
#set(Boost_USE_MULTIEADED ON)
find_package(Boost COMPONENTS
python
REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
# get python
include(FindPythonLibs)
set(PythonLibs_USE_STATIC_LIBS OFF)
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
link_directories(${PYTHON_LIBRARIES})
#
add_library(Spenvis SHARED pySpenvisCSV.cc SpenvisCSV.cc SpenvisCSVCollection.cc)
TARGET_LINK_LIBRARIES(Spenvis ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
And then the second much shorter one:
cmake_minimum_required (VERSION 2.6)
set (Boost_NO_BOOST_CMAKE=ON)
project (PYSPENVIS)
add_subdirectory ("source")
You are linking against the static python library which, I believe, is typically not going to be built with -fPIC so it's code won't be relocatable. Your Spenvis target, on the other hand, is a shared library and will be built with -fPIC, but linking in non-PIC code isn't going to work like this. This is what the linker is saying to you.
If it is possible, can you link against the shared version of the python library (i.e. libpython.so.2.7 or something similar, depending on how your system names it)? I would have expected CMake to prefer linking to the shared library by default, so I'm wondering if either:
You are missing the shared libpython library on your system (unlikely, but possible).
You've included some CMake options which tell it to prefer linking in static libraries.
You've explicitly given CMake the static python library to link in somehow.
If you are using the FindPythonLibs CMake module, I would have expected that to be giving you the shared python library in the PYTHON_LIBRARIES variable, if it is available on your system. If you update your question to include your CMakeLists.txt file, that may help identify the problem.

Eclipse-CDT on x86_64 system cannot link to shared library [duplicate]

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.

Resources