CMake/Tests/Fortran/CMakeLists.txt
Brad King 42bbf1307a CMP0022: Fix link language propagation in NEW behavior
The languages used in compiling STATIC libraries need to be propagated
to dependents regardless of the settings of INTERFACE_LINK_LIBRARIES or
CMP0022.  They are independent of the libraries in the link interface.

Prior to commit v2.8.12~192^2~2 (Introduce the INTERFACE_LINK_LIBRARIES
property, 2013-06-04) the cmTarget::ComputeLinkInterface code path for
"explicitLibraries" could never be taken for STATIC libraries, so the
logic to propagate languages existed only in the non-explicitLibraries
code path.  After that commit, INTERFACE_LINK_LIBRARIES could be set for
STATIC libraries to cause the "explicitLibraries" code path to be taken.
The commit also left the old non-explicitLibraries code path conditional
on CMP0022 not being set to NEW.  Thus link language propagation was
left missing from two cases by that commit.

The explicitLibraries code path was fixed to propagate languages by
commit v2.8.12~149^2~1 (cmTarget: Fix iface libraries and languages for
static libraries, 2013-07-26).  However, the non-explicitLibraries case
was never taught to propagate languages when CMP0022 is set to NEW.  Fix
that now.  Factor the logic to propagate link languages out of the link
interface libraries conditions so that it always occurs.  Update
Tests/Fortran to set CMP0022 to NEW to test this case (because the test
passes only if link language propagation works).
2014-05-19 09:06:20 -04:00

227 lines
8.2 KiB
CMake

