CMake: C++11 not set with CXX_STANDARD - linux

I want to compile a library using C++11. The library is a subproject.
In its CMakeLists.txt I set the C++11 features with CXX_STANDARD and CXX_STANDARD_REQUIRED as seen here.
The cmake command it's executed without errors, but when I start the compilation I obtain errors related to C++11 features missing, like
In file included from /folder/OptionWidget.cpp:1:0:
/folder/OptionWidget.h:14:28: warning: defaulted and deleted functions only available with -std=c++0x or -std=gnu++0x [enabled by default]
/folder/OptionWidget.h:14:28: error: ‘virtual WTradeGui::OptionWidget::~OptionWidget()’ declared virtual cannot be defaulted in the class body
make[2]: *** [.../OptionWidget.cpp.o] Error 1
The error lies where I declare a default virtual destructor in header virtual ~OptionWidget() = default;
If I execute the command make VERBOSE=1 I can see that the C++11 flag is not set in compilation command:
/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -I/folder/wtradegui -I/folder/wtradegui -I/folder/wtrade/src -isystem /qt/include -isystem /qt/QtWidgets -isystem /qt/QtGui -isystem /qt/QtCore -isystem -fPIC -o CMakeFiles/wtradegui.dir/OptionWidget.cpp.o -c /folder/OptionWidget.cpp
I use Ubuntu 15.04 with cmake version 3.3.1 and gcc version 4.6.3.
The same project is built without problems under windows, using MinGW (sorry I don't remember the version, it's the one shipped with Qt 5.5.0 release).
What I must do in order to build the project in Linux?
This is the main CMakeList.txt
# In order to work following variables must be set
#
# QT_DIR: Path to Qt installation.
cmake_minimum_required (VERSION 3.1.0)
# Variables that should be set before execution
if (WIN32)
set (QT_DIR "" CACHE PATH "Qt library path")
else (WIN32)
set (QT_DIR "/usr/include" CACHE PATH "Qt library path")
endif (WIN32)
message ("Generating WPlot project")
message ("Setting QT_DIR To ${QT_DIR}")
add_subdirectory (wplot)
add_subdirectory (demo)
And this is the CMakeLists.txt inside wplot folder
# wPlot project
cmake_minimum_required (VERSION 3.1.0)
project (wplot)
set (major_version 0)
set (minor_version 0)
set (bugfix_version 1)
set (project_version ${major_version}.${minor_version}.${bugfix_version})
set (OUTPUT_DIR "build")
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/export/lib)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/export/lib)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/export/bin)
set (INCLUDE_EXPORT_DIRECTORY ${CMAKE_BINARY_DIR}/export/include/wplot)
set (CMAKE_DOC_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/export/doc)
set (CMAKE_PREFIX_PATH ${QT_DIR}/lib/cmake)
set (CMAKE_AUTOMOC ON)
set (CMAKE_INCLUDE_CURRENT_DIR ON)
message ("=== Generating WPlot ===")
message ("Setting QT_DIR To ${QT_DIR}")
message ("CMAKE_PREFIX_PATH set to ${CMAKE_PREFIX_PATH}")
find_package (Qt5Widgets REQUIRED)
include_directories (${CMAKE_SOURCE_DIR} ${Qt5Widgets_INCLUDE_DIRS})
file (GLOB_RECURSE WPLOT_SOURCES "*.cpp")
file (GLOB WPLOT_PUBLIC_HEADERS "*.h")
file (COPY ${WPLOT_PUBLIC_HEADERS} DESTINATION ${INCLUDE_EXPORT_DIRECTORY})
# Compile project
add_definitions(-DWPLOT_LIBRARY)
add_library (wplot SHARED ${WPLOT_SOURCES})
target_link_libraries(wplot ${Qt5Widgets_LIBRARIES})
set_target_properties(
wplot
PROPERTIES
VERSION ${project_version}
SOVERSION ${project_version}
)
set_property(TARGET wplot PROPERTY CXX_STANDARD 11)
set_property(TARGET wplot PROPERTY CXX_STANDARD_REQUIRED ON)

