| cmake_minimum_required(VERSION 3.24.0) |
| |
| include(CheckFortranCompilerFlag) |
| |
| # NOTE: flang does not currently (as of 2023/03/20) support the -w flag. If |
| # support for the flag is added, this should be removed. |
| remove_definitions(-w) |
| |
| # This option is added because as of 2023/03/20, several tests in this |
| # directory have been disabled. Some of them exercise unsupported non-standard |
| # extensions, others trigger a "not yet implemented" assertion while some cause |
| # flang to crash. This option forces all the tests to build and can be used to |
| # determine if any of the disabled tests can be enabled. |
| option(TEST_SUITE_FORTRAN_FORCE_ALL_TESTS |
| "Build and run all gfortran tests, including those in the 'unsupported', 'unimplemented', 'skipped', and 'failing' categories." |
| OFF) |
| |
| # Since the FORCE_ALL_TESTS option is a bit too blunt, there are some other |
| # options to force building some subsets of the disabled tests. |
| |
| # The 'unsupported' tests exercise non-standard extensions that are not |
| # currently supported. But there is a chance some may be in the future, in which |
| # case, it may be worthwhile seeing if any can be removed from the list and |
| # enabled permanently. |
| option(TEST_SUITE_FORTRAN_FORCE_UNSUPPORTED_TESTS |
| "Build and run all 'unsupported' gfortran tests. These usually test non-standard extensions." |
| OFF) |
| |
| # The 'unimplemented' tests trigger a "not yet implemented" assertion at |
| # compile-time. If those features are implemented, enabling those tests may help |
| # in identifying those that can be removed from the list and permanently enabled |
| # because the root cause has been addressed. |
| option(TEST_SUITE_FORTRAN_FORCE_UNIMPLEMENTED_TESTS |
| "Build and run all 'unimplemented' gfortran tests. These are tests that fail at build-time because of unimplemented features in flang." |
| OFF) |
| |
| # The 'skipped' tests cause flang to crash at compile-time for "non-obvious" |
| # reasons. They could be related to unimplemented features, or they could be |
| # bugs in the compiler. In any case, enabling them may help identify those tests |
| # that can be removed from the list and permanently enabled because the root |
| # cause has been addressed. |
| option(TEST_SUITE_FORTRAN_FORCE_SKIPPED_TESTS |
| "Build and run all 'skipped' gfortran tests. These are tests that cause flang to crash." |
| OFF) |
| |
| # The 'failing' tests fail to pass either because of a bug somewhere in the |
| # compiler or the runtime. Enabling these tests may help identify those tests |
| # that can be removed from the list and permanently enabled because the root |
| # cause has been addressed. |
| option(TEST_SUITE_FORTRAN_FORCE_FAILING_TESTS |
| "Build and run all 'failing' tests. These tests failed at runtime, perhaps due to bugs in the code generator or bugs/unimplemented features in the runtime." |
| OFF) |
| |
| # The ISO_Fortran_binding.h file is required to run some of the tests. This |
| # header is copied to ${CMAKE_INSTALL_PREFIX}/include/flang at flang install |
| # time which can be found automatically. If the compiler being tested here is |
| # not installed, that file will not be found. In that case, the path to it must |
| # be provided explicitly. |
| set(TEST_SUITE_FORTRAN_ISO_C_HEADER_DIR "" CACHE STRING |
| "Path to the directory containing ISO_Fortran_bindings.h header file.") |
| |
| # The following cause errors if they are passed to flang via FFLAGS. This could |
| # be because they are currently unsupported and might eventually be supported |
| # or because they are GCC-specific and will never be supported. |
| set(FLANG_ERRORING_FFLAGS |
| max-completely-peel-loop-nest-depth=1 |
| -fallow-invalid-boz |
| -fcheck-array-temporaries |
| -fcheck=bounds |
| -fcheck=do |
| -fcheck=recursion |
| -fcoarray=lib |
| -fcray-pointer |
| -fdec |
| -fdec-format-defaults |
| -fdec-static |
| -fdec-structure |
| -frecord-marker=4 |
| -fbounds-check |
| -fcheck-bounds |
| -fcheck=all |
| -fcheck=bits |
| # Not sure if the -fdefault-* options will be supported. Maybe in a different |
| # form in which case, this will have to be modified to accommodate those. |
| -fdefault-real-10 |
| -fdefault-real-16 |
| -fdump-ipa-cp-details |
| -fdump-ipa-fnsummary-details |
| -fdump-ipa-inline-details |
| -fdump-rtl-expand |
| -fdump-tree-all |
| -fdump-tree-cunroll-details |
| -fdump-tree-cunrolli-details |
| -fdump-tree-fre1 |
| -fdump-tree-gimple |
| -fdump-tree-ifcvt |
| -fdump-tree-lversion-details |
| -fdump-tree-omplower |
| -fdump-tree-optimized |
| -fdump-tree-original |
| -fdump-tree-pcom-details |
| -fdump-tree-pre-details |
| -fdump-tree-profile-estimate |
| -fdump-tree-reassoc1 |
| -fdump-tree-vect-details |
| -fexpensive-optimizations |
| -ff2c |
| -ffree-line-length-none |
| -ffrontend-optimize |
| -fgcse |
| -finline-matmul-limit=0 |
| -finline-matmul-limit=10 |
| -finline-matmul-limit=100 |
| -finline-matmul-limit=1000 |
| -finline-matmul-limit=2 |
| -finline-matmul-limit=30 |
| -fipa-cp |
| -fipa-cp-clone |
| -fipa-pta |
| -fipa-reference |
| -fmodulo-sched |
| -fno-align-commons |
| -fno-asynchronous-unwind-tables |
| -fno-backtrace |
| -fno-bounds-check |
| -fno-check-array-temporaries |
| -fno-dec |
| -fno-f2c |
| -fno-frontend-optimize |
| -fno-guess-branch-probability |
| -fno-inline |
| -fno-ipa-cp |
| -fno-ipa-modref |
| -fno-ipa-sra |
| -fno-pad-source |
| -fno-range-check |
| -fno-realloc-lhs |
| -fno-sign-zero |
| -fno-strict-aliasing |
| -fno-tree-ccp |
| -fno-tree-forwprop |
| -fno-tree-fre |
| -fno-tree-loop-optimize |
| -fno-tree-loop-vectorize |
| -fpad-source |
| -fpeel-loops |
| -frecursive |
| -fsanitize=undefined |
| -fschedule-insns |
| -fset-g77-defaults |
| -fshort-enums |
| -fstrict-aliasing |
| -ftest-forall-temp |
| -ftree-loop-distribution |
| -ftree-loop-vectorize |
| -ftree-pre |
| -ftree-slp-vectorize |
| -ftree-tail-merge |
| -ftree-vectorize |
| -ftree-vrp |
| -funroll-loops |
| -fwrapv |
| -mdalign |
| -mdejagnu-cpu=power4 |
| -mfpmath=387 |
| -mfpmath=sse |
| -mtune=amdfam10 |
| # -Os might eventually be supported, so this might also need to be removed |
| # at some point |
| -Og |
| -Os |
| # At some point, if we ever support explicit standard flags, some of these |
| # should be removed. |
| -pedantic-errors |
| -std=gnu |
| -std=legacy |
| -std=f95 |
| -std=f2003 |
| -std=f2008 |
| -std=f2008ts |
| # At the time of writing, -W warnings are not supported. flang errors out |
| # saying that only -Werror is supported. |
| -Wall |
| -Wampersand |
| -Wanalyzer-too-complex |
| -Warray-bounds |
| -Warray-temporaries |
| -Wconversion |
| -Wconversion-extra |
| -Werner |
| -Werror |
| -Wextra |
| -Wfunction-elimination |
| -Wimplicit-procedure |
| -Wintrinsic-shadow |
| -Wintrinsics-std |
| -Wline-truncation |
| -Wno-all |
| -Wno-analyzer-null-dereference |
| -Wno-analyzer-possible-null-dereference |
| -Wno-analyzer-too-complex |
| -Wno-analyzer-use-of-uninitialized-value |
| -Wno-c-binding-type |
| -Wno-complain-wrong-lang |
| -Wno-error |
| -Wno-intrinsic-shadow |
| -Wno-intrinsics-std |
| -Wno-lto-type-mismatch |
| -Wno-tabs |
| -Wno-underflow |
| -Wrealloc-lhs |
| -Wrealloc-lhs-all |
| -Wreturn-type |
| -Wstringop-overflow |
| -Wsurprising |
| -Wtabs |
| -Wuninitialized |
| -Wunused |
| -Wunused-dummy-argument |
| -Wunused-function |
| -Wunused-parameter |
| -Wunused-variable |
| -Wzerotrip |
| -w |
| --param |
| ) |
| |
| # Find all the Fortran files in the current source directory that may be test |
| # files. This will filter out those files that have been explicitly disabled |
| # for any reason. The returned files will be consist of the main file for |
| # "execute" and "compile" tests as well as any dependencies for multi-file |
| # tests. |
| function(gfortran_find_test_files unsupported unimplemented skipped failing out) |
| # This will just get all the Fortran source files in the directory. Since |
| # the tests may be a mix of single-source and multi-source tests, this will |
| # include files that are dependencies of some "main" test file as well. |
| file(GLOB files CONFIGURE_DEPENDS LIST_DIRECTORIES false |
| *.f* |
| *.F* |
| ) |
| |
| set(ignore "") |
| |
| # There is still a chance that some of the unsupported tests may need to be |
| # enabled, for instance if the non-standard extensions that they exercise are |
| # supported due to user demand. |
| if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND |
| NOT TEST_SUITE_FORTRAN_FORCE_UNSUPPORTED_TESTS) |
| list(APPEND ignore ${unsupported}) |
| endif() |
| |
| # For the remaining tests, there is cause to build and run the skipped, failing |
| # and unimplemented tests since some could be enabled once some feature is |
| # implemented. Eventually, all the TEST_SUITE_FORTRAN_FORCE_* options (perhaps |
| # with the exception of TEST_SUITE_FORTRAN_FORCE_UNSUPPORTED_TESTS) should |
| # become redundant and removed. |
| if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND |
| NOT TEST_SUITE_FORTRAN_FORCE_UNIMPLEMENTED_TESTS) |
| list(APPEND ignore ${unimplemented}) |
| endif() |
| |
| if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND |
| NOT TEST_SUITE_FORTRAN_FORCE_SKIPPED_TESTS) |
| list(APPEND ignore ${skipped}) |
| endif() |
| |
| if (NOT TEST_SUITE_FORTRAN_FORCE_ALL_TESTS AND |
| NOT TEST_SUITE_FORTRAN_FORCE_FAILING_TESTS) |
| list(APPEND ignore ${failing}) |
| endif() |
| |
| foreach(file ${ignore}) |
| list(REMOVE_ITEM files ${file}) |
| endforeach() |
| |
| set(${out} ${files} PARENT_SCOPE) |
| endfunction() |
| |
| # Populate the tests from the files in the subdirectory. This macro will be |
| # called from each subdirectory containing tests. It is expected that the |
| # subdirectory will contain a file named "DisabledFiles.cmake" which will |
| # provide the list of files that are disabled in that subdirectory for various |
| # reasons. A list named TESTS is expected to be in scope before this macro is |
| # called. |
| macro(gfortran_populate_tests TESTS) |
| string(REPLACE "${CMAKE_SOURCE_DIR}/" "" DIR "${CMAKE_CURRENT_SOURCE_DIR}") |
| message(STATUS "Adding directory ${DIR}") |
| |
| set(UNSUPPORTED "") |
| set(UNIMPLEMENTED "") |
| set(SKIPPED "") |
| set(FAILING "") |
| |
| # This will provide the lists of unsupported, unimplemented, skipped and |
| # failing files. |
| include(${CMAKE_CURRENT_SOURCE_DIR}/DisabledFiles.cmake) |
| |
| list(APPEND UNSUPPORTED ${UNSUPPORTED_FILES}) |
| list(APPEND UNIMPLEMENTED ${UNIMPLEMENTED_FILES}) |
| list(APPEND SKIPPED ${SKIPPED_FILES}) |
| list(APPEND FAILING ${FAILING_FILES}) |
| |
| # do the same for any requested feature extentions |
| foreach(feature ${TEST_SUITE_FORTRAN_FEATURES}) |
| set(UNSUPPORTED_FILES "") |
| set(UNIMPLEMENTED_FILES "") |
| set(SKIPPED_FILES "") |
| set(FAILING_FILES "") |
| include(${CMAKE_CURRENT_SOURCE_DIR}/DisabledFiles${feature}.cmake) |
| list(APPEND UNSUPPORTED ${UNSUPPORTED_FILES}) |
| list(APPEND UNIMPLEMENTED ${UNIMPLEMENTED_FILES}) |
| list(APPEND SKIPPED ${SKIPPED_FILES}) |
| list(APPEND FAILING ${FAILING_FILES}) |
| |
| # enable any tests that now pass for this feature |
| set(SUPPORTED_FILES "") |
| set(IMPLEMENTED_FILES "") |
| set(UNSKIPPED_FILES "") |
| set(PASSING_FILES "") |
| include(${CMAKE_CURRENT_SOURCE_DIR}/EnabledFiles${feature}.cmake) |
| list(REMOVE_ITEM UNSUPPORTED ${SUPPORTED_FILES}) |
| list(REMOVE_ITEM UNIMPLEMENTED ${IMPLEMENTED_FILES}) |
| list(REMOVE_ITEM SKIPPED ${UNSKIPPED_FILES}) |
| list(REMOVE_ITEM FAILING ${PASSING_FILES}) |
| endforeach() |
| |
| # The TESTS variable is expected to be set before the macro is called. |
| gfortran_find_test_files( |
| "${UNSUPPORTED}" "${UNIMPLEMENTED}" "${SKIPPED}" "${FAILING}" "${TESTS}") |
| endmacro() |
| |
| # Generate a unique target name from the given base and prepend it with the |
| # given prefix. |
| function(gfortran_unique_target_name prefix base out) |
| # There are a few tests - in different directories - with duplicate filenames. |
| # CMake requires all target names to be unique, so we add a disambiguator. The |
| # disambiguator uses the path of the file relative to the top-level directory |
| # containing all the tests from the gfortran test suite to ensure that |
| # targets in different directories will have distinct names. |
| set(result "") |
| |
| # The ${base} argument is guaranteed to be the absolute path to a source file. |
| string(REPLACE "${PROJECT_SOURCE_DIR}/Fortran/gfortran/" "" result "${base}") |
| |
| # Replace any '/' separators with 2 underscores. Just replacing it by a single |
| # underscore results in conflicts. For instance, there is a conflict between |
| # regression/coarray_ptr_comp_2.f08 and regression/coarray/ptr_comp_2.f08 |
| # which are unrelated tests. Other such conflicts are probably also unrelated. |
| string(REPLACE "/" "__" result "${result}") |
| |
| # Retain the extension of the source file in the final target name because |
| # there are cases where two source files with the same basename but different |
| # extensions and they, too, represent completely different and unrelated |
| # tests. |
| string(REPLACE "." "_" result "${result}") |
| |
| set(${out} "${prefix}-${result}" PARENT_SCOPE) |
| endfunction() |
| |
| # Several tests in the suite build modules with the same name at build-time. |
| # Others create/write/read files with the same name at test-time. In either |
| # case, these are race conditions which can lead to non-deterministic failures |
| # at build and/or test time. To work around this, have each test run in its |
| # own directory. |
| # |
| # This directory is also used as module directory at build-time. |
| # |
| # It may be "cleaner" to have separate directories - one that serves as the |
| # module directory and the other as the working directory, but that is |
| # probably unnecessary. |
| # |
| # Make a working directory for the given target and return the full path of |
| # the resulting directory. |
| function(gfortran_make_working_dir tgt out) |
| set(working_dir "${CMAKE_CURRENT_BINARY_DIR}/${tgt}.wd") |
| |
| file(MAKE_DIRECTORY ${working_dir}) |
| |
| set("${out}" "${working_dir}" PARENT_SCOPE) |
| endfunction() |
| |
| # Setup a "compile" test. EXPECT_ERROR will be ON if the compile test is |
| # expected to fail, OFF otherwise. MAIN is the main test file. In the case of |
| # multi-file tests, OTHERS will be the remaining files needed by the test. |
| # FFLAGS are compiler flags needed by the test. LDFLAGS are linker flags needed |
| # by the test. |
| function(gfortran_add_compile_test expect_error main others fflags ldflags) |
| # The test-suite expects an executable to be produced at build time and for |
| # that executable to be run at test time. The result (in the form of the |
| # return code or the output written to stdout/stderr) is used to determine |
| # whether the test has succeeded. The "compile" tests are intended to exercise |
| # the behavior of the compiler itself. There isn't a clean way of having the |
| # compiler be executed at test time. Instead, the compiler is run at |
| # build time and the diagnostics/errors saved to a file as needed. This file is |
| # compared to a reference output at test time to determine success/failure of |
| # the test. A dummy executable is also built. This does nothing, but provides |
| # something that the test suite can "run" at test time. |
| |
| # PREFIX_COMPILE will have been defined in the subdirectory from which this |
| # function is called. |
| gfortran_unique_target_name("${PREFIX_COMPILE}" "${main}" target) |
| gfortran_make_working_dir("${target}" working_dir) |
| |
| # The output of the compilation of the test file. This may contain warnings |
| # and error messages. If the compilation succeeded without any warnings or |
| # other diagnostics, it will be empty. |
| set(out ${target}.out) |
| |
| # Add the CMake-wide environment variable CMAKE_Fortran_FLAGS |
| # CMake escapes spaces. To really get a space (between arguments) use a ; |
| string(REPLACE " " ";" fflags ${fflags} ";" ${CMAKE_Fortran_FLAGS}) |
| |
| add_custom_command( |
| OUTPUT ${out} |
| COMMAND ${CMAKE_COMMAND} |
| -DCMD="${CMAKE_Fortran_COMPILER_LAUNCHER};${CMAKE_Fortran_COMPILER};-c;${fflags};${ldflags};${others};${main}" |
| -DALWAYS_SAVE_DIAGS=OFF |
| -DWORKING_DIRECTORY=${working_dir} |
| -DOUTPUT_FILE=${out} |
| -P ${COMPILE_SCRIPT_BIN} |
| USES_TERMINAL |
| COMMENT "Compiling ${main}") |
| |
| add_custom_target(${target} |
| ALL |
| DEPENDS ${out} |
| SOURCES ${main} ${others}) |
| |
| # The dummy and empty reference output files are in |
| # ${CMAKE_BINARY_DIR}/Fortran/gfortran. This function could be called from |
| # any of the subdirectories under ${CMAKE_BINARY_DIR}/Fortran/gfortran. The |
| # tests need paths relative to the directory containing the test, so calculate |
| # the relative path back to ${CMAKE_BINARY_DIR}/Fortran/gfortran. |
| file(RELATIVE_PATH relpath |
| ${CMAKE_CURRENT_BINARY_DIR} |
| ${CMAKE_BINARY_DIR}/Fortran/gfortran) |
| |
| # The test suite expects an executable to run, so give it the dummy (see |
| # comments above). |
| llvm_test_run(EXECUTABLE %S/${relpath}/${DUMMY_EXE}) |
| |
| # The verification compares the saved diagnostics file against what is |
| # expected. For the test. The reference output may have been extracted from |
| # the DejaGNU annotations in the test file, or it may be an empty file if the |
| # compilation of the test file was expected to be successful and without any |
| # diagnostics. |
| if (expect_error) |
| # Since we don't check for any particular error, we expect "some" error. |
| # In that case, the compiler's diagnostic output will be non-empty. |
| llvm_test_verify(%b/not ${DIFFPROG} %S/${relpath}/${EMPTY_FILE} %S/${out}) |
| else () |
| llvm_test_verify(${DIFFPROG} %S/${relpath}/${EMPTY_FILE} %S/${out}) |
| endif () |
| |
| llvm_add_test(${target}.test %S/${relpath}/${DUMMY_EXE}) |
| endfunction() |
| |
| # Look for "compile" tests in TESTS and create a test for each "main" file that |
| # is found. |
| function(gfortran_add_compile_tests_from tests) |
| cmake_parse_arguments(GFORTRAN "" "" "FFLAGS;LDFLAGS" ${ARGN}) |
| |
| foreach (file ${tests}) |
| # Whether this test is expected to pass or fail. |
| set(expect_error OFF) |
| |
| # For multi-file tests, these are the other files needed. For the "compile" |
| # tests, there don't seem to be any multi-file tests at the time of writing, |
| # but leave it general in case that ever changes. |
| set(others "") |
| |
| set(fflags "") |
| set(ldflags "") |
| list(APPEND fflags ${GFORTRAN_FFLAGS}) |
| list(APPEND ldflags ${GFORTRAN_LDFLAGS}) |
| |
| file(STRINGS ${file} lines) |
| foreach (line ${lines}) |
| # The "compile" tests have a { dg-do compile } directive. |
| if (line MATCHES "^.*[{][ ]*dg-do[ ]*compile(.*)[}].*$") |
| # TODO: We completely ignore any target directives that may be attached |
| # to the run directives. For now, it seems to be ok, but as these tests |
| # are enabled on more platforms, the target directives might need to be |
| # handled. |
| elseif (line MATCHES "dg-additional-sources[ ]*[\"]?(.+)[\"]?[ ]*[}]") |
| separate_arguments(others UNIX_COMMAND ${CMAKE_MATCH_1}) |
| list(TRANSFORM others STRIP) |
| elseif (LINE MATCHES "dg-(additional-)?options [{]?[ ]*\"([^\"]*)\"[ ]*[}]?(.*)") |
| # TODO: We completely ignore any target directives that may be attached |
| # to the run directives. For now, it seems to be ok, but as these tests |
| # are enabled on more platforms, the target directives might need to be |
| # handled. |
| separate_arguments(file_fflags UNIX_COMMAND ${CMAKE_MATCH_2}) |
| list(REMOVE_ITEM file_fflags ${FLANG_ERRORING_FFLAGS}) |
| list(APPEND fflags ${file_fflags}) |
| elseif (line MATCHES "[{][ ]*dg-error[ ]*") |
| # Currently, we don't try to match gfortran's expected errors with |
| # flang's expected error messages. Instead, if gfortran expects an |
| # error, we test that flang produces "some" error. |
| # TODO: It may be more useful to match gfortran's error messages to |
| # flang's in which case we should do something more sophisticated here, |
| # but as a first pass, the more basic approach should do. |
| set(expect_error ON) |
| endif() |
| endforeach() |
| |
| # Some files look like they ought to be "compile" tests but they don't |
| # contain a DejaGNU compile directive. Some have an error or other |
| # directive that could be used to infer that they are actually compile tests |
| # but for those that are intended to succeed, there may be no directives |
| # at all. So just treat all files as if they were "compile" tests (even |
| # those that are the main files of execute tests and ones that are |
| # dependencies in multi-file tests). |
| gfortran_add_compile_test(${expect_error} ${file} "${others}" "${fflags}" "${ldflags}") |
| endforeach() |
| endfunction() |
| |
| # Creates a "compile" test from each file in TESTS. It is assumed that the |
| # compilation is intended to succeed. Any compile/link flags that the test needs |
| # must be passed explicitly. |
| function(gfortran_add_compile_tests tests) |
| cmake_parse_arguments(GFORTRAN "" "" "FFLAGS;LDFLAGS" ${ARGN}) |
| |
| list(APPEND fflags ${GFORTRAN_FFLAGS}) |
| list(APPEND ldflags ${GFORTRAN_LDFLAGS}) |
| |
| foreach (file ${tests}) |
| gfortran_add_compile_test(OFF ${file} "" "${fflags}" "${ldflags}") |
| endforeach() |
| endfunction() |
| |
| # Setup an "execute" test. In the case of multi-file tests, MAIN will be the |
| # main file. For multi-file tests, OTHERS will be the remaining files needed by |
| # the test. FFLAGS are additional compiler flags needed by the test. LDFLAGS |
| # are the other linker flags needed by the test. |
| function(gfortran_add_execute_test main others fflags ldflags) |
| # PREFIX_EXECUTE will have been defined in the subdirectory from which this |
| # function is called. |
| gfortran_unique_target_name("${PREFIX_EXECUTE}" "${main}" target) |
| gfortran_make_working_dir("${target}" working_dir) |
| get_filename_component(working_dir_name "${working_dir}" NAME) |
| |
| llvm_test_executable_no_test(${target} ${main} ${others}) |
| llvm_test_run(WORKDIR "%S/${working_dir_name}") |
| llvm_add_test_for_target(${target}) |
| |
| target_include_directories(${target} |
| PRIVATE ${ISO_FORTRAN_C_HEADER_DIR} ${working_dir}) |
| target_compile_options(${target} PRIVATE "${fflags}") |
| target_link_options(${target} PRIVATE "${ldflags}") |
| set_target_properties(${target} PROPERTIES |
| Fortran_MODULE_DIRECTORY ${working_dir}) |
| |
| # This is a workaround because cmake does not currently recognize the .f03 |
| # and .f08 extensions. A patch to fix cmake has been accepted and the fix |
| # should be available in CMake 3.27. It might be better to check the CMake |
| # version and do this conditionally. |
| list(APPEND sources ${main}) |
| list(APPEND sources ${others}) |
| foreach(source ${sources}) |
| get_filename_component(ext ${source} LAST_EXT) |
| if("${ext}" STREQUAL ".f03" OR |
| "${ext}" STREQUAL ".F03" OR |
| "${ext}" STREQUAL ".f08" OR |
| "${ext}" STREQUAL ".F08") |
| set_source_files_properties(${source} PROPERTIES LANGUAGE Fortran) |
| endif() |
| endforeach() |
| |
| set_target_properties(${target} PROPERTIES LINKER_LANGUAGE Fortran) |
| endfunction() |
| |
| # Look for "execute" tests in TESTS and create a test for each "main" file that |
| # is found. In the case of multi-file tests, other files may be needed for the |
| # test. Those will be obtained by parsing the DejaGNU directives in the "main" |
| # file. |
| function(gfortran_add_execute_tests_from tests) |
| cmake_parse_arguments(GFORTRAN "" "" "FFLAGS;LDFLAGS" ${ARGN}) |
| |
| foreach(file ${tests}) |
| # The file containing the "run" directive will be the main file. |
| set(main "") |
| |
| # For multi-file tests, these are the other files needed. |
| set(others "") |
| |
| # Any flags needed to compile the test. These will be flang-specific flags. |
| # Directives in the test files may specify additional flags needed by the |
| # test. Those will be parsed in gfortran_add_execute_test. |
| set(fflags "") |
| set(ldflags "") |
| list(APPEND fflags ${GFORTRAN_FFLAGS}) |
| list(APPEND ldflags ${GFORTRAN_LDFLAGS}) |
| |
| file(STRINGS ${file} lines) |
| foreach (line ${lines}) |
| # The "execute" tests have a { dg-do run }, or a { dg-lto-do run } |
| # directive. |
| if (line MATCHES "^.*[{][ ]*dg-(lto-)?do[ ]*run (.*)[}]$") |
| # TODO: We completely ignore any target directives that may be attached |
| # to the run directives. For now, it seems to be ok, but as these tests |
| # are enabled on more platforms, the target directives might need to be |
| # handled. |
| set(main "${file}") |
| elseif (line MATCHES "dg-additional-sources[ ]*[\"]?(.+)[\"]?[ ]*[}]") |
| separate_arguments(others UNIX_COMMAND ${CMAKE_MATCH_1}) |
| list(TRANSFORM others STRIP) |
| elseif (line MATCHES "dg-(additional-)?options [{]?[ ]*\"([^\"]*)\"[ ]*[}]?(.*)") |
| # TODO: We completely ignore any target-specific options that may be |
| # present. These are usually in the form of target directives. For now, |
| # it seems to be ok, but as these tests are enabled on more platforms, |
| # target directives might need to be handled. |
| separate_arguments(file_fflags UNIX_COMMAND ${CMAKE_MATCH_2}) |
| list(REMOVE_ITEM file_fflags ${FLANG_ERRORING_FFLAGS}) |
| list(APPEND fflags ${file_fflags}) |
| endif() |
| endforeach() |
| |
| # Since any dependent files could also be processed by this function, there |
| # is no guarantee that main will have been set. |
| if (main) |
| gfortran_add_execute_test(${main} "${others}" "${fflags}" "${ldflags}") |
| endif() |
| endforeach() |
| endfunction() |
| |
| # Creates an "execute" test from each file in TESTS. The tests are assumed to |
| # not contain any additional DejaGNU directives. Any compiler/linker flags |
| # needed by the test must be passed explicitly. |
| function(gfortran_add_execute_tests tests) |
| cmake_parse_arguments(GFORTRAN "" "" "FFLAGS;LDFLAGS" ${ARGN}) |
| |
| list(APPEND fflags ${GFORTRAN_FFLAGS}) |
| list(APPEND ldflags ${GFORTRAN_LDFLAGS}) |
| |
| foreach(file ${tests}) |
| gfortran_add_execute_test(${file} "" "${fflags}" "${ldflags}") |
| endforeach() |
| endfunction() |
| |
| set(HEADER_SEARCH_PATH "${TEST_SUITE_FORTRAN_ISO_C_HEADER_DIR}") |
| if (NOT HEADER_SEARCH_PATH) |
| get_filename_component(Fortran_BINDIR ${CMAKE_Fortran_COMPILER} DIRECTORY) |
| get_filename_component(Fortran_PREFIX ${Fortran_BINDIR} DIRECTORY) |
| |
| set(HEADER_SEARCH_PATH "${Fortran_PREFIX}/include/flang") |
| endif() |
| |
| find_file(ISO_FORTRAN_C_HEADER |
| ISO_Fortran_binding.h |
| PATHS ${HEADER_SEARCH_PATH} |
| REQUIRED) |
| |
| get_filename_component(ISO_FORTRAN_C_HEADER_DIR |
| "${ISO_FORTRAN_C_HEADER}" |
| DIRECTORY) |
| |
| # The program to be used to verify the results. The programs here should take |
| # two files as arguments, return 0 if the files are identical, non-zero |
| # otherwise. |
| set(DIFFPROG) |
| if (WIN32) |
| find_program(DIFFPROG |
| NAMES fc.exe |
| REQUIRED) |
| else () |
| find_program(DIFFPROG |
| NAMES diff cmp |
| REQUIRED) |
| endif () |
| |
| # The test suite expects to be able to run something at test-time. For the |
| # compile tests, there is nothing to be run. While a better solution will be |
| # to modify the test suite to allow for cases like this, for the moment, just |
| # create an empty executable that will be run for each test. |
| set(DUMMY_SRC ${CMAKE_CURRENT_BINARY_DIR}/dummy.f90) |
| file(WRITE ${DUMMY_SRC} "program test\nend program test") |
| |
| set(DUMMY_EXE "dummy") |
| add_executable(${DUMMY_EXE} ${DUMMY_SRC}) |
| |
| # This script compiles the files that are "compile" tests. It may save the |
| # diagnostics to file as needed (see the options that the script accepts). There |
| # should be no dependence on the source files at test-time, so copy the compile |
| # script over to the build directory. For the moment, nothing is compiled at |
| # test-time, but that might change. |
| set(COMPILE_SCRIPT compile-save-diags.cmake) |
| set(COMPILE_SCRIPT_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${COMPILE_SCRIPT}) |
| set(COMPILE_SCRIPT_BIN ${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_SCRIPT}) |
| |
| file(COPY |
| ${CMAKE_CURRENT_SOURCE_DIR}/${COMPILE_SCRIPT} |
| DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) |
| |
| # In some case, the "compile" tests are expected to pass. Since diagnostics are |
| # only saved on failure, the diagnostics file produced when compiling the test |
| # should be empty. An empty file can, therefore, be used as reference output. |
| set(EMPTY_FILE "gfortran-compile-empty.reference.out") |
| file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/${EMPTY_FILE}) |
| |
| add_subdirectory(regression) |
| add_subdirectory(torture) |