1

I'm unable to get CMake to find Fortran source files in a subdirectory.

I've set up a minimal example to demonstrate. My directory structure is as follows:

  • CMakeLists.txt
  • build/
  • src/
    • CMakeLists.txt
    • main.f90

The top level CMakeLists.txt:

cmake_minimum_required(VERSION 3.11.4)
project(mwe_proj Fortran)
add_executable(mwe_proj_bin "")
add_subdirectory(src)

The second level CMakeLists.txt:

target_sources(mwe_proj_bin
    PRIVATE
        main.f90
)

main.f90:

program MWEproj
      integer :: i = 5
      print *,i
end program

When I go into build and run cmake .. I get this output:

-- The Fortran compiler identification is GNU 8.3.1
-- Check for working Fortran compiler: /usr/bin/gfortran
-- Check for working Fortran compiler: /usr/bin/gfortran  -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether /usr/bin/gfortran supports Fortran 90
-- Checking whether /usr/bin/gfortran supports Fortran 90 -- yes
-- Configuring done
CMake Error at CMakeLists.txt:3 (add_executable):
  Cannot find source file:

    main.f90

  Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
  .hpp .hxx .in .txx


CMake Error at CMakeLists.txt:3 (add_executable):
  No SOURCES given to target: mwe_proj_bin

However, if I move main.f90 up to the main project folder, remove the add_subdirectory line from the top level CMakeLists.txt, and change the add_executable line to add_executable(mwe_proj_bin "main.f90"), CMake runs without a problem, and after running make the program compiles and runs correctly.

The first configuration worked in the past for my project, but I've had to move to a system with an older version of CMake on it. The project originally had cmake_minimum_required(VERSION 3.13) as the first line, but I can't remember if there was a specific reason I set that version requirement or if it was arbitrary. Is there anything here that would obviously fail on CMake < 3.13? If not, what's wrong with my CMakeLists.txt?

As an addendum, I've tried building and using the latest version of CMake and it still doesn't work, so something must be wrong with the CMakeLists files.

zaen
  • 326
  • 3
  • 14
  • 1
    Correct processing of relative paths in `target_sources` command becomes available only in CMake 3.13. See e.g. [that question](https://stackoverflow.com/questions/49996260/how-to-use-target-sources-command-with-interface-library) and answers for it. – Tsyvarev Feb 15 '21 at 10:58

1 Answers1

0

One way to do this is to create (at least) one cmake library per directory, so the CMakeLists.txt in src would look like

add_library(src main.f90)

And the CMakeLists.txt in the root directory would look like

project(foo)
add_executable(foo foo.f90)
add_subdirectory(src)
target_link_libraries(foo src)

For this method you would need a single source file (foo.f90) in the root directory (or you could use this method), but this can be a simple wrapper such as

program foo
  use main_module
  implicit none
  call main()
end program

and this is probably good practice anyway because of Fortran's behaviour re: interfaces which aren't in modules.

veryreverie
  • 2,871
  • 2
  • 13
  • 26