I want to transfer an old side project to CMake. Previously it used a Makefile with custom variables, defines and etc. I specified the same flags to compile various configurations. I did it this way:
cmake_minimum_required(VERSION 3.2.2)
project(wise_RK)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(SOURCES main.cpp devices/RK.cpp LogWriter/LogWriter.cpp)
set(CMAKE_CXX_FLAGS "-DIMA -std=c++11 -Wall -Wextra -c -O2 -MMD -MP -MF '$#.d'")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories(
structs
devices
LogWriter
/home/data/lib/wise_versioning
/home/data/lib/wisenet
/home/data/lib/wise_log
/home/data/lib/wise_rs_device
/home/data/lib/json
)
# wise_rs_device
add_library(wise_rs_device STATIC IMPORTED GLOBAL)
set_target_properties(wise_rs_device PROPERTIES
IMPORTED_LOCATION "/home/data/lib/wise_rs_device/libwise_rs_device.a"
INTERFACE_INCLUDE_DIRECTORIES "/home/data/lib/wise_rs_device/"
)
# wisenet
add_library(wisenet STATIC IMPORTED GLOBAL)
set_target_properties(wisenet PROPERTIES
IMPORTED_LOCATION "/home/data/lib/wisenet/libwise_net_rs485.so"
INTERFACE_INCLUDE_DIRECTORIES "/home/data/lib/wisenet/"
)
#wise_log
add_library(wise_log STATIC IMPORTED GLOBAL)
set_target_properties(wise_log PROPERTIES
IMPORTED_LOCATION "/home/data/lib/wise_log/Release/GNU-Linux/libwise_log.so"
INTERFACE_INCLUDE_DIRECTORIES "/home/data/lib/wise_log/"
)
add_executable(wise_rk ${SOURCES})
target_link_libraries(wise_rk PRIVATE wise_rs_device wisenet wise_log)
add_definitions(-DSOME_IMPORTANT_DEFINITION)
-D is define of various configurations.
In the Makefile, the list of project object files (not libraries) involved in the assembly was like this:
OBJECTS:=$(shell find * -type f -name "*.cpp" | sed "s/\.cpp/\.o /" | sort)
DEPENDS:=$(addprefix build/$(CONF)/, ${OBJECTS:.o=.o.d})
-include ${DEPENDS}
When I built my CMake:
/usr/local/bin/cmake -E cmake_link_script CMakeFiles/wise_rk.dir/link.txt --verbose=1
/usr/bin/c++ -DIMA -std=c++11 -Wall -Wextra -c -O2 -MMD -MP -MF '$#.d' CMakeFiles/wise_rk.dir/main.cpp.o CMakeFiles/wise_rk.dir/devices/RK.cpp.o CMakeFiles/wise_rk.dir/LogWriter/LogWriter.cpp.o -o wise_rk -rdynamic /home/data/lib/wise_rs_device/libwise_rs_device.a /home/data/lib/wisenet/libwise_net_rs485.so /home/data/lib/wise_log/Release/GNU-Linux/libwise_log.so
c++: warning: CMakeFiles/wise_rk.dir/main.cpp.o: linker input file unused because linking not done
c++: warning: CMakeFiles/wise_rk.dir/devices/RK.cpp.o: linker input file unused because linking not done
c++: warning: CMakeFiles/wise_rk.dir/LogWriter/LogWriter.cpp.o: linker input file unused because linking not done
c++: warning: /home/data/lib/wise_rs_device/libwise_rs_device.a: linker input file unused because linking not done
c++: warning: /home/data/lib/wisenet/libwise_net_rs485.so: linker input file unused because linking not done
c++: warning: /home/data/lib/wise_log/Release/GNU-Linux/libwise_log.so: linker input file unused because linking not done
make[2]: Leaving directory `/home/anzipex/Downloads/wise_RK/build'
/usr/local/bin/cmake -E cmake_progress_report /home/anzipex/Downloads/wise_RK/build/CMakeFiles 1 2 3
[100%] Built target wise_rk
make[1]: Leaving directory `/home/anzipex/Downloads/wise_RK/build'
/usr/local/bin/cmake -E cmake_progress_start /home/anzipex/Downloads/wise_RK/build/CMakeFiles 0
I do not know what to do next to solve this kind of problem.
I changed all the .so libs to SHARED. And also removed part of flags -c -O2 -MMD -MP -MF '$#.d' like #Botje wrote. Seems like project built.
Related
I made simple kernel for studying purposes. I cange MakeFile to CMakeLists.txt to automatically genreate my kernel form sources. But I encounter this relocation error.
/usr/bin/ld: CMakeFiles/x86_64-kernel.bin.dir/src/arch/x86_64/multiboot2_boot32.asm.o: relocation R_X86_64_32 against `.boot.32' can not be used when making a PIE object; recompile with -fPIE
To solve this I think I have to remove -fno-pie in linker flags. By checking log of gcc with make VERBOSE=1, I can found that there is CMAKE_CXX_FLAGS at my linker flags.
[100%] Linking CXX executable x86_64-kernel.bin
/usr/bin/cmake -E cmake_link_script CMakeFiles/x86_64-kernel.bin.dir/link.txt --verbose=1
/usr/bin/gcc -mno-red-zone -mcmodel=large -mno-sse -ffreestanding -nostdlib -fno-pie -fno-pic -rdynamic -n -T /home/ahn9807/study/AOS/src/arch/x86_64/linker.ld CMakeFiles/x86_64-kernel.bin.dir/src/arch/x86_64/kernel_entry.cpp.o CMakeFiles/x86_64-kernel.bin.dir/src/arch/x86_64/multiboot2_boot32.asm.o CMakeFiles/x86_64-kernel.bin.dir/src/arch/x86_64/multiboot2_boot64.asm.o CMakeFiles/x86_64-kernel.bin.dir/src/arch/x86_64/multiboot2_header.asm.o -o x86_64-kernel.bin
/usr/bin/ld: CMakeFiles/x86_64-kernel.bin.dir/src/arch/x86_64/multiboot2_boot32.asm.o: relocation R_X86_64_32 against `.boot.32' can not be used when making a PIE object; recompile with -fPIE
How can I remove this CMAKE_CXX_FLAGS in my LINKER_FLAGS? Why camke automatically insert this useless options for my MakeFile? Is there any other way to bypass this error messages? I hope your answers...
And this is my CMakeLists.txt.
cmake_minimum_required(VERSION 2.17)
project(kernell)
set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 1)
set(CMAKE_CXX_STANDAED 17)
set(KERNEL_BIN "x86_64-kernel.bin")
set(CMAKE_BINARY_DIR ${PROJECT_SOURCE_DIR}/build)
set(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/src/arch/x86_64/linker.ld)
set(GRUB_CFG ${PROJECT_SOURCE_DIR}/src/arch/x86_64/grub.cfg)
set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-red-zone -mcmodel=large -mno-sse -ffreestanding -nostdlib -fno-pie -fno-pic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=large -mno-sse -ffreestanding -nostdlib -fno-pie -fno-pic")
set(CMAKE_ASM_FLAGS "{CMAKE_ASM_FLAGS} -felf64")
set(CMAKE_CXX_COMPILER "/usr/bin/gcc")
set(CMAKE_C_COMPILER "/usr/bin/g++")
set(CMAKE_LINKER "/usr/bin/ld")
enable_language(ASM_NASM)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include/
)
add_executable(
${KERNEL_BIN}
# Header files
include/arch/x86_64/kernel_entry.h
include/arch/x86_64/vga_text.h
include/arch/x86_64/multiboot2.h
# Source files
src/arch/x86_64/kernel_entry.cpp
src/arch/x86_64/multiboot2_boot32.asm
src/arch/x86_64/multiboot2_boot64.asm
src/arch/x86_64/multiboot2_header.asm
)
set_target_properties(${KERNEL_BIN} PROPERTIES LINK_FLAGS "-n -T ${LINKER_SCRIPT}")
add_custom_command(TARGET ${KERNEL_BIN} POST_BUILD
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/build/isofiles/boot/grub
COMMAND cp ${KERNEL_BIN} ${CMAKE_BINARY_DIR}/build/isofiles/boot/${KERNEL_BIN}
COMMAND cp ${GRUB_CFG} ${CMAKE_BINARY_DIR}/build/isofiles/boot/grub
COMMAND grub-mkrescue -o kernel.iso ${CMAKE_BINARY_DIR}/build/isofiles
COMMAND rm -r ${CMAKE_BINARY_DIR}/build/
)
Finally I figure out how to remove useless linker argument from cmake. CMAKE uses compiler as an default linker. In my case, gcc is default linker because I build my source code with gcc. The important fact is that cmake also berings CMAKE_CXX_FLAGS with gcc in linking stage. So we have to use custom linker as like this to avoid cmake linking our oject files with default compiler linker.
set(CMAKE_LINKER "/usr/bin/ld")
set(CMAKE_LINKER_FLAGS "-n -T ${LINKER_SCRIPT}")
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> ${CMAKE_LINKER_FLAGS} <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
In this way, we can automatically generate executable with custom linker.
opencv has been setup in my project but the imported c++ files are giving error
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':app:externalNativeBuildDebug'.
Build command failed.
Error while executing process C:\src\Android\Sdk\cmake\3.10.2.4988404\bin\ninja.exe with arguments {-C C:\Users\azad prajapat\AndroidStudioProjects\sunscape\sunscape\android\app.cxx\cmake\debug\armeabi-v7a native-panorama}
ninja: Entering directory `C:\Users\azad prajapat\AndroidStudioProjects\sunscape\sunscape\android\app.cxx\cmake\debug\armeabi-v7a'
[1/2] Building CXX object CMakeFiles/native-panorama.dir/src/main/jni/com_example_sunscape_NativePanorama.cpp.o
FAILED: CMakeFiles/native-panorama.dir/src/main/jni/com_example_sunscape_NativePanorama.cpp.o
C:\src\Android\Sdk\ndk\22.0.7026061\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi24 --gcc-toolchain=C:/src/Android/Sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/src/Android/Sdk/ndk/22.0.7026061/toolchains/llvm/prebuilt/windows-x86_64/sysroot -Dnative_panorama_EXPORTS -I../../../../src/main/jniIncludes -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -std=gnu++11 -Wno-error=format-security -frtti -fexceptions -stdlib=libstdc++ -O0 -fPIC -MD -MT CMakeFiles/native-panorama.dir/src/main/jni/com_example_sunscape_NativePanorama.cpp.o -MF CMakeFiles\native-panorama.dir\src\main\jni\com_example_sunscape_NativePanorama.cpp.o.d -o CMakeFiles/native-panorama.dir/src/main/jni/com_example_sunscape_NativePanorama.cpp.o -c ../../../../src/main/jni/com_example_sunscape_NativePanorama.cpp
In file included from ../../../../src/main/jni/com_example_sunscape_NativePanorama.cpp:3:
In file included from ../../../../src/main/jniIncludes\opencv2/opencv.hpp:52:
In file included from ../../../../src/main/jniIncludes\opencv2/core.hpp:52:
**../../../../src/main/jniIncludes\opencv2/core/cvdef.h:183:10: fatal error: 'limits' file not found
#include
1 error generated.**
ninja: build stopped: subcommand failed.
my cmake file
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++")
SET(CMAKE_EXE_LINKER_FLAGS "-lopencv_stitching")
include_directories(${CMAKE_SOURCE_DIR}/src/main/jniIncludes)
add_library(native-panorama
SHARED
src/main/jni/com_example_sunscape_NativePanorama.cpp)
add_library(lib_opencv SHARED IMPORTED)
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libopencv_java4.so)
find_library(log-lib
log)
target_link_libraries(native-panorama ${log-lib} lib_opencv)
gradle file
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=clang++","-DANDROID_ARM_NEON=TRUE" ,"-DANDROID_STL_FORCE_FEATURES=OFF"
cppFlags "-std=gnu++11", "-Wno-error=format-security","-frtti -fexceptions"
}
}
ndk {
abiFilters 'x86', 'x86_64', 'armeabi-v7a',
'arm64-v8a'
}
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++")
Don't do that.
When building a C++ executable under Linux using cmake 3.7, I see a -std=gnu++11 flag being added to compile flags. The problem is, I'm already manually adding a -std=c++1z flag, and this new one overwrites mine. This happens only for executables, but I cannot find this being mentioned in the docs. The CMAKE_CXX_STANDARD is empty, and setting the CXX_STANDARD property on the target has no effect. Is there a way to remove this flag?
This seems to be not only limited to executables.
Here's my (simplified) cmake:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z")
find_boost(serialization system)
find_package(Qt5Widgets REQUIRED)
link_directories(${Boost_LIBRARY_DIRS})
include_directories(
${Boost_INCLUDE_DIRS}
${ZMQ_INCLUDE_DIR}
${CPPZMQ_INCLUDE_DIR}
)
if(WIN32)
add_definitions(-DNOMINMAX)
endif()
add_executable(
${PROFILER_CLIENT_NAME}
main.cpp
MainWindow.cpp
MainWindow.h
ProfilerWidget.cpp
ProfilerWidget.h
TimelineWidget.cpp
TimelineWidget.h
ZmqReceiver.cpp
ZmqReceiver.h
)
add_dependencies(${PROFILER_CLIENT_NAME} boost zeromq)
target_link_libraries(
${PROFILER_CLIENT_NAME}
PRIVATE ${PROFILER_NAME}
PRIVATE ${Boost_LIBRARIES}
PRIVATE Qt5::Widgets
)
As #florian suspected, it's Qt5 that's polluting your compile commands. Using a similar CMakeLists.txt:
cmake_minimum_required(VERSION 3.7.2 FATAL_ERROR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z")
set(BOOST_ROOT "/usr/local/opt/boost#1.55")
execute_process(COMMAND brew --prefix qt5
COMMAND tr -d \\n
OUTPUT_VARIABLE QT5_BREW_PATH)
find_package(Boost COMPONENTS serialization system)
find_package(Qt5 COMPONENTS Widgets HINTS ${QT5_BREW_PATH})
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
add_executable(foo main.cpp)
target_link_libraries(foo
PRIVATE ${Boost_LIBRARIES}
PRIVATE Qt5::Widgets
)
I configured and built a dummy executable. You can plainly see the -std=c++1z and the -std=gnu++11 on the compile line:
❯ make VERBOSE=1
/usr/local/Cellar/cmake/3.7.2/bin/cmake -H/Users/nega/foo -B/Users/nega/foo --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/Cellar/cmake/3.7.2/bin/cmake -E cmake_progress_start /Users/nega/foo/CMakeFiles /Users/nega/foo/CMakeFiles/progress.marks
/Applications/Xcode.app/Contents/Developer/usr/bin/make -f CMakeFiles/Makefile2 all
/Applications/Xcode.app/Contents/Developer/usr/bin/make -f CMakeFiles/foo.dir/build.make CMakeFiles/foo.dir/depend
cd /Users/nega/foo && /usr/local/Cellar/cmake/3.7.2/bin/cmake -E cmake_depends "Unix Makefiles" /Users/nega/foo /Users/nega/foo /Users/nega/foo /Users/nega/foo /Users/nega/foo/CMakeFiles/foo.dir/DependInfo.cmake --color=
/Applications/Xcode.app/Contents/Developer/usr/bin/make -f CMakeFiles/foo.dir/build.make CMakeFiles/foo.dir/build
[ 50%] Building CXX object CMakeFiles/foo.dir/main.cpp.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -I/usr/local/opt/boost#1.55/include -iframework /usr/local/opt/qt5/lib -isystem /usr/local/opt/qt5/lib/QtWidgets.framework/Headers -isystem /usr/local/opt/qt5/lib/QtGui.framework/Headers -isystem /System/Library/Frameworks/OpenGL.framework/Headers -isystem /usr/local/opt/qt5/lib/QtCore.framework/Headers -isystem /usr/local/opt/qt5/./mkspecs/macx-clang -std=c++1z -fPIC -std=gnu++11 -o CMakeFiles/foo.dir/main.cpp.o -c /Users/nega/foo/main.cpp
[100%] Linking CXX executable foo
/usr/local/Cellar/cmake/3.7.2/bin/cmake -E cmake_link_script CMakeFiles/foo.dir/link.txt --verbose=1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -std=c++1z -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/foo.dir/main.cpp.o -o foo -L/usr/local/opt/boost#1.55/lib -Wl,-rpath,/usr/local/opt/boost#1.55/lib /usr/local/opt/boost#1.55/lib/libboost_serialization-mt.dylib /usr/local/opt/boost#1.55/lib/libboost_system-mt.dylib /usr/local/opt/qt5/lib/QtWidgets.framework/QtWidgets /usr/local/opt/qt5/lib/QtGui.framework/QtGui /usr/local/opt/qt5/lib/QtCore.framework/QtCore
[100%] Built target foo
/usr/local/Cellar/cmake/3.7.2/bin/cmake -E cmake_progress_start /Users/nega/foo/CMakeFiles 0
If you comment out the Qt5 usage in our CMakeLists.txt and configure and build again, you'll see the -std=gnu++11 disappear (along with the -fPIC which Qt is also adding).
CMakeLists.txt:
cmake_minimum_required(VERSION 3.7.2 FATAL_ERROR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z")
set(BOOST_ROOT "/usr/local/opt/boost#1.55")
execute_process(COMMAND brew --prefix qt5
COMMAND tr -d \\n
OUTPUT_VARIABLE QT5_BREW_PATH)
find_package(Boost COMPONENTS serialization system)
#find_package(Qt5 COMPONENTS Widgets HINTS ${QT5_BREW_PATH})
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
add_executable(foo main.cpp)
target_link_libraries(foo
PRIVATE ${Boost_LIBRARIES}
# PRIVATE Qt5::Widgets
)
make output (abridged):
[...]
[ 50%] Building CXX object CMakeFiles/foo.dir/main.cpp.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -I/usr/local/opt/boost#1.55/include -std=c++1z -o CMakeFiles/foo.dir/main.cpp.o -c /Users/nega/foo/main.cpp
[100%] Linking CXX executable foo
/usr/local/Cellar/cmake/3.7.2/bin/cmake -E cmake_link_script CMakeFiles/foo.dir/link.txt --verbose=1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -std=c++1z -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/foo.dir/main.cpp.o -o foo -L/usr/local/opt/boost#1.55/lib -Wl,-rpath,/usr/local/opt/boost#1.55/lib /usr/local/opt/boost#1.55/lib/libboost_serialization-mt.dylib /usr/local/opt/boost#1.55/lib/libboost_system-mt.dylib
[100%] Built target foo
[...]
Unfortunately, after some brief digging I couldn't see where Qt was setting -std=gnu++11 in its *Config.cmake files. It must be reaching into CMake more than just a few grep's could find. Maybe reading through cmake --trace will provide some insight.
Curiously though, what ever it's doing respects CXX_STANDARD. If we tweak our original CMakeLists.txt and configure and build again:
CMakeLists.txt (abridged):
cmake_minimum_required(VERSION 3.7.2 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z")
set(BOOST_ROOT "/usr/local/opt/boost#1.55")
execute_process(COMMAND brew --prefix qt5
[...]
make output (abridged):
[...]
[ 50%] Building CXX object CMakeFiles/foo.dir/main.cpp.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -I/usr/local/opt/boost#1.55/include -iframework /usr/local/opt/qt5/lib -isystem /usr/local/opt/qt5/lib/QtWidgets.framework/Headers -isystem /usr/local/opt/qt5/lib/QtGui.framework/Headers -isystem /System/Library/Frameworks/OpenGL.framework/Headers -isystem /usr/local/opt/qt5/lib/QtCore.framework/Headers -isystem /usr/local/opt/qt5/./mkspecs/macx-clang -std=c++1z -fPIC -std=gnu++14 -o CMakeFiles/foo.dir/main.cpp.o -c /Users/nega/foo/main.cpp
[100%] Linking CXX executable foo
/usr/local/Cellar/cmake/3.7.2/bin/cmake -E cmake_link_script CMakeFiles/foo.dir/link.txt --verbose=1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -std=c++1z -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/foo.dir/main.cpp.o -o foo -L/usr/local/opt/boost#1.55/lib -Wl,-rpath,/usr/local/opt/boost#1.55/lib /usr/local/opt/boost#1.55/lib/libboost_serialization-mt.dylib /usr/local/opt/boost#1.55/lib/libboost_system-mt.dylib /usr/local/opt/qt5/lib/QtWidgets.framework/QtWidgets /usr/local/opt/qt5/lib/QtGui.framework/QtGui /usr/local/opt/qt5/lib/QtCore.framework/QtCore
[100%] Built target foo
[...]
You can see that the (Qt added) -fPIC -std=gnu++11 is now -fPIC -std=gnu++14. Unfortunately this won't help you until CMake 3.8.0 is released and its CXX_STANDARD/CMAKE_CXX_STANDARD will understand "C++17".
This question already has an answer here:
How to link against PIC version of a library's dependency in CMake?
(1 answer)
Closed 6 years ago.
I'm trying to create a static library with -fPIC specified.
add_library(cpp-netlib_pic
STATIC
${SRCS})
set_property(TARGET cpp-netlib_pic PROPERTY POSITION_INDEPENDENT_CODE)
This doesn't work.
The library (cpp-netlib_pic) is built without the -fPIC flags.
Other targets which link against cpp-netlib_pic
do however, have -fPIC added to their compiler flags, but the linking fails because cpp-netlib_pic didn't.
Here foo will have -fPIC added:
add_library(foo
SHARED
${SRCS})
target_link_libraries(foo cpp-netlib_pic)
I've proved this to myself with make VERBOSE=1
[ 87%] Building CXX object third_party/cpp-netlib/CMakeFiles/cpp-netlib_pic.dir/src/server_request_parsers_impl.cpp.o
/usr/bin/c++ ... -std=c++14 -Werror -Wall -Wextra ... \
-o CMakeFiles/cpp-netlib_pic.dir/src/server_request_parsers_impl.cpp.o \
-c .../third_party/cpp-netlib/src/server_request_parsers_impl.cpp
Note no -fPIC here.
When building target foo which uses cpp-netlib_pic, -fPIC appears:
[ 93%] Building CXX object foo.cc.o
/usr/bin/c++ ... -std=c++14 -Werror -Wall -Wextra ... -fPIC ... \
-o CMakeFiles/foo_shared_lib.dir/foo.cc.o \
-c .../foo/foo.cc
How can I configure CMake to build the 1st library (cpp-netlib_pic) with -fPIC?
You seem to have forgotten the ON:
set_property(TARGET cpp-netlib_pic PROPERTY POSITION_INDEPENDENT_CODE ON)
When using Qt CMake automatically adds the -fPIC flag to compile options. I want to use -fpic, so I went through all Cmake variables and replaced -fPIC with -fpic.
cmake_minimum_required(VERSION 3.5)
project(sss)
find_package(Qt5 REQUIRED COMPONENTS Core Sql)
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if (NOT "${${_variableName}}" STREQUAL "")
string(REPLACE "-fPIC" "-fpic" ${_variableName} ${${_variableName}})
string(REPLACE "-fPIE" "-fpie" ${_variableName} ${${_variableName}})
endif()
#message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
set(CMAKE_CXX_FLAGS "-fpie")
set(CMAKE_EXE_LINKER_FLAGS "-fpie -pie")
add_executable(sss main.cpp)
target_link_libraries(sss Qt5::Core Qt5::Sql)
main.cpp contains
#include <QSqlDatabase>
int main(){
QSqlDatabase::addDatabase("QPSQL");
}
Unfortunately CMake still adds the -fPIC flag, althoguh the listed variables does not contain it:
Building CXX object CMakeFiles/sss.dir/main.cpp.o
/usr/bin/c++ -DQT_CORE_LIB -DQT_NO_DEBUG -DQT_SQL_LIB -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -isystem /usr/include/x86_64-linux-gnu/qt5/QtSql -fPIC -o CMakeFiles/sss.dir/main.cpp.o -c src/main.cpp
How can I replace -fPIC with -fpic?
Turning my comment into an answer
Your code overwrites CMake global variables like CMAKE_CXX_COMPILE_OPTIONS_PIC or CMAKE_CXX_COMPILE_OPTIONS_PIE.
But Qt brings its own -fPIC option through target properties. The Qt5::Core target does have INTERFACE_COMPILE_OPTIONS set to -fPIC (see e.g. here).
Try overwriting the target properties by adding
set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_OPTIONS "-fpic")
after your find_package(Qt5 ...) call.