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.
I want to compile a native code writing by C with a arm-linux-android Compiler from android-ndk, so that that codes can be executed in a android pad.
First I write a Toolchain_armgcc_android.cmake. In this file i have put the codes
set(CMAKE_STRIP arm-linux-androideabi-strip)
set(CMAKE_C_COMPILER bin/arm-linux-androideabi-gcc)
set(CMAKE_CXX_COMPILER arm-linux-androideabi-cpp)
set(CMAKE_FIND_ROOT_PATH /home/name/tmp/my-android-toolchain)
Then write a CMAKE with the codes unders
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-armgcc-android.cmake -DBUILD_EXAMPLESERVER=On -DPYTHON_EXECUTABLE=/usr/bin/python ..
It is executed and the follows codes was come out,
-- The C compiler identification is GNU 4.8.0
-- Check for working C compiler: /home/name/tmp/my-android-toolchain /bin/arm-linux-androideabi-gcc
-- Check for working C compiler: /home/name/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Found Git: /usr/bin/git (found version "1.9.1")
-- Git version: v0.1.0-RC4-31-g1a03d02-dirty
-- CMAKE_BUILD_TYPE not given; setting to 'RelWithDebInfo'.
-- Configuring done
-- Generating done
CMake Warning:
Manually-specified variables were not used by the project:
PYTHON_EXECUTABLE
- Build files have been written to: /home/name/open62541/build
in the same file i wrote a command ,make,. Then the errors come out, like
can anyone tall me the reasons? thanks a lot in advance`
I am trying to generate some Boost 1.58 libraries that I need (chrono, regex and thread) for Visual Studio 2012 and link the libraries with CMake. I have real problems for CMake and Visual Studio to find or link the libs, depending on the configuration I set.
I am finally using the following configuration:
bjam.exe --link=static --threading multi --variant=debug stage
But this doesn't seem to generate static libs.
How should I generate the libs and search them with CMake in order for Visual Studio to link them properly?
I finally came up with the solution and I think it is detailed enough to become a generic answer.
Visual Studio searches for dynamic libraries so we need to compile Boost libraries as shared, multithreaded, debug and release, and runtime-link shared. In windows using bjam.exe all commands have the prefix "--" except link, so the right way to build the libraries is:
bjam.exe link=shared --threading=multi --variant=debug --variant=release --with-chrono --with-regex --with-thread stage
This will generate the libs and DLLs in the folder Boost/stage/lib, so we need to set an environment variable Boost_LIBRARY_DIR C:/Boost/stage/lib, for example.
There are more options that may come in hand:
runtime-link = shared/static
toolset= msvc-11.0
The libraries will have a name like this for release:
boost_chrono-vc110-mt-1_58.lib
boost_chrono-vc110-mt-1_58.dll
And for debug:
boost_chrono-vc110-mt-gd-1_58.lib
boost_chrono-vc110-mt-gd-1_58.dll
In order for CMake to link them properly we need to write the following in the CMakeLists.txt:
add_definitions( -DBOOST_ALL_DYN_LINK ) //If not VS will give linking errors of redefinitions
set(Boost_USE_STATIC_LIBS OFF )
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost COMPONENTS thread chrono regex REQUIRED )
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES( ${PROJ_NAME} ${Boost_LIBRARIES} )
bjam.exe --link=static --threading multi --variant=debug stage
But this doesn't seem to generate static libs.
Building the special stage target places Boost library binaries in the stage\lib\ subdirectory of the Boost tree.
More about building Boost on Windows here
CMake:
SET (CMAKE_BUILD_TYPE Debug) # in order to link with boost debug libs you may need to set that to build your program in debug mode (or do that from command line)
FIND_PACKAGE (Boost 1.58 COMPONENTS "chrono" "regex" "thread" REQUIRED)
#ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) # make sure you don't have this as it will try to link with boost .dll's
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
TARGET_LINK_LIBRARIES(${EXE_OR_LIB_NAME} ${Boost_LIBRARIES})
I'm having trouble trying to do something seemingly very simple with CMake 2.8.11.2 . I have a folder with two files:
-- CMAkeLists.txt --
add_executable(test test.c)
target_link_libraries (test somelib)
-- test.c --
// Some c code
when I create a build directory and issue cmake .., cmake runs with the following output:
C:\Users\Enis\workspace_kepler\tmp\build>cmake ..
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Enis/workspace_kepler/tmp/build
And an MSVC 2012 solution is generated inside the build folder (as I have MSVC2012 installed). Now, the problem is that when I open that solution and check the linker configuration of the test project under Properties->Configuration Properties->Linker->Input->Additional Dependencies I see that somelib is added as ;-lsomelib.lib and visual studio doesn't like that. It links successfuly only if I change that to somelib.lib manually.
What am I doing wrong? Why does CMake make such a simple mistake? What can I do to change the prefix it generates?
I faced the same issue. The root of the problem is CMAKE_LINK_LIBRARY_FLAG but I have no idea what sets it. Resetting it, demonstrated in the snippet below, should help you.
set(CMAKE_LINK_LIBRARY_FLAG "")
I am working a project that uses the Discrete Gaussian Image Filter within ITK. I am using CMake to automate the build process but it seems that CMake is leaving out certain ITK libraries during the configuration/generate step. I am currently using other headers in the ITK library without any issue. There are no configuration error messages in CMake for the project.
The CMakeLists.txt for my project:
#PROJECT(REGISTRATION)
#
# List of source files
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# Top of file: the name of the program
PROJECT(MultiObjModelToUSReg)
INCLUDE_REGULAR_EXPRESSION("^.*$")
FIND_PACKAGE( ITK REQUIRED)
IF( ITK_FOUND )
INCLUDE( ${USE_ITK_FILE} )
ENDIF( ITK_FOUND )
# Directories to search for #include (add more if needed)
# (ITK is already included through the use of INCLUDE(${ITK_USE_FILE})
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
src
)
# Name of the executable
#SET(MultiObjModelToUSReg MultiObjModelToUSReg_EXE)
# All source files (only .cxx, not .h or .txx)
SET(MultiObjModelToUSReg_SRCS
src/Utilities.cpp
src/MultiObjModel.cpp
src/USVolume.cpp
src/Registration.cpp
src/BoneProbabilityMap.cpp
#src/MultiObjModelToUSRegistration.cpp
#src/USRegistrationDialog.cpp
#src/MainPanel.cpp
#src/ModelRegistration.cxx
)
#only .h files that use QT_ macros!
#SET(MultiObjModelToUSReg_HEADERS
#src/USRegistrationDialog.h
#src/MainPanel.h
#src/ModelRegistration.h)
#SET(MultiObjModelToUSReg_FORMS
##ui/USRegistrationDialog.ui
##ui/MainPanel.ui
#ui/ModelRegistration.ui)
#SET(MultiObjModelToUSReg_RESOURCES)
# These two lines will compile and link your executable
#ADD_EXECUTABLE(MultiObjModelToUSReg
#${MultiObjModelToUSReg_EXE}
#${MultiObjModelToUSReg_SRCS}
#${MultiObjModelToUSReg_HEADERS_MOC}
#${MultiObjModelToUSReg_FORMS_HEADERS}
#${MultiObjModelToUSReg_RESOURCES_RCC}
#)
ADD_LIBRARY(MultiObjModelToUSReg STATIC ${MultiObjModelToUSReg_SRCS})
TARGET_LINK_LIBRARIES(MultiObjModelToUSReg ${ITK_LIBRARIES} )
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ENABLE_TESTING()
INCLUDE(CTEST)
IF (BUILD_TESTING)
ADD_SUBDIRECTORY (Test)
ENDIF (BUILD_TESTING)
CMake's error-free output:
Check for working C compiler using: Visual Studio 9 2008
Check for working C compiler using: Visual Studio 9 2008 -- works
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working CXX compiler using: Visual Studio 9 2008
Check for working CXX compiler using: Visual Studio 9 2008 -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Configuring done
Generating done
However, when I compile in Visual C++ 2008:
1>------ Build started: Project: MultiObjModelToUSReg, Configuration: Debug Win32 ------
1>Compiling...
1>BoneProbabilityMap.cpp
1>..\src\BoneProbabilityMap.cpp(8) : fatal error C1083: Cannot open include file: 'itkDiscreteGaussianImageFilter.h': No such file or directory
1>Build log was saved at "file://c:\MultiObjModelToUSReg\bin\MultiObjModelToUSReg.dir\Debug\BuildLog.htm"
1>MultiObjModelToUSReg - 1 error(s), 0 warning(s)
2>------ Skipped Build: Project: ALL_BUILD, Configuration: Debug Win32 ------
2>Project not selected to build for this solution configuration
========== Build: 0 succeeded, 1 failed, 12 up-to-date, 1 skipped ==========
While there is a workaround to manually it into the project's configuration, I will need to collaborate with others so it would be ideal to have the build process automated.
Any help would be greatly appreciated! (I am quite new to Stackoverflow, please let me know if I made anything unclear).
You need to build ITK with ITK_BUILD_ALL_MODULES=ON.