GCC support for C++11 have progressively grown since GCC 4.3 to GCC 4.9.
GCC 4.6 officially supports a subset of C++0x (the name of the C++11 draft standard before it even had a name). Qt 5.5 ships with MinGW 4.9 which has essentially full C++11 support.
It seems reasonable that CMake would not consider GCC 4.6 to have C++11 support, though I'm not sure why CXX_STANDARD_REQUIRED=ON does not force the configure step to fail. Anyway, the better approach is to tell CMake what C++11 features you need using the target_compile_features command and let it determine what compiler flags are necessary to enable those features.

Related

CMake Ubuntu set soname for shared object

How to set the SONAME for a shared library with CMake in Ubuntu?
With help of How to add linker flag for libraries with CMake? I have created a CMakeLists.txt:
project(mylib VERSION 1.2.3)
set(src_files_mylib
Client.cpp
Server.cpp
)
set(hdr_files_mylib
Client.h
Server.h
)
add_library(mylib SHARED ${src_files_mylib} ${hdr_files_mylib})
set_target_properties(mylib PROPERTIES PREFIX "")
set_target_properties(mylib PROPERTIES SUFFIX "")
set_target_properties(mylib PROPERTIES OUTPUT_NAME "mylib.so.${PROJECT_VERSION}")
add_link_options("LINKER: -l,soname,mylib.so.${PROJECT_VERSION_MAJOR}")
Using CMake 3.16 and out of source build. It produces the library named mylib.so.1.2.3 but it does not seem to have an SONAME in it. When executing ldconfig -n . in the library dir, it does not produce a link.
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,soname,mylib.so.${PROJECT_VERSION_MAJOR}")
instead of
add_link_options("LINKER: -l,soname,mylib.so.${PROJECT_VERSION_MAJOR}")
behaves the same to me.
When writing the Makefile manually, the target is built correctly with this (going ldconfig -n . like above produces a link):
(...)
MYLIB_SO=mylib.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
MYLIB_SONAME=mylib.so.$(VERSION_MAJOR)
(...)
$(MYLIB_SO): $(OBJ_MYLIB)
$(CXX) $(SO_FLAGS) -Wl,-soname,$(MYLIB_SONAME) -o $(MYLIB_SO) $(DEBUGFLAGS) $(OBJ_MYLIB)
if libraries is called SoundTouch
project(SoundTouch VERSION 2.3.0 LANGUAGES CXX)
add_library(SoundTouch [SHARED]
sources/animation.cpp
sources/buffers.cpp
[...]
)
set_target_properties(SoundTouch PROPERTIES VERSION ${CMAKE_PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR} )

How do I write the cmake script for clion to include glfw?

