Change the rule name of executable Cmake - cmake

I would like to change the name of the rule in the makefile generated by cmake. Currently, the rule is named like the executable itself. How do I change to a custom name?
cmake_minimum_required(VERSION 3.22)
project(jetpack2tek3 C)
include_directories(inc)
set(CMAKE_C_STANDARD 11 )
add_executable(serverJ2T3
src/socket_server.c
src/socket.c
src/socket_commands.c
src/commands/id.c
src/commands/map.c
src/commands/ready.c
src/commands/fire.c
src/commands/start.c
src/commands/player.c
src/commands/coin.c
src/commands/finish.c
My makefile generated:
# Build rule for target.
serverJ2T3: cmake_check_build_system
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 serverJ2T3
.PHONY : serverJ2T3
Expected output:
# Build rule for target.
server: cmake_check_build_system
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 serverJ2T3
.PHONY : serverJ2T3

Try this:
add_executable(server ...)
set_target_properties(server PROPERTIES OUTPUT_NAME serverJ2T3)
That gives you a make target named server but with serverJ2T3 as the executable filename.
Ref: https://cmake.org/cmake/help/latest/prop_tgt/OUTPUT_NAME.html

Related

How to write specific multiple target parallel build-able CMakeLists.txt?

This is related question of How to build specific multiple targets parallelly using make?
Multiple targets Makefile can parallel build with specific multiple target.
For example, I have target a, b, and c.
I can do as follows:
make -j2 a b
The targets a and b parallelly.
However my Makefile that is generated by cmake and CMakeList.txt doesn't work parallelly.
Here is my CMakeLists.txt
CMAKE_MINIMUM_REQUIRED (VERSION 3.13.0)
PROJECT (para)
ADD_EXECUTABLE (a a.cpp)
ADD_EXECUTABLE (b b.cpp)
ADD_EXECUTABLE (c c.cpp)
a.cpp, b.cpp, and c.cpp has the same contents
int main() {}
I create build directory as follows:
mkdir build
Then execute cmake as follows:
cd buid
cmake ..
Then execute make with -j2 option no specific target.
make -j2
[master][~/work/training/code/cmake/parallel/build]
[ 16%] Building CXX object CMakeFiles/b.dir/b.cpp.o
[ 33%] Building CXX object CMakeFiles/c.dir/c.cpp.o
[ 50%] Linking CXX executable b
[ 66%] Linking CXX executable c
[ 66%] Built target c
[ 66%] Built target b
[ 83%] Building CXX object CMakeFiles/a.dir/a.cpp.o
[100%] Linking CXX executable a
[100%] Built target a
It is expected result. Two targets build parallelly.
However, if I pass specific targets as follows, build becomes sequentially.
make -j2 a b
[ 50%] Building CXX object CMakeFiles/a.dir/a.cpp.o
[100%] Linking CXX executable a
[100%] Built target a
[ 50%] Building CXX object CMakeFiles/b.dir/b.cpp.o
[100%] Linking CXX executable b
[100%] Built target b
How should I write CMakeLists.txt to build parallelly with specific targets ?
Here is generated Makefile by cmake and CMakeLists.txt above.
;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with C-x C-f and enter text in its buffer.
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.18
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Disable VCS-based implicit rules.
% : %,v
# Disable VCS-based implicit rules.
% : RCS/%
# Disable VCS-based implicit rules.
% : RCS/%,v
# Disable VCS-based implicit rules.
% : SCCS/s.%
# Disable VCS-based implicit rules.
% : s.%
.SUFFIXES: .hpux_make_needs_suffix_list
# Command-line flag to silence nested $(MAKE).
$(VERBOSE)MAKESILENT = -s
#Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E rm -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/kondo/work/training/code/cmake/parallel
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/kondo/work/training/code/cmake/parallel/build
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
/usr/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/kondo/work/training/code/cmake/parallel/build/CMakeFiles /home/kondo/work/training/code/cmake/parallel/build//CMakeFiles/progress.marks
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/kondo/work/training/code/cmake/parallel/build/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named c
# Build rule for target.
c : cmake_check_build_system
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 c
.PHONY : c
# fast build rule for target.
c/fast:
$(MAKE) $(MAKESILENT) -f CMakeFiles/c.dir/build.make CMakeFiles/c.dir/build
.PHONY : c/fast
#=============================================================================
# Target rules for targets named b
# Build rule for target.
b : cmake_check_build_system
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 b
.PHONY : b
# fast build rule for target.
b/fast:
$(MAKE) $(MAKESILENT) -f CMakeFiles/b.dir/build.make CMakeFiles/b.dir/build
.PHONY : b/fast
#=============================================================================
# Target rules for targets named a
# Build rule for target.
a : cmake_check_build_system
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 a
.PHONY : a
# fast build rule for target.
a/fast:
$(MAKE) $(MAKESILENT) -f CMakeFiles/a.dir/build.make CMakeFiles/a.dir/build
.PHONY : a/fast
a.o: a.cpp.o
.PHONY : a.o
# target to build an object file
a.cpp.o:
$(MAKE) $(MAKESILENT) -f CMakeFiles/a.dir/build.make CMakeFiles/a.dir/a.cpp.o
.PHONY : a.cpp.o
a.i: a.cpp.i
.PHONY : a.i
# target to preprocess a source file
a.cpp.i:
$(MAKE) $(MAKESILENT) -f CMakeFiles/a.dir/build.make CMakeFiles/a.dir/a.cpp.i
.PHONY : a.cpp.i
a.s: a.cpp.s
.PHONY : a.s
# target to generate assembly for a file
a.cpp.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/a.dir/build.make CMakeFiles/a.dir/a.cpp.s
.PHONY : a.cpp.s
b.o: b.cpp.o
.PHONY : b.o
# target to build an object file
b.cpp.o:
$(MAKE) $(MAKESILENT) -f CMakeFiles/b.dir/build.make CMakeFiles/b.dir/b.cpp.o
.PHONY : b.cpp.o
b.i: b.cpp.i
.PHONY : b.i
# target to preprocess a source file
b.cpp.i:
$(MAKE) $(MAKESILENT) -f CMakeFiles/b.dir/build.make CMakeFiles/b.dir/b.cpp.i
.PHONY : b.cpp.i
b.s: b.cpp.s
.PHONY : b.s
# target to generate assembly for a file
b.cpp.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/b.dir/build.make CMakeFiles/b.dir/b.cpp.s
.PHONY : b.cpp.s
c.o: c.cpp.o
.PHONY : c.o
# target to build an object file
c.cpp.o:
$(MAKE) $(MAKESILENT) -f CMakeFiles/c.dir/build.make CMakeFiles/c.dir/c.cpp.o
.PHONY : c.cpp.o
c.i: c.cpp.i
.PHONY : c.i
# target to preprocess a source file
c.cpp.i:
$(MAKE) $(MAKESILENT) -f CMakeFiles/c.dir/build.make CMakeFiles/c.dir/c.cpp.i
.PHONY : c.cpp.i
c.s: c.cpp.s
.PHONY : c.s
# target to generate assembly for a file
c.cpp.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/c.dir/build.make CMakeFiles/c.dir/c.cpp.s
.PHONY : c.cpp.s
# Help Target
help:
#echo "The following are some of the valid targets for this Makefile:"
#echo "... all (the default if no target is provided)"
#echo "... clean"
#echo "... depend"
#echo "... edit_cache"
#echo "... rebuild_cache"
#echo "... a"
#echo "... b"
#echo "... c"
#echo "... a.o"
#echo "... a.i"
#echo "... a.s"
#echo "... b.o"
#echo "... b.i"
#echo "... b.s"
#echo "... c.o"
#echo "... c.i"
#echo "... c.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
The top level Makefile that is generated by cmake has .NOPARALLEL:. It prevents parallel build.
So even if I execute make -j2 a b, target a and b build sequentially.
cmake also generates CMakeFiles/Makefile2. It is used as follows from the top level Makefile:
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/kondo/work/training/code/cmake/parallel/build/CMakeFiles /home/kondo/work/training/code/cmake/parallel/build//CMakeFiles/progress.marks
$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/kondo/work/training/code/cmake/parallel/build/CMakeFiles 0
.PHONY : all
CMakeFiles/Makefile2 doesn't prevent parallel build.
So I can parallel build the specific targets if I use explicitly the CMakeFiles/Makefile2.
The command is here.
make -f CMakeFiles/Makefile2 -j2 a b
Thank you #Tsyvarev , your comments are very helpful.

CMake: require building of files in addition to building targets

In this simple CMakefile, the first script list.sh outputs a list of 2 generated files file1.proto;file2.proto, instructing CMake that they can be built from source source.xml (using the second script gen.sh).
cmake_minimum_required(VERSION 3.13)
set(source "source.xml")
execute_process(
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/list.sh ${source}
OUTPUT_VARIABLE protos
)
message("${protos}: ${source}")
add_custom_command(
OUTPUT ${protos}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/gen.sh ${source}
DEPENDS ${source}
)
add_custom_target(my_target DEPENDS ${protos})
Everything works well if I run:
$ cmake ..
file1.proto;file2.proto: source.xml
-- Configuring done
-- Generating done
-- Build files have been written to: /build
$ make my_target
[100%] Generating file1.proto, file2.proto
[100%] Built target my_target
What should I add to be able to also run the code generation with:
$ make file1.proto
[EDIT] autocomplete suggests only the following for command make:
$ make (TAB TAB)
all cmake_force edit_cache/ preinstall
clean default_target help preinstall/
clean/ depend my_target rebuild_cache
cmake_check_build_system edit_cache my_target/ rebuild_cache/
Solution from #KamilCuk :
Adding the following makes it possible to build each proto file individually
(it works, but then cmake complains about circular dependencies!)
foreach(p ${protos})
add_custom_target(${p} DEPENDS {CMAKE_CURRENT_BINARY_DIR}/${p})
endforeach()

How do I build/compile Fortran with MinGW gfortran via CMake?

I've got much more I've got to get figured out with CMake than just the following problem, but it's the first and simplest one which I still can't get past. I've scoured the interwebs and even borrowed the 'Mastering CMake' book from a friend, but I'm still having the hardest time... A lot of stuff exists online with regards to CMake, Fortran, and MinGW, and even combinations of two at a time. But all three together seem to be almost non-existent.
All I want to do (at this point) is get a simple Fortran program built and compiling using CMake on Windows, using MinGW's gfortran compiler.
...And I'm a CMake n00b.
This is what I've been working with so far:
CMakeLists.txt:
project(cmake_test Fortran)
add_executable(testf test.f90)
test.f90:
program test
write(*,*)"hello world"
endprogram test
I've got the MSYS2 version of MinGW, since that's the only version that the code I'm eventually going to be compiling will compile with on Windows. (Ie. when I compile it with my own Makefile in the MSYS2 shell, it compiles.)
I've got my Windows Path appended with ;C:\msys64\mingw64\bin. (I've also tried ;C:\msys64\usr\bin, but it complains about sh.exe being in the same directory, among other issues.)
Then I pop open the CMake-GUI, load in the CMakeLists above, hit Configure, specify the generator for the project to be "MinGW Makefiles", select "Use default native compilers", and get the following output:
The Fortran compiler identification is GNU 5.4.0
Check for working Fortran compiler: C:/msys64/mingw64/bin/gfortran.exe
Check for working Fortran compiler: C:/msys64/mingw64/bin/gfortran.exe -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/mingw64/bin/gfortran.exe supports Fortran 90
Checking whether C:/msys64/mingw64/bin/gfortran.exe supports Fortran 90 -- yes
Configuring done
Then I click Configure again and get:
Configuring done
Then Generate:
Generating done
In my build directory there is then a Makefile and a number of other files and directories.
I try running make in the MSYS2 shell, and I get this:
myself#COMPUTER MSYS /c/users/myself/desktop/dll_test/with_fortran_cmake/build
$ make
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\users\myself\desktop\dll_test\with_fortran_cmake\build>
That last line is a prompt. If I type stuff like make it seems to run it again and it just brings up the prompt again, within the prompt. If I hit Ctrl+C, it kills it and returns to the normal MSYS2 prompt.
So I can't figure out how to actually make it, assuming I'm even doing the CMake part right.
Question: How do I get this example code to build/compile/run given the constraints I've listed?
(What I'd actually rather do, once I get past this part, is get it to work with Visual Studio 13, since I have a C++ project being built with CMake (written mostly by someone else to whom I have limited access for questions and aid) from which I want to be able to call my Fortran. Once I get the Fortran into a library of some sort which is callable by the C++ from Visual Studio, the Fortran can pretty much just be left alone as a pre-built library. I know that editing Fortran from VS is not really much of a possibility, and I'm not interested in doing it.)
Here are the contents of the generated Makefile (note my editor replaced tabs with spaces when I copied it here):
# CMAKE generated file: DO NOT EDIT!
# Generated by "MinGW Makefiles" Generator, CMake Version 3.5
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
SHELL = cmd.exe
# The CMake executable.
CMAKE_COMMAND = "C:\Program Files (x86)\CMake\bin\cmake.exe"
# The command to remove a file.
RM = "C:\Program Files (x86)\CMake\bin\cmake.exe" -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = C:\Users\myself\Desktop\dll_test\with_fortran_cmake
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
"C:\Program Files (x86)\CMake\bin\cmake-gui.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
"C:\Program Files (x86)\CMake\bin\cmake.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles\progress.marks
$(MAKE) -f CMakeFiles\Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles\Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named testf
# Build rule for target.
testf: cmake_check_build_system
$(MAKE) -f CMakeFiles\Makefile2 testf
.PHONY : testf
# fast build rule for target.
testf/fast:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/build
.PHONY : testf/fast
test.obj: test.f90.obj
.PHONY : test.obj
# target to build an object file
test.f90.obj:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.obj
.PHONY : test.f90.obj
test.i: test.f90.i
.PHONY : test.i
# target to preprocess a source file
test.f90.i:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.i
.PHONY : test.f90.i
test.s: test.f90.s
.PHONY : test.s
# target to generate assembly for a file
test.f90.s:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.s
.PHONY : test.f90.s
# Help Target
help:
#echo The following are some of the valid targets for this Makefile:
#echo ... all (the default if no target is provided)
#echo ... clean
#echo ... depend
#echo ... testf
#echo ... edit_cache
#echo ... rebuild_cache
#echo ... test.obj
#echo ... test.i
#echo ... test.s
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0
.PHONY : cmake_check_build_system
Version information:
GNU Fortran (GCC) 5.3.0
Windows 7 Enterprise
Cmake 3.5.2
MSYS2 - I'm not sure how to find the version for this
MinGW - I'm not sure how to find the version for this
I've been through a lot of different pages online during my search, and I didn't bother keeping track of them all, but this one in particular is one I keep coming across because it seems like it's very related from the title, but the actual issue and resolution are totally not:
How can I get a basic Fortran file to compile on Windows/MinGW using CMake?
Here is a quick shell session showing how I was able to build your Fortran program using MSYS2, cmake, make, and gfortran. You should try running the same commands that I did and see if they give different outputs then investigate the reason.
The MSYSTEM variable is especially important; it is determined by what shortcut you click on when starting MSYS2.
$ echo $MSYSTEM
MINGW64
$ which cmake
/mingw64/bin/cmake
$ which gfortran
/mingw64/bin/gfortran
$ which make
/usr/bin/make
$ ls
CMakeLists.txt test.f90
$ cat CMakeLists.txt
project(cmake_test Fortran)
add_executable(testf test.f90)
$ cat test.f90
program test
write(*,*)"hello world"
endprogram test
$ mkdir build && cd build
$ cmake -G"MSYS Makefiles" ..
-- The Fortran compiler identification is GNU 6.2.0
-- Check for working Fortran compiler: D:/msys64/mingw64/bin/gfortran.exe
-- Check for working Fortran compiler: D:/msys64/mingw64/bin/gfortran.exe -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether D:/msys64/mingw64/bin/gfortran.exe supports Fortran 90
-- Checking whether D:/msys64/mingw64/bin/gfortran.exe supports Fortran 90 -- yes
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/david/Documents/scraps/test_fortran/build
$ make
Scanning dependencies of target testf
[ 50%] Building Fortran object CMakeFiles/testf.dir/test.f90.obj
[100%] Linking Fortran executable testf.exe
[100%] Built target testf
$ ./testf.exe
hello world
Edit: There IS a working solution here -- read till the end!
Thanks to David Grayson's comment on the original question, I've found a partial solution. "Partial" because it uses f95 instead of gfortran. I'm posting it because it might work for someone else, and if I'm able to figure out how to get it to work with gfortran, I'll just update it.
Turns out the main issue was a pretty simple mistake: I was using "MinGW Makefiles" instad of "MSYS Makefiles".
When I only changed that, however, I got the following output in the CMake-GUI when I clicked Configure:
CMake Error: CMake was unable to find a build program corresponding to "MSYS Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMake was unable to find a build program corresponding to "MSYS Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMAKE_Fortran_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_AR was not found, please set to archive program. Configuring incomplete, errors occurred!
To fix this, I changed my Windows Path again. I'd been using ;C:\msys64\mingw64\bin, and so I switched it to ;C:\msys64\usr\bin.
This then worked (I clicked Configure a second time, clicked Generate, and then ran make via the MSYS2 terminal in the /build directory), but as you can see in the following output, it used f95 instead of gfortran:
The Fortran compiler identification is GNU 5.3.0
Check for working Fortran compiler: C:/msys64/usr/bin/f95.exe
Check for working Fortran compiler: C:/msys64/usr/bin/f95.exe -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/usr/bin/f95.exe supports Fortran 90
Checking whether C:/msys64/usr/bin/f95.exe supports Fortran 90 -- yes
Configuring done
I'm still working to get it to use gfortran, and I'll update this solution if I figure it out.
Edit:
Okay, this is obviously more of a hack and I'm sure that there's a better solution. I renamed C:\msys64\usr\bin\f95.exe to something else (so that MSYS2 wouldn't find it as another Fortran compiler before finding gfortran). I also had to clear CMake's cache and restart it. But now it works:
The Fortran compiler identification is GNU 5.3.0
Check for working Fortran compiler: C:/msys64/usr/bin/gfortran.exe
Check for working Fortran compiler: C:/msys64/usr/bin/gfortran.exe -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/usr/bin/gfortran.exe supports Fortran 90
Checking whether C:/msys64/usr/bin/gfortran.exe supports Fortran 90 -- yes
Configuring done
Working on figuring out how to do this the "correct" way.
Edit:
Okay, I'm guessing this is the more proper way to do it, as I assume it essentially does the same thing as setting environment variables on the commandline when calling CMake from there.
In the CMake-GUI, I set everything up as explained before, but before clicking Configure for the first time, I clicked the "Add Entry" button with the little plus symbol. I then set two new Cache Entries -- though only one is really necessary:
Name: CMAKE_Fortran_COMPILER
Type: FILEPATH
Value: C:\msys64\usr\bin\gfortran.exe
I also set the following, but this was only to verify that it was calling gfortran properly, as you'll see in the output below:
Name: CMAKE_VERBOSE_MAKEFILE
Type: BOOL
Value: [True]
Then, running make in the MSYS2 terminal, I got the following:
$ make
"/C/Program Files (x86)/CMake/bin/cmake.exe" -H/C/Users/myself/Desktop/dll_test/with_fortran_cmake -B/C/Users/myself/Desktop/dll_test/with_fortran_cmake/build --check-build-system CMakeFiles/Makefile.cmake 0
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/depend
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_depends "MSYS Makefiles" /C/Users/myself/Desktop/dll_test/with_fortran_cmake /C/Users/myself/Desktop/dll_test/with_fortran_cmake /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles/testf.dir/DependInfo.cmake --color=
Scanning dependencies of target testf
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/requires
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make[2]: Nothing to be done for 'CMakeFiles/testf.dir/requires'.
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/build
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
[ 50%] Building Fortran object CMakeFiles/testf.dir/test.f90.obj
/C/msys64/usr/bin/gfortran.exe -c /C/Users/myself/Desktop/dll_test/with_fortran_cmake/test.f90 -o CMakeFiles/testf.dir/test.f90.obj
[100%] Linking Fortran executable testf.exe
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E remove -f CMakeFiles/testf.dir/objects.a
/C/msys64/usr/bin/ar.exe cr CMakeFiles/testf.dir/objects.a #CMakeFiles/testf.dir/objects1.rsp
/C/msys64/usr/bin/gfortran.exe -Wl,--whole-archive CMakeFiles/testf.dir/objects.a -Wl,--no-whole-archive -o testf.exe -Wl,--out-implib,libtestf.dll.a -Wl,--major-image-version,0,--minor-image-version,0
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
[100%] Built target testf
make[1]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles 0
And the resulting program works both via the MSYS2 terminal and a Windows command prompt.
...Now I need to figure out how to get this all together with C++ in Visual Studio. Stay tuned for more SO questions! :D

How to instruct CMake to use the build architecture compiler

When using CMake for cross compiling, one generally specifies a toolchain file via the CMAKE_TOOLCHAIN_FILE option. In GNU terminology, one can specify the host architecture toolset using this file. However, one can generally not expect to be able to execute anything built with this toolchain. So often enough, some build tools need to be compiled for the build architecture.
Consider the following setup. I have two source files genfoo.c and bar.c. During build, genfoo.c needs to be compiled and run. Its output needs to be written to foo.h. Then I can compile bar.c, which #include "foo.h". Since CMake defaults to using the host architecture toolchain, the instructions for bar.c are easy. But how do I tell it to use the build architecture toolchain for compiling genfoo.c? Simply saying add_executable(genfoo genfoo.c) will result in using the wrong compiler.
CMake can only handle one compiler at a time. So - if you don't go the long way to set up the other compiler as a new language - you will end up with two configuration cycles.
I see the following approaches to automate this process:
Taking the example "CMake Cross Compiling - Using executables in the build created during the build?" from the CMake pages as a starting point I'll get:
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(FooBarTest)
# When crosscompiling import the executable targets
if (CMAKE_CROSSCOMPILING)
set(IMPORT_PATH "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file path from a native build")
file(TO_CMAKE_PATH "${IMPORT_PATH}" IMPORT_PATH_CMAKE)
include(${IMPORT_PATH_CMAKE}/genfooTargets.cmake)
# Then use the target name as COMMAND, CMake >= 2.6 knows how to handle this
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
COMMAND genfoo
)
add_executable(bar bar.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Only build the generator if not crosscompiling
if (NOT CMAKE_CROSSCOMPILING)
add_executable(genfoo genfoo.cpp)
export(TARGETS genfoo FILE "${CMAKE_CURRENT_BINARY_DIR}/genfooTargets.cmake")
endif()
Then using a script like:
build.sh
#!/bin/bash
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ..
fi
cmake --build hostBuild
if [ ! -d crossBuild ]; then
cmake -E make_directory crossBuild
cmake -E chdir crossBuild cmake .. -DIMPORT_PATH=${PWD}/hostBuild -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
fi
cmake --build crossBuild
I'll get the desired results by calling ./build.sh.
Splitting the CMakeLists.txt and maybe even replace the export()/include() with something where I know the output path of my build tools e.g. by using CMAKE_RUNTIME_OUTPUT_DIRECTORY would simplify things:
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(FooBarTest)
# Then use the target name as COMMAND. CMake >= 2.6 knows how to handle this
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
COMMAND genfoo
)
add_executable(bar bar.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
buildTools/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(BuildTools)
add_executable(genfoo genfoo.cpp)
build.sh
#!/bin/bash
if [ ! -d crossBuild ]; then
cmake -E make_directory crossBuild
cmake -E chdir crossBuild cmake .. -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
fi
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ../buildTools -DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${PWD}/crossBuild
fi
cmake --build hostBuild
cmake --build crossBuild
References
Making a CMake library accessible by other CMake packages automatically
CMake build multiple targets in different build directories
How do I make CMake output into a 'bin' dir?
It is possible to do that completely within CMake.
The trick is to run a separate CMake configuring stage within its own space, silently dismissing every crosscompiling setting and using the host's default toolchain, then import the generated outputs into it's parent, crosscompiling build.
First part:
set(host_tools_list wxrc generate_foo)
if(CMAKE_CROSSCOMPILING)
# Pawn off the creation of the host utilities into its own dedicated space
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools)
file(TO_NATIVE_PATH ${CMAKE_COMMAND} native_cmake_command)
file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} native_cmake_current_source_dir)
execute_process(
COMMAND "${native_cmake_command}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "${native_cmake_current_source_dir}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools
)
add_custom_target(host_tools
COMMAND ${CMAKE_COMMAND} --build . --target host_tools --config $<CONFIG>
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools
)
include(${CMAKE_CURRENT_BINARY_DIR}/host_tools/host_tools.cmake)
foreach(tgt IN ITEMS ${host_tools_list})
add_dependencies(host${tgt} host_tools)
endforeach()
else()
# Add an empty target, host tools are built inplace
add_custom_target(host_tools
DEPENDS ${host_tools_list}
)
endif()
... then you add the usual add_executable and whatever ...
At the end:
if(NOT CMAKE_CROSSCOMPILING)
foreach(tgt IN ITEMS ${host_tools_list})
add_executable(host${tgt} ALIAS ${tgt})
endforeach()
export(TARGETS ${host_tools_list} NAMESPACE host FILE host_tools.cmake)
endif()
When it crosscompiles, it pawns off the creation of the host-run tools into its own dedicated space, and imports the targets as "hostwxrc" and "hostgenerate_foo", with a dependency on generating the host_tools themselves .
When it doesn't crosscompile, it builds wxrc and generate_foo as-is, and aliases them to hostwxrc and hostgenerate_foo.
After this, when you use $<TARGET_FILE:wxrc>, you refer to the wxrc built for the target platform, and $<TARGET_FILE:hostwxrc> refers to the wxrc built for the host platform, regardless whether they are the same or not.

