Reputation: 115
I have seens some answers, but most of them does not work for me. So I would like to make everything clear by adding a new question, my CMakeLists.txt
is like this:
cmake_minimum_required(VERSION 3.17)
project(example)
include_directories(./)
link_directories(./)
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Os -g ${CMAKE_CXX_FLAGS}")
message("CMAKE_COMPILER_IS_GNUCXX is True")
message("option is: ${CMAKE_CXX_FLAGS}")
endif (CMAKE_COMPILER_IS_GNUCXX)
add_executable(main try.cpp)
target_link_libraries(main fun)
set_property(TARGET main PROPERTY POSITION_INDEPENDENT_CODE 1 LINK_FLAGS -pie)
add_library(fun SHARED func.cpp)
# target_compile_options(fun PUBLIC "-pie")
target_link_libraries(fun PUBLIC "-pie")
set_property(TARGET fun PROPERTY POSITION_INDEPENDENT_CODE 1)
And the source code for try.cpp
is:
#include<iostream>
#include "func.hpp"
int main() {
using namespace std;
cout << "hello from exe main" << endl;
func();
return 0;
}
The code for fun.cpp
and fun.hpp
is like this:
// func.hpp
void func();
// func.cpp
#include <iostream>
using std::cout;
using std::endl;
void func() {
cout << "hell from so func\n";
}
int main() {
cout << "hello from so main\n";
return 0;
}
My problem is that: I got the following link error when I compile it with cmake:
Scanning dependencies of target fun
[ 25%] Building CXX object CMakeFiles/fun.dir/func.cpp.o
[ 50%] Linking CXX shared library libfun.so
[ 50%] Built target fun
Scanning dependencies of target main
[ 75%] Building CXX object CMakeFiles/main.dir/try.cpp.o
[100%] Linking CXX executable main
/usr/bin/ld: CMakeFiles/main.dir/try.cpp.o: in function `main':
/home/coin/learn-coding/projects/C/cmake/try.cpp:8: undefined reference to `func()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:105: main] Error 1
make[1]: *** [CMakeFiles/Makefile2:125: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:104: all] Error 2
What is the problem with the configuration and how could I make it work ?
By the way, I tried to compile with command line:
g++ -fPIC -pie func.cpp -o libfun.so -shared
g++ try.cpp -o main -L. -lfun
Which does work when I run the generated main
, but the generated so file cannot be runnable:
$ ./main
hello from exe main
hell from so func
$ ./libfun.so
Segmentation fault (core dumped)
What did I miss here ?
Upvotes: 0
Views: 1502
Reputation: 140880
The following files based on this answer:
cat >CMakeLists.txt <<EOF
cmake_minimum_required(VERSION 3.17)
project(example)
if(CMAKE_COMPILER_IS_GNUCXX)
add_compile_options(
$<$<COMPILE_LANGUAGE:CXX>:-std=c++11>
-Wall
-Os
-g
)
endif()
add_executable(main try.cpp)
target_link_libraries(main PRIVATE fun)
add_library(fun SHARED func.cpp)
target_link_options(fun PRIVATE -Wl,-e,entry_point)
EOF
cat >func.cpp <<EOF
// func.hpp
void func();
// func.cpp
#include <iostream>
using std::cout;
using std::endl;
void func() {
cout << "hell from so func\n";
}
static inline
int lib_main() {
printf("hello from so main\n");
return 0;
}
extern "C" const char interp_section[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
extern "C" void entry_point()
{
lib_main();
exit(0);
}
EOF
cat >try.cpp <<EOF
#include<iostream>
void func();
int main() {
using namespace std;
cout << "hello from exe main" << endl;
func();
return 0;
}
EOF
when compiled with the following on my 64-bit system with glibc, it generates two files that are executable:
$ cmake -S . -B _build && cmake --build _build -- VERBOSE=1
balbla compilation output
$ _build/main
hello from exe main
hell from so func
$ _build/libfun.so
hello from so main
I replaced std::cout
with printf
because I received a segmentation fault - I suspect global constructors are not beeing run and something in iostream destructors makes it go segfault.
I think adding LINK_FLAGS -pie)
and target_link_libraries(fun PUBLIC "-pie")
makes no point, it's handled with POSITION_INDEPENDENT_CODE
property and I guess for shared library it's TRUE
anyway (but I am not sure about that).
Upvotes: 2