CMAKE set rc compiler flags? - cmake

CMake Version 3.4.3
Visual Studio 14 2015 Solution file
I am trying to set the location flag for rc compiler for CMAKE by using the following syntax however it is always set to the value /l"0x0409".
set(rc_flags "/l 0x809")
set(CMAKE_RC_FLAGS ${rc_flags})
Also CMAKE always sets flags for cl compiler for rc compiler which I cannot stop.
Any help would be appreciated!
Edit
I have added version of cmake and visual studio version, the command still uses the /l"0x0409" flag when using the snippet from #Florian plus it uses flags I have specified for cl.exe command for rc.exe command which is not right.

The quotation problem was fixed with CMake version 3.1 (see "0010194: setting CMAKE_RC_FLAGS has no affect on rc flags").
So I've given your example a try with CMake version 3.6.0 and the "Visual Studio 14 2015" generator and the following code:
CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(TestRCCompilerFlags)
file(WRITE main.cpp "int main() { return 0; }")
file(WRITE main.rc "")
set(rc_flags "/l 0x809")
set(CMAKE_RC_FLAGS ${rc_flags})
add_executable(${PROJECT_NAME} main.cpp main.rc)
And - as expected - the /l 0x809 option shows up under "Project Configuration Properties/Resources/Command Line/Additional Options". So I couldn't reproduce any quotation or ignored options problems.
Makefile vs. Solution
Generally speaking the RC command line - including its flags - is defined in CMakeRCInformation.cmake. But you only have the absolute control over the RC command line if using makefile generators. There you could overwrite CMAKE_RC_COMPILE_OBJECT variable in your CMakeLists.txt file to something like:
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> /l 0x809 /fo<OBJECT> <SOURCE>")
The RC behavior of Visual Studio Solution generators is directly coded into cmVisualStudio10TargetGenerator::WriteRCOptions(). This code doesn't (over-)write any RC <Culture> section, so there you will always see the default /l"0x0409" there. But the <AdditionalOptions> section generated by CMake will take care of this/overwrite those defaults.

Related

cmake generator expressions behave differently in IDE and from command line

I'm trying to use different target property based on build configuration.
There is imported target called libmongocxx and it has 3 properties for different configs:
IMPORTED_LOCATION_DEBUG
IMPORTED_LOCATION_RELEASE
IMPORTED_LOCATION_RELWITHDEBINFO
So, to copy necessary dependencies to build directory I tried to use the following code:
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_PROPERTY:libmongocxx,$<$<CONFIG:Debug>:IMPORTED_LOCATION_DEBUG>$<$<CONFIG:Release>:IMPORTED_LOCATION_RELEASE>$<$<CONFIG:RelWithDebInfo>:IMPORTED_LOCATION_RELWITHDEBINFO>>"
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
The problem is: this works great when I run configuration from IDE (I tried CLion and VS2017), but the same CMakeLists.txt fails to configure when I run cmake from command line.
The error cmake shows:
CMake Error at CMakeLists.txt:93 (add_custom_command):
Error evaluating generator expression:
$<TARGET_PROPERTY:libmongocxx,$<$<CONFIG:Debug>:IMPORTED_LOCATION_DEBUG>$<$<CONFIG:Release>:IMPORTED_LOCATION_RELEASE>$<$<CONFIG:RelWithDebInfo>:IMPORTED_LOCATION_RELWITHDEBINFO>>
$<TARGET_PROPERTY:...> expression requires a non-empty property name.
By the way, I already found out that the same task can be more easily solved by using TARGET_FILE generator expression, but still, why different behavior in IDE and from command line?
I discovered this on CMake version 3.12.3, but later tested on 3.14.4 (cmd line only) and it still fails.
Update
Here is minimal example to reproduce the issue.
No dependencides required. test.cpp is empty file.
Configuration completes successfully from VS2017 but fails from cmd line.
CMakeLists.txt:
project(test LANGUAGES CXX)
cmake_minimum_required(VERSION 3.8.0)
add_executable(${PROJECT_NAME} test.cpp)
set_target_properties(${PROJECT_NAME} PROPERTIES
IMPORTED_LOCATION_DEBUG "libd.dll"
IMPORTED_LOCATION_RELEASE "lib.dll"
IMPORTED_LOCATION_RELWITHDEBINFO "libi.dll"
)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_PROPERTY:${PROJECT_NAME},$<$<CONFIG:Debug>:IMPORTED_LOCATION_DEBUG>$<$<CONFIG:Release>:IMPORTED_LOCATION_RELEASE>$<$<CONFIG:RelWithDebInfo>:IMPORTED_LOCATION_RELWITHDEBINFO>>"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
Command line:
cmake -G "Visual Studio 15 2017 Win64" ..
Update2
Can't agree this question is a duplicate.
The other question is about correct configuration of Visual Studio build.
This question is about usage of cmake generator expressions and about using cmake from command line.
The Visual Studio IDE CMake plugin only uses RelWithDebInfo and Debug configurations (at least for me). When invoking by the command line the default is all four standard configurations: Debug;Release;MinSizeRel;RelWithDebInfo.
Your CMakeLists.txt is incomplete because MinSizeRel is not defined or being used so there is no information for the MinSizeRel configuration.
BTW, CMAKE_BUILD_TYPE is ignored for multi-configuration generators. CMAKE_CONFIGURATION_TYPES defines which build types should be considered during generation.
So either add in the missing values or change CMAKE_CONFIGURATION_TYPES.

