How do I append a "target triple" to a binary name in CMake using rustc's output? - cmake

I'm using a CMake-generated binary as a tauri sidecar app, which requires that I append a "target triple" to the name of the exe.
Following that page as a guide, I came up with this to query rustc -Vv for the triple:
cmake_minimum_required(VERSION 3.15)
project(targettriple)
set(BIN myexe)
add_executable(myexe main.cpp)
# extract target triple for binary name https://tauri.app/v1/guides/building/sidecar/
execute_process(COMMAND rustc -Vv OUTPUT_VARIABLE RUSTC_VV_OUTPUT)
string(REGEX MATCH "host: (.+)" _ "${RUSTC_VV_OUTPUT}")
string(STRIP "${CMAKE_MATCH_1}" RUST_TARGET_TRIPLE)
message(STATUS "RUST_TARGET_TRIPLE = ${RUST_TARGET_TRIPLE}")
# fails:
set_target_properties(${BIN} PROPERTIES OUTPUT_NAME "${BIN}-${RUST_TARGET_TRIPLE}")
# works:
# set_target_properties(${BIN} PROPERTIES OUTPUT_NAME "${BIN}-x86_64-pc-windows-msvc")
I get in the output:
-- RUST_TARGET_TRIPLE = x86_64-pc-windows-msvc
But then when I build I also get:
C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(31,5): error MSB4184: The expression "[MSBuild]::NormalizePath(C:\Users\...\build\, C:\Users\...\bin\Debug\myexe-x86_64-pc-windows-msvc [C:\Users\...\build\myexe.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(31,5): error MSB4184: release: 1.66.0 [C:\Users\...\build\myexe.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(31,5): error MSB4184: LLVM version: 15.0.2.exe)" cannot be evaluated. Illegal characters in path. [C:\Users\...\build\myexe.vcxproj]
This doesn't make much sense to me. If I hardcode the target triple (as in the last line of the CMakeLists above), it all works fine. What am I doing wrong? Are there mysterious characters in this string that I don't know about?

It looks like your regex is too greedy. When I try it on my machine, it matches the desired contents, and then everything else after that as well:
-- RUST_TARGET_TRIPLE = x86_64-unknown-linux-gnu
release: 1.63.0
LLVM version: 14.0.5
Try using "host: ([a-zA-Z0-9_-]+)" or something else appropriate for your needs. When I use this, I get:
-- RUST_TARGET_TRIPLE = x86_64-unknown-linux-gnu
You can find the docs for CMake's regex specification here: https://cmake.org/cmake/help/latest/command/string.html#regex-specification

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.

How to determine platforms like ARM, MIPS and IA32?

