How to set IMAGE_FILE_LARGE_ADDRESS_AWARE in cmake? - cmake

By default 32-bit process can use up to 2GB address space (Windows 10 x64). In Visual Studio 2019 it can be change in the project properties: linker/settings. How to set IMAGE_FILE_LARGE_ADDRESS_AWARE flag in cmake ?

I use the CMAKE_EXE_LINKER_FLAGS and CMAKE_SHARED_LINKER_FLAGS variables for that, e.g.
if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LARGEADDRESSAWARE")
endif()
Another possibility (modern CMake style) is to set the property of the target, i.e.
if (MSVC)
set_target_properties(MyTargetName PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE")
endif()

Related

Add sanitizers only to debug build in CMake

I am trying to add sanitizers to debug build only in CMake. As I understand:
normally you add sanitizers like this:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined")
for compatibility with Visual Studio (and other multi-configuration generators), I need to use a generator expression
$<$<CONFIG:Debug>:-fsanitize=address,undefined>
instead of e.g. if(CMAKE_BUILD_TYPE STREQUAL "Debug").
So how do I combine them? I tried
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $<$<CONFIG:Debug>:-fsanitize=address,undefined>")
and
set(SANITIZE_FLAGS "$<$<CONFIG:Debug>:-fsanitize=address,undefined>")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}")
Both lead to errors looking like
no such file or directory: '../../../src/ffn.cc../../../src/ffn.ccCONFIG:Debug'
The simplest way for set compiler flags only for specific configuration (build type) is appending these flags to corresponded CMAKE_<LANG>_FLAGS_<CONFIG> variable:
# Add sanitizer flags for C++ compiler for "Debug" configuration
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address,undefined")
This way works perfectly in case of multi-configuration generators like Visual Studio.
Setting CMAKE_<LANG>_FLAGS_<CONFIG> variable works even for custom build types. Here <CONFIG> is upper-case variant of a build type.

How to make CLion use different CMake config for debug and release?

I built 2 separate debug and release versions of OpenCV. How can I switch between 2 builds when I debug my project? I tried this:
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
message(WARNING "debug mode")
find_package(OpenCV REQUIRED
PATHS /path/to/debug/build NO_DEFAULT_PATH)
ELSE()
message(WARNING "release mode")
find_package(OpenCV REQUIRED)
ENDIF()
but it doesn't work. It does show release mode when I build normally, but doesn't show debug mode or release mode when the debugger kicks in. My thought is that CMAKE_BUILD_TYPE will be set to Debug when I debug. Is that true?
Thanks for your help.
MATCHES in cmake if is case sensitive. So when comparing CMAKE_BUILD_TYPE you have to decide on case. It's popular to convert to string into upper case and do comparisons then:
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UP)
if (${CMAKE_BUILD_TYPE_UP} STREQUAL "DEBUG")
...
Or the best is to compare against the standard values defiuned in cmake docs: Possible values are empty, Debug, Release, RelWithDebInfo and MinSizeRel. Note that both cmake -DCMAKE_BUILD_TYPE=dEbUg and cmake -DCMAKE_BUILD_TYPE=DeBuG both will configure for Debug build, but the CMAKE_BUILD_TYPE variable will differ. So the safest way is to convert it to upper case.

Should I cache CMAKE_BUILD_TYPE?