CMake Project-level CXX override [duplicate]

This is similar to Force CMake to use C++ compiler for C files with Visual Studio, but its not quite the same. Its not the same because a its CMake file causing the failure; and I'm working on nearly every modern platform, from BSDs and OS X through Solaris and Unix.
I tried to avoid useless checks being performed by CMake:
project(cryptopp, CXX)
Here's what happens when I attempt to generate the makefile:
$ cmake .
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
CMake Error at /usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:82 (try_compile):
Unknown extension ".c" for file
/home/jeffrey/cryptopp/CMakeFiles/CheckTypeSize/CMAKE_SIZEOF_UNSIGNED_SHORT.c
try_compile() works only for enabled languages. Currently these are:
CXX
See project() command to enable other languages.
Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:167 (__check_type_size_impl)
/usr/share/cmake-2.8/Modules/TestBigEndian.cmake:27 (CHECK_TYPE_SIZE)
CMakeLists.txt:49 (TEST_BIG_ENDIAN)
We don't have any C files in our project, so we should be safe with project(cryptopp, CXX) (if I am reading cmake --help-command project correctly).
The cited question talks about project files, but not CMake files.
How do I tell CMake to use C++ compiler for all files, including its own CMake files?
I'm on Ubuntu 12 LTS, and it provides:
$ cmake --version
cmake version 2.8.7
There are ways to add .c as a valid file extension for the CXX compiler. Even this being very advanced CMake stuff, you may need - if you are bound to support older versions of CMake - a "make rules overwrite script" anyway.
So I've successfully tested the following:
CryptoppMakeRulesOverwrite.cmake
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR)
set(CMAKE_USER_MAKE_RULES_OVERRIDE "CryptoppMakeRulesOverwrite.cmake")
project(cryptopp CXX)
include(CheckTypeSize)
CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT)
As #Tsyvarev has commented check_type_size() supports a LANGUAGE parameter, but unfortunately not for CMake version 2.8.7. But this older version does already support CMAKE_USER_MAKE_RULES_OVERRIDE.
So I'm still wondering if not the best solution would be to go to a newer version of CMake (forcing some users of older CMake versions to upgrade). Or writing your own try_compile() snippets.
References
How to add in a CMake project a global file extension (*.pde) to GCC which is treated like C++ code
Change default value of CMAKE_CXX_FLAGS_DEBUG and friends in CMake
set_source_files_properties
The CMake setting of (my) choice here would be the set_source_files_properties command. https://cmake.org/cmake/help/latest/command/set_source_files_properties.html
set(qpid_dispatch_SOURCES
alloc.c
alloc_pool.c
aprintf.c
amqp.c
atomic.c
# [...]
)
set_source_files_properties(${qpid_dispatch_SOURCES} PROPERTIES LANGUAGE CXX)
add_library(qpid-dispatch OBJECT ${qpid_dispatch_SOURCES})
As described in the linked docs, CMake 3.18 changed the scoped effect of set_source_files_properties. See the DIRECTORY and TARGET_DIRECTORY options. Therefore, to apply source file property recursively to all files in your project, your CMakeLists.txt should look something like this
cmake_minimum_required(VERSION 3.20)
project(qpid-dispatch LANGUAGES C CXX)
# [...]
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(router)
# [...]
file(GLOB_RECURSE CFILES "*.c")
set_source_files_properties(${CFILES}
DIRECTORY src tests router
PROPERTIES LANGUAGE CXX)
Copy the world
There is another approach that I've heard can be made to work: in your CMakeLists.txt, recursively copy all *.c files into *.cpp files and declare separate CMake targets to compile the copies. This has the advantage of allowing you to produce C-compiled and CXX-compiled artifacts at the same time, should you need anything like that.
Another braindead way of doing this (I just tried the set_source_files_properties() route and it just didn't even try to compile the files).
Rather than figure out the rats nest of cmake stuff I'm saddled with, I just added a C++ file that #includes the .c file, and added the C++ file to the CMakeLists.txt sources.
Braindead and stupid, but I'm having to deal with horrific code I'm importing. C header files without extern "C" in them, being used by C++ files.

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.

CMAKE_CXX_COMPILER not set in qtcreator

Is there a way (like command line argument or some function in CMakeLists.txt) to print all command line arguments supplied to cmake invocation? Equivalent of bash "echo $#"
I need this to debug, why cmake invoked from qtcreator does not find my compiler (msvc12). After inspecting qtcreator sources, I see that it appends some environment by cmake arguments depending on selected kit. I got messages like
CMAKE_CXX_COMPILER not set
, when I select both "Nmake Desktop Qt MSVC2013 ..." or "Ninja Qt MSVC2013".
When I call cmake from command line, it finds compiler with no additional parameters:
-- Check for working CXX compiler using: Visual Studio 12 2013
-- Check for working CXX compiler using: Visual Studio 12 2013 -- works
My main problem was solved by installing ninja. I thought that the problem was not finding compiler by cmake invoked by qtcreator:
CMAKE_CXX_COMPILER not set
After installing ninja and restarting qtcreator, the problem was gone.
I had the same problem after upgrading Visual Studio 2017.
For some reason, when ADDING (?) CMAKE_CXX_COMPILER in the cmake configuration in Build & Run to the location of the Visual Studio compiler, it should work:
Key: CMAKE_CXX_COMPILER
Value: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx64/x64/cl.exe ==> replace version with the correct one
Don't forget to click "Apply Configuration Changes" below.
Very strange though, because after building, the cmake run becomes CMake Project was parsed successfully.and believe-it-or-not, the CMAKE_CXX_COMPILER is gone!

Using CMake with ifort compiler

I am using CMake 2.8.7 on a Linux machine with Intel 11.0 compilers. I am trying to use CMake for the first time as I would like to build this project on both Windows and Linux machines.
I though of using a simple approach first and used a standard Hello World example:
My src/HelloWorld.f90:
!Test helloworld in Fortran using Cmake
program hello
print *, "Hello World!"
end program hello
My main CMakeLists.txt:
# States that CMake required version must be greater than 2.8.7
cmake_minimum_required(VERSION 2.8.7)
enable_language (Fortran)
project(helloworld Fortran)
add_subdirectory(src)
SET_TARGET_PROPERTIES(helloworld PROPERTIES LINKER_LANGUAGE FORTRAN)
My src/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.7)
# Include the directory itself as a path to include directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# For a large number of source files you can create it in a simpler way
# using file() function:
file(GLOB helloworld_SOURCES *.f90)
I still get an error which says CMAKE_FORTRAN_LINK_EXECUTABLE variable missing. I looked at Abinader's CMake tutorial#1, but haven't had success so far.
any suggestions?? Thanks in advance !
Not a direct answer, as I've never used fortran with cmake, but I can see a few issues here.
First of all: where is your target helloworld defined? project is not a target.
Secondly: where do you use helloworld_SOURCES variable?
Try a more regular way. In your src/CMakeLists.txt add line at the end of file with:
add_executable(helloworld ${helloworld_SOURCES})
Also remove SET_TARGET_PROPERTIES(helloworld PROPERTIES LINKER_LANGUAGE FORTRAN) from main one as it should not be necessary.
Last advice: try not to use file(GLOB ). It is better to define list of all files manualy.
Probably the upper-case "FORTRAN", when setting the linker language is the problem. Try writing it as "Fortran" as in the enable_language statement. CMake derives the variables it uses from the language and this causes CMake to look for CMAKE_FORTRAN_LINK_EXECUTABLE instead of CMAKE_Fortran_LINK_EXECUTABLE.
As also mentioned by Michal, the add_executable has to be added to your CMakeLists.txt.
I tested your issue with the following CMake configurations files
main CMakeLists.txt:
# States that CMake required version must be greater than 2.8.7
cmake_minimum_required(VERSION 2.8.7)
enable_language (Fortran)
project(helloworld Fortran)
add_subdirectory(src)
src/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.7)
add_executable(helloworld HelloWorld.f90)
under Linux for following versions:
ifort (IFORT) 16.0.0.20150815
cmake version 2.8.12.2
I prefer to use cmake-gui. There you can define the ifort compiler as follows:
After definition of source code and binary folder, e.g. build, press "Configure" and select
Click "Next" and define the following compilers
Click "Finish" and "Generate".
Go to build/src folder and execute make. The helloworld executable is generated with ifort successfully and could be called here.
Hint: If ifort is already the default native compiler on your Linux computer then you don't have to specify it in cmake-gui and can go ahead with the first option "Use default native compilers".
Hope it helps.
Let's try this step-by-step:
1) Your Fortran Hello, world is OK!
src/hello.f90
!Test helloworld in Fortran using Cmake
program hello
print *, "Hello World!"
end program hello
2) Now let's write the "inner" CMakeLists.txt
src/CMakeLists.txt
add_executable(helloworld hello.f90)
set_target_properties(
helloworld
PROPERTIES
LINKER_LANGUAGE Fortran
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build)
Here we've created an executable file, which you haven't in your question. Also, we've set its linker language to Fortran (it's case-sensitive parameter!) and the output directory for the compiled file.
3) Now we'll create the "main" CMakeLists.txt
CMakeLists.txt
# States that CMake required version must be greater than 2.8.7
cmake_minimum_required(VERSION 2.8.7)
project(helloworld Fortran)
add_subdirectory(src)
Here we've specified the src subdirectory with inner CMakeLists.txt and the compiler language - it's enough to use project() function, there's not need to use it together with enable_language().
4) Finally, let's build our code in out-of-source manner and run it!
cmake -S . -B build
cmake --build build
./build/helloworld