Race condition during copying of Fortran modules
During building of Fortran projects CMake creates commands for copying *.mod files(cmake_copy_f90_mod). If there are 2+ targets, that produce *.mod file with the same name in the same directory, these copy commands may copy wrong files during parallel build.
Reproducible example:
!test.f90
MODULE test_module
IMPLICIT NONE
#if defined(TEST_FOO)
INTERFACE
REAL FUNCTION test_foo()
END FUNCTION test_foo
END INTERFACE
#elif defined(TEST_BAR)
INTERFACE
REAL FUNCTION test_bar()
END FUNCTION test_bar
END INTERFACE
#endif
ENDMODULE test_module
SUBROUTINE test()
#if defined(TEST_FOO)
USE test_module, ONLY:test_foo
#elif defined(TEST_BAR)
USE test_module, ONLY:test_bar
#endif
ENDSUBROUTINE test
#CMakeLists.txt
cmake_minimum_required(VERSION "3.0")
project(main Fortran)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
add_compile_options("-cpp")
add_library(test_foo SHARED test.f90)
target_compile_definitions(test_foo PRIVATE "TEST_FOO")
add_library(test_bar SHARED test.f90)
target_compile_definitions(test_bar PRIVATE "TEST_BAR")
cmake3 -S . -B build
cmake3 --build build --clean-first -j 2
If you build it with -j 1
everything goes fine, but -j 2
leads to 50% chance to get the compilation error:
Fatal Error: Can't rename module file 'test_module.mod0' to 'test_module.mod': No such file or directory
/home/jjack/test_fortran/test.f90:24.26:
USE test_module, ONLY:test_bar
1
Error: Symbol 'test_bar' referenced at (1) not found in module 'test_module'
My system:
[✓ jjack@localhost test_fortran]$ uname -a
Linux localhost.localdomain 3.10.0-862.11.6.el7.x86_64 #1 SMP Tue Aug 14 21:49:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[✓ jjack@localhost test_fortran]$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.5.1804 (Core)
Release: 7.5.1804
Codename: Core
[✓ jjack@localhost test_fortran]$ cmake3 --version
cmake3 version 3.13.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).