Something is sideways in our CmakeFileList.txt file. Its trying to build an IA32 component on an ARM platform. I'm trying to fix the issue.
The file in question was filtered-out from the GLOB, which is named rdrand.cpp:
list(REMOVE_ITEM cryptopp_SOURCES
...
${CMAKE_CURRENT_SOURCE_DIR}/rdrand.cpp
...
${cryptopp_SOURCES_TEST}
)
set(cryptopp_SOURCES
Now I am trying to add rdrand,cpp back in for IA32 platforms. According to Building c++ project on Windows with CMake, Clang and Ninja (not a good fit, but it has useful information) and CMakePlatformId.h.in, it looks like I need a predicate using ARCHITECTURE_ID and "X86", "X32", "X64" or "x64" (not a dup, the x is lowercase instead of uppercase).
Here's my attempt to create the predicate:
# http://github.com/weidai11/cryptopp/issues/419
if (${ARCHITECTURE_ID} == "X86" OR ${ARCHITECTURE_ID} == "X32" OR ${ARCHITECTURE_ID} == "X64" )
list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.cpp)
endif()
The results below are from a BeagleBoard with Cmake 3.5.2. Neither ==, =,STREQUAL seems to work:
CMake Error at CMakeLists.txt:310 (if):
if given arguments:
"==" "X86" "OR" "==" "X32" "OR" "==" "X64"
Unknown arguments specified
And:
$ cmake .
CMake Error at CMakeLists.txt:310 (if):
if given arguments:
"STREQUAL" "X86" "OR" "STREQUAL" "X32" "OR" "STREQUAL" "X64"
Unknown arguments specified
My attempts to search for how to use ARCHITECTURE_ID are nearly useless. I can't find an example or the docs on Cmake's site. Adding quotes around "${ARCHITECTURE_ID}" did not help; nor did removing the braces to denote a variable ARCHITECTURE_ID.
I also tried to use CMAKE_SYSTEM_PROCESSOR and other related defines, but Cmake mostly returns "unknown" for them. Its not very helpful to say the least.
How do I use ARCHITECTURE_ID to identify IA32 platforms? Or, is there something else I should be using in this instance?
Thanks in advance.
Here's what we do in our GNUmakefile. Make is not a build system, so we have to do the heavy lifting:
IS_X86 := $(shell uname -m | $(EGREP) -v "x86_64" | $(EGREP) -i -c "i.86|x86|i86")
IS_X64 := $(shell uname -m | $(EGREP) -i -c "(_64|d64)")
...
# Need RDRAND for X86/X64/X32
ifeq ($(IS_X86)$(IS_X32)$(IS_X64),000)
SRCS := $(filter-out rdrand.cpp, $(SRCS))
endif
I don't think a variable named ARCHITECTURE_ID does exist in CMake to query. That's probably the reason why you can't find any hints in CMake's documentation. It's only used in CMakePlatformId.h to fill MSVC specific internal variable like MSVC_CXX_ARCHITECTURE_ID.
/* For windows compilers MSVC and Intel we can determine
the architecture of the compiler being used. This is because
the compilers do not have flags that can change the architecture,
but rather depend on which compiler is being used
*/
What you are actually looking for is the cmake_host_system_information()command. The problem there is, that it does not export all the information it actually has. I'm thinking that to be a missing feature and probably will make a pull request for CMake's source Git over the next days to extend its functionality, but that won't help you for the near future.
If you have CMake's source code on the system(s) in question you could run one of the tests
$ cmsysTestscxx testSystemInformation
to see what system information CMake actually has.
𝓝𝓸𝓽𝓮: Querying the host system won't help when cross-compiling or e.g. compiling for 32 Bit on a 64 Bit machine (that could also be a possible flaw in your GNUMakefile example).
To answer your question about the if statement, this can simply be solved by an Regular Expression:
cmake_minimum_required(VERSION 2.4)
project(TestArchitectureId)
if (ARCHITECTURE_ID MATCHES "^(X86|X32|X64|x64)$" )
message(STATUS "Hello ${CMAKE_MATCH_1}")
endif()
Otherwise isn't this somewhat related to Detect 32-bit x86 processor in CMakeList.txt?
Alternatives
CMake itself uses
if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "ia64")
or
if(NOT CMAKE_GENERATOR MATCHES "IA64")
or - even this may be going the extra mile - call try_compile() with rdrand.cpp:
# 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()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
string(TOUPPER "${CMAKE_TRY_COMPILE_CONFIGURATION}" cryptopp_TRY_COMPILE_CONFIGURATION)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS}" "${CMAKE_CXX_FLAGS_${cryptopp_TRY_COMPILE_CONFIGURATION}}")
get_directory_property(CMAKE_REQUIRED_INCLUDES INCLUDE_DIRECTORIES)
get_directory_property(CMAKE_REQUIRED_DEFINITIONS COMPILE_DEFINITIONS)
if (CMAKE_REQUIRED_DEFINITIONS)
string(REPLACE ";" ";-D" CMAKE_REQUIRED_DEFINITIONS "-D${CMAKE_REQUIRED_DEFINITIONS}")
endif()
try_compile(
cryptopp_RDRAND_WORKS
${CMAKE_CURRENT_BINARY_DIR}
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.cpp
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}
-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}
COMPILE_DEFINITIONS
${CMAKE_REQUIRED_DEFINITIONS}
)

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 - get the used commandline flags "-D"

