Ninja: Fortran support for Cray compiler
Using Cray PrgEnv-cce v6.0.5
. Tried with CMake versions 3.16.2
(PrgEnv module), 3.15.3
(PrgEnv module), 3.17.2
(built using spack)
Description
When configuring a project with Fortran source with cce
as the compiler, using the Ninja
buildtool errors.
Minimal example
CMakeLists.txt
project(TEST)
cmake_minimum_required(VERSION 3.15)
enable_language(Fortran)
add_executable(prog1
prog1.f90
)
When configured with
$> cmake -G "Ninja" -DCMAKE_SYSTEM_NAME=CrayLinuxEnvironment .
Produces an error
-- The Fortran compiler identification is Cray 9.1
-- Cray Programming Environment 2.6.4 Fortran
-- Check for working Fortran compiler: /opt/cray/pe/craype/2.6.4/bin/ftn
CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.
Missing variable is:
CMAKE_Fortran_PREPROCESS_SOURCE
CMake Error at /usr/projects/hpcsoft/cle7.0/common/aarch64/cmake/3.16.2/share/cmake-3.16/Modules/CMakeTestFortranCompiler.cmake:30 (try_compile):
Failed to generate test project build system.
Call Stack (most recent call first):
CMakeLists.txt:14 (enable_language)
-- Configuring incomplete, errors occurred!
Using CMakeDetermineFortranCompiler
allows configure to complete but halts on generation with same error
CMakeList.txt
:
project(TEST)
cmake_minimum_required(VERSION 3.15)
include(CMakeDetermineFortranCompiler)
enable_language(Fortran)
add_executable(prog1
prog1.f90
)
output:
$> cmake -G "Ninja" -DCMAKE_SYSTEM_NAME=CrayLinuxEnvironment .
...
-- The Fortran compiler identification is Cray 9.1
-- Cray Programming Environment 2.6.4 Fortran
-- Configuring done
CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.
Missing variable is:
CMAKE_Fortran_PREPROCESS_SOURCE
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
Workaround
The problem arises from Ninja having to preprocess the Fortran source, but CMake does not have a configuration for Cray compilers that do this, or at least I didn't find any.
using Makefile generator:
A simple but not ideal solution is to use Unix Makefiles
as generator
$> cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=CrayLinuxEnvironment .
...completes without error
using Ninja generator:
To use ninja
generator, I need to implement preprocessing explicitly.
CMakeLists.txt
project(TEST)
cmake_minimum_required(VERSION 3.15)
# it appears this is required that this be prepended before setting preprocessing
include(CMakeDetermineFortranCompiler)
if(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Cray")
set(CMAKE_Fortran_PREPROCESS_SOURCE
"${CMAKE_CURRENT_LIST_DIR}/preprocess_crayftn <CMAKE_Fortran_COMPILER> \"<DEFINES>\" \"<INCLUDES>\" \"<FLAGS>\" <SOURCE> <PREPROCESSED_SOURCE>")
# required to try_compile() to work, e.g. in find_package()
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_Fortran_PREPROCESS_SOURCE)
endif()
enable_language(Fortran)
add_executable(prog1
prog1.f90
)
preprocess_crayftn
is a simple script that preprocesses the source; because cray doesn't give an option to rename the preprocessed filename, this is done by hand
preprocess_crayftn
set -e
cray_compiler=$1 # <CMAKE_Fortran_COMPILER>
defines=$2 # <DEFINES>
includes=$3 # <INCLUDES>
flags=$4 # <FLAGS>
source=$5 # <SOURCE>
destination=$6 # <PREPROCESSED_SOURCE>
extension=${source##*.}
filename=$(basename $source)
filename=${filename%.*}
preprocessed=${filename}.i
# preprocess <source_base>.f90 to <source_base>.i, and rename to <preprocessed_source>
$cray_compiler $defines $includes $flags -eP $source && mv $preprocessed $destination
Also note that set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_Fortran_PREPROCESS_SOURCE)
is necessary for any modules that call try_compile()
, as it appears that when try_compile()
is staging tests the same issue is encountered.
Expected behavior
CMake with the Ninja generator should be configured to preprocess fortran source files when the fortran compiler is Cray.