cmake_minimum_required(VERSION 3.15)
project(hello)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
set(CMAKE_CXX_STANDARD 11)
add_executable(hello main.cpp)
INCLUDE_DIRECTORIES(${GLFW_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(hello ${GLFW_STATIC_LIBRARIES})
It tells me
CMake Error at /home/user/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/193.5233.144/bin/cmake/linux/share/cmake-3.15/Modules/FindPkgConfig.cmake:696 (message):
None of the required 'glfw3' found
when I try to build it. My glfw folder is located at /usr/local/include/GLFW.
AFAIK, glfw3 is using CMake as the build system,
(src: packages.debian.org/fr/sid/amd64/libglfw3-dev/filelist)
which uses modern CMake, so you don't need GLFW_INCLUDE_DIRS etc...
Inside this file /usr/lib/cmake/glfw3/glfw3Targets.cmake (loaded by /usr/lib/cmake/glfw3/glfw3Config.cmake), you'll see:
...
# Create imported target glfw
add_library(glfw SHARED IMPORTED)
set_target_properties(glfw PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "GLFW_DLL"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include"
)
...
So you can simply use:
find_package(glfw3 REQUIRED)
...
target_link_libraries(Foo glfw)
ps: same as my previous comment

How to set compiler options with CMake in Visual Studio 2017

Visual Studio 2017 comes with full CMake integration. To learn about this combination, I was starting with this basic sample:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(foo)
add_executable(foo foo.cpp)
and
// foo.cpp
int main() {}
This properly generates build scripts, and compiles and links with no issues. That was easy.
Trying to set compiler options, on the other hand, turned out to be anything but trivial. In my case I was attempting to set the warning level to 4.
The obvious solution
add_compile_options("/W4")
didn't pan out as expected. The command line passed to the compiler now contains both /W4 (as intended) as well as /W3 (picked up from somewhere else), producing the following warning:
cl : Command line warning D9025: overriding '/W3' with '/W4'
To work around this, I would need to replace any incompatible compiler option(s) instead of just adding one. CMake does not provide any immediate support for this, and the standard solution (as this Q&A suggests) seems to be:
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
This, however, has two issues:
It sets the global CMAKE_CXX_FLAGS, applying to all C++ targets. This may not be intended (not an issue for me right now).
It doesn't scale. For every compiler option to add, you would have to read up on incompatible options, and manually strip those first. This will inevitably fail1.
My question is two-fold:
Where does the CMake integration pick up default settings from, and can this be controlled?
How do you set compiler options in general? (If this is too broad a topic, I'd be happy for help on setting the warning level only.)
1 Incidentally, the solution I replicated fails to account for the /Wall option, that is incompatible with /W4 as well.
The default settings for the compiler are picked up from standard module files located in the Modules directory of the CMake installation. The actual module file used depends on both the platform and the compiler. E.g., for Visual Studio 2017, CMake will load the default settings from the file Windows-MSVC.cmake and language specific settings from Windows-MSVC-C.cmake or Windows-MSVC-CXX.cmake.
To inspect the default settings, create a file CompilerOptions.cmake in the project directory with the following contents:
# log all *_INIT variables
get_cmake_property(_varNames VARIABLES)
list (REMOVE_DUPLICATES _varNames)
list (SORT _varNames)
foreach (_varName ${_varNames})
if (_varName MATCHES "_INIT$")
message(STATUS "${_varName}=${${_varName}}")
endif()
endforeach()
Then initialize the CMAKE_USER_MAKE_RULES_OVERRIDE variable in your CMakeLists.txt:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
set (CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_LIST_DIR}/CompilerOptions.cmake")
project(foo)
add_executable(foo foo.cpp)
When the project is configured upon opening the directory using Open Folder in Visual Studio 2017, the following information will be shown in the IDE's output window:
...
-- CMAKE_CXX_FLAGS_DEBUG_INIT= /MDd /Zi /Ob0 /Od /RTC1
-- CMAKE_CXX_FLAGS_INIT= /DWIN32 /D_WINDOWS /W3 /GR /EHsc
-- CMAKE_CXX_FLAGS_MINSIZEREL_INIT= /MD /O1 /Ob1 /DNDEBUG
-- CMAKE_CXX_FLAGS_RELEASE_INIT= /MD /O2 /Ob2 /DNDEBUG
-- CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT= /MD /Zi /O2 /Ob1 /DNDEBUG
...
So the warning setting /W3 is picked up from the CMake variable CMAKE_CXX_FLAGS_INIT which then applies to all CMake targets generated in the project.
To control the warning level on the CMake project or target level, one can alter the CMAKE_CXX_FLAGS_INIT variable in the CompilerOptions.cmake by adding the following lines to the file:
if (MSVC)
# remove default warning level from CMAKE_CXX_FLAGS_INIT
string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}")
endif()
The warning flags can then be controlled by setting the target compile options in CMakeLists.txt:
...
add_executable(foo foo.cpp)
target_compile_options(foo PRIVATE "/W4")
For most CMake projects it makes sense to control the default compiler options in a rules override file instead of manually tweaking variables like CMAKE_CXX_FLAGS.
When making changes to the CompilerOptions.cmake file, it is necessary to recreate the build folder. When using Visual Studio 2017 in Open Folder mode, choose the command Cache ... -> Delete Cache Folders from the CMake menu and then Cache ... -> Generate from the CMake menu to recreate the build folder.
Turning my comment into an answer
CMake does come with some compiler switches preset. For visual studio those are mainly standard link libraries, warning levels, optimization levels, exception handling, debug information and platform specific defines.
What you now have to differentiate when you want to change a CMake generated compiler settings are the following use cases:
Additional compiler flags CMake does not define vs. changing CMake's preset settings
Project default settings vs. project user defined settings
So let's discuss common solutions for those cases.
User changes/adds to Project/CMake Compiler Flags Defaults
The standard way would be to modify the cached compiler flags variables by using tools shipped with CMake like cmake-gui and ccmake.
To achieve this in Visual Studio you would have to:
CMake / Cache / View CMakeCache
Manually change e.g. CMAKE_CXX_FLAGS to /Wall
CMakeCache.txt
//Flags used by the compiler during all build types.
CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /Wall /GR /EHsc
CMake / Cache / Generate
Or you preset the CMAKE_CXX_FLAGS cache variable via a CMakeSettings.json file:
CMake / Change CMake Settings
Force the cache entry with -DCMAKE_CXX_FLAGS:STRING=... in cmakeCommandArgs
CMakeSettings.json
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug (all warnings)",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_CXX_FLAGS:STRING=\"/DWIN32 /D_WINDOWS /Wall /GR /EHsc\"",
"buildCommandArgs": "-m -v:minimal"
}
]
}
If you deliver this CMakeSettings.json file with your CMake project it gets permanent
Project changes to CMake Compiler Flags Defaults
If you want to keep most of CMake's compiler flags in place, #sakra's answer is definitely the way to go.
For my VS projects I've put the CXX flag settings into a toolchain file coming with the project itself. Mainly to freeze those settings and don't have a dependency the CMake version used or any environment variables set.
Taking the example from above that would look like:
VS2017Toolchain.cmake
set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /Wall /GR /EHsc" CACHE INTERNAL "")
CMakeSettings.json
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug (all warnings)",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=\"${projectDir}\\VS2017Toolchain.cmake\"",
"buildCommandArgs": "-m -v:minimal"
}
]
}
References
Visual C++ Team Blog: CMake support in Visual Studio – the Visual Studio 2017 RC update
set diagnostics:caret from CMakeLists.txt
Is Cmake set variable recursive?
Passing compiler options cmake
In CMake 3.15, CMake introduced a fix for this MSVC-specific warning:
cl : Command line warning D9025: overriding '/W3' with '/W4'
and the compiler warning flags (like /W3) are no longer automatically added. So by upgrading to CMake 3.15 or greater, this warning should no longer appear. From the docs:
When using MSVC-like compilers in CMake 3.14 and below, warning flags like /W3 are added to CMAKE_<LANG>_FLAGS by default. This is problematic for projects that want to choose a different warning level programmatically. In particular, it requires string editing of the CMAKE_<LANG>_FLAGS variables with knowledge of the CMake builtin defaults so they can be replaced.
CMake 3.15 and above prefer to leave out warning flags from the value of CMAKE_<LANG>_FLAGS by default.
Along with this fix, CMake introduced policy CMP0092, which allows you to switch back to the OLD behavior (adding the warning flags by default) if necessary.