If you don't set the CMAKE_BUILD_TYPE, then, by default, it doesn't get cached. Should I cache it? e.g. should I have:
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" )
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Type of build (Debug, Release etc." FORCE)
endif()
or just:
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" )
endif()
Or does it not really matter?
Caching of CMAKE_BUILD_TYPE is usefull for cmake-gui: user of your project would able to change a build type in a nice manner.
There is a good template for setting default CMAKE_BUILD_TYPE from developers:
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Debug' as none was specified.")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
"MinSizeRel" "RelWithDebInfo")
endif()
CMAKE_BUILD_TYPE in CMake's Cache
The user would normally define CMAKE_BUILD_TYPE via the command line with cmake -D .... So this does generate a cached entry.
And even when you don't give a CMAKE_BUILD_TYPE for single configuration makefile generators, CMake will automatically create an empty cache entry (so the user can choose in e.g. cmake-gui):
//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.
CMAKE_BUILD_TYPE:STRING=
If no default for CMAKE_BUILD_TYPE is given by the CMake's Platform/Compiler definitions via CMAKE_BUILD_TYPE_INIT like for Windows-MSVC:
# default to Debug builds
set(CMAKE_BUILD_TYPE_INIT Debug)
Settings a Default for CMAKE_BUILD_TYPE
So yes, if you want to force a default that is visible in the GUI then set the cached variable (see #Tsyvarev answer).
I don't normally force the cached defaults, I just set a temporary value if none is given. This allows e.g. my project to be used as a sub-project.
But that's more a matter of your personal taste.
In my project's those default CMAKE_BUILD_TYPE checks look a little more complex, since I allow more use cases:
# Make RelWithDebInfo the default (it does e.g. add '-O2 -g -DNDEBUG' for GNU)
# If not in multi-configuration environments, no explicit build type
# is set by the user and if we are the root CMakeLists.txt file.
if (NOT CMAKE_CONFIGURATION_TYPES AND
NOT CMAKE_NO_BUILD_TYPE AND
NOT CMAKE_BUILD_TYPE AND
CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
if (CMAKE_BUILD_TYPE)
string(TOUPPER "_${CMAKE_BUILD_TYPE}" MY_PROJECT_BUILD_TYPE_EXT)
endif()
# Choose a configuration for our compiler tests
if (NOT CMAKE_CONFIGURATION_TYPES AND
NOT CMAKE_NO_BUILD_TYPE)
set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}")
else()
set(CMAKE_TRY_COMPILE_CONFIGURATION RelWithDebInfo)
endif()
But probably I should update this code to take the new GENERATOR_IS_MULTI_CONFIG global property into account (instead of checking for CMAKE_NO_BUILD_TYPE).
References
"CMake and the Default Build Type" blog post by Marcus D. Hanwell
CMake Issue #16768: Add reliable way to detect multi-config generators

How to check if generator is a multi-config generator in a CMakeLists.txt

The Cmake FAQ
and
other
places
recommend to check CMAKE_CONFIGURATION_TYPES to recognize a multi-configuration generator. I have found several questions where this did not work (for example this one). The issue seems to be that the variable is not set the first time cmake is called.
I tested with the following file
cmake_minimum_required(VERSION 2.6)
if(CMAKE_CONFIGURATION_TYPES)
message("Multi-configuration generator")
else()
message("Single-configuration generator")
endif()
project(foo)
and called it like this
mkdir build
cd build
cmake -G "Visual Studio 12 2013" ..
and got Single-configuration generator.
How should I distinguish whether the current generator supports multiple configurations?
EDITED: Added information on checking and changing CMAKE_CONFIGURATION_TYPES
Check and Changing CMAKE_CONFIGURATION_TYPES
Taking the suggestions from this question you could check and change CMAKE_CONFIGURATION_TYPES, but be aware that there was a bug 0015577: The 'project' command overwrites CMAKE_CONFIGURATION_TYPES in CMake 3.2.2 that did break this behaviour for the initial VS solution generation (fixed with CMake 3.3.0):
cmake_minimum_required(VERSION 3.3)
project(foo NONE)
if(CMAKE_CONFIGURATION_TYPES)
message("Multi-configuration generator")
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "My multi config types" FORCE)
else()
message("Single-configuration generator")
endif()
enable_language(C CXX)
Preset CMAKE_CONFIGURATION_TYPES
If you just need a certain set of configurations for multi-configuration environments you can do (thanks to #Tsyvarev for the suggestion):
cmake_minimum_required(VERSION 2.8)
# NOTE: Only used in multi-configuration environments
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "My multi config types" FORCE)
project(foo)
None multi-configuration environments will just ignore it. But be aware that other CMake modules like findBoost.cmake, findCUDA.cmake may rely on CMAKE_CONFIGURATION_TYPES being empty for single-configuration environments (thanks again #Tsyvarev for the hint).
So a better solution would be adding toolchain files for all your supported generators. They are generally useful, because there you can handle all the toolchain/generator specific parts.
Here is an extract of my VSToolchain.txt:
# Reduce the config types to only Debug and Release
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
# Standard is a console app. If you need a windows app, use WIN32 define in add_executable
set(CMAKE_WIN32_EXECUTABLE 0 CACHE INTERNAL "")
CMAKE_WIN32_EXECUTABLE is just there to show what kind of settings I have put in my Visual Studio toolchain file.
Another CMake command line solution is suggested here: How to create cmake build configuration without debug symbols and without optimizations?
Only Checking CMAKE_CONFIGURATION_TYPES
If you only want do check what CMake does set in CMAKE_CONFIGURATION_TYPES:
I just tested your above code with Visual Studio 2013 and MinGW/GCC (both with empty build directories). You just need one small change and move the check after the project() command:
project(foo)
message("CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}")
if(CMAKE_CONFIGURATION_TYPES)
message("Multi-configuration generator")
else()
message("Single-configuration generator")
endif()
And I get for VS2013:
CMAKE_CONFIGURATION_TYPES Debug;Release;MinSizeRel;RelWithDebInfo
Multi-configuration generator
And for GCC:
CMAKE_CONFIGURATION_TYPES
Single-configuration generator
For more details about what CMake does see:
CMAKE_CONFIGURATION_TYPES set by EnableLanguage() in cmGlobalVisualStudio7Generator.cxx
CMake: In which Order are Files parsed (Cache, Toolchain, …)?
I see you are on CMake v2.6, but for anyone who is on v3.9+, v3.9 introduced the global property called GENERATOR_IS_MULTI_CONFIG:
Read-only property that is true on multi-configuration generators.
You can load the value into a CMake variable like so:
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
This very approach is recommended in "Professional CMake" by Craig Scott, along with explanations of the shortcomings of other approaches- especially those involving CMAKE_CONFIGURATION_TYPES. The book is $30 but the section I'm referring to is in the sample chapters.

Project build configuration in CMake

My question is very similar to CMake : Changing name of Visual Studio and Xcode exectuables depending on configuration in a project generated by CMake. In that post the output file name will change according to the project configuration (Debug, Release and so on). I want to go further. When I know the configuration of the project, I want to tell the executable program to link different library names depending on project configurations. I was wondering whether there is a variable in CMake that can tell the project configuration. If there exists such a variable, my task will become easier:
if (Project_Configure_Name STREQUAL "Debug")
#do some thing
elseif (Project_Configure_Name STREQUAL "Release")
#do some thing
endif()
According to http://cmake.org/cmake/help/v2.8.8/cmake.html#command:target_link_libraries, you can specify libraries according to the configurations, for example:
target_link_libraries(mytarget
debug mydebuglibrary
optimized myreleaselibrary
)
Be careful that the optimized mode means every configuration that is not debug.
Following is a more complicated but more controllable solution:
Assuming you are linking to an imported library (not compiled in your cmake project), you can add it using:
add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION_RELEASE c:/path/to/foo.lib)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION_DEBUG c:/path/to/foo_d.lib)
add_executable(myexe src1.c src2.c)
target_link_libraries(myexe foo)
See http://www.cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_Targets for more details.
There is always another way:
if(CMAKE_BUILD_TYPE MATCHES "release")
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
else(CMAKE_BUILD_TYPE MATCHES "debug")
SET(CMAKE_BUILD_TYPE "debug")
endif(CMAKE_BUILD_TYPE MATCHES "release")
We can use the variable CMAKE_BUILD_TYPE. We can also change this variable at the beginning of invoking CMAKE:
cmake .. -DCMAKE_BUILD_TYPE:STRING=debug
Then we can use this variable as an indicator of build configuration.