i recently switched a few projects from autotools to cmake.
one common thing i liked on autotools is that - if i go into the src build directory. there is config.log/config.status - where at the top the ./configure --params command is listed - so it is easy to rerun the former used commandline flags.
(like after compiling some stuff - i want to add a another --enable-this - so copy & paste from config.log/status - and rerun the ./configure --old-params --enable-this)
in cmake - i have a bunch of -D flags - how can i find the used commandline like in config.log/status - with a cmake project?
i know there is the CMakeCache... - but its hard to extract the used flags
edit:
i came up with the following solution:
#save commandline to rebuild this :)
set(USED_CMD_LINE "cmake ")
set(MY_CMAKE_FLAGS CMAKE_BUILD_TYPE CMAKE_INSTALL_PREFIX ENABLE_SSL ENABLE_LUA ENABLE_SSH ENABLE_SNMP MYSQL_USER MYSQL_PASS MYSQL_HOST MYSQL_DB FULL_FEATURES USE_COVERAGE)
FOREACH(cmd_line_loop IN ITEMS ${MY_CMAKE_FLAGS})
if(${cmd_line_loop})
STRING(CONCAT USED_CMD_LINE ${USED_CMD_LINE} "-D" ${cmd_line_loop} "=" ${${cmd_line_loop}} " ")
endif()
ENDFOREACH(cmd_line_loop)
STRING(CONCAT USED_CMD_LINE ${USED_CMD_LINE} " .. ")
#store to a file aka "config.status"
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/config.status ${USED_CMD_LINE} )
creates a file config.status in the build folder - containing all set cmake params.
pro:
seems to solve my problem
seems to work on subsequent cmake calls
con:
unable to set chmod on FILE(write ? the variable
MY_CMAKE_FLAGScontains the known flags - needs to be manually
updated if a new flag is added
regards
Cmake does not give you easy way to list all used -D flags (defines). However, for correctly written CMakeLists, it is not needed to know the full command line with all -D flags to change one particular define/option.
Consider this snipplet:
SET(my_var_1 TRUE CACHE BOOL "my var 1")
SET(my_var_2 TRUE CACHE BOOL "my var 2")
message(STATUS "my_var_1 ${my_var_1}")
message(STATUS "my_var_2 ${my_var_2}")
First cmake invocation:
>cmake .. -Dmy_var_1=FALSE
-- my_var_1 FALSE
-- my_var_2 TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: out
Second cmake invocation:
>cmake .. -Dmy_var_2=FALSE
-- my_var_1 FALSE
-- my_var_2 FALSE
-- Configuring done
-- Generating done
-- Build files have been written to: out
Note that my_var_1=FALSE even it is not explicitely stated (taken from cache)
One feature that may be helpful is turning on the flag CMAKE_EXPORT_COMPILE_COMMANDS in the project's CMake cache. During build, this will make CMake generate a JSON file compile_commands.json in the binary directory that contains the exact compiler calls for all translation units.
You may want to take a look at what is done in the bootstrap script in CMake's source code:
# Write our default settings to Bootstrap${_cmk}/InitialCacheFlags.cmake.
echo '
# Generated by '"${cmake_source_dir}"'/bootstrap
# Default cmake settings. These may be overridden any settings below.
set (CMAKE_INSTALL_PREFIX "'"${cmake_prefix_dir}"'" CACHE PATH "Install path prefix, prepended onto install directories." FORCE)
set (CMAKE_DOC_DIR "'"${cmake_doc_dir}"'" CACHE PATH "Install location for documentation (relative to prefix)." FORCE)
set (CMAKE_MAN_DIR "'"${cmake_man_dir}"'" CACHE PATH "Install location for man pages (relative to prefix)." FORCE)
set (CMAKE_DATA_DIR "'"${cmake_data_dir}"'" CACHE PATH "Install location for data (relative to prefix)." FORCE)
' > "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
[...]
"${cmake_bootstrap_dir}/cmake" "${cmake_source_dir}" "-C${cmake_bootstrap_dir}/InitialCacheFlags.cmake" "-G${cmake_bootstrap_generator}" ${cmake_options} ${cmake_bootstrap_system_libs} "$#"
The boostrap script is generating a InitialCacheFlags.cmake file and is then preloading it with the cmake -C option.
And - if you additionally want to output the values to stdout - this initial-cache CMake script also accepts message() commands besides the set(... CACHE) commands.
See also How to store CMake build settings

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