Incorrect Dynamic Libraries linking after explicit set in Cmake

I've got a very frustrating issue a the moment. I'm attempting to build an executable that uses ROS and a compiled Matlab .so file. Due to what I believe is a boost conflict, I'm trying to build this exe using an earlier version of boost. Now, I've set up the cmakelist file, ran catkin_make (as its a ros project) and everything compiles, and the correct boost version is seen.
However, when running a ldd on the compiled exe, it still seems to be linking to the more recent version. Its rather annoying. I've posted the cmakelists file, and the ldd outcome. My system is Ubuntu 14.04 with ROS Indigo.
Any help would be really good, as I'm pulling my hair out trying to figure out what is wrong!
Many thanks in advance!
##CMAKE FILE
cmake_minimum_required(VERSION 2.8.3)
project(testmatlabdll)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wfatal-errors -O4 -march=native")
add_definitions(-std=c++11)
find_package(catkin REQUIRED)
find_package(PCL 1.7 REQUIRED)
link_directories(${PCL_LIBRARY_DIRS})
include_directories(${PCL_INCLUDE_DIRS})
add_definitions(${PCL_DEFINITIONS})
set(Boost_NO_SYSTEM_PATHS ON)
set(BOOST_ROOT /home/devbot/Downloads/boost_1_50_0)
set(BOOST_DIR /home/devbot/Downloads/boost_1_50_0)
set(Boost_INCLUDE_DIR /home/devbot/Downloads/boost_1_50_0)
set(BOOST_INCLUDEDIR /home/devbot/Downloads/boost_1_50_0)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
message(STATUS "BOOST_ROOT = ${BOOST_ROOT}")
message(STATUS "Boost_VERSION = ${Boost_VERSION}")
message(STATUS "Boost_LIB_VERSION = ${Boost_LIB_VERSION}")
message(STATUS "Boost_MAJOR_VERSION = ${Boost_MAJOR_VERSION}")
message(STATUS "Boost_MINOR_VERSION = ${Boost_MINOR_VERSION}")
message(STATUS "Boost_LIBRARIES = ${Boost_LIBRARIES}")
message(STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARY_DIRS = ${Boost_LIBRARY_DIRS}")
find_package(Boost COMPONENTS REQUIRED
system filesystem thread date_time iostreams serialization chrono)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation image_transport cv_bridge)
find_package(OpenCV REQUIRED)
catkin_package(CATKIN_DEPENDS roscpp
std_msgs
pcl_ros
sensor_msgs
cv_bridge
message_runtime
LIBRARIES ${PROJECT_NAME}
DEPENDS system_lib)
include_directories(include ${catkin_INCLUDE_DIRS})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(/usr/local/MATLAB/R2013b/extern/include/)
include_directories(/opt/matlab/extern/include)
include_directories(/home/devbot/catkin_ws/src/testmatlabdll/src)
link_directories(/home/devbot/catkin_ws/src/testmatlabdll/src)
add_library(mwmc SHARED IMPORTED)
set_property(TARGET mwmc PROPERTY IMPORTED_LOCATION /usr/local/MATLAB/MATLAB_Compiler_Runtime/v82/runtime/glnxa64/libmwmclmcrrt.so)
add_executable(testMatlab src/testMatlab.cpp)
target_link_libraries(testMatlab ${Boost_LIBRARIES} ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})
target_link_libraries(testMatlab roughlib mwmc)
OUTPUT FROM LDD
ldd testMatlab | grep boost
libboost_system.so.1.50.0 => /home/devbot/Downloads/boost_1_50_0/stage/lib/libboost_system.so.1.50.0 (0x00007f7456f8a000)
libboost_system.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.54.0 (0x00007f7454662000)
libboost_thread.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0 (0x00007f745444c000)
libboost_filesystem.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.54.0 (0x00007f7454018000)
libboost_regex.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.54.0 (0x00007f744d5d8000)

openmp Linker flags in MSVC

when I try to compile my project in MSVC2008 with the linker flag (Configuration properties>>Linker>>Command line>> Additional options) set to :
"/STACK:10000000 /machine:x64 /openmp"
it warns me that the /openmp flag is unknown.
"LINK : warning LNK4044: unrecognized option '/openmp'; ignored"
I want to know that MSVC automatically links the openmp libs when I added the compiler flag (Configuration properties>>C/C++>>Command line>>Additional options)
" /Zm1000 /EHs /MP /openmp /fp:fast"
or I should do sth else for getting rid of the warning.
The /openmp switch should be applied to the compiler, not linker. You can switch it on in C/C++ -> Language -> Open MP Support. The compiler then automatically instructs the linker to include the corresponding libraries.

Resources