From 538c3452ad660a45c3d6ca32f8c09ee7c93a8b84 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 9 Dec 2011 18:04:19 -0500 Subject: [PATCH 01/10] Add CMakeAddFortranSubdirectory to use MinGW gfortran in VS This patch adds a new module that allows for easy integration of MinGW gfortran and the Visual Studio compiler. It is done in a function called cmake_add_fortran_subdirectory. The patch also includes a test for this feature. --- Modules/CMakeAddFortranSubdirectory.cmake | 167 ++++++++++++++++++ .../build_mingw.cmake.in | 2 + .../config_mingw.cmake.in | 8 + Tests/CMakeLists.txt | 9 + Tests/VSGNUFortran/CMakeLists.txt | 39 ++++ Tests/VSGNUFortran/c_code/CMakeLists.txt | 2 + Tests/VSGNUFortran/c_code/main.c | 7 + Tests/VSGNUFortran/fortran/CMakeLists.txt | 12 ++ Tests/VSGNUFortran/fortran/hello.f | 7 + Tests/VSGNUFortran/fortran/world.f | 6 + Tests/VSGNUFortran/runtest.cmake.in | 23 +++ 11 files changed, 282 insertions(+) create mode 100644 Modules/CMakeAddFortranSubdirectory.cmake create mode 100644 Modules/CMakeAddFortranSubdirectory/build_mingw.cmake.in create mode 100644 Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in create mode 100644 Tests/VSGNUFortran/CMakeLists.txt create mode 100644 Tests/VSGNUFortran/c_code/CMakeLists.txt create mode 100644 Tests/VSGNUFortran/c_code/main.c create mode 100644 Tests/VSGNUFortran/fortran/CMakeLists.txt create mode 100644 Tests/VSGNUFortran/fortran/hello.f create mode 100644 Tests/VSGNUFortran/fortran/world.f create mode 100644 Tests/VSGNUFortran/runtest.cmake.in diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake new file mode 100644 index 0000000000..4e351a6fbe --- /dev/null +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -0,0 +1,167 @@ +# - Use MinGW gfortran from VS if a fortran compiler is not found. +# The 'add_fortran_subdirectory' function adds a subdirectory +# to a project that contains a fortran only sub-project. The module +# will check the current compiler and see if it can support fortran. +# If no fortran compiler is found and the compiler is MSVC, then +# this module will find the MinGW gfortran. It will then use +# an external project to build with the MinGW tools. It will also +# create imported targets for the libraries created. This will only +# work if the fortran code is built into a dll, so BUILD_SHARED_LIBS +# is turned on in the project. In addition the GNUtoMS option is set +# to on, so that the MS .lib files are created. +# Usage is as follows: +# cmake_add_fortran_subdirectory( +# # name of subdirectory +# PROJECT # project name in sbudir toplevel CMakeLists.txt +# ARCHIVE_DIR # .lib location relative to root binary tree (lib) +# RUNTIME_DIR # .dll location relative to root binary tree (bin) +# LIBRARIES lib2 lib2 # names of libraries created and exported +# LINK_LIBRARIES # link interface libraries for LIBRARIES +# LINK_LIBS ... +# LINK_LIBS ... +# CMAKE_COMMAND_LINE # extra command line flags to pass to cmake +# ) +# + +#============================================================================= +# Copyright 2002-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +set(_MS_MINGW_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) +include(CheckLanguage) +include(ExternalProject) +include(CMakeParseArguments) + +function(_setup_mingw_config_and_build source_dir) + find_program(MINGW_GFORTRAN NAMES gfortran + HINTS + c:/MinGW/bin + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MinGW;InstallLocation]/bin" ) + if(NOT MINGW_GFORTRAN) + message(FATAL_ERROR + "gfortran not found, please install MinGW with the gfortran option." + "Or set the cache variable MINGW_GFORTRAN to the full path. " + " This is required to build") + endif() + execute_process(COMMAND ${MINGW_GFORTRAN} -v ERROR_VARIABLE out) + if(NOT "${out}" MATCHES "Target:.*mingw32") + message(FATAL_ERROR "Non-MinGW gfortran found: ${MINGW_GFORTRAN}\n" + "output from -v [${out}]\n" + "set MINGW_GFORTRAN to the path to MinGW fortran.") + endif() + get_filename_component(MINGW_PATH ${MINGW_GFORTRAN} PATH) + file(TO_NATIVE_PATH "${MINGW_PATH}" MINGW_PATH) + string(REPLACE "\\" "\\\\" MINGW_PATH "${MINGW_PATH}") + configure_file( + ${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/config_mingw.cmake + @ONLY) + configure_file( + ${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/build_mingw.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/build_mingw.cmake + @ONLY) +endfunction() + +function(_add_fortran_library_link_interface library depend_library) + set_target_properties(${library} PROPERTIES + IMPORTED_LINK_INTERFACE_LIBRARIES_NOCONFIG "${depend_library}") +endfunction() + + +function(cmake_add_fortran_subdirectory subdir) + # if we are not using MSVC without fortran support + # then just use the usual add_subdirectory to build + # the fortran library + check_language(Fortran) + if(NOT (MSVC AND (NOT CMAKE_Fortran_COMPILER))) + add_subdirectory(${subdir}) + return() + endif() + + # if we have MSVC without Intel fortran then setup + # external projects to build with mingw fortran + + # Parse arguments to function + set(oneValueArgs PROJECT ARCHIVE_DIR RUNTIME_DIR) + set(multiValueArgs LIBRARIES LINK_LIBRARIES CMAKE_COMMAND_LINE) + cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") + set(project_name "${ARGS_PROJECT}") + set(library_dir "${ARGS_ARCHIVE_DIR}") + set(binary_dir "${ARGS_RUNTIME_DIR}") + set(libraries ${ARGS_LIBRARIES}) + # use the same directory that add_subdirectory would have used + set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/${subdir}") + # create build and configure wrapper scripts + _setup_mingw_config_and_build(${source_dir}) + # create the external project + externalproject_add(${project_name}_build + SOURCE_DIR ${source_dir} + BINARY_DIR ${build_dir} + CONFIGURE_COMMAND ${CMAKE_COMMAND} + -P ${CMAKE_CURRENT_BINARY_DIR}/config_mingw.cmake + BUILD_COMMAND ${CMAKE_COMMAND} + -P ${CMAKE_CURRENT_BINARY_DIR}/build_mingw.cmake + INSTALL_COMMAND "" + ) + # make the external project always run make with each build + externalproject_add_step(${project_name}_build forcebuild + COMMAND ${CMAKE_COMMAND} + -E remove + ${CMAKE_CURRENT_BUILD_DIR}/${project_name}-prefix/src/${project_name}-stamp/${project_name}-build + DEPENDEES configure + DEPENDERS build + ALWAYS 1 + ) + # create imported targets for all libraries + foreach(lib ${libraries}) + add_library(${lib} SHARED IMPORTED) + set_property(TARGET ${lib} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) + set_target_properties(${lib} PROPERTIES + IMPORTED_IMPLIB_NOCONFIG + "${build_dir}/${library_dir}/lib${lib}.lib" + IMPORTED_LOCATION_NOCONFIG + "${build_dir}/${binary_dir}/lib${lib}.dll" + ) + add_dependencies(${lib} ${project_name}_build) + endforeach() + + # now setup link libraries for targets + set(start FALSE) + set(target) + foreach(lib ${ARGS_LINK_LIBRARIES}) + if("${lib}" STREQUAL "LINK_LIBS") + set(start TRUE) + else() + if(start) + if(DEFINED target) + # process current target and target_libs + _add_fortran_library_link_interface(${target} "${target_libs}") + # zero out target and target_libs + set(target) + set(target_libs) + endif() + # save the current target and set start to FALSE + set(target ${lib}) + set(start FALSE) + else() + # append the lib to target_libs + list(APPEND target_libs "${lib}") + endif() + endif() + endforeach() + # process anything that is left in target and target_libs + if(DEFINED target) + _add_fortran_library_link_interface(${target} "${target_libs}") + endif() +endfunction() diff --git a/Modules/CMakeAddFortranSubdirectory/build_mingw.cmake.in b/Modules/CMakeAddFortranSubdirectory/build_mingw.cmake.in new file mode 100644 index 0000000000..55b271a2d0 --- /dev/null +++ b/Modules/CMakeAddFortranSubdirectory/build_mingw.cmake.in @@ -0,0 +1,2 @@ +set(ENV{PATH} "@MINGW_PATH@\;$ENV{PATH}") +execute_process(COMMAND "@CMAKE_COMMAND@" --build . ) diff --git a/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in b/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in new file mode 100644 index 0000000000..96141da6de --- /dev/null +++ b/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in @@ -0,0 +1,8 @@ +set(ENV{PATH} "@MINGW_PATH@\;$ENV{PATH}") +execute_process( + COMMAND "@CMAKE_COMMAND@" "-GMinGW Makefiles" + -DCMAKE_Fortran_COMPILER:PATH=@MINGW_GFORTRAN@ + -DBUILD_SHARED_LIBS=ON + -DCMAKE_GNUtoMS=ON + @ARGS_CMAKE_COMMAND_LINE@ + "@source_dir@") diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 906b40d9de..e949887b09 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -163,6 +163,15 @@ IF(BUILD_TESTING) IF(CMAKE_Fortran_COMPILER) ADD_TEST_MACRO(FortranOnly FortranOnly) ENDIF() + # test Visual Studio GNU Fortran mixing with cmake_add_fortran_subdirectory + # run this project if we have a working fortran compiler or + # the test is enabled with CMAKE_TEST_CMAKE_ADD_FORTRAN cache variable. + # If you enable the test, CMake should find the MinGW fortran install, + # or in some cases you might need to set the PATH so that cmake can find + # the gfortran from mingw. + IF(CMAKE_Fortran_COMPILER OR CMAKE_TEST_CMAKE_ADD_FORTRAN) + ADD_TEST_MACRO(VSGNUFortran ${CMAKE_COMMAND} -P runtest.cmake) + ENDIF() ADD_TEST_MACRO(COnly COnly) ADD_TEST_MACRO(CxxOnly CxxOnly) ADD_TEST_MACRO(IPO COnly/COnly) diff --git a/Tests/VSGNUFortran/CMakeLists.txt b/Tests/VSGNUFortran/CMakeLists.txt new file mode 100644 index 0000000000..2e527f9fe2 --- /dev/null +++ b/Tests/VSGNUFortran/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 2.8) +project(VSGNUFortran) +# force the executable to be put out of Debug/Release dir +# because gmake build of fortran will not be in a config +# directory, and for easier testing we want the exe and .dll +# to be in the same directory. +if(CMAKE_CONFIGURATION_TYPES) + foreach(config ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER "${config}" config) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config} + "${PROJECT_BINARY_DIR}/bin") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config} + "${PROJECT_BINARY_DIR}/bin") + endforeach() +else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +endif() + +include(CMakeAddFortranSubdirectory) +# add the fortran subdirectory as a fortran project +# the subdir is fortran, the project is FortranHello +cmake_add_fortran_subdirectory(fortran + PROJECT FortranHello # project name in toplevel CMakeLists.txt + ARCHIVE_DIR ../bin # .lib location relative to root binary tree + RUNTIME_DIR ../bin # .dll location relative to root binary tree + LIBRARIES hello world # target libraries created + CMAKE_COMMAND_LINE -DEXECUTABLE_OUTPUT_PATH=../bin + -DLIBRARY_OUTPUT_PATH=../bin + LINK_LIBRARIES # link interface libraries + LINK_LIBS hello world # hello needs world to link + ) + +include_directories(${VSGNUFortran_BINARY_DIR}/fortran) +add_subdirectory(c_code) +# use a cmake script to run the executable so that PATH +# can be set with the MinGW/bin in it, and the fortran +# runtime libraries can be found. +configure_file(runtest.cmake.in runtest.cmake @ONLY) diff --git a/Tests/VSGNUFortran/c_code/CMakeLists.txt b/Tests/VSGNUFortran/c_code/CMakeLists.txt new file mode 100644 index 0000000000..27d22fd356 --- /dev/null +++ b/Tests/VSGNUFortran/c_code/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(c_using_fortran main.c) +target_link_libraries(c_using_fortran hello) diff --git a/Tests/VSGNUFortran/c_code/main.c b/Tests/VSGNUFortran/c_code/main.c new file mode 100644 index 0000000000..391bf26fdc --- /dev/null +++ b/Tests/VSGNUFortran/c_code/main.c @@ -0,0 +1,7 @@ +#include // created by FortranCInterface +extern void FC_hello(void); +int main() +{ + FC_hello(); + return 0; +} diff --git a/Tests/VSGNUFortran/fortran/CMakeLists.txt b/Tests/VSGNUFortran/fortran/CMakeLists.txt new file mode 100644 index 0000000000..ff22993ad2 --- /dev/null +++ b/Tests/VSGNUFortran/fortran/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) +project(FortranHello Fortran C) + +include(FortranCInterface) +FortranCInterface_HEADER(HelloWorldFCMangle.h + MACRO_NAMESPACE "FC_" + SYMBOL_NAMESPACE "FC_" + SYMBOLS hello world) + +add_library(hello SHARED hello.f) +add_library(world SHARED world.f) +target_link_libraries(hello world) diff --git a/Tests/VSGNUFortran/fortran/hello.f b/Tests/VSGNUFortran/fortran/hello.f new file mode 100644 index 0000000000..e52119add9 --- /dev/null +++ b/Tests/VSGNUFortran/fortran/hello.f @@ -0,0 +1,7 @@ +!DEC$ ATTRIBUTES DLLEXPORT :: HELLO + SUBROUTINE HELLO + + PRINT *, 'Hello' + CALL WORLD + + END diff --git a/Tests/VSGNUFortran/fortran/world.f b/Tests/VSGNUFortran/fortran/world.f new file mode 100644 index 0000000000..0598eeea66 --- /dev/null +++ b/Tests/VSGNUFortran/fortran/world.f @@ -0,0 +1,6 @@ +!DEC$ ATTRIBUTES DLLEXPORT :: WORLD + SUBROUTINE WORLD + + PRINT *, 'World!' + + END diff --git a/Tests/VSGNUFortran/runtest.cmake.in b/Tests/VSGNUFortran/runtest.cmake.in new file mode 100644 index 0000000000..987207bc48 --- /dev/null +++ b/Tests/VSGNUFortran/runtest.cmake.in @@ -0,0 +1,23 @@ +get_filename_component(MINGW_PATH "@MINGW_GFORTRAN@" PATH) +if(NOT EXISTS "${MINGW_PATH}") + set(test_exe + "@VSGNUFortran_BINARY_DIR@/bin/c_using_fortran@CMAKE_EXECUTABLE_SUFFIX@") + message("run: ${test_exe}") + execute_process(COMMAND "${test_exe}" + RESULT_VARIABLE res) + if(NOT "${res}" EQUAL 0) + message(FATAL_ERROR "${test_exe} returned a non 0 value") + endif() + return() +endif() +file(TO_NATIVE_PATH "${MINGW_PATH}" MINGW_PATH) +string(REPLACE "\\" "\\\\" MINGW_PATH "${MINGW_PATH}") +message("${MINGW_PATH}") +set(test_exe "@VSGNUFortran_BINARY_DIR@/bin/c_using_fortran.exe") +set(ENV{PATH} "${MINGW_PATH}";$ENV{PATH}) +message("run ${test_exe}") +execute_process(COMMAND "${test_exe}" + RESULT_VARIABLE res) +if(NOT "${res}" EQUAL 0) + message(FATAL_ERROR "${test_exe} returned a non 0 value") +endif() From e4ae038f5d9f0fa14d63f9eaea71e0466dc86619 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Dec 2011 10:19:46 -0500 Subject: [PATCH 02/10] CMakeAddFortranSubdirectory: Allow full paths to directories Fix the implementation to allow full paths with spaces. Change the interpretation of relative paths to be with respect to the current binary directory. This matches the convention used in ExternalProject. Test both full and relative paths in the VSGNUFortran test. --- Modules/CMakeAddFortranSubdirectory.cmake | 19 +++++++++++----- .../config_mingw.cmake.in | 3 ++- Tests/VSGNUFortran/CMakeLists.txt | 22 ++++++++++--------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index 4e351a6fbe..e92dcb47fb 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -13,14 +13,17 @@ # cmake_add_fortran_subdirectory( # # name of subdirectory # PROJECT # project name in sbudir toplevel CMakeLists.txt -# ARCHIVE_DIR # .lib location relative to root binary tree (lib) -# RUNTIME_DIR # .dll location relative to root binary tree (bin) +# ARCHIVE_DIR # dir where project places .lib files +# RUNTIME_DIR # dir where project places .dll files # LIBRARIES lib2 lib2 # names of libraries created and exported # LINK_LIBRARIES # link interface libraries for LIBRARIES # LINK_LIBS ... # LINK_LIBS ... # CMAKE_COMMAND_LINE # extra command line flags to pass to cmake # ) +# Relative paths in ARCHIVE_DIR and RUNTIME_DIR are interpreted with respect +# to the build directory corresponding to the source directory in which the +# function is invoked. # #============================================================================= @@ -102,6 +105,12 @@ function(cmake_add_fortran_subdirectory subdir) set(libraries ${ARGS_LIBRARIES}) # use the same directory that add_subdirectory would have used set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/${subdir}") + foreach(dir_var library_dir binary_dir) + if(NOT IS_ABSOLUTE "${${dir_var}}") + get_filename_component(${dir_var} + "${CMAKE_CURRENT_BINARY_DIR}/${${dir_var}}" ABSOLUTE) + endif() + endforeach() # create build and configure wrapper scripts _setup_mingw_config_and_build(${source_dir}) # create the external project @@ -128,10 +137,8 @@ function(cmake_add_fortran_subdirectory subdir) add_library(${lib} SHARED IMPORTED) set_property(TARGET ${lib} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) set_target_properties(${lib} PROPERTIES - IMPORTED_IMPLIB_NOCONFIG - "${build_dir}/${library_dir}/lib${lib}.lib" - IMPORTED_LOCATION_NOCONFIG - "${build_dir}/${binary_dir}/lib${lib}.dll" + IMPORTED_IMPLIB_NOCONFIG "${library_dir}/lib${lib}.lib" + IMPORTED_LOCATION_NOCONFIG "${binary_dir}/lib${lib}.dll" ) add_dependencies(${lib} ${project_name}_build) endforeach() diff --git a/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in b/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in index 96141da6de..97f67693af 100644 --- a/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in +++ b/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in @@ -1,8 +1,9 @@ set(ENV{PATH} "@MINGW_PATH@\;$ENV{PATH}") +set(CMAKE_COMMAND_LINE "@ARGS_CMAKE_COMMAND_LINE@") execute_process( COMMAND "@CMAKE_COMMAND@" "-GMinGW Makefiles" -DCMAKE_Fortran_COMPILER:PATH=@MINGW_GFORTRAN@ -DBUILD_SHARED_LIBS=ON -DCMAKE_GNUtoMS=ON - @ARGS_CMAKE_COMMAND_LINE@ + ${CMAKE_COMMAND_LINE} "@source_dir@") diff --git a/Tests/VSGNUFortran/CMakeLists.txt b/Tests/VSGNUFortran/CMakeLists.txt index 2e527f9fe2..422350a5c5 100644 --- a/Tests/VSGNUFortran/CMakeLists.txt +++ b/Tests/VSGNUFortran/CMakeLists.txt @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 2.8) project(VSGNUFortran) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") + # force the executable to be put out of Debug/Release dir # because gmake build of fortran will not be in a config # directory, and for easier testing we want the exe and .dll @@ -7,14 +12,9 @@ project(VSGNUFortran) if(CMAKE_CONFIGURATION_TYPES) foreach(config ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER "${config}" config) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config} - "${PROJECT_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config} - "${PROJECT_BINARY_DIR}/bin") + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) endforeach() -else() - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) endif() include(CMakeAddFortranSubdirectory) @@ -22,11 +22,13 @@ include(CMakeAddFortranSubdirectory) # the subdir is fortran, the project is FortranHello cmake_add_fortran_subdirectory(fortran PROJECT FortranHello # project name in toplevel CMakeLists.txt - ARCHIVE_DIR ../bin # .lib location relative to root binary tree - RUNTIME_DIR ../bin # .dll location relative to root binary tree + ARCHIVE_DIR ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + RUNTIME_DIR bin # ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} LIBRARIES hello world # target libraries created - CMAKE_COMMAND_LINE -DEXECUTABLE_OUTPUT_PATH=../bin - -DLIBRARY_OUTPUT_PATH=../bin + CMAKE_COMMAND_LINE + -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} LINK_LIBRARIES # link interface libraries LINK_LIBS hello world # hello needs world to link ) From d6b031283a686eaeff643a13f8368c7828850229 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Dec 2011 10:48:33 -0500 Subject: [PATCH 03/10] CMakeAddFortranSubdirectory: Fix documentation format and typos Indent the function signature correctly. Fix some typos. Fix the copyright year. --- Modules/CMakeAddFortranSubdirectory.cmake | 26 +++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index e92dcb47fb..10935a804d 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -7,27 +7,25 @@ # an external project to build with the MinGW tools. It will also # create imported targets for the libraries created. This will only # work if the fortran code is built into a dll, so BUILD_SHARED_LIBS -# is turned on in the project. In addition the GNUtoMS option is set -# to on, so that the MS .lib files are created. +# is turned on in the project. In addition the CMAKE_GNUtoMS option +# is set to on, so that the MS .lib files are created. # Usage is as follows: -# cmake_add_fortran_subdirectory( -# # name of subdirectory -# PROJECT # project name in sbudir toplevel CMakeLists.txt -# ARCHIVE_DIR # dir where project places .lib files -# RUNTIME_DIR # dir where project places .dll files -# LIBRARIES lib2 lib2 # names of libraries created and exported -# LINK_LIBRARIES # link interface libraries for LIBRARIES -# LINK_LIBS ... -# LINK_LIBS ... -# CMAKE_COMMAND_LINE # extra command line flags to pass to cmake +# cmake_add_fortran_subdirectory( +# # name of subdirectory +# PROJECT # project name in subdir top CMakeLists.txt +# ARCHIVE_DIR # dir where project places .lib files +# RUNTIME_DIR # dir where project places .dll files +# LIBRARIES ... # names of library targets to import +# LINK_LIBRARIES # link interface libraries for LIBRARIES +# [LINK_LIBS ...]... +# CMAKE_COMMAND_LINE ... # extra command line flags to pass to cmake # ) # Relative paths in ARCHIVE_DIR and RUNTIME_DIR are interpreted with respect # to the build directory corresponding to the source directory in which the # function is invoked. -# #============================================================================= -# Copyright 2002-2009 Kitware, Inc. +# Copyright 2011 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. From 7e0d9f15d626c13b452bc213172cd54c24f5b41a Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Dec 2011 10:50:55 -0500 Subject: [PATCH 04/10] CMakeAddFortranSubdirectory: Find gfortran in PATH In the find_program(MINGW_GFORTRAN) call use the PATHS option for hard-coded guesses instead of HINTS. This allows the user environment to override the guesses and corrects usage of the command options. --- Modules/CMakeAddFortranSubdirectory.cmake | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index 10935a804d..d36738c423 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -44,10 +44,13 @@ include(ExternalProject) include(CMakeParseArguments) function(_setup_mingw_config_and_build source_dir) - find_program(MINGW_GFORTRAN NAMES gfortran - HINTS - c:/MinGW/bin - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MinGW;InstallLocation]/bin" ) + # Look for a MinGW gfortran. + find_program(MINGW_GFORTRAN + NAMES gfortran + PATHS + c:/MinGW/bin + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MinGW;InstallLocation]/bin" + ) if(NOT MINGW_GFORTRAN) message(FATAL_ERROR "gfortran not found, please install MinGW with the gfortran option." From 414a780d1c22339e924ea3d880e54482f0d67898 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Dec 2011 11:39:42 -0500 Subject: [PATCH 05/10] CMakeAddFortranSubdirectory: Validate gfortran architecture Verify that MINGW_GFORTRAN not only points to a MinGW gfortran but also one that compiles for the target architecture. This prevents using a 32-bit gfortran in a 64-bit MSVC build. --- Modules/CMakeAddFortranSubdirectory.cmake | 26 ++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index d36738c423..c846b55a91 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -57,12 +57,28 @@ function(_setup_mingw_config_and_build source_dir) "Or set the cache variable MINGW_GFORTRAN to the full path. " " This is required to build") endif() - execute_process(COMMAND ${MINGW_GFORTRAN} -v ERROR_VARIABLE out) - if(NOT "${out}" MATCHES "Target:.*mingw32") - message(FATAL_ERROR "Non-MinGW gfortran found: ${MINGW_GFORTRAN}\n" - "output from -v [${out}]\n" - "set MINGW_GFORTRAN to the path to MinGW fortran.") + + # Validate the MinGW gfortran we found. + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_mingw_target "Target:.*64.*mingw") + else() + set(_mingw_target "Target:.*mingw32") endif() + execute_process(COMMAND "${MINGW_GFORTRAN}" -v + ERROR_VARIABLE out ERROR_STRIP_TRAILING_WHITESPACE) + if(NOT "${out}" MATCHES "${_mingw_target}") + string(REPLACE "\n" "\n " out " ${out}") + message(FATAL_ERROR + "MINGW_GFORTRAN is set to\n" + " ${MINGW_GFORTRAN}\n" + "which is not a MinGW gfortran for this architecture. " + "The output from -v does not match \"${_mingw_target}\":\n" + "${out}\n" + "Set MINGW_GFORTRAN to a proper MinGW gfortran for this architecture." + ) + endif() + + # Configure scripts to run MinGW tools with the proper PATH. get_filename_component(MINGW_PATH ${MINGW_GFORTRAN} PATH) file(TO_NATIVE_PATH "${MINGW_PATH}" MINGW_PATH) string(REPLACE "\\" "\\\\" MINGW_PATH "${MINGW_PATH}") From bd69e1c567cc4fc1bf30d321d888dd2567d82e7a Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 16 Dec 2011 17:01:19 -0500 Subject: [PATCH 06/10] VSGNUFortran: Add special case for SunPro Fortran runtime library The SunPro compiler does not add the fortran runtime library when creating a shared fortran library. Link to the SunPro Fortran runtime libraries explicitly. --- Tests/VSGNUFortran/fortran/CMakeLists.txt | 36 ++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Tests/VSGNUFortran/fortran/CMakeLists.txt b/Tests/VSGNUFortran/fortran/CMakeLists.txt index ff22993ad2..3ee1855c33 100644 --- a/Tests/VSGNUFortran/fortran/CMakeLists.txt +++ b/Tests/VSGNUFortran/fortran/CMakeLists.txt @@ -1,12 +1,46 @@ cmake_minimum_required(VERSION 2.8) project(FortranHello Fortran C) +# add a function to test for -lsunquad on sunpro sun systems. +function(test_sunquad result) + set( TEST_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/sunq") + file(WRITE "${TEST_DIR}/testsunq.f" " + PROGRAM TEST + END + ") + file(WRITE ${TEST_DIR}/CMakeLists.txt " +project(sunq Fortran) +add_library(sunq SHARED testsunq.f) +target_link_libraries(sunq sunquad) +") + message(STATUS "looking for -lsunquad") + try_compile(RESULT "${TEST_DIR}" "${TEST_DIR}" sunq OUTPUT_VARIABLE OUT) + if("${RESULT}") + message(STATUS "-lsunquad found") + else() + message(STATUS "-lsunquad not found") + endif() + message(STATUS + "looking for sunquad:\nRESULT=[${RESULT}]\nOUTPUT=[\n${OUT}\n]") + set(${result} "${RESULT}" PARENT_SCOPE) +endfunction() + +# check for the fortran c interface mangling include(FortranCInterface) FortranCInterface_HEADER(HelloWorldFCMangle.h MACRO_NAMESPACE "FC_" SYMBOL_NAMESPACE "FC_" SYMBOLS hello world) - add_library(hello SHARED hello.f) add_library(world SHARED world.f) target_link_libraries(hello world) +if(CMAKE_Fortran_COMPILER_ID MATCHES SunPro) + target_link_libraries(hello fsu) + if(CMAKE_Fortran_PLATFORM_ID MATCHES SunOS) + target_link_libraries(hello sunmath m) + test_sunquad(CMAKE_HAS_SUNQUAD) + if(CMAKE_HAS_SUNQUAD) + target_link_libraries(hello sunquad) + endif() + endif() +endif() From 067c1f44a80ed8fb32e56918a57437142c64b049 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 16 Dec 2011 18:20:46 -0500 Subject: [PATCH 07/10] VSGNUFortran: Disable test in special cases The ifort compiler found on some test machines does not support Mac universal binaries or the Linux Standard Base. --- Tests/CMakeLists.txt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e949887b09..9c97828226 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -170,7 +170,24 @@ IF(BUILD_TESTING) # or in some cases you might need to set the PATH so that cmake can find # the gfortran from mingw. IF(CMAKE_Fortran_COMPILER OR CMAKE_TEST_CMAKE_ADD_FORTRAN) - ADD_TEST_MACRO(VSGNUFortran ${CMAKE_COMMAND} -P runtest.cmake) + SET(CMAKE_SKIP_VSGNUFortran FALSE) + # disable test for apple builds using ifort if they are building + # more than one architecture, as ifort does not support that. + IF(APPLE AND (CMAKE_Fortran_COMPILER MATCHES ifort)) + LIST(LENGTH CMAKE_OSX_ARCHITECTURES len) + IF("${len}" GREATER 1) + MESSAGE(STATUS "Skip VSGNUFortran for ifort dual cpu mac build") + SET(CMAKE_SKIP_VSGNUFortran TRUE) + ENDIF() + ENDIF() + IF((CMAKE_C_COMPILER MATCHES lsb) + AND (CMAKE_Fortran_COMPILER MATCHES ifort)) + MESSAGE(STATUS "Skip VSGNUFortran for ifort and lsb compilers") + SET(CMAKE_SKIP_VSGNUFortran TRUE) + ENDIF() + IF(NOT CMAKE_SKIP_VSGNUFortran) + ADD_TEST_MACRO(VSGNUFortran ${CMAKE_COMMAND} -P runtest.cmake) + ENDIF() ENDIF() ADD_TEST_MACRO(COnly COnly) ADD_TEST_MACRO(CxxOnly CxxOnly) From 48a09f82ccadf93eb2d60c9efe5da783327a8520 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 27 Jan 2012 11:14:00 -0500 Subject: [PATCH 08/10] CMakeAddFortranSubdirectory: Make IMPORTED targets GLOBAL cmake_add_fortran_directory uses imported targets when using the mingw fortran compiler. This change makes those targets global in scope so they act just like the real targets that exist when a fortran compiler exists and regular add_subdirectory is used. --- Modules/CMakeAddFortranSubdirectory.cmake | 4 ++-- Tests/VSGNUFortran/CMakeLists.txt | 19 ++----------------- Tests/VSGNUFortran/subdir/CMakeLists.txt | 15 +++++++++++++++ .../{ => subdir}/fortran/CMakeLists.txt | 0 .../VSGNUFortran/{ => subdir}/fortran/hello.f | 0 .../VSGNUFortran/{ => subdir}/fortran/world.f | 0 6 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 Tests/VSGNUFortran/subdir/CMakeLists.txt rename Tests/VSGNUFortran/{ => subdir}/fortran/CMakeLists.txt (100%) rename Tests/VSGNUFortran/{ => subdir}/fortran/hello.f (100%) rename Tests/VSGNUFortran/{ => subdir}/fortran/world.f (100%) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index c846b55a91..5c3e9a2064 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -25,7 +25,7 @@ # function is invoked. #============================================================================= -# Copyright 2011 Kitware, Inc. +# Copyright 2011-2012 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -151,7 +151,7 @@ function(cmake_add_fortran_subdirectory subdir) ) # create imported targets for all libraries foreach(lib ${libraries}) - add_library(${lib} SHARED IMPORTED) + add_library(${lib} SHARED IMPORTED GLOBAL) set_property(TARGET ${lib} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) set_target_properties(${lib} PROPERTIES IMPORTED_IMPLIB_NOCONFIG "${library_dir}/lib${lib}.lib" diff --git a/Tests/VSGNUFortran/CMakeLists.txt b/Tests/VSGNUFortran/CMakeLists.txt index 422350a5c5..229c3156c1 100644 --- a/Tests/VSGNUFortran/CMakeLists.txt +++ b/Tests/VSGNUFortran/CMakeLists.txt @@ -17,23 +17,8 @@ if(CMAKE_CONFIGURATION_TYPES) endforeach() endif() -include(CMakeAddFortranSubdirectory) -# add the fortran subdirectory as a fortran project -# the subdir is fortran, the project is FortranHello -cmake_add_fortran_subdirectory(fortran - PROJECT FortranHello # project name in toplevel CMakeLists.txt - ARCHIVE_DIR ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} - RUNTIME_DIR bin # ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - LIBRARIES hello world # target libraries created - CMAKE_COMMAND_LINE - -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} - -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} - LINK_LIBRARIES # link interface libraries - LINK_LIBS hello world # hello needs world to link - ) - -include_directories(${VSGNUFortran_BINARY_DIR}/fortran) +add_subdirectory(subdir) +include_directories(${VSGNUFortran_BINARY_DIR}/subdir/fortran) add_subdirectory(c_code) # use a cmake script to run the executable so that PATH # can be set with the MinGW/bin in it, and the fortran diff --git a/Tests/VSGNUFortran/subdir/CMakeLists.txt b/Tests/VSGNUFortran/subdir/CMakeLists.txt new file mode 100644 index 0000000000..df018b3d92 --- /dev/null +++ b/Tests/VSGNUFortran/subdir/CMakeLists.txt @@ -0,0 +1,15 @@ +include(CMakeAddFortranSubdirectory) +# add the fortran subdirectory as a fortran project +# the subdir is fortran, the project is FortranHello +cmake_add_fortran_subdirectory(fortran + PROJECT FortranHello # project name in toplevel CMakeLists.txt + ARCHIVE_DIR ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + RUNTIME_DIR bin # ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + LIBRARIES hello world # target libraries created + CMAKE_COMMAND_LINE + -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} + -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + LINK_LIBRARIES # link interface libraries + LINK_LIBS hello world # hello needs world to link + ) diff --git a/Tests/VSGNUFortran/fortran/CMakeLists.txt b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt similarity index 100% rename from Tests/VSGNUFortran/fortran/CMakeLists.txt rename to Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt diff --git a/Tests/VSGNUFortran/fortran/hello.f b/Tests/VSGNUFortran/subdir/fortran/hello.f similarity index 100% rename from Tests/VSGNUFortran/fortran/hello.f rename to Tests/VSGNUFortran/subdir/fortran/hello.f diff --git a/Tests/VSGNUFortran/fortran/world.f b/Tests/VSGNUFortran/subdir/fortran/world.f similarity index 100% rename from Tests/VSGNUFortran/fortran/world.f rename to Tests/VSGNUFortran/subdir/fortran/world.f From 6f6891b33736918f149279dc7d1e9ade50efd917 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 8 Feb 2012 11:55:07 -0500 Subject: [PATCH 09/10] CMakeAddFortranSubdirectory: Always parse arguments Parse arguments even in add_subdirectory() mode to validate them. --- Modules/CMakeAddFortranSubdirectory.cmake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index 5c3e9a2064..681b09ed0f 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -99,6 +99,11 @@ endfunction() function(cmake_add_fortran_subdirectory subdir) + # Parse arguments to function + set(oneValueArgs PROJECT ARCHIVE_DIR RUNTIME_DIR) + set(multiValueArgs LIBRARIES LINK_LIBRARIES CMAKE_COMMAND_LINE) + cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + # if we are not using MSVC without fortran support # then just use the usual add_subdirectory to build # the fortran library @@ -111,10 +116,6 @@ function(cmake_add_fortran_subdirectory subdir) # if we have MSVC without Intel fortran then setup # external projects to build with mingw fortran - # Parse arguments to function - set(oneValueArgs PROJECT ARCHIVE_DIR RUNTIME_DIR) - set(multiValueArgs LIBRARIES LINK_LIBRARIES CMAKE_COMMAND_LINE) - cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") set(project_name "${ARGS_PROJECT}") set(library_dir "${ARGS_ARCHIVE_DIR}") From 1e16406dc9a8c5bdad7adbed8c3b6cee0a7020d0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 8 Feb 2012 11:58:57 -0500 Subject: [PATCH 10/10] CMakeAddFortranSubdirectory: Add NO_EXTERNAL_INSTALL option We do not yet support "make install" in the external project case. Document this explicitly in the interface. Require the caller to use an option to "disable" the unsupported behavior. This will allow us to add the behavior by default in the future without clobbering existing projects that handle the installation themselves. --- Modules/CMakeAddFortranSubdirectory.cmake | 16 +++++++++++++++- Tests/VSGNUFortran/subdir/CMakeLists.txt | 3 ++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index 681b09ed0f..ddb79fb474 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -19,10 +19,17 @@ # LINK_LIBRARIES # link interface libraries for LIBRARIES # [LINK_LIBS ...]... # CMAKE_COMMAND_LINE ... # extra command line flags to pass to cmake +# NO_EXTERNAL_INSTALL # skip installation of external project # ) # Relative paths in ARCHIVE_DIR and RUNTIME_DIR are interpreted with respect # to the build directory corresponding to the source directory in which the # function is invoked. +# +# Limitations: +# +# NO_EXTERNAL_INSTALL is required for forward compatibility with a +# future version that supports installation of the external project +# binaries during "make install". #============================================================================= # Copyright 2011-2012 Kitware, Inc. @@ -100,9 +107,16 @@ endfunction() function(cmake_add_fortran_subdirectory subdir) # Parse arguments to function + set(options NO_EXTERNAL_INSTALL) set(oneValueArgs PROJECT ARCHIVE_DIR RUNTIME_DIR) set(multiValueArgs LIBRARIES LINK_LIBRARIES CMAKE_COMMAND_LINE) - cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT ARGS_NO_EXTERNAL_INSTALL) + message(FATAL_ERROR + "Option NO_EXTERNAL_INSTALL is required (for forward compatibility) " + "but was not given." + ) + endif() # if we are not using MSVC without fortran support # then just use the usual add_subdirectory to build diff --git a/Tests/VSGNUFortran/subdir/CMakeLists.txt b/Tests/VSGNUFortran/subdir/CMakeLists.txt index df018b3d92..0b99199539 100644 --- a/Tests/VSGNUFortran/subdir/CMakeLists.txt +++ b/Tests/VSGNUFortran/subdir/CMakeLists.txt @@ -12,4 +12,5 @@ cmake_add_fortran_subdirectory(fortran -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} LINK_LIBRARIES # link interface libraries LINK_LIBS hello world # hello needs world to link - ) + NO_EXTERNAL_INSTALL + )