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.
Related
I am reading a C++ project and want to print out the #ifdef _DEBUG message when running the program at a Linux terminal. For example:
#ifdef _DEBUG
cout << s1 << endl;
#endif
Currently, it doesn't print out the debug info above, but only prints out logger info as below:
logger_(MY_MODULE_LOG_ERROR, "config is null ");
The project is made through cmake. It has a top level CMakeLists.txt file, in addition to each CZMakeLists.txt under src/ and its subdirectories. The content of the top-level CMakelists.txt is below:
cmake_minimum_required (VERSION 3.12)
project (TAGS_NEW )
set(CMAKE_VERBOSE_MAKEFILE true)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -w")
# gdb debug : -g
add_compile_options(
-Wall
-Wextra
-Wstrict-aliasing
-Wno-unused-parameter
-Wno-missing-field-initializers
-Wchar-subscripts
-Wpointer-arith
-Wformat
-Wformat-security
-Werror=format-security
-fstack-protector-all
-fPIE
-fpie
-fPIC
-fpic
-pipe
-fdata-sections
-ffunction-sections
)
option(DEBUG_OUTPUT "option for debug out" OFF)
if (DEBUG_OUTPUT)
add_definitions(-D_DEBUG)
endif()
# option(DEBUG_GDB "option for gdb debug" OFF)
# if (DEBUG_GDB)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb")
# endif()
# set(CMAKE_BUILD_TYPE "Debug")
option(CMAKE_BUILD_TYPE "option for gdb debug" DEBUG)
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
option(COMPILE_DLL "option for generate dynamic library" OFF)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${TAGS_NEW_SOURCE_DIR}/output)
add_definitions(-D_Python_CALL -D_ChaiScriptON)
include_directories(${TAGS_NEW_SOURCE_DIR}/third-party/include ${TAGS_MINING_NEW_SOURCE_DIR}/include )
# $(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")
find_package( PythonLibs 2.7 REQUIRED )
include_directories( ${PYTHON_INCLUDE_DIRS} )
link_directories(${TAGS_NEW_SOURCE_DIR}/third-party/lib)
add_subdirectory (src)
execute_process(COMMAND sh genGlobal.sh ${TAGS_NEW_SOURCE_DIR} WORKING_DIRECTORY ${TAGS_NEW_SOURCE_DIR})
I tried to change the OFF to ON in the line below, but it doesn't help:
option(DEBUG_OUTPUT "option for debug out" OFF)
I am new to CMake. How to print out all the debug info?
Options are meant to be provided from outside not to be modified in the CMake file. In fact you can't change an option with the option command once it is set in the cache (after the first CMake run). So run your cmake like this: cmake -DDEBUG_OUTPUT=ON .. and you will get your macro defined.
I tried to use -rdynamic option in my CMakeLists.txt file, like this:
cmake_minimum_required(VERSION 3.5)
project(Tmuduo CXX)
...
set(CMAKE_CXX_STANDARD 11)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(-Wthread-safety )
endif()
add_compile_options(
# -DVALGRIND
-Wall
-Wno-unused-parameter
-Woverloaded-virtual
-Wpointer-arith
-Wwrite-strings
-O3
-rdynamic
)
...
When I use cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang and make VERBOSE=1, I got some message as follow:
Just as you can see, the -rdynamic compile option did appear in the clang++ command and the compiler also complainted that the argument was unused. But when I used the command below, something strange happended.
clang++ -I/home/phoenix/MyProject/Tmuduo -g -Wthread-safety -Wall -Wno-unused-parameter -Woverloaded-virtual -Wpointer-arith -Wwrite-strings -rdynamic -std=gnu++11 test/Exception_test.cc base/Exception.cc base/CurrentThread.cc -o exception_test -O3
Everything goes well. This time, the -rdynamic option works. That reall make me confuse. Can anyone tell me what's going on here? Why the clang++ command works while the cmake failed?
Because -rdynamic is a linker option, so if you use when compiling a source file into an object *.o it does nothing, there is no link phase here.
When linking all the *.o and libraries into the finally executable, then it is actually used.
From man gcc (but clang uses the same):
-rdynamic
Pass the flag -export-dynamic to the ELF linker, on targets that support it.
This instructs the linker to add all symbols, not only used ones, to the
dynamic symbol table. This option is needed for some uses of "dlopen" or to
allow obtaining backtraces from within a program.
I am interfacing with an old code base which extensively uses old style casts (thousands). I am trying to disable these warnings in Cmake, but it just isn't working (I do not want to see 1000s of warnings, nor do I care to fix the root cause). To do this, I assume that I should be setting -Wno-old-style-cast. I tried doing this in 3 separate places in the CMakeLists.txt file, but to no avail. Here is the complete file:
set(example "train")
project(${example} CXX)
# Python
message(STATUS "We are going to force it to use Python 3. If you change this, you will need to remove the build folder and reload the cmake project.")
find_package(PythonLibs 3 EXACT)
find_package(PythonInterp 3 EXACT)
# PCL library
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-old-style-cast")
set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-old-style-cast")
add_executable(${example} src/${example}.cpp)
target_compile_options(${example} PUBLIC -Wno-old-style-cast)
target_link_libraries(${example} ${Boost_LIBRARIES} ${PCL_LIBRARIES} ${PYTHON_LIBRARIES})
target_include_directories(${example} PRIVATE include/ ${PYTHON_INCLUDE_DIRS})
I am compiling on Ubuntu 18.04 with GCC 7.4.0. I see thousands of errors like this:
/usr/include/python3.7m/object.h:118:49: warning: use of old-style cast [-Wold-style-cast]
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
EDIT:
The output of make VERBOSE=1 yields:
/usr/bin/c++ -DDISABLE_LIBUSB_1_0 -DDISABLE_PCAP -DDISABLE_PNG -DPCL_NO_PRECOMPILE=0 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -Dqh_QHpointer -DvtkRenderingContext2D_AUTOINIT="1(vtkRenderingContextOpenGL2)" -DvtkRenderingCore_AUTOINIT="3(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingOpenGL2)" -isystem /usr/include/vtk-7.1 -isystem /usr/include/freetype2 -isystem /usr/include/x86_64-linux-gnu -isystem /usr/local/include/pcl-1.9 -isystem /usr/include/eigen3 -I/home/bob/Desktop/choc/include -I/usr/include/python3.7m -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -Wno-old-style-cast -Wno-old-style-cast -march=native -msse4.2 -mfpmath=sse -fPIC -std=gnu++14 -o CMakeFiles/train.dir/src/train.cpp.o -c /home/bob/Desktop/choc/src/train.cpp
Some libraries of pcl set -Wold-style-cast warnings using Diagnostic Pragmas. For this reason this warnings should appear whatever you set in you cmake configuration. Disabling it using pragmas before of including pcl headers solved the problem in my case.
#include <pcl/surface/concave_hull.h>
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
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".
To prevent "undefined reference to..." boost errors, I need to append the boost libraries at the very end of the compiler flags. Therefore, in CMakeLists.txt I set:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem")
However, verbose output of cmake shows me that additional flags are appended behind the ones I defined:
g++ -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem CMakeFiles/My_Project.dir/main.cpp.o -o My_Project -L/usr/local/boost_1_60_0/lib
Is it possible to change the order?
The complete CMakeLists.txt:
cmake_minimum_required(VERSION 3.4)
project(My_Project)
set(CMAKE_VERBOSE_MAKEFILE ON)
# This is bad but I currently don't have another working solution.
set(BOOSTROOT "/usr/local/boost_1_60_0/")
set(BOOST_ROOT "/usr/local/boost_1_60_0/")
find_package(Boost 1.60.0 COMPONENTS system filesystem REQUIRED)
if(Boost_FOUND)
message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}")
message(STATUS "Boost_VERSION: ${Boost_VERSION}")
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
endif()
add_executable(BoostTest main.cpp)
if(Boost_FOUND)
target_link_libraries(BoostTest ${Boost_LIBRARIES})
endif()
# Boost libraries appended at the end. However, cmake generates flags like this:
# c++ -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem CMakeFiles/My_Project.dir/main.cpp.o -o My_Project -L/usr/local/boost_1_60_0/lib
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem")
set(SOURCE_FILES main.cpp)
add_executable(My_Project ${SOURCE_FILES})
Thanks
You should use target_link_libraries instead of manually appending -lboost directives into your compiler flags.
TARGET_LINK_LIBRARIES(My_Project boost)
It should also be mentioned that it's possible the linker might be invoked as a separate invocation after the compilation of object files