Make does not implicitly invoke Fortran preprocessor while ninja and MSVC do
Hi,
when building this simple application with CMake+make Fortran preprocessor is not invoked, but when building with CMake+ninja or CMake+MSVC it is invoked. This is not Fortran compiler issue because behavior is identical with Intel Fortran or gfortran.
cmake_minimum_required(VERSION 3.12)
project(preprocessor Fortran)
add_executable(test main.f90)
program test
#ifdef FOO
print *, FOO
#else
print *, "BAR"
#endif
end program test
$ make VERBOSE=1 && ./test
/usr/bin/cmake -S/home/gz/test/fortran/preprocessor -B/home/gz/test/fortran/preprocessor/build-make --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/gz/test/fortran/preprocessor/build-make/CMakeFiles /home/gz/test/fortran/preprocessor/build-make/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/gz/test/fortran/preprocessor/build-make'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/depend
make[2]: Entering directory '/home/gz/test/fortran/preprocessor/build-make'
cd /home/gz/test/fortran/preprocessor/build-make && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/gz/test/fortran/preprocessor /home/gz/test/fortran/preprocessor /home/gz/test/fortran/preprocessor/build-make /home/gz/test/fortran/preprocessor/build-make /home/gz/test/fortran/preprocessor/build-make/CMakeFiles/test.dir/DependInfo.cmake --color=
Dependee "/home/gz/test/fortran/preprocessor/main.f90" is newer than depends file "/home/gz/test/fortran/preprocessor/build-make/CMakeFiles/test.dir/depend.internal".
Clearing dependencies in "/home/gz/test/fortran/preprocessor/build-make/CMakeFiles/test.dir/depend.make".
Scanning dependencies of target test
make[2]: Leaving directory '/home/gz/test/fortran/preprocessor/build-make'
make -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build
make[2]: Entering directory '/home/gz/test/fortran/preprocessor/build-make'
[ 50%] Building Fortran object CMakeFiles/test.dir/main.f90.o
/home/gz/intel/compilers_and_libraries_2018/linux/bin/intel64/ifort -c /home/gz/test/fortran/preprocessor/main.f90 -o CMakeFiles/test.dir/main.f90.o
/home/gz/test/fortran/preprocessor/main.f90(3): warning #5117: Bad # preprocessor line
#ifdef FOO
-^
/home/gz/test/fortran/preprocessor/main.f90(5): warning #5117: Bad # preprocessor line
#else
-^
/home/gz/test/fortran/preprocessor/main.f90(7): warning #5117: Bad # preprocessor line
#endif
-^
[100%] Linking Fortran executable test
/usr/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
/home/gz/intel/compilers_and_libraries_2018/linux/bin/intel64/ifort CMakeFiles/test.dir/main.f90.o -o test
make[2]: Leaving directory '/home/gz/test/fortran/preprocessor/build-make'
[100%] Built target test
make[1]: Leaving directory '/home/gz/test/fortran/preprocessor/build-make'
/usr/bin/cmake -E cmake_progress_start /home/gz/test/fortran/preprocessor/build-make/CMakeFiles 0
0.0000000E+00
BAR
$ ninja -v && ./test
[1/4] /home/gz/intel/compilers_and_libraries_2018/linux/bin/intel64/ifort -fpp -E ../main.f90 > CMakeFiles/test.dir/main.f90-pp.f90 && /usr/bin/cmake -E cmake_ninja_depends --tdi=CMakeFiles/test.dir/FortranDependInfo.json --pp=CMakeFiles/test.dir/main.f90-pp.f90 --dep=CMakeFiles/test.dir/main.f90-pp.f90.d --obj=CMakeFiles/test.dir/main.f90.o --ddi=CMakeFiles/test.dir/main.f90-pp.f90.ddi
[2/4] /usr/bin/cmake -E cmake_ninja_dyndep --tdi=CMakeFiles/test.dir/FortranDependInfo.json --dd=CMakeFiles/test.dir/Fortran.dd @CMakeFiles/test.dir/Fortran.dd.rsp
[3/4] /home/gz/intel/compilers_and_libraries_2018/linux/bin/intel64/ifort -I../ -c CMakeFiles/test.dir/main.f90-pp.f90 -o CMakeFiles/test.dir/main.f90.o
[4/4] : && /home/gz/intel/compilers_and_libraries_2018/linux/bin/intel64/ifort CMakeFiles/test.dir/main.f90.o -o test && :
BAR
I had a simple fix: unconditionally add -cpp flag:
# Runs the Fortran preprocessor on source files before compilation
target_compile_options(test PRIVATE -cpp)
Unfortunately debugging in QtCreator in CMake+ninja configuration does not work. Breakpoints would not get hit or debugger would switch to disassembly window. Most probably because when using ninja Fortran preprocessor would be called twice and that somehow confuses debugger (it messes up debug symbols).
So my current fix is to conditionally add -cpp flag:
# Runs the Fortran preprocessor on source files before compilation. Visual Studio
# and ninja as CMake generators already run Fortran preprocessor, only make does not.
if (NOT WIN32 AND ${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
target_compile_options(test PRIVATE -cpp)
endif ()
My request would be to have consistent behavior across generators: preprocessor flag should be implicitly set by all generators or none. Current situation is confusing. It took me quite some time to realize that CMake+ninja would implicitly invoke preprocessor and that debugging actually works in that configuration.