cmake_minimum_required (VERSION 3.0)
project(testf C CXX Fortran)
if(NOT DEFINED CMake_TEST_NESTED_MAKE_PROGRAM AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
set(CMake_TEST_NESTED_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM}")
endif()
message("CTEST_FULL_OUTPUT ")
set(CMAKE_VERBOSE_MAKEFILE 1)
message("ENV_FLAGS = $ENV{FFLAGS}")
message("CMAKE_Fortran_COMPILER_INIT = ${CMAKE_Fortran_COMPILER_INIT}")
message("CMAKE_Fortran_COMPILER_FULLPATH = ${CMAKE_Fortran_COMPILER_FULLPATH}")
message("CMAKE_Fortran_COMPILER = ${CMAKE_Fortran_COMPILER}")
message("CMAKE_Fortran_FLAGS = ${CMAKE_Fortran_FLAGS}")
set(_SHARED SHARED)
if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "^(XL|VisualAge)$")
# We do not implement SHARED Fortran libs on AIX yet!
# Workaround: Set LINKER_LANGUAGE to C, which uses 'xlc' and Fortran implicits.
set(_SHARED STATIC)
elseif("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "GNU")
# g77 2.96 does not support shared libs on Itanium because g2c is not -fPIC
execute_process(COMMAND ${CMAKE_Fortran_COMPILER} --version
OUTPUT_VARIABLE output ERROR_VARIABLE output)
if("${output}" MATCHES "Red Hat .* 2\\.96")
set(_SHARED STATIC)
endif()
endif()
# Pick a module .def file with the properly mangled symbol name.
set(world_def "")
if(WIN32 AND NOT CYGWIN)
if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
set(world_def world_gnu.def)
elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "Intel" OR
"${CMAKE_GENERATOR}" MATCHES "Visual Studio") # Intel plugin
set(world_def world_icl.def)
endif()
endif()
add_library(hello STATIC hello.f)
add_library(world ${_SHARED} world.f ${world_def})
add_executable(testf testf.f)
target_link_libraries(testf hello world)
function(test_fortran_c_interface_module)
message(STATUS "Testing FortranCInterface module")
# test the C to Fortran interface module
include(FortranCInterface)
FortranCInterface_VERIFY()
FortranCInterface_VERIFY(CXX)
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "SunPro|MIPSpro|PathScale|Absoft")
set(module_expected 1)
endif()
if(FortranCInterface_MODULE_FOUND OR module_expected)
set(srcs foo.f)
set(FORTRAN_FUNCTIONS test_mod:sub)
set(MYC_DEFS TEST_MOD)
else()
message("${CMAKE_Fortran_COMPILER_ID} compilers do not support"
" linking Fortran module procedures from C")
endif()
endif()
list(APPEND FORTRAN_FUNCTIONS my_sub mysub)
FortranCInterface_HEADER(foo.h
MACRO_NAMESPACE "FC_"
SYMBOL_NAMESPACE "F_"
SYMBOLS ${FORTRAN_FUNCTIONS}
)
include_directories("${testf_BINARY_DIR}")
# if the name mangling is not found for a F90 compiler
# print out some diagnostic stuff for the dashboard
if(NOT FortranCInterface_GLOBAL_FOUND OR
(NOT FortranCInterface_MODULE_FOUND AND module_expected) )
find_program(FortranCInterface_EXE
NAMES FortranCInterface
PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Debug
NO_DEFAULT_PATH
)
find_program(DUMPBIN dumpbin)
find_program(NM nm)
if(FortranCInterface_EXE)
if(DEPENDS)
execute_process(COMMAND ${DUMPBIN} /symbols "${FortranCInterface_EXE}"
OUTPUT_VARIABLE out)
message("symbols in ${FortranCInterface_EXE}:\n${out}")
endif()
if(NM)
execute_process(COMMAND ${NM} "${FortranCInterface_EXE}"
OUTPUT_VARIABLE out)
message("symbols in ${FortranCInterface_EXE}:\n${out}")
endif()
endif()
endif()
message("Fortran = ${CMAKE_Fortran_COMPILER_ID}")
message("C = ${CMAKE_C_COMPILER_ID}")
add_library(myfort mysub.f ${srcs})
add_library(myc myc.c)
target_link_libraries(myc myfort)
set_property(TARGET myc PROPERTY COMPILE_DEFINITIONS ${MYC_DEFS})
add_library(mycxx mycxx.cxx)
target_link_libraries(mycxx myc)
add_executable(mainc mainc.c)
target_link_libraries(mainc myc)
add_executable(maincxx maincxx.c)
target_link_libraries(maincxx mycxx)
# print out some stuff to help debug on machines via cdash
file(READ "${testf_BINARY_DIR}/foo.h" fooh)
message("foo.h contents:\n${fooh}")
endfunction()
# if the id's match or the compilers are compatible, then
# call the test_fortran_c_interface_module function
if("${CMAKE_Fortran_COMPILER_ID}:${CMAKE_C_COMPILER_ID}" MATCHES
"(Intel:MSVC|Absoft:GNU)"
OR ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "${CMAKE_C_COMPILER_ID}" ))
test_fortran_c_interface_module()
else()
message("Fortran does not match c compiler")
message("Fortran = ${CMAKE_Fortran_COMPILER_ID}")
message("C = ${CMAKE_C_COMPILER_ID}")
# hack to make g77 work after CL has been enabled
# as a languge, cmake needs language specific versions
# of these variables....
if(WIN32 AND "${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_CREATE_CONSOLE_EXE )
set(CMAKE_LIBRARY_PATH_FLAG "-L")
set(CMAKE_LINK_LIBRARY_FLAG "-l")
set(CMAKE_LINK_LIBRARY_SUFFIX )
endif()
# gnu and sunpro do not use the same flags here...
# however if LDFLAGS is used to set -m64 it causes odd stuf
# with the fortran build
if( ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU")
AND ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "SunPro"))
set(CMAKE_EXE_LINKER_FLAGS "")
set(CMAKE_Fortran_FLAGS "")
endif()
endif()
set(TEST_MODULE_DEPENDS 0)
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
add_executable(test_module
test_module_main.f90
test_module_implementation.f90
test_module_interface.f90)
add_executable(test_use_in_comment_fixedform
test_use_in_comment_fixedform.f)
set_property(SOURCE test_use_in_comment_fixedform.f PROPERTY Fortran_FORMAT FIXED)
add_executable(test_use_in_comment_freeform
test_use_in_comment_freeform.f90)
set_property(SOURCE test_use_in_comment_freeform.f90 PROPERTY Fortran_FORMAT FREE)
add_executable(test_in_interface
in_interface/main.f90
in_interface/module.f90)
add_definitions(-DFOO -DBAR=1)
include_directories(${testf_SOURCE_DIR}/include)
add_executable(test_preprocess test_preprocess.F90)
set(TEST_MODULE_DEPENDS 1)
endif()
if(TEST_MODULE_DEPENDS)
# Build the external project separately using a custom target.
# Make sure it uses the same build configuration as this test.
if(CMAKE_CONFIGURATION_TYPES)
set(External_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}")
set(External_BUILD_TYPE)
else()
set(External_CONFIG_TYPE)
set(External_BUILD_TYPE -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
endif()
set(External_SOURCE_DIR "${testf_SOURCE_DIR}/External")
set(External_BINARY_DIR "${testf_BINARY_DIR}/External")
if("${testf_BINARY_DIR}" MATCHES " ")
# Our build tree has a space, so the build tool supports spaces.
# Test using modules from a path with spaces.
set(External_BINARY_DIR "${External_BINARY_DIR} Build")
endif()
add_custom_command(
OUTPUT ${testf_BINARY_DIR}/ExternalProject
COMMAND ${CMAKE_CTEST_COMMAND}
ARGS ${External_CONFIG_TYPE}
--build-and-test
${External_SOURCE_DIR}
${External_BINARY_DIR}
--build-noclean
--build-two-config
--build-project ExtFort
--build-generator ${CMAKE_GENERATOR}
--build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}"
--build-options -DCMAKE_Fortran_COMPILER:STRING=${CMAKE_Fortran_COMPILER}
-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}
-DCMAKE_Fortran_FLAGS_DEBUG:STRING=${CMAKE_Fortran_FLAGS_DEBUG}
-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}
-DCMAKE_Fortran_FLAGS_MINSIZEREL:STRING=${CMAKE_Fortran_FLAGS_MINSIZEREL}
-DCMAKE_Fortran_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_Fortran_FLAGS_RELWITHDEBINFO}
-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMake_TEST_NESTED_MAKE_PROGRAM}
${External_BUILD_TYPE}
VERBATIM
)
add_custom_target(ExternalTarget ALL DEPENDS ${testf_BINARY_DIR}/ExternalProject)
# Test module output directory if available.
if(CMAKE_Fortran_MODDIR_FLAG)
set(Library_MODDIR "${testf_BINARY_DIR}/Library/modules")
else()
set(Library_MODDIR "${testf_BINARY_DIR}/Library")
endif()
add_subdirectory(Library)
add_subdirectory(Executable)
endif()