Weird edge case with gcov

I’m trying to detect coverage testing flags in CMake before passing them to gfortran using check_fortran_compiler_flag(). This works fine on Linux (GCC 9.4.0). With MinGW64 on Windows, some flags aren’t detected (GCC 10.2.0). I suspect this might be an issue with the underlying test not finding libgcov but that’s speculation; I don’t know why it’s failing.

In the process of diagnosing this problem, I manually built sample code with a variety of options ( --coverage, -fprofile-arcs, -ftest-coverage) under both the Windows command shell and under MSYS2’s version of bash. The build process was essentially gfortran <options I'm testing> -o mytest mytest.f && mytest but with environment-specific paths, file extensions, etc.

Here’s the weird part: running gfortran from the same directory as mytest.f succeeds under both cmd and bash. If I run gfortran against mytest.f in a different directory (say ../mytest.f), bash puts the coverage files in the directory gfortran was run from. Running this under cmd puts the files in the directory containing the source file. I’m not doing anything weird with environment variables (that I know of) and I’m running the exact same gfortran executable in both cases, literally invoking the same file and path.

The GCC docs say that the coverage files will be placed in the same directory as the object files. My tests originally just specified the input .f file and the result executable with -o. Breaking the build process into separate compilation and executable generation steps shows that object files are created in the source directory under cmd and in the compilation directory under bash. That’s consistent with the original tests.

This leaves me wondering if CMake’s fortran compiler flag checking is being affected by gfortran’s inconsistency in where it writes object files by default.

The workaround is to completely skip option checking, just assume --coverage works, and manually change the options if --coverage fails. Not great but it’s a step forward.

So the main questions are what’s the cleanest way to resolve this and has anyone seen this behavior before? Failing that, how do I get more visibility of what CMake actually invokes from the call to check_fortran_compiler_flag()?

You can use --debug-trycompile and inspect what is left under CMakeFiles/ for that test. CMakeFiles/CMakeError.log may also be of interest.

Thanks; that confirmed my suspicion that it wasn’t linking to gcov in the tests. The current workaround is placing:

set(CMAKE_REQUIRED_LIBRARIES gcov)

right before the check_fortran_compiler_flag() calls for --coverage and -fprofile-arcs

then call unset(CMAKE_REQUIRED_LIBRARIES).

This seems like good variable hygiene; my project typically uses target_link_libraries() and I otherwise don’t use CMAKE_REQUIRED_LIBRARIES. Is this liable to break anything else?

FWIW, diggging down to Internal/CheckSourceCompiles.cmake let me see what was going on. Setting CMAKE_REQUIRED_LIBRARIES seemed like the least worst option.