简体   繁体   中英

Linker PIC error when statically linking a library built with PIC enabled

I'm building a library ( libproj ) using g++-9 and CMake (on Xenial, on Travis), so I can statically link it in a Rust crate. My build.rs sets up and runs CMake with the following config:

cmake proj-7.0.1
-DBUILD_SHARED_LIBS=ON
-DBUILD_TESTING=OFF
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_FLAGS="-std=c++11 -fPIC"
-DCMAKE_INSTALL_PREFIX=[path snipped]/out
-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64
-DCMAKE_C_COMPILER=/usr/bin/gcc-9
-DCMAKE_CXX_COMPILER=/usr/bin/g++-9
-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64
-DCMAKE_ASM_COMPILER=/usr/bin/gcc-9

Which builds and installs libproj successfully .

I then tell cargo to statically link it:

cargo:root=[path snipped]/out
cargo:rustc-link-search=native=[path snipped]/out/lib
cargo:rustc-link-lib=static=proj

However, the link step fails, saying I can't use relocation in a shared object:

note: /usr/bin/ld: [path snipped]/out/lib/libproj.a(4D_api.cpp.o): relocation
R_X86_64_32 against `.rodata.str1.8' can not be used when making a
shared object; recompile with -fPIC`

[path snipped]/out/lib/libproj.a(4D_api.cpp.o): error adding symbols: Bad value
collect2: error: ld returned 1 exit status

What am I doing wrong here? I've also tried to build libproj as a static lib by setting BUILD_SHARED_LIBS to OFF as per the install instructions , but that hasn't had any effect.

UPDATE:

I've managed to enable PIC for g++ (by default it's only enabled for gcc)

running: "cmake" "-Wdev" "--debug-output" "[snipped]/proj-7.0.1" "-DCMAKE_CXX_FLAGS=-std=c++11" "-DCMAKE_CXX_FLAGS=-fPIC" "-DBUILD_SHARED_LIBS=OFF" "-DCMAKE_INSTALL_PREFIX=[snipped]/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_C_COMPILER=/usr/bin/gcc-9" "-DCMAKE_CXX_COMPILER=/usr/bin/g++-9" "-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_ASM_COMPILER=/usr/bin/gcc-9" "-DCMAKE_BUILD_TYPE=Debug" "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"

Resulting in the following g++-9 invocation, which includes -fPIC :

/usr/bin/g++-9  -DCURL_ENABLED -DMUTEX_pthread -DPROJ_LIB=\"/[snip]/proj\" -DTIFF_ENABLED -I/[snip]/src -I/[snip]/include -I/[snip]/src -I/usr/include/x86_64-linux-gnu  -fPIC -g -fvisibility=hidden   -Wall -Wextra -Wswitch -Wshadow -Wunused-parameter -Wmissing-declarations -Wformat -Wformat-security -std=c++11 -o CMakeFiles/proj.dir/aasincos.cpp.o -c /[snip]/proj/proj-7.0.1/src/aasincos.cpp

However, I know get a completely different error (thousands of lines), that looks like my static library hasn't been correctly linked to the c++11 stdlib:

Error :
undefined reference to std::allocator<char>::allocator()

UPDATE 2:

I've managed to remove the -nodefaultlibs flag from ld . The latest g++ invocation:

/usr/bin/g++-9   -I/[snipped]/src -I/[snipped]/include -I/[snipped]/src -isystem /[snipped]/include -isystem /[snipped]/googletest  -fPIC -g -fvisibility=hidden   -Wall -Wextra -Wswitch -Wshadow -Wunused-parameter -Wmissing-declarations -Wformat -Wformat-security -pthread -std=c++11 -o CMakeFiles/proj_context_test.dir/proj_context_test.cpp.o -c /[snipped]/proj_context_test.cpp

And I've managed to add lstdc++ to the linker invocation:

"cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/[snip]/lib" "/home/travis/build/georust/proj-sys/target/debug/deps/proj_sys-95cbd73f2c3f0bde.20tasg77xuhsj5z6.rcgu.o" "/home/travis/build/georust/proj-sys/target/debug/deps/proj_sys-95cbd73f2c3f0bde.57y4784ihm3qw715.rcgu.o" "-o" "/[snip]/deps/proj_sys-95cbd73f2c3f0bde" "/home/travis/build/georust/proj-sys/target/debug/deps/proj_sys-95cbd73f2c3f0bde.3kiafs23968zh4mj.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-L" "/home/travis/build/georust/proj-sys/target/debug/deps" "-L" "/home/travis/build/georust/proj-sys/target/debug/build/proj-sys-aff2ac9d43b77886/out/lib" "-L" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-lsqlite3" "-lcurl" "-ltiff" "-lstdc++" "-Wl,-Bstatic" "-Wl,--whole-archive" "-lproj" "-Wl,--no-whole-archive" [trimmed rlib details] "-Wl,--end-group" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-2541f1e09df1c67d.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"

But the undefined reference error remains.

As I can see from your example, you have quotation marks around CMAKE_CXX_FLAGS and do not have ones around CMAKE_C_FLAGS . It looks odd.

I have built libgproj myself with cmake + your flags and with make VERBOSE=1 .

I can see, that C-files compiled without fPIC , m64 and fdata-sections . I suppose, that the cause is in the quotation marks around CMAKE_C_FLAGS . I saw your log in Travis, and there is configuration for cmake from cargo :

"cmake" "/home/travis/build/georust/proj-sys/PROJSRC/proj/proj-7.0.1" "-DBUILD_SHARED_LIBS=ON" "-DBUILD_TESTING=OFF" "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_CXX_FLAGS=-std=c++11 -fPIC" "-DCMAKE_INSTALL_PREFIX=/home/travis/build/georust/proj-sys/target/debug/build/proj-sys-03a5fe6428bb060a/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_C_COMPILER=/usr/bin/gcc-9" "-DCMAKE_CXX_COMPILER=/usr/bin/g++-9" "-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_ASM_COMPILER=/usr/bin/gcc-9"

Note, that -DCMAKE_C_FLAGS and CMAKE_CXX_FLAGS escaped with their values, and not values by itself. I suppose, that these options become in the shell:

cmake -DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64 -DCVMAKE_CXX_FLAGS=-std=c++11 -fPIC

I have tried this command, without quotation marks and cmake just ignored unknown options. So it will not fail.

I suggest you to add cmake option -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON to cmake configuration or VERBOSE=1 to the make options, if you can, and then you can see real compile options passed to gcc in Travis.

You will see somethig like this:

[ 19%] Building C object src/CMakeFiles/proj.dir/wkt1_generated_parser.c.o
cd [some path]/PROJ/cmake_build/src && /usr/bin/cc -DCURL_ENABLED -DMUTEX_pthread 
-DPROJ_LIB=\"/usr/local/share/proj\" -DTIFF_ENABLED -I[some path]PROJ/src -I[some 
path]/PROJ/include -I[some path]/PROJ/cmake_build/src  -O3 -DNDEBUG - 
fvisibility=hidden   -Wall -Wextra -Wswitch -Wshadow -Wunused-parameter -Wmissing- 
declarations -Wformat -Wformat-security -Wmissing-prototypes -std=c99 -o 
CMakeFiles/proj.dir/wkt1_generated_parser.c.o   -c [some 
path]/PROJ/src/wkt1_generated_parser.c

Conclusion:

  1. You can try adding verbosity to see real compile options.

  2. You can try to escape options properly, if it's necessary after first step.

Also I want to note, that SHARED_BUILD_LIBS=ON in my test forbids building static lib, which you want to link. When I set shared libs building setting option to OFF , static lib was built.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM