diff options
48 files changed, 1447 insertions, 118 deletions
diff --git a/Docs/cmake-completion b/Docs/cmake-completion index d82d608..d70ac24 100644 --- a/Docs/cmake-completion +++ b/Docs/cmake-completion @@ -130,6 +130,16 @@ _cpack() COMPREPLY=( $(compgen -f ${cur}) ) return 0 ;; + --help-variable) + local running=$(for x in `cpack --help-variable-list | grep -v "cpack version" `; do echo ${x} ; done ) + COMPREPLY=( $(compgen -W "${running}" -- ${cur}) ) + return 0 + ;; + --help-command) + local running=$(for x in `cpack --help-command-list | grep -v "cpack version" `; do echo ${x} ; done ) + COMPREPLY=( $(compgen -W "${running}" -- ${cur}) ) + return 0 + ;; *) ;; esac diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake new file mode 100644 index 0000000..ddb79fb --- /dev/null +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -0,0 +1,206 @@ +# - 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 CMAKE_GNUtoMS option +# is set to on, so that the MS .lib files are created. +# Usage is as follows: +# cmake_add_fortran_subdirectory( +# <subdir> # name of subdirectory +# PROJECT <project_name> # project name in subdir top CMakeLists.txt +# ARCHIVE_DIR <dir> # dir where project places .lib files +# RUNTIME_DIR <dir> # dir where project places .dll files +# LIBRARIES <lib>... # names of library targets to import +# LINK_LIBRARIES # link interface libraries for LIBRARIES +# [LINK_LIBS <lib> <dep>...]... +# 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. +# +# 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) + # 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." + "Or set the cache variable MINGW_GFORTRAN to the full path. " + " This is required to build") + endif() + + # 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}") + 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) + # 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 "${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 + # 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 + + 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}") + 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 + 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 GLOBAL) + set_property(TARGET ${lib} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) + set_target_properties(${lib} PROPERTIES + IMPORTED_IMPLIB_NOCONFIG "${library_dir}/lib${lib}.lib" + IMPORTED_LOCATION_NOCONFIG "${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 0000000..55b271a --- /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 0000000..97f6769 --- /dev/null +++ b/Modules/CMakeAddFortranSubdirectory/config_mingw.cmake.in @@ -0,0 +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 + ${CMAKE_COMMAND_LINE} + "@source_dir@") diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index efcba29..ade6d58 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -50,7 +50,7 @@ IF(NOT CMAKE_Fortran_COMPILER) # fort77: native F77 compiler under HP-UX (and some older Crays) # frt: Fujitsu F77 compiler # pathf90/pathf95/pathf2003: PathScale Fortran compiler - # pgf77/pgf90/pgf95: Portland Group F77/F90/F95 compilers + # pgf77/pgf90/pgf95/pgfortran: Portland Group F77/F90/F95 compilers # xlf/xlf90/xlf95: IBM (AIX) F77/F90/F95 compilers # lf95: Lahey-Fujitsu F95 compiler # fl32: Microsoft Fortran 77 "PowerStation" compiler @@ -64,8 +64,8 @@ IF(NOT CMAKE_Fortran_COMPILER) # then 77 or older compilers, gnu is always last in the group, # so if you paid for a compiler it is picked by default. SET(CMAKE_Fortran_COMPILER_LIST - ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 lf95 xlf95 fort - gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77 + ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 pgfortran lf95 xlf95 + fort gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77 frt pgf77 xlf fl32 af77 g77 f77 ) @@ -73,7 +73,7 @@ IF(NOT CMAKE_Fortran_COMPILER) SET(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77) SET(_Fortran_COMPILER_NAMES_Intel ifort ifc efc) SET(_Fortran_COMPILER_NAMES_Absoft af95 af90 af77) - SET(_Fortran_COMPILER_NAMES_PGI pgf95 pgf90 pgf77) + SET(_Fortran_COMPILER_NAMES_PGI pgf95 pgfortran pgf90 pgf77) SET(_Fortran_COMPILER_NAMES_PathScale pathf2003 pathf95 pathf90) SET(_Fortran_COMPILER_NAMES_XL xlf) SET(_Fortran_COMPILER_NAMES_VisualAge xlf95 xlf90 xlf) diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 2cc27cf..8a44991 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -1,5 +1,7 @@ -# - Build binary and source package installers -# +##section Variables common to all CPack generators +##end +##module +# - Build binary and source package installers. # The CPack module generates binary and source installers in a variety # of formats using the cpack program. Inclusion of the CPack module # adds two new targets to the resulting makefiles, package and @@ -29,16 +31,16 @@ # on a per-generator basis. It only need contain overrides. # # Here's how it works: -# - cpack runs -# - it includes CPackConfig.cmake -# - it iterates over the generators listed in that file's -# CPACK_GENERATOR list variable (unless told to use just a -# specific one via -G on the command line...) +# - cpack runs +# - it includes CPackConfig.cmake +# - it iterates over the generators listed in that file's +# CPACK_GENERATOR list variable (unless told to use just a +# specific one via -G on the command line...) # -# - foreach generator, it then -# - sets CPACK_GENERATOR to the one currently being iterated -# - includes the CPACK_PROJECT_CONFIG_FILE -# - produces the package for that generator +# - foreach generator, it then +# - sets CPACK_GENERATOR to the one currently being iterated +# - includes the CPACK_PROJECT_CONFIG_FILE +# - produces the package for that generator # # This is the key: For each generator listed in CPACK_GENERATOR # in CPackConfig.cmake, cpack will *reset* CPACK_GENERATOR @@ -48,95 +50,142 @@ # Before including this CPack module in your CMakeLists.txt file, # there are a variety of variables that can be set to customize # the resulting installers. The most commonly-used variables are: +##end # +##variable # CPACK_PACKAGE_NAME - The name of the package (or application). If # not specified, defaults to the project name. +##end # -# CPACK_PACKAGE_VENDOR - The name of the package vendor (e.g., +##variable +# CPACK_PACKAGE_VENDOR - The name of the package vendor. (e.g., # "Kitware"). +##end # +##variable # CPACK_PACKAGE_VERSION_MAJOR - Package major Version +##end # +##variable # CPACK_PACKAGE_VERSION_MINOR - Package minor Version +##end # +##variable # CPACK_PACKAGE_VERSION_PATCH - Package patch Version +##end # +##variable # CPACK_PACKAGE_DESCRIPTION_FILE - A text file used to describe the # project. Used, for example, the introduction screen of a # CPack-generated Windows installer to describe the project. +##end # +##variable # CPACK_PACKAGE_DESCRIPTION_SUMMARY - Short description of the # project (only a few words). +##end # +##variable # CPACK_PACKAGE_FILE_NAME - The name of the package file to generate, # not including the extension. For example, cmake-2.6.1-Linux-i686. +##end # +##variable # CPACK_PACKAGE_INSTALL_DIRECTORY - Installation directory on the # target system, e.g., "CMake 2.5". +##end # +##variable # CPACK_PROJECT_CONFIG_FILE - File included at cpack time, once per # generator after setting CPACK_GENERATOR to the actual generator # being used. Allows per-generator setting of CPACK_* variables at # cpack time. +##end # +##variable # CPACK_RESOURCE_FILE_LICENSE - License file for the project, which # will typically be displayed to the user (often with an explicit # "Accept" button, for graphical installers) prior to installation. +##end # +##variable # CPACK_RESOURCE_FILE_README - ReadMe file for the project, which # typically describes in some detail +##end # +##variable # CPACK_RESOURCE_FILE_WELCOME - Welcome file for the project, which # welcomes users to this installer. Typically used in the graphical # installers on Windows and Mac OS X. +##end # +##variable # CPACK_MONOLITHIC_INSTALL - Disables the component-based # installation mechanism, so that all components are always installed. +##end # +##variable # CPACK_GENERATOR - List of CPack generators to use. If not # specified, CPack will create a set of options (e.g., # CPACK_BINARY_NSIS) allowing the user to enable/disable individual # generators. +##end # +##variable # CPACK_OUTPUT_CONFIG_FILE - The name of the CPack configuration file # for binary installers that will be generated by the CPack # module. Defaults to CPackConfig.cmake. +##end # +##variable # CPACK_PACKAGE_EXECUTABLES - Lists each of the executables along # with a text label, to be used to create Start Menu shortcuts on # Windows. For example, setting this to the list ccmake;CMake will # create a shortcut named "CMake" that will execute the installed # executable ccmake. +##end # +##variable # CPACK_STRIP_FILES - List of files to be stripped. Starting with # CMake 2.6.0 CPACK_STRIP_FILES will be a boolean variable which # enables stripping of all files (a list of files evaluates to TRUE # in CMake, so this change is compatible). +##end # # The following CPack variables are specific to source packages, and # will not affect binary packages: # +##variable # CPACK_SOURCE_PACKAGE_FILE_NAME - The name of the source package, # e.g., cmake-2.6.1 +##end # +##variable # CPACK_SOURCE_STRIP_FILES - List of files in the source tree that # will be stripped. Starting with CMake 2.6.0 # CPACK_SOURCE_STRIP_FILES will be a boolean variable which enables # stripping of all files (a list of files evaluates to TRUE in CMake, # so this change is compatible). +##end # +##variable # CPACK_SOURCE_GENERATOR - List of generators used for the source # packages. As with CPACK_GENERATOR, if this is not specified then # CPack will create a set of options (e.g., CPACK_SOURCE_ZIP) # allowing users to select which packages will be generated. +##end # +##variable # CPACK_SOURCE_OUTPUT_CONFIG_FILE - The name of the CPack # configuration file for source installers that will be generated by # the CPack module. Defaults to CPackSourceConfig.cmake. +##end # +##variable # CPACK_SOURCE_IGNORE_FILES - Pattern of files in the source tree # that won't be packaged when building a source package. This is a # list of patterns, e.g., /CVS/;/\\.svn/;\\.swp$;\\.#;/#;.*~;cscope.* +##end # # The following variables are specific to the DragNDrop installers # built on Mac OS X: @@ -195,27 +244,41 @@ # # The following variables are for advanced uses of CPack: # +##variable # CPACK_CMAKE_GENERATOR - What CMake generator should be used if the # project is CMake project. Defaults to the value of CMAKE_GENERATOR; # few users will want to change this setting. +##end # +##variable # CPACK_INSTALL_CMAKE_PROJECTS - List of four values that specify # what project to install. The four values are: Build directory, # Project Name, Project Component, Directory. If omitted, CPack will # build an installer that installers everything. +##end # +##variable # CPACK_SYSTEM_NAME - System name, defaults to the value of # ${CMAKE_SYSTEM_NAME}. +##end # +##variable # CPACK_PACKAGE_VERSION - Package full version, used internally. By # default, this is built from CPACK_PACKAGE_VERSION_MAJOR, # CPACK_PACKAGE_VERSION_MINOR, and CPACK_PACKAGE_VERSION_PATCH. +##end # +##variable # CPACK_TOPLEVEL_TAG - Directory for the installed files. +##end # +##variable # CPACK_INSTALL_COMMANDS - Extra commands to install components. +##end # +##variable # CPACK_INSTALLED_DIRECTORIES - Extra directories to install. +##end # #============================================================================= @@ -259,7 +322,7 @@ MACRO(cpack_set_if_not_set name value) ENDIF(NOT DEFINED "${name}") ENDMACRO(cpack_set_if_not_set) -# Macro to encode variables for the configuration file +# cpack_encode_variables - Macro to encode variables for the configuration file # find any variable that starts with CPACK and create a variable # _CPACK_OTHER_VARIABLES_ that contains SET commands for # each cpack variable. _CPACK_OTHER_VARIABLES_ is then diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake index 1c10372..016cb8c 100644 --- a/Modules/CPackComponent.cmake +++ b/Modules/CPackComponent.cmake @@ -1,3 +1,6 @@ +##section Variables common to all CPack generators +##end +##module # - Build binary and source package installers # # The CPackComponent module is the module which handles @@ -20,7 +23,9 @@ # components are identified by the COMPONENT argument of CMake's # INSTALL commands, and should be further described by the following # CPack commands: +##end # +##macro # cpack_add_component - Describes a CPack installation component # named by the COMPONENT argument to a CMake INSTALL command. # @@ -90,7 +95,9 @@ # create a file with some name based on CPACK_PACKAGE_FILE_NAME and # the name of the component. See cpack_configure_downloads for more # information. +##end # +##macro # cpack_add_component_group - Describes a group of related CPack # installation components. # @@ -134,7 +141,9 @@ # # BOLD_TITLE indicates that the group title should appear in bold, # to call the user's attention to the group. +##end # +##macro # cpack_add_install_type - Add a new installation type containing a # set of predefined component selections to the graphical installer. # @@ -153,7 +162,9 @@ # DISPLAY_NAME is the displayed name of the install type, which will # typically show up in a drop-down box within a graphical # installer. This value can be any string. +##end # +##macro # cpack_configure_downloads - Configure CPack to download selected # components on-the-fly as part of the installation process. # @@ -203,6 +214,7 @@ # that can be called from Windows' Add/Remove Programs dialog (via the # "Modify" button) to change the set of installed components. NO_ADD_REMOVE # turns off this behavior. This option is ignored on Mac OS X. +##endmacro #============================================================================= # Copyright 2006-2009 Kitware, Inc. diff --git a/Modules/CPackDeb.cmake b/Modules/CPackDeb.cmake index 26433bb..0916843 100644 --- a/Modules/CPackDeb.cmake +++ b/Modules/CPackDeb.cmake @@ -1,3 +1,6 @@ +##section Variables specific to a CPack generator +##end +##module # - The builtin (binary) CPack Deb generator (Unix only) # CPackDeb may be used to create Deb package using CPack. # CPackDeb is a CPack generator thus it uses the CPACK_XXX variables @@ -11,43 +14,63 @@ # the wiki: # http://www.cmake.org/Wiki/CMake:CPackPackageGenerators#DEB_.28UNIX_only.29 # However as a handy reminder here comes the list of specific variables: +##end # +##variable # CPACK_DEBIAN_PACKAGE_NAME # Mandatory : YES # Default : CPACK_PACKAGE_NAME (lower case) # The debian package summary +##end +##variable # CPACK_DEBIAN_PACKAGE_VERSION # Mandatory : YES # Default : CPACK_PACKAGE_VERSION # The debian package version +##end +##variable # CPACK_DEBIAN_PACKAGE_ARCHITECTURE # Mandatory : YES # Default : Output of dpkg --print-architecture (or i386 if dpkg is not found) # The debian package architecture +##end +##variable # CPACK_DEBIAN_PACKAGE_DEPENDS # Mandatory : NO # Default : - # May be used to set deb dependencies. +##end +##variable # CPACK_DEBIAN_PACKAGE_MAINTAINER # Mandatory : YES # Default : CPACK_PACKAGE_CONTACT # The debian package maintainer +##end +##variable # CPACK_DEBIAN_PACKAGE_DESCRIPTION # Mandatory : YES # Default : CPACK_PACKAGE_DESCRIPTION_SUMMARY # The debian package description +##end +##variable # CPACK_DEBIAN_PACKAGE_SECTION # Mandatory : YES # Default : 'devel' # The debian package section +##end +##variable # CPACK_DEBIAN_PACKAGE_PRIORITY # Mandatory : YES # Default : 'optional' # The debian package priority +##end +##variable # CPACK_DEBIAN_PACKAGE_HOMEPAGE # Mandatory : NO # Default : - # The URL of the web site for this package +##end +##variable # CPACK_DEBIAN_PACKAGE_SHLIBDEPS # Mandatory : NO # Default : OFF @@ -57,11 +80,15 @@ # if you use this feature, because if you don't dpkg-shlibdeps # may fail to find your own shared libs. # See http://www.cmake.org/Wiki/CMake_RPATH_handling. +##end +##variable # CPACK_DEBIAN_PACKAGE_DEBUG # Mandatory : NO # Default : - # May be set when invoking cpack in order to trace debug information # during CPackDeb run. +##end +##variable # CPACK_DEBIAN_PACKAGE_PREDEPENDS # Mandatory : NO # Default : - @@ -69,12 +96,16 @@ # This field is like Depends, except that it also forces dpkg to complete installation of # the packages named before even starting the installation of the package which declares # the pre-dependency. +##end +##variable # CPACK_DEBIAN_PACKAGE_ENHANCES # Mandatory : NO # Default : - # see http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps # This field is similar to Suggests but works in the opposite direction. # It is used to declare that a package can enhance the functionality of another package. +##end +##variable # CPACK_DEBIAN_PACKAGE_BREAKS # Mandatory : NO # Default : - @@ -82,23 +113,30 @@ # When one binary package declares that it breaks another, dpkg will refuse to allow the # package which declares Breaks be installed unless the broken package is deconfigured first, # and it will refuse to allow the broken package to be reconfigured. +##end +##variable # CPACK_DEBIAN_PACKAGE_CONFLICTS # Mandatory : NO # Default : - # see http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps # When one binary package declares a conflict with another using a Conflicts field, # dpkg will refuse to allow them to be installed on the system at the same time. +##end +##variable # CPACK_DEBIAN_PACKAGE_PROVIDES # Mandatory : NO # Default : - # see http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps # A virtual package is one which appears in the Provides control field of another package. +##end +##variable # CPACK_DEBIAN_PACKAGE_REPLACES # Mandatory : NO # Default : - # see http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps # Packages can declare in their control file that they should overwrite # files in certain other packages, or completely replace other packages. +##end #============================================================================= # Copyright 2007-2009 Kitware, Inc. diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index e1e76ed..f76e91e 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -1,3 +1,6 @@ +##section Variables specific to a CPack generator +##end +##module # - The builtin (binary) CPack RPM generator (Unix only) # CPackRPM may be used to create RPM package using CPack. # CPackRPM is a CPack generator thus it uses the CPACK_XXX variables @@ -15,52 +18,67 @@ # You'll find a detailed usage of CPackRPM on the wiki: # http://www.cmake.org/Wiki/CMake:CPackPackageGenerators#RPM_.28Unix_Only.29 # However as a handy reminder here comes the list of specific variables: +##end # -# CPACK_RPM_PACKAGE_SUMMARY +##variable +# CPACK_RPM_PACKAGE_SUMMARY - The RPM package summary. # Mandatory : YES # Default : CPACK_PACKAGE_DESCRIPTION_SUMMARY -# The RPM package summary -# CPACK_RPM_PACKAGE_NAME +##end +##variable +# CPACK_RPM_PACKAGE_NAME - The RPM package name. # Mandatory : YES # Default : CPACK_PACKAGE_NAME -# The RPM package name -# CPACK_RPM_PACKAGE_VERSION +##end +##variable +# CPACK_RPM_PACKAGE_VERSION - The RPM package version. # Mandatory : YES # Default : CPACK_PACKAGE_VERSION -# The RPM package version -# CPACK_RPM_PACKAGE_ARCHITECTURE +##end +##variable +# CPACK_RPM_PACKAGE_ARCHITECTURE - The RPM package architecture. # Mandatory : NO # Default : - -# The RPM package architecture. This may be set to "noarch" if you +# This may be set to "noarch" if you # know you are building a noarch package. -# CPACK_RPM_PACKAGE_RELEASE +##end +##variable +# CPACK_RPM_PACKAGE_RELEASE - The RPM package release. # Mandatory : YES # Default : 1 -# The RPM package release. This is the numbering of the RPM package +# This is the numbering of the RPM package # itself, i.e. the version of the packaging and not the version of the # content (see CPACK_RPM_PACKAGE_VERSION). One may change the default # value if the previous packaging was buggy and/or you want to put here # a fancy Linux distro specific numbering. -# CPACK_RPM_PACKAGE_LICENSE +##end +##variable +# CPACK_RPM_PACKAGE_LICENSE - The RPM package license policy. # Mandatory : YES # Default : "unknown" -# The RPM package license policy. -# CPACK_RPM_PACKAGE_GROUP +##end +##variable +# CPACK_RPM_PACKAGE_GROUP - The RPM package group. # Mandatory : YES # Default : "unknown" -# The RPM package group. -# CPACK_RPM_PACKAGE_VENDOR +##end +##variable +# CPACK_RPM_PACKAGE_VENDOR - The RPM package vendor. # Mandatory : YES # Default : CPACK_PACKAGE_VENDOR if set or "unknown" -# The RPM package vendor. -# CPACK_RPM_PACKAGE_URL +##end +##variable +# CPACK_RPM_PACKAGE_URL - The projects URL. # Mandatory : NO # Default : - -# The projects URL. -# CPACK_RPM_PACKAGE_DESCRIPTION +##end +##variable +# CPACK_RPM_PACKAGE_DESCRIPTION - RPM package description. # Mandatory : YES # Default : CPACK_PACKAGE_DESCRIPTION_FILE if set or "no package description available" -# CPACK_RPM_COMPRESSION_TYPE +##end +##variable +# CPACK_RPM_COMPRESSION_TYPE - RPM compression type. # Mandatory : NO # Default : - # May be used to override RPM compression type to be used @@ -68,7 +86,9 @@ # to lzma or xz compression whereas older cannot use such RPM. # Using this one can enforce compression type to be used. # Possible value are: lzma, xz, bzip2 and gzip. -# CPACK_RPM_PACKAGE_REQUIRES +##end +##variable +# CPACK_RPM_PACKAGE_REQUIRES - RPM spec requires field. # Mandatory : NO # Default : - # May be used to set RPM dependencies (requires). @@ -77,22 +97,30 @@ # set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.5.0, cmake >= 2.8") # The required package list of an RPM file could be printed with # rpm -qp --requires file.rpm -# CPACK_RPM_PACKAGE_SUGGESTS +##end +##variable +# CPACK_RPM_PACKAGE_SUGGESTS - RPM spec suggest field. # Mandatory : NO # Default : - # May be used to set weak RPM dependencies (suggests). # Note that you must enclose the complete requires string between quotes. -# CPACK_RPM_PACKAGE_PROVIDES +##end +##variable +# CPACK_RPM_PACKAGE_PROVIDES - RPM spec provides field. # Mandatory : NO # Default : - # May be used to set RPM dependencies (provides). # The provided package list of an RPM file could be printed with # rpm -qp --provides file.rpm -# CPACK_RPM_PACKAGE_OBSOLETES +##end +##variable +# CPACK_RPM_PACKAGE_OBSOLETES - RPM spec obsoletes field. # Mandatory : NO # Default : - # May be used to set RPM packages that are obsoleted by this one. -# CPACK_RPM_PACKAGE_RELOCATABLE +##end +##variable +# CPACK_RPM_PACKAGE_RELOCATABLE - build a relocatable RPM. # Mandatory : NO # Default : CPACK_PACKAGE_RELOCATABLE # If this variable is set to TRUE or ON CPackRPM will try @@ -103,7 +131,9 @@ # If CPACK_SET_DESTDIR is set then you will get a warning message # but if there is file installed with absolute path you'll get # unexpected behavior. -# CPACK_RPM_SPEC_INSTALL_POST [deprecated] +##end +##variable +# CPACK_RPM_SPEC_INSTALL_POST - [deprecated]. # Mandatory : NO # Default : - # This way of specifying post-install script is deprecated use @@ -111,23 +141,31 @@ # May be used to set an RPM post-install command inside the spec file. # For example setting it to "/bin/true" may be used to prevent # rpmbuild to strip binaries. -# CPACK_RPM_SPEC_MORE_DEFINE +##end +##variable +# CPACK_RPM_SPEC_MORE_DEFINE - RPM extended spec definitions lines. # Mandatory : NO # Default : - # May be used to add any %define lines to the generated spec file. -# CPACK_RPM_PACKAGE_DEBUG +##end +##variable +# CPACK_RPM_PACKAGE_DEBUG - Toggle CPackRPM debug output. # Mandatory : NO # Default : - # May be set when invoking cpack in order to trace debug information # during CPack RPM run. For example you may launch CPack like this # cpack -D CPACK_RPM_PACKAGE_DEBUG=1 -G RPM -# CPACK_RPM_USER_BINARY_SPECFILE +##end +##variable +# CPACK_RPM_USER_BINARY_SPECFILE - A user provided spec file. # Mandatory : NO # Default : - # May be set by the user in order to specify a USER binary spec file # to be used by CPackRPM instead of generating the file. # The specified file will be processed by CONFIGURE_FILE( @ONLY). -# CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE +##end +##variable +# CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE - Spec file template. # Mandatory : NO # Default : - # If set CPack will generate a template for USER specified binary @@ -135,6 +173,8 @@ # cpack -D CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE=1 -G RPM # The user may then use this file in order to hand-craft is own # binary spec file which may be used with CPACK_RPM_USER_BINARY_SPECFILE. +##end +##variable # CPACK_RPM_PRE_INSTALL_SCRIPT_FILE # CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE # Mandatory : NO @@ -148,6 +188,8 @@ # CPACK_RPM_<COMPONENT>_PRE_UNINSTALL_SCRIPT_FILE # One may verify which scriptlet has been included with # rpm -qp --scripts package.rpm +##end +##variable # CPACK_RPM_POST_INSTALL_SCRIPT_FILE # CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE # Mandatory : NO @@ -161,6 +203,8 @@ # CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE # One may verify which scriptlet has been included with # rpm -qp --scripts package.rpm +##end +##variable # CPACK_RPM_USER_FILELIST # CPACK_RPM_<COMPONENT>_USER_FILELIST # Mandatory : NO @@ -170,12 +214,15 @@ # that be found in the %files section. Since CPackRPM is generating # the list of files (and directories) the user specified files of # the CPACK_RPM_<COMPONENT>_USER_FILELIST list will be removed from the generated list. -# CPACK_RPM_CHANGELOG_FILE +##end +##variable +# CPACK_RPM_CHANGELOG_FILE - RPM changelog file. # Mandatory : NO # Default : - # May be used to embed a changelog in the spec file. # The refered file will be read and directly put after the %changelog # section. +##end #============================================================================= # Copyright 2007-2009 Kitware, Inc. diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake new file mode 100644 index 0000000..87a4018 --- /dev/null +++ b/Modules/CheckLanguage.cmake @@ -0,0 +1,65 @@ +# - Check if a language can be enabled +# Usage: +# check_language(<lang>) +# where <lang> is a language that may be passed to enable_language() +# such as "Fortran". If CMAKE_<lang>_COMPILER is already defined the +# check does nothing. Otherwise it tries enabling the language in a +# test project. The result is cached in CMAKE_<lang>_COMPILER as the +# compiler that was found, or NOTFOUND if the language cannot be enabled. +# +# Example: +# check_language(Fortran) +# if(CMAKE_Fortran_COMPILER) +# enable_language(Fortran) +# else() +# message(STATUS "No Fortran support") +# endif() + +#============================================================================= +# Copyright 2009-2012 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.) + +macro(check_language lang) + if(NOT DEFINED CMAKE_${lang}_COMPILER) + set(_desc "Looking for a ${lang} compiler") + message(STATUS ${_desc}) + file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/CMakeLists.txt" + "cmake_minimum_required(VERSION 2.8) +project(Check${lang} ${lang}) +file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" + \"set(CMAKE_${lang}_COMPILER \\\"\${CMAKE_${lang}_COMPILER}\\\")\\n\" + ) +") + execute_process( + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang} + COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR} + OUTPUT_VARIABLE output + ERROR_VARIABLE output + RESULT_VARIABLE result + ) + include(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/result.cmake OPTIONAL) + if(CMAKE_${lang}_COMPILER AND "${result}" STREQUAL "0") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "${_desc} passed with the following output:\n" + "${output}\n") + else() + set(CMAKE_${lang}_COMPILER NOTFOUND) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "${_desc} failed with the following output:\n" + "${output}\n") + endif() + message(STATUS "${_desc} - ${CMAKE_${lang}_COMPILER}") + set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER}" CACHE FILEPATH "${lang} compiler") + mark_as_advanced(CMAKE_${lang}_COMPILER) + endif() +endmacro() diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index c56827e..9b646b4 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -588,8 +588,9 @@ IF (QT_QMAKE_EXECUTABLE AND QTVERSION) SET(QT_LIBRARY_DIR ${QT_LIBRARY_DIR_TMP} CACHE INTERNAL "Qt library dir" FORCE) SET(QT_QTCORE_FOUND 1) ELSE() - MESSAGE("Warning: QT_QMAKE_EXECUTABLE reported QT_INSTALL_LIBS as ${QT_LIBRARY_DIR_TMP}") - MESSAGE("Warning: But QtCore couldn't be found. Qt must NOT be installed correctly, or it wasn't found for cross compiling.") + MESSAGE(WARNING "${QT_QMAKE_EXECUTABLE} reported QT_INSTALL_LIBS as \"${QT_LIBRARY_DIR_TMP}\" " + "but QtCore could not be found there. " + "Qt is NOT installed correctly for the target build environment.") IF(Qt4_FIND_REQUIRED) MESSAGE( FATAL_ERROR "Could NOT find QtCore. Check ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log for more details.") ENDIF(Qt4_FIND_REQUIRED) diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake index 04646c0..1735bd4 100644 --- a/Modules/FindX11.cmake +++ b/Modules/FindX11.cmake @@ -29,6 +29,7 @@ # X11_Xkb_INCLUDE_PATH, X11_Xkb_FOUND # X11_Xkblib_INCLUDE_PATH, X11_Xkb_FOUND # X11_Xkbfile_INCLUDE_PATH, X11_Xkbfile_LIB, X11_Xkbfile_FOUND +# X11_Xmu_INCLUDE_PATH, X11_Xmu_LIB, X11_Xmu_FOUND # X11_Xpm_INCLUDE_PATH, X11_Xpm_LIB, X11_Xpm_FOUND # X11_XTest_INCLUDE_PATH, X11_XTest_LIB, X11_XTest_FOUND # X11_Xrandr_INCLUDE_PATH, X11_Xrandr_LIB, X11_Xrandr_FOUND @@ -103,6 +104,7 @@ IF (UNIX) FIND_PATH(X11_Xkb_INCLUDE_PATH X11/extensions/XKB.h ${X11_INC_SEARCH_PATH}) FIND_PATH(X11_Xkblib_INCLUDE_PATH X11/XKBlib.h ${X11_INC_SEARCH_PATH}) FIND_PATH(X11_Xkbfile_INCLUDE_PATH X11/extensions/XKBfile.h ${X11_INC_SEARCH_PATH}) + FIND_PATH(X11_Xmu_INCLUDE_PATH X11/Xmu/Xmu.h ${X11_INC_SEARCH_PATH}) FIND_PATH(X11_Xpm_INCLUDE_PATH X11/xpm.h ${X11_INC_SEARCH_PATH}) FIND_PATH(X11_XTest_INCLUDE_PATH X11/extensions/XTest.h ${X11_INC_SEARCH_PATH}) FIND_PATH(X11_XShm_INCLUDE_PATH X11/extensions/XShm.h ${X11_INC_SEARCH_PATH}) @@ -134,6 +136,7 @@ IF (UNIX) FIND_LIBRARY(X11_Xinerama_LIB Xinerama ${X11_LIB_SEARCH_PATH}) FIND_LIBRARY(X11_Xinput_LIB Xi ${X11_LIB_SEARCH_PATH}) FIND_LIBRARY(X11_Xkbfile_LIB xkbfile ${X11_LIB_SEARCH_PATH}) + FIND_LIBRARY(X11_Xmu_LIB Xmu ${X11_LIB_SEARCH_PATH}) FIND_LIBRARY(X11_Xpm_LIB Xpm ${X11_LIB_SEARCH_PATH}) FIND_LIBRARY(X11_Xrandr_LIB Xrandr ${X11_LIB_SEARCH_PATH}) FIND_LIBRARY(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH}) @@ -297,6 +300,11 @@ IF (UNIX) SET(X11_INCLUDE_DIR ${X11_INCLUDE_DIR} ${X11_Xkbfile_INCLUDE_PATH} ) ENDIF (X11_Xkbfile_INCLUDE_PATH AND X11_Xkbfile_LIB AND X11_Xlib_INCLUDE_PATH) + IF (X11_Xmu_INCLUDE_PATH AND X11_Xmu_LIB) + SET(X11_Xmu_FOUND TRUE) + SET(X11_INCLUDE_DIR ${X11_INCLUDE_DIR} ${X11_Xmu_INCLUDE_PATH}) + ENDIF (X11_Xmu_INCLUDE_PATH AND X11_Xmu_LIB) + IF (X11_Xinput_INCLUDE_PATH AND X11_Xinput_LIB) SET(X11_Xinput_FOUND TRUE) SET(X11_INCLUDE_DIR ${X11_INCLUDE_DIR} ${X11_Xinput_INCLUDE_PATH}) @@ -456,6 +464,8 @@ IF (UNIX) X11_Xkblib_INCLUDE_PATH X11_Xkbfile_INCLUDE_PATH X11_Xkbfile_LIB + X11_Xmu_INCLUDE_PATH + X11_Xmu_LIB X11_Xscreensaver_INCLUDE_PATH X11_Xscreensaver_LIB X11_Xpm_INCLUDE_PATH diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake index 4da1a3f..f327125 100644 --- a/Modules/Qt4Macros.cmake +++ b/Modules/Qt4Macros.cmake @@ -393,7 +393,13 @@ MACRO(QT4_CREATE_TRANSLATION _qm_files) FOREACH(_pro_src ${_my_sources}) SET(_pro_srcs "${_pro_srcs} \"${_pro_src}\"") ENDFOREACH(_pro_src ${_my_sources}) - FILE(WRITE ${_ts_pro} "SOURCES = ${_pro_srcs}") + SET(_pro_includes) + GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES) + FOREACH(_pro_include ${_inc_DIRS}) + GET_FILENAME_COMPONENT(_abs_include "${_pro_include}" ABSOLUTE) + SET(_pro_includes "${_pro_includes} \"${_abs_include}\"") + ENDFOREACH(_pro_include ${CMAKE_CXX_INCLUDE_PATH}) + FILE(WRITE ${_ts_pro} "SOURCES = ${_pro_srcs}\nINCLUDEPATH = ${_pro_includes}\n") ENDIF(_my_sources) ADD_CUSTOM_COMMAND(OUTPUT ${_ts_file} COMMAND ${QT_LUPDATE_EXECUTABLE} diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b5115b7..0c420b9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -449,6 +449,8 @@ SET(CPACK_SRCS CPack/cmCPackTarBZip2Generator.cxx CPack/cmCPackTarCompressGenerator.cxx CPack/cmCPackZIPGenerator.cxx + CPack/cmCPackDocumentVariables.cxx + CPack/cmCPackDocumentMacros.cxx ) IF(CYGWIN) diff --git a/Source/CPack/cmCPackDocumentMacros.cxx b/Source/CPack/cmCPackDocumentMacros.cxx new file mode 100644 index 0000000..ddc75a4 --- /dev/null +++ b/Source/CPack/cmCPackDocumentMacros.cxx @@ -0,0 +1,16 @@ +#include "cmCPackDocumentMacros.h" + +void cmCPackDocumentMacros::GetMacrosDocumentation( + std::vector<cmDocumentationEntry>& ) +{ + // Commented-out example of use + // + // cmDocumentationEntry e("cpack_<macro>", + // "Brief Description" + // "which may be on several lines.", + // "Long description in pre-formatted format" + // " blah\n" + // " blah\n" + //); + //v.push_back(e); +} diff --git a/Source/CPack/cmCPackDocumentMacros.h b/Source/CPack/cmCPackDocumentMacros.h new file mode 100644 index 0000000..544f74f --- /dev/null +++ b/Source/CPack/cmCPackDocumentMacros.h @@ -0,0 +1,21 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + 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. +============================================================================*/ +#ifndef cmCPackDocumentMacros_h +#define cmCPackDocumentMacros_h +#include "cmStandardIncludes.h" +class cmCPackDocumentMacros +{ +public: + static void GetMacrosDocumentation(std::vector<cmDocumentationEntry>& v); +}; + +#endif diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx new file mode 100644 index 0000000..68cde78 --- /dev/null +++ b/Source/CPack/cmCPackDocumentVariables.cxx @@ -0,0 +1,32 @@ +#include "cmCPackDocumentVariables.h" +#include "cmake.h" + +void cmCPackDocumentVariables::DefineVariables(cmake* cm) +{ + // Subsection: variables defined/used by cpack, + // which are common to all CPack generators + + cm->DefineProperty + ("CPACK_PACKAGING_INSTALL_PREFIX", cmProperty::VARIABLE, + "The prefix used in the built package.", + "Each CPack generator has a default value (like /usr)." + " This default value may" + " be overwritten from the CMakeLists.txt or the cpack command line" + " by setting an alternative value.\n" + "e.g. " + " set(CPACK_PACKAGING_INSTALL_PREFIX \"/opt\")\n" + "This is not the same purpose as CMAKE_INSTALL_PREFIX which" + " is used when installing from the build tree without building" + " a package." + "", false, + "Variables common to all CPack generators"); + + // Subsection: variables defined/used by cpack, + // which are specific to one CPack generator +// cm->DefineProperty +// ("CPACK_RPM_PACKAGE_NAME", cmProperty::VARIABLE, +// "RPM specific package name.", +// "If not specified, defaults to CPACK_PACKAGE_NAME." +// "", false, +// "Variables specific to a CPack generator"); +} diff --git a/Source/CPack/cmCPackDocumentVariables.h b/Source/CPack/cmCPackDocumentVariables.h new file mode 100644 index 0000000..e7971be --- /dev/null +++ b/Source/CPack/cmCPackDocumentVariables.h @@ -0,0 +1,21 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + 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. +============================================================================*/ +#ifndef cmCPackDocumentVariables_h +#define cmCPackDocumentVariables_h +class cmake; +class cmCPackDocumentVariables +{ +public: + static void DefineVariables(cmake* cm); +}; + +#endif diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 2b94067..0787ef9 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -344,9 +344,9 @@ int cmCPackNSISGenerator::InitializeInternal() if ( cmSystemTools::IsOn(this->GetOption( "CPACK_INCLUDE_TOPLEVEL_DIRECTORY")) ) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "NSIS Generator cannot work with CPACK_INCLUDE_TOPLEVEL_DIRECTORY. " - "This option will be ignored." + cmCPackLogger(cmCPackLog::LOG_WARNING, + "NSIS Generator cannot work with CPACK_INCLUDE_TOPLEVEL_DIRECTORY set. " + "This option will be reset to 0 (for this generator only)." << std::endl); this->SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", 0); } diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 163f744..c541610 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -14,6 +14,8 @@ // Need these for documentation support. #include "cmake.h" #include "cmDocumentation.h" +#include "cmCPackDocumentVariables.h" +#include "cmCPackDocumentMacros.h" #include "cmCPackGeneratorFactory.h" #include "cmCPackGenerator.h" #include "cmake.h" @@ -24,6 +26,7 @@ #include "cmCPackLog.h" #include <cmsys/CommandLineArguments.hxx> +#include <cmsys/SystemTools.hxx> #include <memory> // auto_ptr //---------------------------------------------------------------------------- @@ -90,6 +93,40 @@ static const char * cmDocumentationOptions[][3] = "If vendor is not specified on cpack command line " "(or inside CMakeLists.txt) then" "CPack.cmake defines it with a default value"}, + {"--help-command cmd [file]", "Print help for a single command and exit.", + "Full documentation specific to the given command is displayed. " + "If a file is specified, the documentation is written into and the output " + "format is determined depending on the filename suffix. Supported are man " + "page, HTML, DocBook and plain text."}, + {"--help-command-list [file]", "List available commands and exit.", + "The list contains all commands for which help may be obtained by using " + "the --help-command argument followed by a command name. " + "If a file is specified, the documentation is written into and the output " + "format is determined depending on the filename suffix. Supported are man " + "page, HTML, DocBook and plain text."}, + {"--help-commands [file]", "Print help for all commands and exit.", + "Full documentation specific for all current command is displayed." + "If a file is specified, the documentation is written into and the output " + "format is determined depending on the filename suffix. Supported are man " + "page, HTML, DocBook and plain text."}, + {"--help-variable var [file]", + "Print help for a single variable and exit.", + "Full documentation specific to the given variable is displayed." + "If a file is specified, the documentation is written into and the output " + "format is determined depending on the filename suffix. Supported are man " + "page, HTML, DocBook and plain text."}, + {"--help-variable-list [file]", "List documented variables and exit.", + "The list contains all variables for which help may be obtained by using " + "the --help-variable argument followed by a variable name. If a file is " + "specified, the help is written into it." + "If a file is specified, the documentation is written into and the output " + "format is determined depending on the filename suffix. Supported are man " + "page, HTML, DocBook and plain text."}, + {"--help-variables [file]", "Print help for all variables and exit.", + "Full documentation for all variables is displayed." + "If a file is specified, the documentation is written into and the output " + "format is determined depending on the filename suffix. Supported are man " + "page, HTML, DocBook and plain text."}, {0,0,0} }; @@ -137,12 +174,15 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, return 1; } + //---------------------------------------------------------------------------- // this is CPack. int main (int argc, char *argv[]) { cmSystemTools::FindExecutableDirectory(argv[0]); cmCPackLog log; + int nocwd = 0; + log.SetErrorPrefix("CPack Error: "); log.SetWarningPrefix("CPack Warning: "); log.SetOutputPrefix("CPack: "); @@ -154,6 +194,7 @@ int main (int argc, char *argv[]) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Current working directory cannot be established." << std::endl); + nocwd = 1; } std::string generator; @@ -179,7 +220,6 @@ int main (int argc, char *argv[]) cpackConfigFile = ""; - cmDocumentation doc; cmsys::CommandLineArguments arg; arg.Initialize(argc, argv); typedef cmsys::CommandLineArguments argT; @@ -252,17 +292,25 @@ int main (int argc, char *argv[]) generators.SetLogger(&log); cmCPackGenerator* cpackGenerator = 0; - if ( !helpFull.empty() || !helpMAN.empty() || - !helpHTML.empty() || helpVersion ) + cmDocumentation doc; + doc.addCPackStandardDocSections(); + /* Were we invoked to display doc or to do some work ? */ + if(doc.CheckOptions(argc, argv,"-G") || nocwd) { - help = true; + help = true; } + else + { + help = false; + } + + // This part is used for cpack documentation lookup as well. + cminst.AddCMakePaths(); if ( parsed && !help ) { // find out which system cpack is running on, so it can setup the search // paths, so FIND_XXX() commands can be used in scripts - cminst.AddCMakePaths(); std::string systemFile = globalMF->GetModulesFile("CMakeDetermineSystem.cmake"); if (!globalMF->ReadListFile(0, systemFile.c_str())) @@ -465,14 +513,49 @@ int main (int argc, char *argv[]) */ if ( help ) { - doc.CheckOptions(argc, argv); // Construct and print requested documentation. + std::vector<cmDocumentationEntry> variables; + doc.SetName("cpack"); doc.SetSection("Name",cmDocumentationName); doc.SetSection("Usage",cmDocumentationUsage); doc.SetSection("Description",cmDocumentationDescription); doc.PrependSection("Options",cmDocumentationOptions); + // statically (in C++ code) defined variables + cmCPackDocumentVariables::DefineVariables(&cminst); + + std::vector<cmDocumentationEntry> commands; + + std::string docedFile; + std::string docPath; + cmDocumentation::documentedModulesList_t docedModList; + + docedFile = globalMF->GetModulesFile("CPack.cmake"); + if (docedFile.length()!=0) + { + docPath = cmSystemTools::GetFilenamePath(docedFile.c_str()); + doc.getDocumentedModulesListInDir(docPath,"CPack*.cmake",docedModList); + } + + // parse the files for documentation. + cmDocumentation::documentedModulesList_t::iterator docedIt; + for (docedIt = docedModList.begin(); + docedIt!= docedModList.end(); ++docedIt) + { + doc.GetStructuredDocFromFile( + (docedIt->first).c_str(), + commands,&cminst,(docedIt->second).c_str()); + } + + std::map<std::string,cmDocumentationSection *> propDocs; + cminst.GetPropertiesDocumentation(propDocs); + doc.SetSections(propDocs); + cminst.GetCommandDocumentation(commands,true,false); + // statically (in C++ code) defined macros/commands + cmCPackDocumentMacros::GetMacrosDocumentation(commands); + doc.SetSection("Commands",commands); + std::vector<cmDocumentationEntry> v; cmCPackGeneratorFactory::DescriptionsMap::const_iterator generatorIt; for( generatorIt = generators.GetGeneratorsList().begin(); diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index b1a72af..623d7d3 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -102,6 +102,7 @@ int main(int argc, char** argv) { cmSystemTools::FindExecutableDirectory(argv[0]); cmDocumentation doc; + doc.addCMakeStandardDocSections(); if(doc.CheckOptions(argc, argv)) { cmake hcm; diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 4785188..056e48e 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -10,11 +10,11 @@ # See the License for more information. #============================================================================= PROJECT(QtDialog) -SET(QT_MIN_VERSION "4.3.0") +SET(QT_MIN_VERSION "4.4.0") FIND_PACKAGE(Qt4 REQUIRED) IF(NOT QT4_FOUND) - MESSAGE(SEND_ERROR "Failed to find Qt 4.3 or greater.") + MESSAGE(SEND_ERROR "Failed to find Qt 4.4 or greater.") ELSE(NOT QT4_FOUND) INCLUDE(${QT_USE_FILE}) diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 7ba7f51..b4f3d72 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -64,6 +64,7 @@ int main(int argc, char** argv) // check docs first so that X is not need to get docs // do docs, if args were given cmDocumentation doc; + doc.addCMakeStandardDocSections(); if(argc >1 && doc.CheckOptions(argc, argv)) { // Construct and print requested documentation. diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 338eaff..45b4cd3 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -554,8 +554,7 @@ void CMakeSetupDialog::doHelp() void CMakeSetupDialog::doInterrupt() { this->enterState(Interrupting); - QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), - "interrupt", Qt::QueuedConnection); + this->CMakeThread->cmakeInstance()->interrupt(); } void CMakeSetupDialog::doSourceBrowse() diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index a40a175..73050f3 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -63,6 +63,8 @@ QCMake::QCMake(QObject* p) #endif this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this); + cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this); + std::vector<std::string> generators; this->CMakeInstance->GetRegisteredGenerators(generators); std::vector<std::string>::iterator iter; @@ -170,6 +172,7 @@ void QCMake::configure() this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode); this->CMakeInstance->PreLoadCMakeFiles(); + InterruptFlag = 0; cmSystemTools::ResetErrorOccuredFlag(); int err = this->CMakeInstance->Configure(); @@ -188,7 +191,9 @@ void QCMake::generate() UINT lastErrorMode = SetErrorMode(0); #endif + InterruptFlag = 0; cmSystemTools::ResetErrorOccuredFlag(); + int err = this->CMakeInstance->Generate(); #ifdef Q_OS_WIN @@ -337,7 +342,13 @@ QCMakePropertyList QCMake::properties() const void QCMake::interrupt() { - cmSystemTools::SetFatalErrorOccured(); + this->InterruptFlag.ref(); +} + +bool QCMake::interruptCallback(void* cd) +{ + QCMake* self = reinterpret_cast<QCMake*>(cd); + return self->InterruptFlag; } void QCMake::progressCallback(const char* msg, float percent, void* cd) diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 0d10823..0d68586 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -23,6 +23,7 @@ #include <QList> #include <QStringList> #include <QMetaType> +#include <QAtomicInt> class cmake; @@ -78,7 +79,7 @@ public slots: void generate(); /// set the property values void setProperties(const QCMakePropertyList&); - /// interrupt the configure or generate process + /// interrupt the configure or generate process (if connecting, make a direct connection) void interrupt(); /// delete the cache in binary directory void deleteCache(); @@ -133,6 +134,7 @@ signals: protected: cmake* CMakeInstance; + static bool interruptCallback(void*); static void progressCallback(const char* msg, float percent, void* cd); static void errorCallback(const char* msg, const char* title, bool&, void* cd); @@ -145,6 +147,7 @@ protected: QString Generator; QStringList AvailableGenerators; QString CMakeExecutable; + QAtomicInt InterruptFlag; }; #endif // __QCMake_h diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 7817eb3..e046096 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -111,6 +111,17 @@ public: } /** + * This is used to avoid including this command + * in documentation. This is mainly used by + * cmMacroHelperCommand and cmFunctionHelperCommand + * which cannot provide appropriate documentation. + */ + virtual bool ShouldAppearInDocumentation() + { + return true; + } + + /** * The name of the command as specified in CMakeList.txt. */ virtual const char* GetName() = 0; diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 07683d0..02f69f1 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -14,6 +14,7 @@ #include "cmSystemTools.h" #include "cmVersion.h" #include <cmsys/Directory.hxx> +#include <cmsys/Glob.hxx> //---------------------------------------------------------------------------- @@ -220,55 +221,7 @@ cmDocumentation::cmDocumentation() :CurrentFormatter(0) { this->SetForm(TextForm); - - cmDocumentationSection *sec; - - sec = new cmDocumentationSection("Author","AUTHOR"); - sec->Append(cmDocumentationEntry - (0, - "This manual page was generated by the \"--help-man\" option.", - 0)); - this->AllSections["Author"] = sec; - - sec = new cmDocumentationSection("Copyright","COPYRIGHT"); - sec->Append(cmDocumentationCopyright); - this->AllSections["Copyright"] = sec; - - sec = new cmDocumentationSection("See Also","SEE ALSO"); - sec->Append(cmDocumentationStandardSeeAlso); - this->AllSections["Standard See Also"] = sec; - - sec = new cmDocumentationSection("Options","OPTIONS"); - sec->Append(cmDocumentationStandardOptions); - this->AllSections["Options"] = sec; - - sec = new cmDocumentationSection("Properties","PROPERTIES"); - sec->Append(cmPropertiesDocumentationDescription); - this->AllSections["Properties Description"] = sec; - - sec = new cmDocumentationSection("Generators","GENERATORS"); - sec->Append(cmDocumentationGeneratorsHeader); - this->AllSections["Generators"] = sec; - - sec = new cmDocumentationSection("Compatibility Commands", - "COMPATIBILITY COMMANDS"); - sec->Append(cmCompatCommandsDocumentationDescription); - this->AllSections["Compatibility Commands"] = sec; - - - this->PropertySections.push_back("Properties of Global Scope"); - this->PropertySections.push_back("Properties on Directories"); - this->PropertySections.push_back("Properties on Targets"); - this->PropertySections.push_back("Properties on Tests"); - this->PropertySections.push_back("Properties on Source Files"); - this->PropertySections.push_back("Properties on Cache Entries"); - - this->VariableSections.push_back("Variables that Provide Information"); - this->VariableSections.push_back("Variables That Change Behavior"); - this->VariableSections.push_back("Variables That Describe the System"); - this->VariableSections.push_back("Variables that Control the Build"); - this->VariableSections.push_back("Variables for Languages"); - + this->addCommonStandardDocSections(); this->ShowGenerators = true; } @@ -559,6 +512,8 @@ bool cmDocumentation::CreateSingleModule(const char* fname, { if(line.size() && line[0] == '#') { + /* line beginnings with ## are mark-up ignore them */ + if (line.size()>=2 && line[1] == '#') continue; // blank line if(line.size() <= 2) { @@ -710,6 +665,410 @@ cmDocumentation::Form cmDocumentation::GetFormFromFilename( } //---------------------------------------------------------------------------- +void cmDocumentation::addCommonStandardDocSections() +{ + cmDocumentationSection *sec; + + sec = new cmDocumentationSection("Author","AUTHOR"); + sec->Append(cmDocumentationEntry + (0, + "This manual page was generated by the \"--help-man\" option.", + 0)); + this->AllSections["Author"] = sec; + + sec = new cmDocumentationSection("Copyright","COPYRIGHT"); + sec->Append(cmDocumentationCopyright); + this->AllSections["Copyright"] = sec; + + sec = new cmDocumentationSection("See Also","SEE ALSO"); + sec->Append(cmDocumentationStandardSeeAlso); + this->AllSections["Standard See Also"] = sec; + + sec = new cmDocumentationSection("Options","OPTIONS"); + sec->Append(cmDocumentationStandardOptions); + this->AllSections["Options"] = sec; + + sec = new cmDocumentationSection("Compatibility Commands", + "COMPATIBILITY COMMANDS"); + sec->Append(cmCompatCommandsDocumentationDescription); + this->AllSections["Compatibility Commands"] = sec; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::addCMakeStandardDocSections() +{ + cmDocumentationSection *sec; + + sec = new cmDocumentationSection("Properties","PROPERTIES"); + sec->Append(cmPropertiesDocumentationDescription); + this->AllSections["Properties Description"] = sec; + + sec = new cmDocumentationSection("Generators","GENERATORS"); + sec->Append(cmDocumentationGeneratorsHeader); + this->AllSections["Generators"] = sec; + + this->PropertySections.push_back("Properties of Global Scope"); + this->PropertySections.push_back("Properties on Directories"); + this->PropertySections.push_back("Properties on Targets"); + this->PropertySections.push_back("Properties on Tests"); + this->PropertySections.push_back("Properties on Source Files"); + this->PropertySections.push_back("Properties on Cache Entries"); + + this->VariableSections.push_back("Variables that Provide Information"); + this->VariableSections.push_back("Variables That Change Behavior"); + this->VariableSections.push_back("Variables That Describe the System"); + this->VariableSections.push_back("Variables that Control the Build"); + this->VariableSections.push_back("Variables for Languages"); + +} + +//---------------------------------------------------------------------------- +void cmDocumentation::addCTestStandardDocSections() +{ + // This is currently done for backward compatibility reason + // We may suppress some of these. + addCMakeStandardDocSections(); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::addCPackStandardDocSections() +{ + cmDocumentationSection *sec; + + sec = new cmDocumentationSection("Generators","GENERATORS"); + sec->Append(cmDocumentationGeneratorsHeader); + this->AllSections["Generators"] = sec; + + this->VariableSections.push_back( + "Variables common to all CPack generators"); + this->VariableSections.push_back( + "Variables specific to a CPack generator"); +} + +//---------------------------------------------------------------------------- +int cmDocumentation::getDocumentedModulesListInDir( + std::string path, + std::string globExpr, + documentedModulesList_t& docedModuleList) +{ + cmsys::Glob gl; + std::string findExpr; + std::vector<std::string> files; + std::string line; + documentedModuleSectionPair_t docPair; + int nbDocumentedModules = 0; + + findExpr = path + "/" + globExpr; + if (gl.FindFiles(findExpr)) + { + files = gl.GetFiles(); + for (std::vector<std::string>::iterator itf=files.begin(); + itf!=files.end();++itf) + { + std::ifstream fin((*itf).c_str()); + // file access trouble ignore it (ignore this kind of error) + if (!fin) continue; + /* read first line in order to get doc section */ + if (cmSystemTools::GetLineFromStream(fin, line)) + { + /* Doc section indicates that + * this file has structured doc in it. + */ + if (line.find("##section")!=std::string::npos) + { + // ok found one more documented module + ++nbDocumentedModules; + docPair.first = *itf; + // 10 is the size of '##section' + 1 + docPair.second = line.substr(10,std::string::npos); + docedModuleList.push_back(docPair); + } + // No else if no section is found (undocumented module) + } + // No else cannot read first line (ignore this kind of error) + line = ""; + } + } + if (nbDocumentedModules>0) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +static void trim(std::string& s) +{ + std::string::size_type pos = s.find_last_not_of(' '); + if(pos != std::string::npos) + { + s.erase(pos + 1); + pos = s.find_first_not_of(' '); + if(pos != std::string::npos) s.erase(0, pos); + } + else + { + s.erase(s.begin(), s.end()); + } +} + +int cmDocumentation::GetStructuredDocFromFile( + const char* fname, + std::vector<cmDocumentationEntry>& commands, + cmake* cm, + const char *docSection) +{ + typedef enum sdoce { + SDOC_NONE, SDOC_MODULE, SDOC_MACRO, SDOC_FUNCTION, SDOC_VARIABLE, + SDOC_SECTION, + SDOC_UNKNOWN} sdoc_t; + int nbDocItemFound = 0; + int docCtxIdx = 0; + std::vector<int> docContextStack(60); + docContextStack[docCtxIdx]=SDOC_NONE; + cmDocumentationEntry e; + std::ifstream fin(fname); + if(!fin) + { + return nbDocItemFound; + } + std::string name; + std::string full; + std::string brief; + std::string line; + bool newCtx = false; /* we've just entered ##<beginkey> context */ + bool inBrief = false; /* we are currently parsing brief desc. */ + bool inFullFirstParagraph = false; /* we are currently parsing full + desc. first paragraph */ + brief = ""; + full = ""; + bool newParagraph = true; + while ( fin && cmSystemTools::GetLineFromStream(fin, line) ) + { + if(line.size() && line[0] == '#') + { + /* handle structured doc context */ + if ((line.size()>=2) && line[1]=='#') + { + /* markup word is following '##' stopping at first space + * Some markup word like 'section' may have more characters + * following but we don't handle those here. + */ + std::string mkword = line.substr(2,line.find(' ',2)-2); + if (mkword=="macro") + { + docCtxIdx++; + docContextStack[docCtxIdx]=SDOC_MACRO; + newCtx = true; + } + else if (mkword=="variable") + { + docCtxIdx++; + docContextStack[docCtxIdx]=SDOC_VARIABLE; + newCtx = true; + } + else if (mkword=="function") + { + docCtxIdx++; + docContextStack[docCtxIdx]=SDOC_FUNCTION; + newCtx = true; + } + else if (mkword=="module") + { + docCtxIdx++; + docContextStack[docCtxIdx]=SDOC_MODULE; + newCtx = true; + } + else if (mkword=="section") + { + docCtxIdx++; + docContextStack[docCtxIdx]=SDOC_SECTION; + /* drop the rest of the line */ + line = ""; + newCtx = true; + } + else if (mkword.substr(0,3)=="end") + { + switch (docContextStack[docCtxIdx]) { + case SDOC_MACRO: + /* for now MACRO and FUNCTION are handled in the same way */ + case SDOC_FUNCTION: + commands.push_back(cmDocumentationEntry(name.c_str(), + brief.c_str(),full.c_str())); + break; + case SDOC_VARIABLE: + cm->DefineProperty + (name.c_str(), cmProperty::VARIABLE, + brief.c_str(), + full.c_str(),false, + docSection); + break; + case SDOC_MODULE: + /* not implemented */ + break; + case SDOC_SECTION: + /* not implemented */ + break; + default: + /* ignore other cases */ + break; + } + docCtxIdx--; + newCtx = false; + ++nbDocItemFound; + } + else + { + // error out unhandled context + return nbDocItemFound; + } + /* context is set go to next doc line */ + continue; + } + + // Now parse the text attached to the context + + // The first line after the context mark-up contains:: + // name - brief until. (brief is dot terminated or + // followed by a blank line) + if (newCtx) + { + // no brief (for easy variable definition) + if (line.find("-")==std::string::npos) + { + name = line.substr(1,std::string::npos); + trim(name); + brief = ""; + inBrief = false; + full = ""; + } + // here we have a name and brief beginning + else + { + name = line.substr(1,line.find("-")-1); + trim(name); + // we are parsing the brief context + brief = line.substr(line.find("-")+1,std::string::npos); + trim(brief); + // Brief may already be terminated on the first line + if (brief.find('.')!=std::string::npos) + { + inBrief = false; + full = brief.substr(brief.find('.')+1,std::string::npos); + trim(full); + inFullFirstParagraph = true; + brief = brief.substr(0,brief.find('.')); + } + // brief is continued on following lines + else + { + inBrief = true; + full = ""; + } + } + newCtx = false; + continue; + } + // blank line + if(line.size() <= 2) + { + if (inBrief) { + inBrief = false; + full = ""; + } else { + if (full.length()>0) + { + full += "\n"; + } + // the first paragraph of full has ended + inFullFirstParagraph = false; + } + newParagraph = true; + } + // brief is terminated by '.' + else if (inBrief && (line.find('.')!=std::string::npos)) + { + /* the brief just ended */ + inBrief = false; + std::string endBrief = line.substr(1,line.find('.')); + trim(endBrief); + trim(brief); + brief += " " + endBrief; + full += line.substr(line.find('.')+1,std::string::npos); + trim(full); + inFullFirstParagraph = true; + } + // we handle full text or multi-line brief. + else + { + std::string* text; + if (inBrief) + { + text = &brief; + } + else + { + text = &full; + } + // two spaces + if(line[1] == ' ' && line[2] == ' ') + { + // there is no "full first paragraph at all." + if (line[3] == ' ') + { + inFullFirstParagraph = false; + } + + if(!newParagraph && !inFullFirstParagraph) + { + *text += "\n"; + newParagraph = true; + } + // Skip #, and leave space for pre-formatted + if (inFullFirstParagraph) + { + std::string temp = line.c_str()+1; + trim(temp); + *text += " " + temp; + } + else + { + *text += line.c_str()+1; + *text += "\n"; + } + } + else if(line[1] == ' ') + { + if(!newParagraph) + { + *text += " "; + } + newParagraph = false; + // skip # and space + *text += line.c_str()+2; + } + else + { + if(!newParagraph) + { + *text += " "; + } + newParagraph = false; + // skip # + *text += line.c_str()+1; + } + } + } + /* next line is not the first context line */ + newCtx = false; + } + return nbDocItemFound; +} + +//---------------------------------------------------------------------------- bool cmDocumentation::CheckOptions(int argc, const char* const* argv, const char* exitOpt) { diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 34b83b1..00dba1a 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -21,6 +21,7 @@ #include "cmDocumentationFormatterText.h" #include "cmDocumentationFormatterUsage.h" #include "cmDocumentationSection.h" +#include "cmake.h" namespace cmsys { @@ -34,6 +35,21 @@ public: cmDocumentation(); ~cmDocumentation(); + + /** + * An helper type pair for [structured] documented modules. + * The comment of those module contains structure markup + * which makes it possible to retrieve the documentation + * of variables, macros and functions defined in the module. + * - first is the filename of the module + * - second is the section of the doc the module belongs too + */ + typedef std::pair<std::string,std::string> documentedModuleSectionPair_t; + /** + * A list of documented module(s). + */ + typedef std::list<documentedModuleSectionPair_t> documentedModulesList_t; + // High-level interface for standard documents: /** @@ -119,6 +135,58 @@ public: static Form GetFormFromFilename(const std::string& filename); + /** Add common (to all tools) documentation section(s) */ + void addCommonStandardDocSections(); + + /** Add the CMake standard documentation section(s) */ + void addCMakeStandardDocSections(); + + /** Add the CTest standard documentation section(s) */ + void addCTestStandardDocSections(); + + /** Add the CPack standard documentation section(s) */ + void addCPackStandardDocSections(); + + /** + * Retrieve the list of documented module located in + * path which match the globing expression globExpr. + * @param[in] path, directory where to start the search + * we will recurse into it. + * @param[in] globExpr, the globing expression used to + * match the file in path. + * @param[out] the list of obtained pairs (may be empty) + * @return 0 on success 1 on error or empty list + */ + int getDocumentedModulesListInDir( + std::string path, + std::string globExpr, + documentedModulesList_t& docModuleList); + + /** + * Get the documentation of macros, functions and variable documented + * with CMake structured documentation in a CMake script. + * (in fact it may be in any file which follow the structured doc format) + * Structured documentation begin with + * ## (double sharp) in column 1 & 2 immediately followed + * by a markup. Those ## are ignored by the legacy module + * documentation parser @see CreateSingleModule. + * Current markup are ##section, ##module, + * ##macro, ##function, ##variable and ##end. + * ##end is closing either of the previous ones. + * @param[in] fname the script file name to be parsed for documentation + * @param[in,out] commands the vector of command/macros documentation + * entry found in the script file. + * @param[in,out] the cmake object instance to which variable documentation + * will be attached (using @see cmake::DefineProperty) + * @param[in] the documentation section in which the property will be + * inserted. + * @return the number of documented items (command and variable) + * found in the file. + */ + int GetStructuredDocFromFile(const char* fname, + std::vector<cmDocumentationEntry>& commands, + cmake* cm, + const char *docSection); private: void SetForm(Form f); void SetDocName(const char* docname); diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index ec4fd16..7a80a1c 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -23,6 +23,17 @@ public: ~cmFunctionHelperCommand() {}; /** + * This is used to avoid including this command + * in documentation. This is mainly used by + * cmMacroHelperCommand and cmFunctionHelperCommand + * which cannot provide appropriate documentation. + */ + virtual bool ShouldAppearInDocumentation() + { + return false; + } + + /** * This is a virtual constructor for the command. */ virtual cmCommand* Clone() diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 774f32b..f81a63d 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -23,6 +23,17 @@ public: ~cmMacroHelperCommand() {}; /** + * This is used to avoid including this command + * in documentation. This is mainly used by + * cmMacroHelperCommand and cmFunctionHelperCommand + * which cannot provide appropriate documentation. + */ + virtual bool ShouldAppearInDocumentation() + { + return false; + } + + /** * This is a virtual constructor for the command. */ virtual cmCommand* Clone() diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 02060ca..15e689b 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -131,6 +131,8 @@ void (*cmSystemTools::s_ErrorCallback)(const char*, const char*, void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*); void* cmSystemTools::s_ErrorCallbackClientData = 0; void* cmSystemTools::s_StdoutCallbackClientData = 0; +bool (*cmSystemTools::s_InterruptCallback)(void*); +void* cmSystemTools::s_InterruptCallbackClientData = 0; // replace replace with with as many times as it shows up in source. // write the result into source. @@ -220,6 +222,20 @@ void cmSystemTools::Error(const char* m1, const char* m2, cmSystemTools::Message(message.c_str(),"Error"); } +void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData) +{ + s_InterruptCallback = f; + s_InterruptCallbackClientData = clientData; +} + +bool cmSystemTools::GetInterruptFlag() +{ + if(s_InterruptCallback) + { + return (*s_InterruptCallback)(s_InterruptCallbackClientData); + } + return false; +} void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 2137340..7afc701 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -78,6 +78,11 @@ public: ///! Send a string to stderr. Stdout callbacks will not be invoced. static void Stderr(const char* s, int length); + + typedef bool (*InterruptCallback)(void*); + static void SetInterruptCallback(InterruptCallback f, void* clientData=0); + static bool GetInterruptFlag(); + ///! Return true if there was an error at any point. static bool GetErrorOccuredFlag() { @@ -96,7 +101,7 @@ public: ///! Return true if there was an error at any point. static bool GetFatalErrorOccured() { - return cmSystemTools::s_FatalErrorOccured; + return cmSystemTools::s_FatalErrorOccured || GetInterruptFlag(); } ///! Set the error occured flag and fatal error back to false @@ -467,8 +472,10 @@ private: static bool s_DisableRunCommandOutput; static ErrorCallback s_ErrorCallback; static StdoutCallback s_StdoutCallback; + static InterruptCallback s_InterruptCallback; static void* s_ErrorCallbackClientData; static void* s_StdoutCallbackClientData; + static void* s_InterruptCallbackClientData; static std::string s_Windows9xComspecSubstitute; }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 71dca3a..cce5080 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2660,7 +2660,9 @@ void cmake::GetCommandDocumentation(std::vector<cmDocumentationEntry>& v, j != this->Commands.end(); ++j) { if ((( withCompatCommands == false) && ( (*j).second->IsDiscouraged())) - || ((withCurrentCommands == false) && (!(*j).second->IsDiscouraged()))) + || ((withCurrentCommands == false) && (!(*j).second->IsDiscouraged())) + || (!((*j).second->ShouldAppearInDocumentation())) + ) { continue; } diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 436236d..c3de8ca 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -355,6 +355,7 @@ int do_cmake(int ac, char** av) #ifdef CMAKE_BUILD_WITH_CMAKE cmDocumentation doc; + doc.addCMakeStandardDocSections(); if(doc.CheckOptions(ac, av, "-E") || nocwd) { // Construct and print requested documentation. diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 85cecea..d41627e 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -291,6 +291,7 @@ int main (int argc, char *argv[]) << "*********************************" << std::endl); } cmDocumentation doc; + doc.addCTestStandardDocSections(); if(doc.CheckOptions(argc, argv) || nocwd) { // Construct and print requested documentation. diff --git a/Source/kwsys/kwsysDateStamp.cmake b/Source/kwsys/kwsysDateStamp.cmake index 7b31670..f50f803 100644 --- a/Source/kwsys/kwsysDateStamp.cmake +++ b/Source/kwsys/kwsysDateStamp.cmake @@ -18,4 +18,4 @@ SET(KWSYS_DATE_STAMP_YEAR 2012) SET(KWSYS_DATE_STAMP_MONTH 02) # KWSys version date day component. Format is DD. -SET(KWSYS_DATE_STAMP_DAY 09) +SET(KWSYS_DATE_STAMP_DAY 14) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 906b40d..9c97828 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -163,6 +163,32 @@ 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) + 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) ADD_TEST_MACRO(IPO COnly/COnly) diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index 33c426a..4407efb 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -17,6 +17,8 @@ add_CMakeOnly_test(CheckCXXSymbolExists) add_CMakeOnly_test(CheckCXXCompilerFlag) +add_CMakeOnly_test(CheckLanguage) + add_CMakeOnly_test(AllFindModules) add_CMakeOnly_test(TargetScope) diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt new file mode 100644 index 0000000..f5336dc --- /dev/null +++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required (VERSION 2.8) +project(CheckLanguage NONE) +include(CheckLanguage) + +set(langs ) +set(expect_C 1) +set(expect_CXX 1) +unset(expect_Fortran) +set(expect_NoSuchLanguage 0) +foreach(lang C CXX Fortran NoSuchLanguage) + check_language(${lang}) + if(NOT DEFINED CMAKE_${lang}_COMPILER) + message(FATAL_ERROR "check_language(${lang}) did not set result") + endif() + if(DEFINED expect_${lang}) + if(expect_${lang} AND NOT CMAKE_${lang}_COMPILER) + message(FATAL_ERROR "check_language(${lang}) should not fail!") + elseif(NOT expect_${lang} AND CMAKE_${lang}_COMPILER) + message(FATAL_ERROR "check_language(${lang}) should not succeed!") + endif() + endif() +endforeach() diff --git a/Tests/VSGNUFortran/CMakeLists.txt b/Tests/VSGNUFortran/CMakeLists.txt new file mode 100644 index 0000000..229c315 --- /dev/null +++ b/Tests/VSGNUFortran/CMakeLists.txt @@ -0,0 +1,26 @@ +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 +# to be in the same directory. +if(CMAKE_CONFIGURATION_TYPES) + foreach(config ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER "${config}" config) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config} + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + endforeach() +endif() + +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 +# 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 0000000..27d22fd --- /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 0000000..391bf26 --- /dev/null +++ b/Tests/VSGNUFortran/c_code/main.c @@ -0,0 +1,7 @@ +#include <HelloWorldFCMangle.h> // created by FortranCInterface +extern void FC_hello(void); +int main() +{ + FC_hello(); + return 0; +} diff --git a/Tests/VSGNUFortran/runtest.cmake.in b/Tests/VSGNUFortran/runtest.cmake.in new file mode 100644 index 0000000..987207b --- /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() diff --git a/Tests/VSGNUFortran/subdir/CMakeLists.txt b/Tests/VSGNUFortran/subdir/CMakeLists.txt new file mode 100644 index 0000000..0b99199 --- /dev/null +++ b/Tests/VSGNUFortran/subdir/CMakeLists.txt @@ -0,0 +1,16 @@ +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 + NO_EXTERNAL_INSTALL + ) diff --git a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt new file mode 100644 index 0000000..3ee1855 --- /dev/null +++ b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt @@ -0,0 +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() diff --git a/Tests/VSGNUFortran/subdir/fortran/hello.f b/Tests/VSGNUFortran/subdir/fortran/hello.f new file mode 100644 index 0000000..e52119a --- /dev/null +++ b/Tests/VSGNUFortran/subdir/fortran/hello.f @@ -0,0 +1,7 @@ +!DEC$ ATTRIBUTES DLLEXPORT :: HELLO + SUBROUTINE HELLO + + PRINT *, 'Hello' + CALL WORLD + + END diff --git a/Tests/VSGNUFortran/subdir/fortran/world.f b/Tests/VSGNUFortran/subdir/fortran/world.f new file mode 100644 index 0000000..0598eee --- /dev/null +++ b/Tests/VSGNUFortran/subdir/fortran/world.f @@ -0,0 +1,6 @@ +!DEC$ ATTRIBUTES DLLEXPORT :: WORLD + SUBROUTINE WORLD + + PRINT *, 'World!' + + END |