Add custom commands to CMakeLists.txt file

Recently I have switched my project compilation procedure from make to cmake. I would like to add custom non-compilation related commands to my CMakeLists.txt file. These commands should be inherited from classical Makefile. Commands that I would like to re-use in CMakeLists.txt are:
CODE=main
ARCHIVE=$(CODE)_`date +%F`.tar.bz2
BACKUP=$(HOME)/backup/src/$(CODE)
run:
{ time ./$(CODE); } 2> $(CODE)_time
rerun: fresh run
fresh:
rm -rvf $(CODE)_time *~ fort.* *.ver
rm -rvf coef? enc skin_depths log input_params.out
clean: fresh
rm -rvf $(CODE) *.o *.a *.mod
backup: *
tar -cjvf $(ARCHIVE) $?
tar -tjvf $(ARCHIVE)
mv -vf $(ARCHIVE) $(BACKUP)
ls -lrth $(BACKUP)
How may I transfer these commands to CMakeLists.txt so that they will be automatically inserted into cmake generated Makefile?
CMakeLists.txt
# Minimum cmake version
cmake_minimum_required(VERSION 2.8)
# Project name
project(main Fortran)
# Toolchain selection, possible arguments: Intel, GNU
SET(Toolchain GNU)
# Compiler selection
include(CMakeForceCompiler)
# GNU compilers
if(${Toolchain} MATCHES GNU)
CMAKE_FORCE_Fortran_COMPILER(gfortran "GNU Fortran Compiler")
set(CMAKE_Fortran_FLAGS "-g -O0 -fimplicit-none -fbounds-check -fbacktrace ${CMAKE_Fortran_FLAGS}")
endif(${Toolchain} MATCHES GNU)
# Source code files
SET(src variables.F90
init.F90
io.F90)
# Main executable
ADD_EXECUTABLE(${PROJECT_NAME} ${src})
# EoF: CMakeLists.txt
Use the ADD_CUSTOM_TARGET and/or ADD_CUSTOM_COMMAND commands, e.g.:
ADD_CUSTOM_TARGET(myTarget
COMMAND firstCommand arg1 arg2
COMMAND secondCommand arg1 arg2 arg3)
Then you can use make myTarget.