I ran into a rather bizarre issue while building a dynamic library. Here are details with a small example:
A simple file called static.h whose contents are:
#pragma once
#include <string>
std::string static_speak();
static.cpp looks like this:
#include "static.h"
std::string static_speak() {
return "I am static";
}
one can build a static library with these two files (using cmake) as:
add_library(static
static.cpp
)
Now, consider another file called shared.cpp whose contents are:
#include "static.h"
std::string dynamic_speak() {
return static_speak() + " I am dynamic";
}
One can try to build a dynamic library (again using cmake) as:
add_library(shared SHARED
shared.cpp
)
target_link_libraries(shared PRIVATE
static
)
When one tries to build the above, one will run into the following error:
[4/4] Linking CXX shared library libshared.so
FAILED: libshared.so
: && /opt/vatic/bin/clang++ -fPIC -g -shared -Wl,-soname,libshared.so -o libshared.so CMakeFiles/shared.dir/shared.cpp.o libstatic.a && :
/usr/bin/ld: libstatic.a(static.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
This makes sense. We didn't compile static with POSITION_INDEPENDENT_CODE. That is easily fixable via:
add_library(static
static.cpp
)
set_target_properties(static
PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
Everything works perfectly now when one compiles shared library.
Now here is the problem. Let's say I didn't enable POSITION_INDEPENDENT_CODE but instead disabled exceptions (!) in my code as:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
Now when I try to compile shared, everything still works!!
How are exceptions and fPIC related to each other?
Here is a repo to reproduce the issue: https://github.com/skgbanga/shared