summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Auxiliary/bash-completion/cmake2
-rw-r--r--Help/manual/cmake-modules.7.rst1
-rw-r--r--Help/manual/cmake.1.rst57
-rw-r--r--Help/module/FindEnvModules.rst1
-rw-r--r--Help/policy/CMP0082.rst8
-rw-r--r--Help/release/dev/FindGLEW-updates.rst5
-rw-r--r--Help/release/dev/cmake--install_option.rst6
-rw-r--r--Help/release/dev/cmake-e-tar-creating-archive.rst6
-rw-r--r--Help/release/dev/cuda-compiler-generator-expressions.rst5
-rw-r--r--Help/release/dev/environment-modules.rst5
-rw-r--r--Modules/CMakeCheckCompilerFlagCommonPatterns.cmake1
-rw-r--r--Modules/CMakeCompilerIdDetection.cmake2
-rw-r--r--Modules/CheckTypeSize.c.in2
-rw-r--r--Modules/ExternalProject.cmake118
-rw-r--r--Modules/FindBLAS.cmake26
-rw-r--r--Modules/FindEnvModules.cmake333
-rw-r--r--Modules/FindGLEW.cmake302
-rw-r--r--Source/CMakeLists.txt8
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx3
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx10
-rw-r--r--Source/cmArchiveWrite.cxx11
-rw-r--r--Source/cmDepends.cxx9
-rw-r--r--Source/cmDepends.h9
-rw-r--r--Source/cmDependsC.cxx16
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx5
-rw-r--r--Source/cmFileCopier.cxx2
-rw-r--r--Source/cmFileCopier.h4
-rw-r--r--Source/cmFileTime.cxx49
-rw-r--r--Source/cmFileTime.h130
-rw-r--r--Source/cmFileTimeCache.cxx57
-rw-r--r--Source/cmFileTimeCache.h51
-rw-r--r--Source/cmFileTimeComparison.cxx233
-rw-r--r--Source/cmFileTimeComparison.h45
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx2
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx3
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx10
-rw-r--r--Source/cmGlobalXCodeGenerator.h4
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx17
-rw-r--r--Source/cmQtAutoGen.cxx2
-rw-r--r--Source/cmQtAutoGenerator.cxx6
-rw-r--r--Source/cmQtAutoGenerator.h6
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx2
-rw-r--r--Source/cmSystemTools.cxx40
-rw-r--r--Source/cmSystemTools.h6
-rw-r--r--Source/cm_utf8.c29
-rw-r--r--Source/cm_utf8.h4
-rw-r--r--Source/cmake.cxx43
-rw-r--r--Source/cmake.h6
-rw-r--r--Source/cmakemain.cxx125
-rw-r--r--Source/cmcmd.cxx4
-rw-r--r--Tests/CMakeLib/testUTF8.cxx104
-rw-r--r--Tests/CMakeLists.txt8
-rw-r--r--Tests/FindEnvModules/CMakeLists.txt3
-rw-r--r--Tests/FindEnvModules/EnvModules.cmake35
-rw-r--r--Tests/FindGLEW/CMakeLists.txt10
-rw-r--r--Tests/FindGLEW/Test/CMakeLists.txt18
-rw-r--r--Tests/FindGLEW/Test/main.cpp8
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake15
-rw-r--r--Tests/RunCMake/CommandLine/install-bad-dir-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/install-no-dir-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/install-no-dir-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/install-options-to-vars-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt4
-rw-r--r--Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/CommandLineTar/bad-file-result.txt1
-rw-r--r--Tests/RunCMake/CommandLineTar/bad-file-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLineTar/test-file.txt0
-rw-r--r--Tests/RunCMake/CommandLineTar/without-files-stderr.txt1
-rw-r--r--Utilities/cmzstd/CMakeLists.txt3
-rwxr-xr-xbootstrap3
78 files changed, 1545 insertions, 535 deletions
diff --git a/Auxiliary/bash-completion/cmake b/Auxiliary/bash-completion/cmake
index 5d67b0b..8c0c5e8 100644
--- a/Auxiliary/bash-completion/cmake
+++ b/Auxiliary/bash-completion/cmake
@@ -96,7 +96,7 @@ _cmake()
_filedir
return
;;
- --build|--open)
+ --build|--install|--open)
_filedir -d
return
;;
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index d9b939f..fc4bfdc 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -125,6 +125,7 @@ They are normally called through the :command:`find_package` command.
/module/FindDCMTK
/module/FindDevIL
/module/FindDoxygen
+ /module/FindEnvModules
/module/FindEXPAT
/module/FindFLEX
/module/FindFLTK2
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index a3c7834..b67fa3a 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -16,6 +16,9 @@ Synopsis
`Build a Project`_
cmake --build <dir> [<options>] [-- <build-tool-options>]
+ `Install a Project`_
+ cmake --install <dir> [<options>]
+
`Open a Project`_
cmake --open <dir>
@@ -39,8 +42,8 @@ buildsystem generator CMake. The above `Synopsis`_ lists various actions
the tool can perform as described in sections below.
To build a software project with CMake, `Generate a Project Buildsystem`_.
-Optionally use **cmake** to `Build a Project`_ or just run the
-corresponding build tool (e.g. ``make``) directly. **cmake** can also
+Optionally use **cmake** to `Build a Project`_, `Install a Project`_ or just
+run the corresponding build tool (e.g. ``make``) directly. **cmake** can also
be used to `View Help`_.
The other actions are meant for use by software developers writing
@@ -302,6 +305,41 @@ following options:
Run ``cmake --build`` with no options for quick help.
+Install a Project
+=================
+
+CMake provides a command-line signature to install an already-generated
+project binary tree:
+
+.. code-block:: shell
+
+ cmake --install <dir> [<options>]
+
+This may be used after building a project to run installation without
+using the generated build system or the native build tool.
+The options are:
+
+``--install <dir>``
+ Project binary directory to install. This is required and must be first.
+
+``--config <cfg>``
+ For multi-configuration tools, choose configuration ``<cfg>``.
+
+``--component <comp>``
+ Component-based install. Only install component ``<comp>``.
+
+``--prefix <prefix>``
+ The installation prefix CMAKE_INSTALL_PREFIX.
+
+``--strip``
+ Strip before installing by setting CMAKE_INSTALL_DO_STRIP.
+
+``-v, --verbose``
+ Enable verbose output.
+
+ This option can be omitted if :envvar:`VERBOSE` environment variable is set.
+
+Run ``cmake --install`` with no options for quick help.
Open a Project
==============
@@ -483,6 +521,21 @@ Available commands are:
``tar [cxt][vf][zjJ] file.tar [<options>] [--] [<file>...]``
Create or extract a tar or zip archive. Options are:
+ ``c``
+ Create a new archive containing the specified files.
+ If used, the <file> argument is mandatory.
+ ``x``
+ Extract to disk from the archive.
+ ``t``
+ List archive contents to stdout.
+ ``v``
+ Produce verbose output.
+ ``z``
+ Compress the resulting archive with gzip.
+ ``j``
+ Compress the resulting archive with bzip2.
+ ``J``
+ Compress the resulting archive with XZ.
``--``
Stop interpreting options and treat all remaining arguments
as file names even if they start in ``-``.
diff --git a/Help/module/FindEnvModules.rst b/Help/module/FindEnvModules.rst
new file mode 100644
index 0000000..72c120f
--- /dev/null
+++ b/Help/module/FindEnvModules.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindEnvModules.cmake
diff --git a/Help/policy/CMP0082.rst b/Help/policy/CMP0082.rst
index 7b2ef04..8256444 100644
--- a/Help/policy/CMP0082.rst
+++ b/Help/policy/CMP0082.rst
@@ -6,9 +6,11 @@ those in caller.
CMake 3.13 and lower ran the install rules from :command:`add_subdirectory`
after all other install rules, even if :command:`add_subdirectory` was called
-before the other install rules. CMake 3.14 and later interleaves these
-:command:`add_subdirectory` install rules with the others so that they are
-run in the order they are declared.
+before the other install rules. CMake 3.14 and above prefer to interleave
+these :command:`add_subdirectory` install rules with the others so that
+they are run in the order they are declared. This policy provides
+compatibility for projects that have not been updated to expect the
+new behavior.
The ``OLD`` behavior for this policy is to run the install rules from
:command:`add_subdirectory` after the other install rules. The ``NEW``
diff --git a/Help/release/dev/FindGLEW-updates.rst b/Help/release/dev/FindGLEW-updates.rst
new file mode 100644
index 0000000..6487052
--- /dev/null
+++ b/Help/release/dev/FindGLEW-updates.rst
@@ -0,0 +1,5 @@
+FindGLEW-updates
+----------------
+
+* The :module:`FindGLEW` module now provides an interface more consistent
+ with what upstream GLEW provides in its own CMake package files.
diff --git a/Help/release/dev/cmake--install_option.rst b/Help/release/dev/cmake--install_option.rst
new file mode 100644
index 0000000..8e526a0
--- /dev/null
+++ b/Help/release/dev/cmake--install_option.rst
@@ -0,0 +1,6 @@
+cmake--install-option
+---------------------
+
+* A new ``--install`` option was added to :manual:`cmake(1)`.
+ This may be used after building a project to run installation without
+ using the generated build system or the native build tool.
diff --git a/Help/release/dev/cmake-e-tar-creating-archive.rst b/Help/release/dev/cmake-e-tar-creating-archive.rst
new file mode 100644
index 0000000..717855c
--- /dev/null
+++ b/Help/release/dev/cmake-e-tar-creating-archive.rst
@@ -0,0 +1,6 @@
+cmake-e-tar-creating-archive
+----------------------------
+
+* The :manual:`cmake(1)` ``-E tar`` tool now continues adding files to an
+ archive, even if some of the files aren't readable. This behavior is more
+ consistent with the classic ``tar`` tool.
diff --git a/Help/release/dev/cuda-compiler-generator-expressions.rst b/Help/release/dev/cuda-compiler-generator-expressions.rst
new file mode 100644
index 0000000..2610a39
--- /dev/null
+++ b/Help/release/dev/cuda-compiler-generator-expressions.rst
@@ -0,0 +1,5 @@
+cuda-compiler-generator-expressions
+-----------------------------------
+
+* The ``$<CUDA_COMPILER_ID:...>`` and ``$<CUDA_COMPILER_VERSION:...>``
+ :manual:`generator expressions <cmake-generator-expressions(7)>` were added.
diff --git a/Help/release/dev/environment-modules.rst b/Help/release/dev/environment-modules.rst
new file mode 100644
index 0000000..eace35d
--- /dev/null
+++ b/Help/release/dev/environment-modules.rst
@@ -0,0 +1,5 @@
+environment-modules
+-------------------
+
+* The :module:`FindEnvModules` module was added to use Lua- and TCL-based
+ environment modules in :ref:`CTest Scripts <CTest Script>`.
diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
index e60ffe0..5b9ed34 100644
--- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
+++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
@@ -30,5 +30,6 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR)
FAIL_REGEX "Incorrect command line option:" # Borland
FAIL_REGEX "Warning: illegal option" # SunStudio 12
FAIL_REGEX "[Ww]arning: Invalid suboption" # Fujitsu
+ FAIL_REGEX "An invalid option .* appears on the command line" # Cray
)
endmacro ()
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index 7aac846..ed288f5 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -74,13 +74,13 @@ function(compiler_id_detection outvar lang)
endif()
list(APPEND ordered_compilers
SCO
+ ARMCC
AppleClang
Clang
GNU
MSVC
ADSP
IAR
- ARMCC
)
if (lang STREQUAL C)
list(APPEND ordered_compilers
diff --git a/Modules/CheckTypeSize.c.in b/Modules/CheckTypeSize.c.in
index 2303c4e..82035a3 100644
--- a/Modules/CheckTypeSize.c.in
+++ b/Modules/CheckTypeSize.c.in
@@ -18,7 +18,7 @@
#endif
#define SIZE (sizeof(@type@))
-char info_size[] = {'I', 'N', 'F', 'O', ':', 's','i','z','e','[',
+static char info_size[] = {'I', 'N', 'F', 'O', ':', 's','i','z','e','[',
('0' + ((SIZE / 10000)%10)),
('0' + ((SIZE / 1000)%10)),
('0' + ((SIZE / 100)%10)),
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 22e0523..948b921 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -251,6 +251,9 @@ External Project Definition
The lack of such deterministic behavior makes the main project lose
traceability and repeatability.
+ If ``GIT_SHALLOW`` is enabled then ``GIT_TAG`` works only with
+ branch names and tags. A commit hash is not allowed.
+
``GIT_REMOTE_NAME <name>``
The optional name of the remote. If this option is not specified, it
defaults to ``origin``.
@@ -1053,11 +1056,6 @@ define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED
)
function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify)
- if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10)
- set(git_clone_shallow_options "--depth 1 --no-single-branch")
- else()
- set(git_clone_shallow_options "--depth 1")
- endif()
if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
# Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
set(git_checkout_explicit-- "--")
@@ -1067,18 +1065,41 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git
# because that will not search for remote branch names, a common use case.
set(git_checkout_explicit-- "")
endif()
- file(WRITE ${script_filename}
-"if(\"${git_tag}\" STREQUAL \"\")
- message(FATAL_ERROR \"Tag for git checkout should not be empty.\")
-endif()
+ if("${git_tag}" STREQUAL "")
+ message(FATAL_ERROR "Tag for git checkout should not be empty.")
+ endif()
+
+ set(git_clone_options)
+ if(git_shallow)
+ if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10)
+ list(APPEND git_clone_options "--depth 1 --no-single-branch")
+ else()
+ list(APPEND git_clone_options "--depth 1")
+ endif()
+ endif()
+ if(git_progress)
+ list(APPEND git_clone_options --progress)
+ endif()
+ foreach(config IN LISTS git_config)
+ list(APPEND git_clone_options --config ${config})
+ endforeach()
+ if(NOT ${git_remote_name} STREQUAL "origin")
+ list(APPEND git_clone_options --origin \"${git_remote_name}\")
+ endif()
-set(run 0)
+ string (REPLACE ";" " " git_clone_options "${git_clone_options}")
-if(\"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\")
- set(run 1)
-endif()
+ set(git_options)
+ # disable cert checking if explicitly told not to do it
+ if(NOT "x${tls_verify}" STREQUAL "x" AND NOT tls_verify)
+ set(git_options
+ -c http.sslVerify=false)
+ endif()
+ string (REPLACE ";" " " git_options "${git_options}")
-if(NOT run)
+ file(WRITE ${script_filename}
+"
+if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\")
message(STATUS \"Avoiding repeated git clone, stamp file is up to date: '${gitclone_stampfile}'\")
return()
endif()
@@ -1091,38 +1112,12 @@ if(error_code)
message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\")
endif()
-set(git_options)
-
-# disable cert checking if explicitly told not to do it
-set(tls_verify \"${tls_verify}\")
-if(NOT \"x${tls_verify}\" STREQUAL \"x\" AND NOT tls_verify)
- list(APPEND git_options
- -c http.sslVerify=false)
-endif()
-
-set(git_clone_options)
-
-set(git_shallow \"${git_shallow}\")
-if(git_shallow)
- list(APPEND git_clone_options ${git_clone_shallow_options})
-endif()
-
-set(git_progress \"${git_progress}\")
-if(git_progress)
- list(APPEND git_clone_options --progress)
-endif()
-
-set(git_config \"${git_config}\")
-foreach(config IN LISTS git_config)
- list(APPEND git_clone_options --config \${config})
-endforeach()
-
# try the clone 3 times in case there is an odd git clone issue
set(error_code 1)
set(number_of_tries 0)
while(error_code AND number_of_tries LESS 3)
execute_process(
- COMMAND \"${git_EXECUTABLE}\" \${git_options} clone \${git_clone_options} --origin \"${git_remote_name}\" \"${git_repository}\" \"${src_name}\"
+ COMMAND \"${git_EXECUTABLE}\" ${git_options} clone ${git_clone_options} \"${git_repository}\" \"${src_name}\"
WORKING_DIRECTORY \"${work_dir}\"
RESULT_VARIABLE error_code
)
@@ -1137,7 +1132,7 @@ if(error_code)
endif()
execute_process(
- COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} ${git_checkout_explicit--}
+ COMMAND \"${git_EXECUTABLE}\" ${git_options} checkout ${git_tag} ${git_checkout_explicit--}
WORKING_DIRECTORY \"${work_dir}/${src_name}\"
RESULT_VARIABLE error_code
)
@@ -1146,16 +1141,7 @@ if(error_code)
endif()
execute_process(
- COMMAND \"${git_EXECUTABLE}\" \${git_options} submodule init ${git_submodules}
- WORKING_DIRECTORY \"${work_dir}/${src_name}\"
- RESULT_VARIABLE error_code
- )
-if(error_code)
- message(FATAL_ERROR \"Failed to init submodules in: '${work_dir}/${src_name}'\")
-endif()
-
-execute_process(
- COMMAND \"${git_EXECUTABLE}\" \${git_options} submodule update --recursive --init ${git_submodules}
+ COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules}
WORKING_DIRECTORY \"${work_dir}/${src_name}\"
RESULT_VARIABLE error_code
)
@@ -1169,7 +1155,6 @@ execute_process(
COMMAND \${CMAKE_COMMAND} -E copy
\"${gitclone_infofile}\"
\"${gitclone_stampfile}\"
- WORKING_DIRECTORY \"${work_dir}/${src_name}\"
RESULT_VARIABLE error_code
)
if(error_code)
@@ -1182,18 +1167,12 @@ endif()
endfunction()
function(_ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile)
+ if("${hg_tag}" STREQUAL "")
+ message(FATAL_ERROR "Tag for hg checkout should not be empty.")
+ endif()
file(WRITE ${script_filename}
-"if(\"${hg_tag}\" STREQUAL \"\")
- message(FATAL_ERROR \"Tag for hg checkout should not be empty.\")
-endif()
-
-set(run 0)
-
-if(\"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\")
- set(run 1)
-endif()
-
-if(NOT run)
+"
+if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\")
message(STATUS \"Avoiding repeated hg clone, stamp file is up to date: '${hgclone_stampfile}'\")
return()
endif()
@@ -1230,7 +1209,6 @@ execute_process(
COMMAND \${CMAKE_COMMAND} -E copy
\"${hgclone_infofile}\"
\"${hgclone_stampfile}\"
- WORKING_DIRECTORY \"${work_dir}/${src_name}\"
RESULT_VARIABLE error_code
)
if(error_code)
@@ -1244,16 +1222,16 @@ endfunction()
function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name git_submodules git_repository work_dir)
+ if("${git_tag}" STREQUAL "")
+ message(FATAL_ERROR "Tag for git checkout should not be empty.")
+ endif()
if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.6)
set(git_stash_save_options --all --quiet)
else()
set(git_stash_save_options --quiet)
endif()
file(WRITE ${script_filename}
-"if(\"${git_tag}\" STREQUAL \"\")
- message(FATAL_ERROR \"Tag for git checkout should not be empty.\")
-endif()
-
+"
execute_process(
COMMAND \"${git_EXECUTABLE}\" rev-list --max-count=1 HEAD
WORKING_DIRECTORY \"${work_dir}\"
@@ -2460,7 +2438,7 @@ function(_ep_add_download_command name)
#
set(repository ${git_repository})
set(module)
- set(tag)
+ set(tag ${git_remote_name})
configure_file(
"${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
"${stamp_dir}/${name}-gitinfo.txt"
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 0aa4f50..bfa449f 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -83,6 +83,13 @@ This module defines the following variables:
set(BLA_VENDOR Intel10_64lp)
find_package(BLAS)
+
+Hints
+^^^^^
+
+Set ``MKLROOT`` environment variable to a directory that contains an MKL
+installation.
+
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake)
@@ -394,6 +401,24 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
endif ()
endif ()
+ if (DEFINED ENV{MKLROOT})
+ set(_BLAS_MKLROOT_LIB_DIR "$ENV{MKLROOT}")
+ endif ()
+ if (_BLAS_MKLROOT_LIB_DIR)
+ if( SIZEOF_INTEGER EQUAL 8 )
+ set( _BLAS_MKL_PATH_PREFIX "intel64" )
+ else()
+ set( _BLAS_MKL_PATH_PREFIX "ia32" )
+ endif()
+ if (WIN32)
+ string(APPEND _BLAS_MKLROOT_LIB_DIR "/lib/${_BLAS_MKL_PATH_PREFIX}_win")
+ elseif (APPLE)
+ string(APPEND _BLAS_MKLROOT_LIB_DIR "/lib/${_BLAS_MKL_PATH_PREFIX}_mac")
+ else ()
+ string(APPEND _BLAS_MKLROOT_LIB_DIR "/lib/${_BLAS_MKL_PATH_PREFIX}_lin")
+ endif ()
+ endif ()
+
foreach (IT ${BLAS_SEARCH_LIBS})
string(REPLACE " " ";" SEARCH_LIBS ${IT})
if (NOT ${_LIBRARIES})
@@ -404,6 +429,7 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
""
"${SEARCH_LIBS}"
"${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}"
+ "${_BLAS_MKLROOT_LIB_DIR}"
)
endif ()
endforeach ()
diff --git a/Modules/FindEnvModules.cmake b/Modules/FindEnvModules.cmake
new file mode 100644
index 0000000..5d3452d
--- /dev/null
+++ b/Modules/FindEnvModules.cmake
@@ -0,0 +1,333 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindEnvModules
+--------------
+
+Locate an environment module implementation and make commands available to
+CMake scripts to use them. This is compatible with both Lua-based Lmod
+and TCL-based EnvironmentModules.
+
+This module is intended for the use case of setting up the compiler and library
+environment within a :ref:`CTest Script <CTest Script>` (``ctest -S``). It can
+also be used in a :ref:`CMake Script <Script Processing Mode>` (``cmake -P``).
+
+.. note::
+
+ The loaded environment will not survive past the end of the calling process.
+ Do not use this module in project code (``CMakeLists.txt`` files) to load
+ a compiler environment; it will not be available during the build. Instead
+ load the environment manually before running CMake or using the generated
+ build system.
+
+Example Usage
+^^^^^^^^^^^^^
+
+.. code-block:: cmake
+
+ set(CTEST_BUILD_NAME "CrayLinux-CrayPE-Cray-dynamic")
+ set(CTEST_BUILD_CONFIGURATION Release)
+ set(CTEST_BUILD_FLAGS "-k -j8")
+ set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
+
+ ...
+
+ find_package(EnvModules REQUIRED)
+
+ env_module(purge)
+ env_module(load modules)
+ env_module(load craype)
+ env_module(load PrgEnv-cray)
+ env_module(load craype-knl)
+ env_module(load cray-mpich)
+ env_module(load cray-libsci)
+
+ set(ENV{CRAYPE_LINK_TYPE} dynamic)
+
+ ...
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project:
+
+``EnvModules_FOUND``
+ Found the a compatible environment modules framework
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+The following cache variable will be set:
+
+``EnvModules_COMMAND``
+ The low level module command to use. Currently supported are
+ implementations are the Lua based Lmod and TCL based EnvironmentModules.
+
+Environment Variables
+^^^^^^^^^^^^^^^^^^^^^
+
+``ENV{MODULESHOME}``
+ Usually set by the module environment implementation, used as a hint to
+ locate the module command to execute.
+
+Provided Functions
+^^^^^^^^^^^^^^^^^^
+
+This defines the following cmake functions for interacting with environment
+modules:
+
+.. command:: env_module
+
+ Execute an aribitrary module command:
+
+ .. code-block:: cmake
+
+ env_module(cmd arg1 ... argN)
+ env_module(
+ COMMAND cmd arg1 ... argN
+ [OUTPUT_VARIABLE <out-var>]
+ [RESULT_VARIABLE <ret-var>]
+ )
+
+ The options are:
+
+ ``cmd arg1 ... argN``
+ The module sub-command and arguments to execute as if they were
+ passed directly to the module command in your shell environment.
+
+ ``OUTPUT_VARIABLE <out-var>``
+ The standard output from executing the module command.
+
+ ``RESULT_VARIABLE <ret-var>``
+ The return code from executing the module command.
+
+.. command:: env_module_swap
+
+ Swap one module for another:
+
+ .. code-block:: cmake
+
+ env_module_swap(out_mod in_mod
+ [OUTPUT_VARIABLE <out-var>]
+ [RESULT_VARIABLE <ret-var>]
+ )
+
+ This is functionally equivalent to the ``module swap out_mod in_mod`` shell
+ command. The options are:
+
+ ``OUTPUT_VARIABLE <out-var>``
+ The standard output from executing the module command.
+
+ ``RESULT_VARIABLE <ret-var>``
+ The return code from executing the module command.
+
+.. command:: env_module_list
+
+ Retrieve the list of currently loaded modules:
+
+ .. code-block:: cmake
+
+ env_module_list(<out-var>)
+
+ This is functionally equivalent to the ``module list`` shell command.
+ The result is stored in ``<out-var>`` as a properly formatted CMake
+ :ref:`semicolon-separated list <CMake Language Lists>` variable.
+
+.. command:: env_module_avail
+
+ Retrieve the list of available modules:
+
+ .. code-block:: cmake
+
+ env_module_avail([<mod-prefix>] <out-var>)
+
+ This is functionally equivalent to the ``module avail <mod-prefix>`` shell
+ command. The result is stored in ``<out-var>`` as a properly formatted
+ CMake :ref:`semicolon-separated list <CMake Language Lists>` variable.
+
+#]=======================================================================]
+
+function(env_module)
+ if(NOT EnvModules_COMMAND)
+ message(FATAL_ERROR "Failed to process module command. EnvModules_COMMAND not found")
+ return()
+ endif()
+
+ set(options)
+ set(oneValueArgs OUTPUT_VARIABLE RESULT_VARIABLE)
+ set(multiValueArgs COMMAND)
+ cmake_parse_arguments(MOD_ARGS
+ "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV}
+ )
+ if(NOT MOD_ARGS_COMMAND)
+ # If no explicit command argument was given, then treat the calling syntax
+ # as: module(cmd args...)
+ set(exec_cmd ${ARGV})
+ else()
+ set(exec_cmd ${MOD_ARGS_COMMAND})
+ endif()
+
+ if(MOD_ARGS_OUTPUT_VARIABLE)
+ set(err_var_args ERROR_VARIABLE err_var)
+ endif()
+
+ execute_process(
+ COMMAND mktemp -t module.cmake.XXXXXXXXXXXX
+ OUTPUT_VARIABLE tempfile_name
+ )
+ string(STRIP "${tempfile_name}" tempfile_name)
+
+ # If the $MODULESHOME/init/cmake file exists then assume that the CMake
+ # "shell" functionality exits
+ if(EXISTS "$ENV{MODULESHOME}/init/cmake")
+ execute_process(
+ COMMAND ${EnvModules_COMMAND} cmake ${exec_cmd}
+ OUTPUT_FILE ${tempfile_name}
+ ${err_var_args}
+ RESULT_VARIABLE ret_var
+ )
+
+ else() # fallback to the sh shell and manually convert to CMake
+ execute_process(
+ COMMAND ${EnvModules_COMMAND} sh ${exec_cmd}
+ OUTPUT_VARIABLE out_var
+ ${err_var_args}
+ RESULT_VARIABLE ret_var
+ )
+ endif()
+
+ # If we executed successfully then process and cleanup the temp file
+ if(ret_var EQUAL 0)
+ # No CMake shell so we need to process the sh output into CMake code
+ if(NOT EXISTS "$ENV{MODULESHOME}/init/cmake")
+ file(WRITE ${tempfile_name} "")
+ string(REPLACE "\n" ";" out_var "${out_var}")
+ foreach(sh_cmd IN LISTS out_var)
+ if(sh_cmd MATCHES "^ *unset *([^ ]*)")
+ set(cmake_cmd "unset(ENV{${CMAKE_MATCH_1}})")
+ elseif(sh_cmd MATCHES "^ *export *([^ ]*)")
+ set(cmake_cmd "set(ENV{${CMAKE_MATCH_1}} \"\${${CMAKE_MATCH_1}}\")")
+ elseif(sh_cmd MATCHES " *([^ =]*) *= *(.*)")
+ set(var_name "${CMAKE_MATCH_1}")
+ set(var_value "${CMAKE_MATCH_2}")
+ if(var_value MATCHES "^\"(.*[^\\])\"")
+ # If it's in quotes, take the value as is
+ set(var_value "${CMAKE_MATCH_1}")
+ else()
+ # Otherwise, strip trailing spaces
+ string(REGEX REPLACE "([^\\])? +$" "\\1" var_value "${var_value}")
+ endif()
+ string(REPLACE "\\ " " " var_value "${var_value}")
+ set(cmake_cmd "set(${var_name} \"${var_value}\")")
+ else()
+ continue()
+ endif()
+ file(APPEND ${tempfile_name} "${cmake_cmd}\n")
+ endforeach()
+ endif()
+
+ # Process the change in environment variables
+ include(${tempfile_name})
+ file(REMOVE ${tempfile_name})
+ endif()
+
+ # Push the output back out to the calling scope
+ if(MOD_ARGS_OUTPUT_VARIABLE)
+ set(${MOD_ARGS_OUTPUT_VARIABLE} "${err_var}" PARENT_SCOPE)
+ endif()
+ if(MOD_ARGS_RESULT_VARIABLE)
+ set(${MOD_ARGS_RESULT_VARIABLE} ${ret_var} PARENT_SCOPE)
+ endif()
+endfunction(env_module)
+
+#------------------------------------------------------------------------------
+function(env_module_swap out_mod in_mod)
+ set(options)
+ set(oneValueArgs OUTPUT_VARIABLE RESULT_VARIABLE)
+ set(multiValueArgs)
+
+ cmake_parse_arguments(MOD_ARGS
+ "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV}
+ )
+
+ env_module(COMMAND -t swap ${out_mod} ${in_mod}
+ OUTPUT_VARIABLE tmp_out
+ RETURN_VARIABLE tmp_ret
+ )
+
+ if(MOD_ARGS_OUTPUT_VARIABLE)
+ set(${MOD_ARGS_OUTPUT_VARIABLE} "${err_var}" PARENT_SCOPE)
+ endif()
+ if(MOD_ARGS_RESULT_VARIABLE)
+ set(${MOD_ARGS_RESULT_VARIABLE} ${tmp_ret} PARENT_SCOPE)
+ endif()
+endfunction()
+
+#------------------------------------------------------------------------------
+function(env_module_list out_var)
+ cmake_policy(SET CMP0007 NEW)
+ env_module(COMMAND -t list OUTPUT_VARIABLE tmp_out)
+
+ # Convert output into a CMake list
+ string(REPLACE "\n" ";" ${out_var} "${tmp_out}")
+
+ # Remove title headers and empty entries
+ list(REMOVE_ITEM ${out_var} "No modules loaded")
+ if(${out_var})
+ list(FILTER ${out_var} EXCLUDE REGEX "^(.*:)?$")
+ endif()
+ list(FILTER ${out_var} EXCLUDE REGEX "^(.*:)?$")
+
+ set(${out_var} ${${out_var}} PARENT_SCOPE)
+endfunction()
+
+#------------------------------------------------------------------------------
+function(env_module_avail)
+ cmake_policy(SET CMP0007 NEW)
+
+ if(ARGC EQUAL 1)
+ set(mod_prefix)
+ set(out_var ${ARGV0})
+ elseif(ARGC EQUAL 2)
+ set(mod_prefix ${ARGV0})
+ set(out_var ${ARGV1})
+ else()
+ message(FATAL_ERROR "Usage: env_module_avail([mod_prefix] out_var)")
+ endif()
+ env_module(COMMAND -t avail ${mod_prefix} OUTPUT_VARIABLE tmp_out)
+
+ # Convert output into a CMake list
+ string(REPLACE "\n" ";" tmp_out "${tmp_out}")
+
+ set(${out_var})
+ foreach(MOD IN LISTS tmp_out)
+ # Remove directory entries and empty values
+ if(MOD MATCHES "^(.*:)?$")
+ continue()
+ endif()
+
+ # Convert default modules
+ if(MOD MATCHES "^(.*)/$" ) # "foo/"
+ list(APPEND ${out_var} ${CMAKE_MATCH_1})
+ elseif(MOD MATCHES "^((.*)/.*)\\(default\\)$") # "foo/1.2.3(default)"
+ list(APPEND ${out_var} ${CMAKE_MATCH_2})
+ list(APPEND ${out_var} ${CMAKE_MATCH_1})
+ else()
+ list(APPEND ${out_var} ${MOD})
+ endif()
+ endforeach()
+
+ set(${out_var} ${${out_var}} PARENT_SCOPE)
+endfunction()
+
+#------------------------------------------------------------------------------
+# Make sure we know where the underlying module command is
+find_program(EnvModules_COMMAND
+ NAMES lmod modulecmd
+ HINTS ENV MODULESHOME
+ PATH_SUFFIXES libexec
+)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(EnvModules DEFAULT_MSG EnvModules_COMMAND)
diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake
index ad8a810..34ee873 100644
--- a/Modules/FindGLEW.cmake
+++ b/Modules/FindGLEW.cmake
@@ -7,64 +7,300 @@ FindGLEW
Find the OpenGL Extension Wrangler Library (GLEW)
-IMPORTED Targets
+Input Variables
+^^^^^^^^^^^^^^^
+
+The following variables may be set to influence this module’s behavior:
+
+``GLEW_USE_STATIC_LIBS``
+ to find and create :prop_tgt:`IMPORTED` target for static linkage.
+
+``GLEW_VERBOSE``
+ to output a detailed log of this module.
+
+Imported Targets
^^^^^^^^^^^^^^^^
-This module defines the :prop_tgt:`IMPORTED` target ``GLEW::GLEW``,
-if GLEW has been found.
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+
+``GLEW::glew``
+ The GLEW shared library.
+``GLEW::glew_s``
+ The GLEW static library, if ``GLEW_USE_STATIC_LIBS`` is set to ``TRUE``.
+``GLEW::GLEW``
+ Duplicates either ``GLEW::glew`` or ``GLEW::glew_s`` based on availability.
Result Variables
^^^^^^^^^^^^^^^^
This module defines the following variables:
-::
+``GLEW_INCLUDE_DIRS``
+ include directories for GLEW
+``GLEW_LIBRARIES``
+ libraries to link against GLEW
+``GLEW_SHARED_LIBRARIES``
+ libraries to link against shared GLEW
+``GLEW_STATIC_LIBRARIES``
+ libraries to link against static GLEW
+``GLEW_FOUND``
+ true if GLEW has been found and can be used
+``GLEW_VERSION``
+ GLEW version
+``GLEW_VERSION_MAJOR``
+ GLEW major version
+``GLEW_VERSION_MINOR``
+ GLEW minor version
+``GLEW_VERSION_MICRO``
+ GLEW micro version
- GLEW_INCLUDE_DIRS - include directories for GLEW
- GLEW_LIBRARIES - libraries to link against GLEW
- GLEW_FOUND - true if GLEW has been found and can be used
#]=======================================================================]
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
+find_package(GLEW CONFIG QUIET)
+
+if(GLEW_FOUND)
+ find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_CONFIG)
+ return()
+endif()
+
+if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: did not find GLEW CMake config file. Searching for libraries.")
+endif()
+
+
+function(__glew_set_find_library_suffix shared_or_static)
+ if(UNIX AND "${shared_or_static}" MATCHES "SHARED")
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" PARENT_SCOPE)
+ elseif(UNIX AND "${shared_or_static}" MATCHES "STATIC")
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" PARENT_SCOPE)
+ elseif(APPLE AND "${shared_or_static}" MATCHES "SHARED")
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib;.so" PARENT_SCOPE)
+ elseif(APPLE AND "${shared_or_static}" MATCHES "STATIC")
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" PARENT_SCOPE)
+ elseif(WIN32 AND "${shared_or_static}" MATCHES "SHARED")
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" PARENT_SCOPE)
+ elseif(WIN32 AND "${shared_or_static}" MATCHES "STATIC")
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib;.dll.a" PARENT_SCOPE)
+ endif()
+
+ if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: CMAKE_FIND_LIBRARY_SUFFIXES for ${shared_or_static}: ${CMAKE_FIND_LIBRARY_SUFFIXES}")
+ endif()
+endfunction()
+
+
+if(GLEW_VERBOSE)
+ if(DEFINED GLEW_USE_STATIC_LIBS)
+ message(STATUS "FindGLEW: GLEW_USE_STATIC_LIBS: ${GLEW_USE_STATIC_LIBS}.")
+ else()
+ message(STATUS "FindGLEW: GLEW_USE_STATIC_LIBS is undefined. Treated as FALSE.")
+ endif()
+endif()
+
find_path(GLEW_INCLUDE_DIR GL/glew.h)
+mark_as_advanced(GLEW_INCLUDE_DIR)
-if(NOT GLEW_LIBRARY)
- find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64 libx32)
- find_library(GLEW_LIBRARY_DEBUG NAMES GLEWd glew32d glewd PATH_SUFFIXES lib64)
+set(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR})
- include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
- select_library_configurations(GLEW)
-endif ()
+if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: GLEW_INCLUDE_DIR: ${GLEW_INCLUDE_DIR}")
+ message(STATUS "FindGLEW: GLEW_INCLUDE_DIRS: ${GLEW_INCLUDE_DIRS}")
+endif()
+
+if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "x64" OR "${CMAKE_GENERATOR}" MATCHES "Win64")
+ set(_arch "x64")
+else()
+ set(_arch "Win32")
+endif()
+
+
+__glew_set_find_library_suffix(SHARED)
+
+find_library(GLEW_SHARED_LIBRARY_RELEASE
+ NAMES GLEW glew glew32
+ PATH_SUFFIXES lib lib64 libx32 lib/Release/${_arch}
+ PATHS ENV GLEW_ROOT)
+
+find_library(GLEW_SHARED_LIBRARY_DEBUG
+ NAMES GLEWd glewd glew32d
+ PATH_SUFFIXES lib lib64
+ PATHS ENV GLEW_ROOT)
+
+
+__glew_set_find_library_suffix(STATIC)
+
+find_library(GLEW_STATIC_LIBRARY_RELEASE
+ NAMES GLEW glew glew32s
+ PATH_SUFFIXES lib lib64 libx32 lib/Release/${_arch}
+ PATHS ENV GLEW_ROOT)
+
+find_library(GLEW_STATIC_LIBRARY_DEBUG
+ NAMES GLEWds glewds glew32ds
+ PATH_SUFFIXES lib lib64
+ PATHS ENV GLEW_ROOT)
+
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+
+select_library_configurations(GLEW_SHARED)
+select_library_configurations(GLEW_STATIC)
+
+if(NOT GLEW_USE_STATIC_LIBS)
+ set(GLEW_LIBRARIES ${GLEW_SHARED_LIBRARY})
+else()
+ set(GLEW_LIBRARIES ${GLEW_STATIC_LIBRARY})
+endif()
+
+
+if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: GLEW_SHARED_LIBRARY_RELEASE: ${GLEW_SHARED_LIBRARY_RELEASE}")
+ message(STATUS "FindGLEW: GLEW_STATIC_LIBRARY_RELEASE: ${GLEW_STATIC_LIBRARY_RELEASE}")
+ message(STATUS "FindGLEW: GLEW_SHARED_LIBRARY_DEBUG: ${GLEW_SHARED_LIBRARY_DEBUG}")
+ message(STATUS "FindGLEW: GLEW_STATIC_LIBRARY_DEBUG: ${GLEW_STATIC_LIBRARY_DEBUG}")
+ message(STATUS "FindGLEW: GLEW_SHARED_LIBRARY: ${GLEW_SHARED_LIBRARY}")
+ message(STATUS "FindGLEW: GLEW_STATIC_LIBRARY: ${GLEW_STATIC_LIBRARY}")
+ message(STATUS "FindGLEW: GLEW_LIBRARIES: ${GLEW_LIBRARIES}")
+endif()
+
+
+# Read version from GL/glew.h file
+if(EXISTS "${GLEW_INCLUDE_DIR}/GL/glew.h")
+ file(STRINGS "${GLEW_INCLUDE_DIR}/GL/glew.h" _contents REGEX "^VERSION_.+ [0-9]+")
+ if(_contents)
+ string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" GLEW_VERSION_MAJOR "${_contents}")
+ string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" GLEW_VERSION_MINOR "${_contents}")
+ string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" GLEW_VERSION_MICRO "${_contents}")
+ set(GLEW_VERSION "${GLEW_VERSION_MAJOR}.${GLEW_VERSION_MINOR}.${GLEW_VERSION_MICRO}")
+ endif()
+endif()
+
+if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: GLEW_VERSION_MAJOR: ${GLEW_VERSION_MAJOR}")
+ message(STATUS "FindGLEW: GLEW_VERSION_MINOR: ${GLEW_VERSION_MINOR}")
+ message(STATUS "FindGLEW: GLEW_VERSION_MICRO: ${GLEW_VERSION_MICRO}")
+ message(STATUS "FindGLEW: GLEW_VERSION: ${GLEW_VERSION}")
+endif()
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(GLEW
- REQUIRED_VARS GLEW_INCLUDE_DIR GLEW_LIBRARY)
+ REQUIRED_VARS GLEW_INCLUDE_DIRS GLEW_LIBRARIES
+ VERSION_VAR GLEW_VERSION)
-if(GLEW_FOUND)
- set(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR})
+if(NOT GLEW_FOUND)
+ if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: could not found GLEW library.")
+ endif()
+ return()
+endif()
+
+
+if(NOT TARGET GLEW::glew AND NOT GLEW_USE_STATIC_LIBS)
+ if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: Creating GLEW::glew imported target.")
+ endif()
+
+ add_library(GLEW::glew UNKNOWN IMPORTED)
+
+ set_target_properties(GLEW::glew
+ PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
+
+ if(GLEW_SHARED_LIBRARY_RELEASE)
+ set_property(TARGET GLEW::glew
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+
+ set_target_properties(GLEW::glew
+ PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_SHARED_LIBRARY_RELEASE}")
+ endif()
+
+ if(GLEW_SHARED_LIBRARY_DEBUG)
+ set_property(TARGET GLEW::glew
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+
+ set_target_properties(GLEW::glew
+ PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_SHARED_LIBRARY_DEBUG}")
+ endif()
- if(NOT GLEW_LIBRARIES)
- set(GLEW_LIBRARIES ${GLEW_LIBRARY})
+elseif(NOT TARGET GLEW::glew_s AND GLEW_USE_STATIC_LIBS)
+ if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: Creating GLEW::glew_s imported target.")
endif()
- if (NOT TARGET GLEW::GLEW)
- add_library(GLEW::GLEW UNKNOWN IMPORTED)
- set_target_properties(GLEW::GLEW PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
+ add_library(GLEW::glew_s UNKNOWN IMPORTED)
- if(GLEW_LIBRARY_RELEASE)
- set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
- set_target_properties(GLEW::GLEW PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_LIBRARY_RELEASE}")
+ set_target_properties(GLEW::glew_s
+ PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
+
+ if(GLEW_STATIC_LIBRARY_RELEASE)
+ set_property(TARGET GLEW::glew_s
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+
+ set_target_properties(GLEW::glew_s
+ PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_STATIC_LIBRARY_RELEASE}")
+ endif()
+
+ if(GLEW_STATIC_LIBRARY_DEBUG)
+ set_property(TARGET GLEW::glew_s
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+
+ set_target_properties(GLEW::glew_s
+ PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_STATIC_LIBRARY_DEBUG}")
+ endif()
+endif()
+
+if(NOT TARGET GLEW::GLEW)
+ if(GLEW_VERBOSE)
+ message(STATUS "FindGLEW: Creating GLEW::GLEW imported target.")
+ endif()
+
+ add_library(GLEW::GLEW UNKNOWN IMPORTED)
+
+ set_target_properties(GLEW::GLEW
+ PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
+
+ if(TARGET GLEW::glew)
+ if(GLEW_SHARED_LIBRARY_RELEASE)
+ set_property(TARGET GLEW::GLEW
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+
+ set_target_properties(GLEW::GLEW
+ PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_SHARED_LIBRARY_RELEASE}")
+ endif()
+
+ if(GLEW_SHARED_LIBRARY_DEBUG)
+ set_property(TARGET GLEW::GLEW
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+
+ set_target_properties(GLEW::GLEW
+ PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_SHARED_LIBRARY_DEBUG}")
endif()
- if(GLEW_LIBRARY_DEBUG)
- set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
- set_target_properties(GLEW::GLEW PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_LIBRARY_DEBUG}")
+ elseif(TARGET GLEW::glew_s)
+ if(GLEW_STATIC_LIBRARY_RELEASE)
+ set_property(TARGET GLEW::GLEW
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+
+ set_target_properties(GLEW::GLEW
+ PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_STATIC_LIBRARY_RELEASE}")
endif()
- if(NOT GLEW_LIBRARY_RELEASE AND NOT GLEW_LIBRARY_DEBUG)
- set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_LOCATION "${GLEW_LIBRARY}")
+ if(GLEW_STATIC_LIBRARY_DEBUG AND GLEW_USE_STATIC_LIBS)
+ set_property(TARGET GLEW::GLEW
+ APPEND
+ PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+
+ set_target_properties(GLEW::GLEW
+ PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_STATIC_LIBRARY_DEBUG}")
endif()
+
+ elseif(GLEW_VERBOSE)
+ message(WARNING "FindGLEW: no `GLEW::glew` or `GLEW::glew_s` target was created. Something went wrong in FindGLEW target creation.")
endif()
endif()
-
-mark_as_advanced(GLEW_INCLUDE_DIR)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 696826f..596c7f5 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -236,8 +236,10 @@ set(SRCS
cmFileLockResult.h
cmFilePathChecksum.cxx
cmFilePathChecksum.h
- cmFileTimeComparison.cxx
- cmFileTimeComparison.h
+ cmFileTime.cxx
+ cmFileTime.h
+ cmFileTimeCache.cxx
+ cmFileTimeCache.h
cmFortranParserImpl.cxx
cmFSPermissions.cxx
cmFSPermissions.h
@@ -796,7 +798,7 @@ foreach(check
else()
set(CMake_${check} 0)
endif()
- set_property(SOURCE cmFileTimeComparison.cxx APPEND PROPERTY
+ set_property(SOURCE cmFileTime.cxx APPEND PROPERTY
COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}})
endforeach()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index c935ef6..243d8fc 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 14)
-set(CMake_VERSION_PATCH 20190318)
+set(CMake_VERSION_PATCH 20190321)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 635de49..cfb5efd 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -195,7 +195,7 @@ bool DebGenerator::generateDataTar() const
// XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
// should not add XXX/application
orderedFiles.insert(currentPath);
- currentPath = cmSystemTools::CollapseCombinedPath(currentPath, "..");
+ currentPath = cmSystemTools::CollapseFullPath("..", currentPath);
}
}
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
index fcf8af1..dd8127d 100644
--- a/Source/CPack/cmCPackFreeBSDGenerator.cxx
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -325,8 +325,7 @@ int cmCPackFreeBSDGenerator::PackageFiles()
ONE_PACKAGE_PER_COMPONENT);
}
- std::string output_dir =
- cmSystemTools::CollapseCombinedPath(toplevel, "../");
+ std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel);
pkg_create_from_manifest(output_dir.c_str(), ::TXZ, toplevel.c_str(),
manifestname.c_str(), nullptr);
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 07bc7e7..8ea9a83 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -5,7 +5,7 @@
#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmDuration.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
@@ -503,7 +503,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml)
class cmCTestBuildHandler::FragmentCompare
{
public:
- FragmentCompare(cmFileTimeComparison* ftc)
+ FragmentCompare(cmFileTimeCache* ftc)
: FTC(ftc)
{
}
@@ -513,14 +513,14 @@ public:
// Order files by modification time. Use lexicographic order
// among files with the same time.
int result;
- if (this->FTC->FileTimeCompare(l, r, &result) && result != 0) {
+ if (this->FTC->Compare(l, r, &result) && result != 0) {
return result < 0;
}
return l < r;
}
private:
- cmFileTimeComparison* FTC = nullptr;
+ cmFileTimeCache* FTC = nullptr;
};
void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
@@ -530,7 +530,7 @@ void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
}
// Sort XML fragments in chronological order.
- cmFileTimeComparison ftc;
+ cmFileTimeCache ftc;
FragmentCompare fragmentCompare(&ftc);
typedef std::set<std::string, FragmentCompare> Fragments;
Fragments fragments(fragmentCompare);
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 23be603..177ba02 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -179,12 +179,10 @@ cmArchiveWrite::~cmArchiveWrite()
bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix,
bool recursive)
{
- if (this->Okay()) {
- if (!path.empty() && path.back() == '/') {
- path.erase(path.size() - 1);
- }
- this->AddPath(path.c_str(), skip, prefix, recursive);
+ if (!path.empty() && path.back() == '/') {
+ path.erase(path.size() - 1);
}
+ this->AddPath(path.c_str(), skip, prefix, recursive);
return this->Okay();
}
@@ -220,6 +218,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
{
+ this->Error = "";
// Skip the file if we have no name for it. This may happen on a
// top-level directory, which does not need to be included anyway.
if (skip >= strlen(file)) {
@@ -241,7 +240,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
cm_archive_entry_copy_pathname(e, dest);
if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) !=
ARCHIVE_OK) {
- this->Error = "archive_read_disk_entry_from_file '";
+ this->Error = "Unable to read from file '";
this->Error += file;
this->Error += "': ";
this->Error += cm_archive_error_string(this->Disk);
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index c128b02..efadaf1 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -2,7 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDepends.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
@@ -177,8 +177,7 @@ bool cmDepends::CheckDependencies(
if (dependerExists) {
// The dependee and depender both exist. Compare file times.
int result = 0;
- if ((!this->FileComparison->FileTimeCompare(depender, dependee,
- &result) ||
+ if ((!this->FileTimeCache->Compare(depender, dependee, &result) ||
result < 0)) {
// The depender is older than the dependee.
regenerate = true;
@@ -195,8 +194,8 @@ bool cmDepends::CheckDependencies(
// The dependee exists, but the depender doesn't. Regenerate if the
// internalDepends file is older than the dependee.
int result = 0;
- if ((!this->FileComparison->FileTimeCompare(internalDependsFileName,
- dependee, &result) ||
+ if ((!this->FileTimeCache->Compare(internalDependsFileName, dependee,
+ &result) ||
result < 0)) {
// The depends-file is older than the dependee.
regenerate = true;
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index 20c91ca..fc6571d 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-class cmFileTimeComparison;
+class cmFileTimeCache;
class cmLocalGenerator;
/** \class cmDepends
@@ -72,10 +72,7 @@ public:
void Clear(const std::string& file);
/** Set the file comparison object */
- void SetFileComparison(cmFileTimeComparison* fc)
- {
- this->FileComparison = fc;
- }
+ void SetFileTimeCache(cmFileTimeCache* fc) { this->FileTimeCache = fc; }
protected:
// Write dependencies for the target file to the given stream.
@@ -101,7 +98,7 @@ protected:
// Flag for verbose output.
bool Verbose = false;
- cmFileTimeComparison* FileComparison = nullptr;
+ cmFileTimeCache* FileTimeCache = nullptr;
std::string Language;
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index a85f5ee..7b78767 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -6,6 +6,7 @@
#include <utility>
#include "cmAlgorithms.h"
+#include "cmFileTime.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
@@ -149,7 +150,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// Construct the name of the file as if it were in the current
// include directory. Avoid using a leading "./".
std::string tmpPath =
- cmSystemTools::CollapseCombinedPath(iPath, current.FileName);
+ cmSystemTools::CollapseFullPath(current.FileName, iPath);
// Look for the file in this location.
if (cmSystemTools::FileExists(tmpPath, true)) {
@@ -247,6 +248,8 @@ void cmDependsC::ReadCacheFile()
cmIncludeLines* cacheEntry = nullptr;
bool haveFileName = false;
+ cmFileTime cacheFileTime;
+ bool const cacheFileTimeGood = cacheFileTime.Load(this->CacheFileName);
while (cmSystemTools::GetLineFromStream(fin, line)) {
if (line.empty()) {
cacheEntry = nullptr;
@@ -256,11 +259,12 @@ void cmDependsC::ReadCacheFile()
// the first line after an empty line is the name of the parsed file
if (!haveFileName) {
haveFileName = true;
- int newer = 0;
- bool res =
- cmSystemTools::FileTimeCompare(this->CacheFileName, line, &newer);
- if (res && newer == 1) // cache is newer than the parsed file
+ cmFileTime fileTime;
+ bool const res = cacheFileTimeGood && fileTime.Load(line);
+ bool const newer = res && cacheFileTime.Newer(fileTime);
+
+ if (res && newer) // cache is newer than the parsed file
{
cacheEntry = new cmIncludeLines;
this->FileCache[line] = cacheEntry;
@@ -358,7 +362,7 @@ void cmDependsC::Scan(std::istream& is, const std::string& directory,
// must check for the file in the directory containing the
// file we are scanning.
entry.QuotedLocation =
- cmSystemTools::CollapseCombinedPath(directory, entry.FileName);
+ cmSystemTools::CollapseFullPath(entry.FileName, directory);
}
// Queue the file if it has not yet been encountered and it
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index a6ce8b7..aece3bc 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -845,6 +845,9 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
const std::vector<cmGeneratorTarget*>& targets =
lgen->GetGeneratorTargets();
for (cmGeneratorTarget* target : targets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
std::vector<std::string> includeDirs;
std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
lgen->GetIncludeDirectories(includeDirs, target, "C", config);
@@ -971,6 +974,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
virtDir, "", "");
}
} break;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
default:
break;
}
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 560d893..8913e6d 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -532,7 +532,7 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
bool copy = true;
if (!this->Always) {
// If both files exist with the same time do not copy.
- if (!this->FileTimes.FileTimesDiffer(fromFile, toFile)) {
+ if (!this->FileTimes.DifferS(fromFile, toFile)) {
copy = false;
}
}
diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h
index a11c371..003b8f6 100644
--- a/Source/cmFileCopier.h
+++ b/Source/cmFileCopier.h
@@ -5,7 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cm_sys_stat.h"
#include "cmsys/RegularExpression.hxx"
@@ -28,7 +28,7 @@ protected:
cmMakefile* Makefile;
const char* Name;
bool Always;
- cmFileTimeComparison FileTimes;
+ cmFileTimeCache FileTimes;
// Whether to install a file not matching any expression.
bool MatchlessFiles;
diff --git a/Source/cmFileTime.cxx b/Source/cmFileTime.cxx
new file mode 100644
index 0000000..253457f
--- /dev/null
+++ b/Source/cmFileTime.cxx
@@ -0,0 +1,49 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileTime.h"
+
+#include <string>
+#include <time.h>
+
+// Use a platform-specific API to get file times efficiently.
+#if !defined(_WIN32) || defined(__CYGWIN__)
+# include "cm_sys_stat.h"
+#else
+# include "cmsys/Encoding.hxx"
+# include <windows.h>
+#endif
+
+bool cmFileTime::Load(std::string const& fileName)
+{
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // POSIX version. Use the stat function.
+ struct stat fst;
+ if (::stat(fileName.c_str(), &fst) != 0) {
+ return false;
+ }
+# if CMake_STAT_HAS_ST_MTIM
+ // Nanosecond resolution
+ this->NS = fst.st_mtim.tv_sec * NsPerS + fst.st_mtim.tv_nsec;
+# elif CMake_STAT_HAS_ST_MTIMESPEC
+ // Nanosecond resolution
+ this->NS = fst.st_mtimespec.tv_sec * NsPerS + fst.st_mtimespec.tv_nsec;
+# else
+ // Second resolution
+ this->NS = fst.st_mtime * NsPerS;
+# endif
+#else
+ // Windows version. Get the modification time from extended file attributes.
+ WIN32_FILE_ATTRIBUTE_DATA fdata;
+ if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fileName).c_str(),
+ GetFileExInfoStandard, &fdata)) {
+ return false;
+ }
+
+ // Copy the file time to the output location.
+ this->NS = (static_cast<NSC>(fdata.ftLastWriteTime.dwHighDateTime) << 32) |
+ static_cast<NSC>(fdata.ftLastWriteTime.dwLowDateTime);
+ // The file time resolution is 100 ns.
+ this->NS *= 100;
+#endif
+ return true;
+}
diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h
new file mode 100644
index 0000000..4c8e556
--- /dev/null
+++ b/Source/cmFileTime.h
@@ -0,0 +1,130 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileTime_h
+#define cmFileTime_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** \class cmFileTime
+ * \brief Abstract file modification time with support for comparison with
+ * other file modification times.
+ */
+class cmFileTime
+{
+public:
+ typedef long long NSC;
+ static constexpr NSC NsPerS = 1000000000;
+
+ cmFileTime() = default;
+ ~cmFileTime() = default;
+
+ /**
+ * @brief Loads the file time of fileName from the file system
+ * @return true on success
+ */
+ bool Load(std::string const& fileName);
+
+ /**
+ * @brief Return true if this is older than ftm
+ */
+ bool Older(cmFileTime const& ftm) const { return (this->NS - ftm.NS) < 0; }
+
+ /**
+ * @brief Return true if this is newer than ftm
+ */
+ bool Newer(cmFileTime const& ftm) const { return (ftm.NS - this->NS) < 0; }
+
+ /**
+ * @brief Return true if this is the same as ftm
+ */
+ bool Equal(cmFileTime const& ftm) const { return this->NS == ftm.NS; }
+
+ /**
+ * @brief Return true if this is not the same as ftm
+ */
+ bool Differ(cmFileTime const& ftm) const { return this->NS != ftm.NS; }
+
+ /**
+ * @brief Compare file modification times.
+ * @return -1, 0, +1 for this older, same, or newer than ftm.
+ */
+ int Compare(cmFileTime const& ftm)
+ {
+ NSC const diff = this->NS - ftm.NS;
+ if (diff == 0) {
+ return 0;
+ }
+ return (diff < 0) ? -1 : 1;
+ }
+
+ // -- Comparison in second resolution
+
+ /**
+ * @brief Return true if this is at least a second older than ftm
+ */
+ bool OlderS(cmFileTime const& ftm) const
+ {
+ return (ftm.NS - this->NS) >= cmFileTime::NsPerS;
+ }
+
+ /**
+ * @brief Return true if this is at least a second newer than ftm
+ */
+ bool NewerS(cmFileTime const& ftm) const
+ {
+ return (this->NS - ftm.NS) >= cmFileTime::NsPerS;
+ }
+
+ /**
+ * @brief Return true if this is within the same second as ftm
+ */
+ bool EqualS(cmFileTime const& ftm) const
+ {
+ NSC diff = this->NS - ftm.NS;
+ if (diff < 0) {
+ diff = -diff;
+ }
+ return (diff < cmFileTime::NsPerS);
+ }
+
+ /**
+ * @brief Return true if this is older or newer than ftm by at least a second
+ */
+ bool DifferS(cmFileTime const& ftm) const
+ {
+ NSC diff = this->NS - ftm.NS;
+ if (diff < 0) {
+ diff = -diff;
+ }
+ return (diff >= cmFileTime::NsPerS);
+ }
+
+ /**
+ * @brief Compare file modification times.
+ * @return -1: this at least a second older, 0: this within the same second
+ * as ftm, +1: this at least a second newer than ftm.
+ */
+ int CompareS(cmFileTime const& ftm) const
+ {
+ NSC const diff = this->NS - ftm.NS;
+ if (diff <= -cmFileTime::NsPerS) {
+ return -1;
+ }
+ if (diff >= cmFileTime::NsPerS) {
+ return 1;
+ }
+ return 0;
+ }
+
+ /**
+ * @brief The file modification time in nanoseconds
+ */
+ NSC GetNS() const { return this->NS; }
+
+private:
+ NSC NS = 0;
+};
+
+#endif
diff --git a/Source/cmFileTimeCache.cxx b/Source/cmFileTimeCache.cxx
new file mode 100644
index 0000000..1fff6a9
--- /dev/null
+++ b/Source/cmFileTimeCache.cxx
@@ -0,0 +1,57 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileTimeCache.h"
+
+#include <string>
+#include <unordered_map>
+#include <utility>
+
+cmFileTimeCache::cmFileTimeCache() = default;
+
+cmFileTimeCache::~cmFileTimeCache() = default;
+
+bool cmFileTimeCache::Load(std::string const& fileName, cmFileTime& fileTime)
+{
+ // Use the stored time if available.
+ {
+ auto fit = this->FileTimes.find(fileName);
+ if (fit != this->FileTimes.end()) {
+ fileTime = fit->second;
+ return true;
+ }
+ }
+ // Read file time from OS
+ if (!fileTime.Load(fileName)) {
+ return false;
+ }
+ // Store file time in cache
+ this->FileTimes[fileName] = fileTime;
+ return true;
+}
+
+bool cmFileTimeCache::Compare(std::string const& f1, std::string const& f2,
+ int* result)
+{
+ // Get the modification time for each file.
+ cmFileTime ft1, ft2;
+ if (this->Load(f1, ft1) && this->Load(f2, ft2)) {
+ // Compare the two modification times.
+ *result = ft1.Compare(ft2);
+ return true;
+ }
+ // No comparison available. Default to the same time.
+ *result = 0;
+ return false;
+}
+
+bool cmFileTimeCache::DifferS(std::string const& f1, std::string const& f2)
+{
+ // Get the modification time for each file.
+ cmFileTime ft1, ft2;
+ if (this->Load(f1, ft1) && this->Load(f2, ft2)) {
+ // Compare the two modification times.
+ return ft1.DifferS(ft2);
+ }
+ // No comparison available. Default to different times.
+ return true;
+}
diff --git a/Source/cmFileTimeCache.h b/Source/cmFileTimeCache.h
new file mode 100644
index 0000000..a47904c
--- /dev/null
+++ b/Source/cmFileTimeCache.h
@@ -0,0 +1,51 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileTimeCache_h
+#define cmFileTimeCache_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmFileTime.h"
+#include <string>
+#include <unordered_map>
+
+/** \class cmFileTimeCache
+ * \brief Caches file modification times in an internal map for fast lookups.
+ */
+class cmFileTimeCache
+{
+public:
+ cmFileTimeCache();
+ ~cmFileTimeCache();
+
+ cmFileTimeCache(const cmFileTimeCache&) = delete;
+ cmFileTimeCache& operator=(const cmFileTimeCache&) = delete;
+
+ /**
+ * @brief Loads the file time from the cache or the file system.
+ * @return true on success
+ */
+ bool Load(std::string const& fileName, cmFileTime& fileTime);
+
+ /**
+ * @brief Compare file modification times.
+ * @return true for successful comparison and false for error.
+ *
+ * When true is returned, result has -1, 0, +1 for
+ * f1 older, same, or newer than f2.
+ */
+ bool Compare(std::string const& f1, std::string const& f2, int* result);
+
+ /**
+ * @brief Compare file modification times.
+ * @return true unless both files exist and have modification times less
+ * than 1 second apart.
+ */
+ bool DifferS(std::string const& f1, std::string const& f2);
+
+private:
+ typedef std::unordered_map<std::string, cmFileTime> FileTimeMap;
+ FileTimeMap FileTimes;
+};
+
+#endif
diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx
deleted file mode 100644
index 8b3911e..0000000
--- a/Source/cmFileTimeComparison.cxx
+++ /dev/null
@@ -1,233 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFileTimeComparison.h"
-
-#include <string>
-#include <time.h>
-#include <unordered_map>
-#include <utility>
-
-// Use a platform-specific API to get file times efficiently.
-#if !defined(_WIN32) || defined(__CYGWIN__)
-# include "cm_sys_stat.h"
-# define cmFileTimeComparison_Type struct stat
-#else
-# include "cmsys/Encoding.hxx"
-# include <windows.h>
-# define cmFileTimeComparison_Type FILETIME
-#endif
-
-class cmFileTimeComparisonInternal
-{
-public:
- // Internal comparison method.
- inline bool FileTimeCompare(const std::string& f1, const std::string& f2,
- int* result);
-
- bool FileTimesDiffer(const std::string& f1, const std::string& f2);
-
-private:
- typedef std::unordered_map<std::string, cmFileTimeComparison_Type>
- FileStatsMap;
- FileStatsMap Files;
-
- // Internal methods to lookup and compare modification times.
- inline bool Stat(const std::string& fname, cmFileTimeComparison_Type* st);
- inline int Compare(cmFileTimeComparison_Type* st1,
- cmFileTimeComparison_Type* st2);
- inline bool TimesDiffer(cmFileTimeComparison_Type* st1,
- cmFileTimeComparison_Type* st2);
-};
-
-bool cmFileTimeComparisonInternal::Stat(const std::string& fname,
- cmFileTimeComparison_Type* st)
-{
- // Use the stored time if available.
- cmFileTimeComparisonInternal::FileStatsMap::iterator fit =
- this->Files.find(fname);
- if (fit != this->Files.end()) {
- *st = fit->second;
- return true;
- }
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
- // POSIX version. Use the stat function.
- int res = ::stat(fname.c_str(), st);
- if (res != 0) {
- return false;
- }
-#else
- // Windows version. Get the modification time from extended file
- // attributes.
- WIN32_FILE_ATTRIBUTE_DATA fdata;
- if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fname).c_str(),
- GetFileExInfoStandard, &fdata)) {
- return false;
- }
-
- // Copy the file time to the output location.
- *st = fdata.ftLastWriteTime;
-#endif
-
- // Store the time for future use.
- this->Files[fname] = *st;
- return true;
-}
-
-cmFileTimeComparison::cmFileTimeComparison()
-{
- this->Internals = new cmFileTimeComparisonInternal;
-}
-
-cmFileTimeComparison::~cmFileTimeComparison()
-{
- delete this->Internals;
-}
-
-bool cmFileTimeComparison::FileTimeCompare(const std::string& f1,
- const std::string& f2, int* result)
-{
- return this->Internals->FileTimeCompare(f1, f2, result);
-}
-
-bool cmFileTimeComparison::FileTimesDiffer(const std::string& f1,
- const std::string& f2)
-{
- return this->Internals->FileTimesDiffer(f1, f2);
-}
-
-int cmFileTimeComparisonInternal::Compare(cmFileTimeComparison_Type* s1,
- cmFileTimeComparison_Type* s2)
-{
-#if !defined(_WIN32) || defined(__CYGWIN__)
-# if CMake_STAT_HAS_ST_MTIM
- // Compare using nanosecond resolution.
- if (s1->st_mtim.tv_sec < s2->st_mtim.tv_sec) {
- return -1;
- }
- if (s1->st_mtim.tv_sec > s2->st_mtim.tv_sec) {
- return 1;
- }
- if (s1->st_mtim.tv_nsec < s2->st_mtim.tv_nsec) {
- return -1;
- }
- if (s1->st_mtim.tv_nsec > s2->st_mtim.tv_nsec) {
- return 1;
- }
-# elif CMake_STAT_HAS_ST_MTIMESPEC
- // Compare using nanosecond resolution.
- if (s1->st_mtimespec.tv_sec < s2->st_mtimespec.tv_sec) {
- return -1;
- }
- if (s1->st_mtimespec.tv_sec > s2->st_mtimespec.tv_sec) {
- return 1;
- }
- if (s1->st_mtimespec.tv_nsec < s2->st_mtimespec.tv_nsec) {
- return -1;
- }
- if (s1->st_mtimespec.tv_nsec > s2->st_mtimespec.tv_nsec) {
- return 1;
- }
-# else
- // Compare using 1 second resolution.
- if (s1->st_mtime < s2->st_mtime) {
- return -1;
- }
- if (s1->st_mtime > s2->st_mtime) {
- return 1;
- }
-# endif
- // Files have the same time.
- return 0;
-#else
- // Compare using system-provided function.
- return (int)CompareFileTime(s1, s2);
-#endif
-}
-
-bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1,
- cmFileTimeComparison_Type* s2)
-{
-#if !defined(_WIN32) || defined(__CYGWIN__)
-# if CMake_STAT_HAS_ST_MTIM
- // Times are integers in units of 1ns.
- long long bil = 1000000000;
- long long t1 = s1->st_mtim.tv_sec * bil + s1->st_mtim.tv_nsec;
- long long t2 = s2->st_mtim.tv_sec * bil + s2->st_mtim.tv_nsec;
- if (t1 < t2) {
- return (t2 - t1) >= bil;
- }
- if (t2 < t1) {
- return (t1 - t2) >= bil;
- }
- return false;
-# elif CMake_STAT_HAS_ST_MTIMESPEC
- // Times are integers in units of 1ns.
- long long bil = 1000000000;
- long long t1 = s1->st_mtimespec.tv_sec * bil + s1->st_mtimespec.tv_nsec;
- long long t2 = s2->st_mtimespec.tv_sec * bil + s2->st_mtimespec.tv_nsec;
- if (t1 < t2) {
- return (t2 - t1) >= bil;
- }
- if (t2 < t1) {
- return (t1 - t2) >= bil;
- }
- return false;
-# else
- // Times are integers in units of 1s.
- if (s1->st_mtime < s2->st_mtime) {
- return (s2->st_mtime - s1->st_mtime) >= 1;
- }
- if (s1->st_mtime > s2->st_mtime) {
- return (s1->st_mtime - s2->st_mtime) >= 1;
- }
- return false;
-# endif
-#else
- // Times are integers in units of 100ns.
- LARGE_INTEGER t1;
- LARGE_INTEGER t2;
- t1.LowPart = s1->dwLowDateTime;
- t1.HighPart = s1->dwHighDateTime;
- t2.LowPart = s2->dwLowDateTime;
- t2.HighPart = s2->dwHighDateTime;
- if (t1.QuadPart < t2.QuadPart) {
- return (t2.QuadPart - t1.QuadPart) >= static_cast<LONGLONG>(10000000);
- } else if (t2.QuadPart < t1.QuadPart) {
- return (t1.QuadPart - t2.QuadPart) >= static_cast<LONGLONG>(10000000);
- } else {
- return false;
- }
-#endif
-}
-
-bool cmFileTimeComparisonInternal::FileTimeCompare(const std::string& f1,
- const std::string& f2,
- int* result)
-{
- // Get the modification time for each file.
- cmFileTimeComparison_Type s1;
- cmFileTimeComparison_Type s2;
- if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) {
- // Compare the two modification times.
- *result = this->Compare(&s1, &s2);
- return true;
- }
- // No comparison available. Default to the same time.
- *result = 0;
- return false;
-}
-
-bool cmFileTimeComparisonInternal::FileTimesDiffer(const std::string& f1,
- const std::string& f2)
-{
- // Get the modification time for each file.
- cmFileTimeComparison_Type s1;
- cmFileTimeComparison_Type s2;
- if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) {
- // Compare the two modification times.
- return this->TimesDiffer(&s1, &s2);
- }
- // No comparison available. Default to different times.
- return true;
-}
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
deleted file mode 100644
index b4e4eb3..0000000
--- a/Source/cmFileTimeComparison.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmFileTimeComparison_h
-#define cmFileTimeComparison_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-
-class cmFileTimeComparisonInternal;
-
-/** \class cmFileTimeComparison
- * \brief Helper class for comparing file modification times.
- *
- * Compare file modification times or test if file modification times differ.
- */
-class cmFileTimeComparison
-{
-public:
- cmFileTimeComparison();
- ~cmFileTimeComparison();
-
- cmFileTimeComparison(const cmFileTimeComparison&) = delete;
- cmFileTimeComparison& operator=(const cmFileTimeComparison&) = delete;
-
- /**
- * Compare file modification times.
- * Return true for successful comparison and false for error.
- * When true is returned, result has -1, 0, +1 for
- * f1 older, same, or newer than f2.
- */
- bool FileTimeCompare(const std::string& f1, const std::string& f2,
- int* result);
-
- /**
- * Compare file modification times. Return true unless both files
- * exist and have modification times less than 1 second apart.
- */
- bool FileTimesDiffer(const std::string& f1, const std::string& f2);
-
-protected:
- cmFileTimeComparisonInternal* Internals;
-};
-
-#endif
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 9f8f12b..c73ec70 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -287,7 +287,7 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout,
if (l.compare(0, 2, "-l") == 0) {
fout << " \"" << l << "\"" << std::endl;
} else {
- std::string rl = cmSystemTools::CollapseCombinedPath(cbd, l);
+ std::string rl = cmSystemTools::CollapseFullPath(l, cbd);
fout << " -l\"" << rl << "\"" << std::endl;
}
}
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 4f1d06a..dba9afa 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -185,8 +185,7 @@ void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
}
} else {
std::string tryPath;
- /* CollapseCombinedPath will check if ts is an absolute path */
- tryPath = cmSystemTools::CollapseCombinedPath(tsd, ts);
+ tryPath = cmSystemTools::CollapseFullPath(ts, tsd);
if (!cmSystemTools::FileExists(tryPath)) {
std::string msg = "GHS toolset \"" + tryPath + "\" not found.";
cmSystemTools::Error(msg);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 53baed5..4bfa0b1 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1022,7 +1022,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
this->CreateString(fileType));
// Store the file path relative to the top of the source tree.
- std::string path = this->RelativeToSource(fullpath.c_str());
+ std::string path = this->RelativeToSource(fullpath);
std::string name = cmSystemTools::GetFilenameName(path);
const char* sourceTree =
(cmSystemTools::FileIsFullPath(path.c_str()) ? "<absolute>"
@@ -3063,7 +3063,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
// Point Xcode at the top of the source tree.
{
std::string pdir =
- this->RelativeToBinary(root->GetCurrentSourceDirectory().c_str());
+ this->RelativeToBinary(root->GetCurrentSourceDirectory());
this->RootObject->AddAttribute("projectDirPath", this->CreateString(pdir));
this->RootObject->AddAttribute("projectRoot", this->CreateString(""));
}
@@ -3457,7 +3457,7 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
cmXCodeScheme schm(obj, testables[targetName],
this->CurrentConfigurationTypes, this->XcodeVersion);
schm.WriteXCodeSharedScheme(xcProjDir,
- this->RelativeToSource(xcProjDir.c_str()));
+ this->RelativeToSource(xcProjDir));
}
}
}
@@ -3559,7 +3559,7 @@ std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(
return cmSystemTools::ConvertToOutputPath(p);
}
-std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
+std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p)
{
// We force conversion because Xcode breakpoints do not work unless
// they are in a file named relative to the source tree.
@@ -3567,7 +3567,7 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p);
}
-std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
+std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p)
{
return this->CurrentLocalGenerator->MaybeConvertToRelativePath(
cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 95db852..b80a9ad 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -119,8 +119,8 @@ private:
const std::string& name);
bool CreateGroups(std::vector<cmLocalGenerator*>& generators);
std::string XCodeEscapePath(const std::string& p);
- std::string RelativeToSource(const char* p);
- std::string RelativeToBinary(const char* p);
+ std::string RelativeToSource(const std::string& p);
+ std::string RelativeToBinary(const std::string& p);
std::string ConvertToRelativeForMake(std::string const& p);
void CreateCustomCommands(cmXCodeObject* buildPhases,
cmXCodeObject* sourceBuildPhase,
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index d1093be..f3d5a94 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -12,7 +12,7 @@
#include "cmAlgorithms.h"
#include "cmCustomCommandGenerator.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -1273,12 +1273,11 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
// happen when a new source file is added and CMake regenerates the
// project but no other sources were touched.
bool needRescanDependInfo = false;
- cmFileTimeComparison* ftc =
- this->GlobalGenerator->GetCMakeInstance()->GetFileComparison();
+ cmFileTimeCache* ftc =
+ this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
{
int result;
- if (!ftc->FileTimeCompare(internalDependFile, tgtInfo, &result) ||
- result < 0) {
+ if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
if (verbose) {
std::ostringstream msg;
msg << "Dependee \"" << tgtInfo << "\" is newer than depender \""
@@ -1297,7 +1296,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
dirInfoFile += "/CMakeFiles";
dirInfoFile += "/CMakeDirectoryInformation.cmake";
int result;
- if (!ftc->FileTimeCompare(internalDependFile, dirInfoFile, &result) ||
+ if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
result < 0) {
if (verbose) {
std::ostringstream msg;
@@ -1318,7 +1317,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
if (!needRescanDirInfo) {
cmDependsC checker;
checker.SetVerbose(verbose);
- checker.SetFileComparison(ftc);
+ checker.SetFileTimeCache(ftc);
// cmDependsC::Check() fills the vector validDependencies() with the
// dependencies for those files where they are still valid, i.e. neither
// the files themselves nor any files they depend on have changed.
@@ -1439,8 +1438,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
if (scanner) {
scanner->SetLocalGenerator(this);
- scanner->SetFileComparison(
- this->GlobalGenerator->GetCMakeInstance()->GetFileComparison());
+ scanner->SetFileTimeCache(
+ this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache());
scanner->SetLanguage(lang);
scanner->SetTargetDirectory(targetDir);
scanner->Write(ruleFileStream, internalRuleFileStream);
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 022947f..87ef112 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -309,7 +309,7 @@ void cmQtAutoGen::RccListConvertFullPath(std::string const& qrcFileDir,
std::vector<std::string>& files)
{
for (std::string& entry : files) {
- std::string tmp = cmSystemTools::CollapseCombinedPath(qrcFileDir, entry);
+ std::string tmp = cmSystemTools::CollapseFullPath(entry, qrcFileDir);
entry = std::move(tmp);
}
}
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index af50c1d..a1abd3f 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -158,11 +158,11 @@ std::string cmQtAutoGenerator::FileSystem::GetRealPath(
return cmSystemTools::GetRealPath(filename);
}
-std::string cmQtAutoGenerator::FileSystem::CollapseCombinedPath(
- std::string const& dir, std::string const& file)
+std::string cmQtAutoGenerator::FileSystem::CollapseFullPath(
+ std::string const& file, std::string const& dir)
{
std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::CollapseCombinedPath(dir, file);
+ return cmSystemTools::CollapseFullPath(file, dir);
}
void cmQtAutoGenerator::FileSystem::SplitPath(
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index 6771dd8..b55bebc 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -77,9 +77,9 @@ public:
// -- Paths
/// @brief Wrapper for cmSystemTools::GetRealPath
std::string GetRealPath(std::string const& filename);
- /// @brief Wrapper for cmSystemTools::CollapseCombinedPath
- std::string CollapseCombinedPath(std::string const& dir,
- std::string const& file);
+ /// @brief Wrapper for cmSystemTools::CollapseFullPath
+ std::string CollapseFullPath(std::string const& file,
+ std::string const& dir);
/// @brief Wrapper for cmSystemTools::SplitPath
void SplitPath(const std::string& p, std::vector<std::string>& components,
bool expand_home_dir = true);
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index b02cd44..cb6f7ea 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -27,7 +27,7 @@
std::string cmQtAutoGeneratorMocUic::BaseSettingsT::AbsoluteBuildPath(
std::string const& relativePath) const
{
- return FileSys->CollapseCombinedPath(AutogenBuildDir, relativePath);
+ return FileSys->CollapseFullPath(relativePath, AutogenBuildDir);
}
/**
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index d762106..d201061 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1510,36 +1510,6 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path,
return relative;
}
-std::string cmSystemTools::CollapseCombinedPath(std::string const& dir,
- std::string const& file)
-{
- if (dir.empty() || dir == ".") {
- return file;
- }
-
- std::vector<std::string> dirComponents;
- std::vector<std::string> fileComponents;
- cmSystemTools::SplitPath(dir, dirComponents);
- cmSystemTools::SplitPath(file, fileComponents);
-
- if (fileComponents.empty()) {
- return dir;
- }
- if (!fileComponents[0].empty()) {
- // File is not a relative path.
- return file;
- }
-
- std::vector<std::string>::iterator i = fileComponents.begin() + 1;
- while (i != fileComponents.end() && *i == ".." && dirComponents.size() > 1) {
- ++i; // Remove ".." file component.
- dirComponents.pop_back(); // Remove last dir component.
- }
-
- dirComponents.insert(dirComponents.end(), i, fileComponents.end());
- return cmSystemTools::JoinPath(dirComponents);
-}
-
#ifdef CMAKE_BUILD_WITH_CMAKE
bool cmSystemTools::UnsetEnv(const char* value)
{
@@ -1658,20 +1628,18 @@ bool cmSystemTools::CreateTar(const char* outFileName,
a.SetMTime(mtime);
a.SetVerbose(verbose);
+ bool tarCreatedSuccessfully = true;
for (auto path : files) {
if (cmSystemTools::FileIsFullPath(path)) {
// Get the relative path to the file.
path = cmSystemTools::RelativePath(cwd, path);
}
if (!a.Add(path)) {
- break;
+ cmSystemTools::Error(a.GetError());
+ tarCreatedSuccessfully = false;
}
}
- if (!a) {
- cmSystemTools::Error(a.GetError());
- return false;
- }
- return true;
+ return tarCreatedSuccessfully;
#else
(void)outFileName;
(void)files;
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 60e8c18..b5f65c7 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -374,12 +374,6 @@ public:
static std::string ForceToRelativePath(std::string const& local_path,
std::string const& remote_path);
- /** Joins two paths while collapsing x/../ parts
- * For example CollapseCombinedPath("a/b/c", "../../d") results in "a/d"
- */
- static std::string CollapseCombinedPath(std::string const& dir,
- std::string const& file);
-
#ifdef CMAKE_BUILD_WITH_CMAKE
/** Remove an environment variable */
static bool UnsetEnv(const char* value);
diff --git a/Source/cm_utf8.c b/Source/cm_utf8.c
index 52af4a6..62e7e8c 100644
--- a/Source/cm_utf8.c
+++ b/Source/cm_utf8.c
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cm_utf8.h"
+#include <string.h>
+
/*
RFC 3629
07-bit: 0xxxxxxx
@@ -71,7 +73,34 @@ const char* cm_utf8_decode_character(const char* first, const char* last,
return 0;
}
+ /* UTF-16 surrogate halves. */
+ if (0xD800 <= uc && uc <= 0xDFFF) {
+ return 0;
+ }
+
+ /* Invalid codepoints. */
+ if (0x10FFFF < uc) {
+ return 0;
+ }
+
*pc = uc;
return first;
}
}
+
+int cm_utf8_is_valid(const char* s)
+{
+ if (!s) {
+ return 0;
+ }
+
+ const char* last = s + strlen(s);
+ const char* pos = s;
+ unsigned int pc;
+
+ while (pos != last && (pos = cm_utf8_decode_character(pos, last, &pc))) {
+ /* Nothing to do. */
+ }
+
+ return pos == last;
+}
diff --git a/Source/cm_utf8.h b/Source/cm_utf8.h
index fcb43e0..27dc559 100644
--- a/Source/cm_utf8.h
+++ b/Source/cm_utf8.h
@@ -13,6 +13,10 @@ extern "C" {
const char* cm_utf8_decode_character(const char* first, const char* last,
unsigned int* pc);
+/** Returns whether a C string is a sequence of valid UTF-8 encoded Unicode
+ codepoints. Returns non-zero on success. */
+int cm_utf8_is_valid(const char* s);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 08e284e..e1b775e 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -9,7 +9,7 @@
#include "cmDocumentationFormatter.h"
#include "cmDuration.h"
#include "cmExternalMakefileProjectGenerator.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
@@ -138,7 +138,7 @@ cmake::cmake(Role role, cmState::Mode mode)
this->DebugOutput = false;
this->DebugTryCompile = false;
this->ClearBuildSystem = false;
- this->FileComparison = new cmFileTimeComparison;
+ this->FileTimeCache = new cmFileTimeCache;
this->State = new cmState;
this->State->SetMode(mode);
@@ -222,7 +222,7 @@ cmake::~cmake()
#ifdef CMAKE_BUILD_WITH_CMAKE
delete this->VariableWatch;
#endif
- delete this->FileComparison;
+ delete this->FileTimeCache;
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -2139,7 +2139,7 @@ int cmake::CheckBuildSystem()
std::string dep_newest = *dep++;
for (; dep != depends.end(); ++dep) {
int result = 0;
- if (this->FileComparison->FileTimeCompare(dep_newest, *dep, &result)) {
+ if (this->FileTimeCache->Compare(dep_newest, *dep, &result)) {
if (result < 0) {
dep_newest = *dep;
}
@@ -2158,7 +2158,7 @@ int cmake::CheckBuildSystem()
std::string out_oldest = *out++;
for (; out != outputs.end(); ++out) {
int result = 0;
- if (this->FileComparison->FileTimeCompare(out_oldest, *out, &result)) {
+ if (this->FileTimeCache->Compare(out_oldest, *out, &result)) {
if (result > 0) {
out_oldest = *out;
}
@@ -2175,8 +2175,7 @@ int cmake::CheckBuildSystem()
// If any output is older than any dependency then rerun.
{
int result = 0;
- if (!this->FileComparison->FileTimeCompare(out_oldest, dep_newest,
- &result) ||
+ if (!this->FileTimeCache->Compare(out_oldest, dep_newest, &result) ||
result < 0) {
if (verbose) {
std::ostringstream msg;
@@ -2431,20 +2430,22 @@ static bool cmakeCheckStampFile(const std::string& stampName)
}
// Compare the stamp dependencies against the dependency file itself.
- cmFileTimeComparison ftc;
- std::string dep;
- while (cmSystemTools::GetLineFromStream(fin, dep)) {
- int result;
- if (!dep.empty() && dep[0] != '#' &&
- (!ftc.FileTimeCompare(stampDepends, dep, &result) || result < 0)) {
- // The stamp depends file is older than this dependency. The
- // build system is really out of date.
- std::cout << "CMake is re-running because " << stampName
- << " is out-of-date.\n";
- std::cout << " the file '" << dep << "'\n";
- std::cout << " is newer than '" << stampDepends << "'\n";
- std::cout << " result='" << result << "'\n";
- return false;
+ {
+ cmFileTimeCache ftc;
+ std::string dep;
+ while (cmSystemTools::GetLineFromStream(fin, dep)) {
+ int result;
+ if (!dep.empty() && dep[0] != '#' &&
+ (!ftc.Compare(stampDepends, dep, &result) || result < 0)) {
+ // The stamp depends file is older than this dependency. The
+ // build system is really out of date.
+ std::cout << "CMake is re-running because " << stampName
+ << " is out-of-date.\n";
+ std::cout << " the file '" << dep << "'\n";
+ std::cout << " is newer than '" << stampDepends << "'\n";
+ std::cout << " result='" << result << "'\n";
+ return false;
+ }
}
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 1ffeabc..f8a2319 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -26,7 +26,7 @@
class cmExternalMakefileProjectGeneratorFactory;
class cmFileAPI;
-class cmFileTimeComparison;
+class cmFileTimeCache;
class cmGlobalGenerator;
class cmGlobalGeneratorFactory;
class cmMakefile;
@@ -329,7 +329,7 @@ public:
/**
* Get the file comparison class
*/
- cmFileTimeComparison* GetFileComparison() { return this->FileComparison; }
+ cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache; }
// Do we want debug output during the cmake run.
bool GetDebugOutput() { return this->DebugOutput; }
@@ -509,7 +509,7 @@ private:
std::unordered_set<std::string> HeaderFileExtensionsSet;
bool ClearBuildSystem;
bool DebugTryCompile;
- cmFileTimeComparison* FileComparison;
+ cmFileTimeCache* FileTimeCache;
std::string GraphVizFile;
InstalledFilesMap InstalledFiles;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index b83c744..d70c9d9 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -23,6 +23,7 @@
# include "cmsys/ConsoleBuf.hxx"
#endif
+#include <cassert>
#include <ctype.h>
#include <iostream>
#include <string.h>
@@ -72,11 +73,20 @@ static const char* cmDocumentationUsageNote[][2] = {
" the build commands to be executed. \n" \
" -- = Pass remaining options to the native tool.\n"
+# define CMAKE_INSTALL_OPTIONS \
+ " <dir> = Project binary directory to install.\n" \
+ " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
+ " --component <comp> = Component-based install. Only install <comp>.\n" \
+ " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n" \
+ " --strip = Performing install/strip.\n" \
+ " -v --verbose = Enable verbose output.\n"
+
static const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
{ "-E", "CMake command mode." },
{ "-L[A][H]", "List non-advanced cached variables." },
{ "--build <dir>", "Build a CMake-generated project binary tree." },
+ { "--install <dir>", "Install a CMake-generated project binary tree." },
{ "--open <dir>", "Open generated project in the associated application." },
{ "-N", "View mode only." },
{ "-P <file>", "Process script mode." },
@@ -115,6 +125,7 @@ static int do_command(int ac, char const* const* av)
int do_cmake(int ac, char const* const* av);
static int do_build(int ac, char const* const* av);
+static int do_install(int ac, char const* const* av);
static int do_open(int ac, char const* const* av);
static cmMakefile* cmakemainGetMakefile(cmake* cm)
@@ -189,6 +200,9 @@ int main(int ac, char const* const* av)
if (strcmp(av[1], "--build") == 0) {
return do_build(ac, av);
}
+ if (strcmp(av[1], "--install") == 0) {
+ return do_install(ac, av);
+ }
if (strcmp(av[1], "--open") == 0) {
return do_open(ac, av);
}
@@ -525,6 +539,117 @@ static int do_build(int ac, char const* const* av)
#endif
}
+static int do_install(int ac, char const* const* av)
+{
+#ifndef CMAKE_BUILD_WITH_CMAKE
+ std::cerr << "This cmake does not support --install\n";
+ return -1;
+#else
+ assert(1 < ac);
+
+ std::string config;
+ std::string component;
+ std::string prefix;
+ std::string dir;
+ bool strip = false;
+ bool verbose = cmSystemTools::HasEnv("VERBOSE");
+
+ enum Doing
+ {
+ DoingNone,
+ DoingDir,
+ DoingConfig,
+ DoingComponent,
+ DoingPrefix,
+ };
+
+ Doing doing = DoingDir;
+
+ for (int i = 2; i < ac; ++i) {
+ if (strcmp(av[i], "--config") == 0) {
+ doing = DoingConfig;
+ } else if (strcmp(av[i], "--component") == 0) {
+ doing = DoingComponent;
+ } else if (strcmp(av[i], "--prefix") == 0) {
+ doing = DoingPrefix;
+ } else if (strcmp(av[i], "--strip") == 0) {
+ strip = true;
+ doing = DoingNone;
+ } else if ((strcmp(av[i], "--verbose") == 0) ||
+ (strcmp(av[i], "-v") == 0)) {
+ verbose = true;
+ doing = DoingNone;
+ } else {
+ switch (doing) {
+ case DoingDir:
+ dir = cmSystemTools::CollapseFullPath(av[i]);
+ doing = DoingNone;
+ break;
+ case DoingConfig:
+ config = av[i];
+ doing = DoingNone;
+ break;
+ case DoingComponent:
+ component = av[i];
+ doing = DoingNone;
+ break;
+ case DoingPrefix:
+ prefix = av[i];
+ doing = DoingNone;
+ break;
+ default:
+ std::cerr << "Unknown argument " << av[i] << std::endl;
+ dir.clear();
+ break;
+ }
+ }
+ }
+
+ if (dir.empty()) {
+ std::cerr << "Usage: cmake --install <dir> "
+ "[options]\nOptions:\n" CMAKE_INSTALL_OPTIONS;
+ return 1;
+ }
+
+ cmake cm(cmake::RoleScript, cmState::Script);
+
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
+ });
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.SetDebugOutputOn(verbose);
+ cm.SetWorkingMode(cmake::SCRIPT_MODE);
+
+ std::vector<std::string> args{ av[0] };
+
+ if (!prefix.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_PREFIX=" + prefix);
+ }
+
+ if (!component.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_COMPONENT=" + component);
+ }
+
+ if (strip) {
+ args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1");
+ }
+
+ if (!config.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config);
+ }
+
+ args.emplace_back("-P");
+ args.emplace_back(dir + "/cmake_install.cmake");
+
+ return cm.Run(args) ? 1 : 0;
+#endif
+}
+
static int do_open(int ac, char const* const* av)
{
#ifndef CMAKE_BUILD_WITH_CMAKE
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index f996a3e..0828a16 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1114,6 +1114,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
} else if (flags.find_first_of('c') != std::string::npos) {
+ if (files.empty()) {
+ cmSystemTools::Message("tar: No files or directories specified",
+ "Warning");
+ }
if (!cmSystemTools::CreateTar(outFile.c_str(), files, compress,
verbose, mtime, format)) {
cmSystemTools::Error("Problem creating tar: " + outFile);
diff --git a/Tests/CMakeLib/testUTF8.cxx b/Tests/CMakeLib/testUTF8.cxx
index c99c46d..a0bb5cd 100644
--- a/Tests/CMakeLib/testUTF8.cxx
+++ b/Tests/CMakeLib/testUTF8.cxx
@@ -13,6 +13,21 @@ static void test_utf8_char_print(test_utf8_char const c)
static_cast<int>(d[3]));
}
+static void byte_array_print(char const* s)
+{
+ unsigned char const* d = reinterpret_cast<unsigned char const*>(s);
+ bool started = false;
+ printf("[");
+ for (; *d; ++d) {
+ if (started) {
+ printf(",");
+ }
+ started = true;
+ printf("0x%02X", static_cast<int>(*d));
+ }
+ printf("]");
+}
+
struct test_utf8_entry
{
int n;
@@ -21,17 +36,36 @@ struct test_utf8_entry
};
static test_utf8_entry const good_entry[] = {
- { 1, "\x20\x00\x00\x00", 0x0020 }, /* Space. */
- { 2, "\xC2\xA9\x00\x00", 0x00A9 }, /* Copyright. */
- { 3, "\xE2\x80\x98\x00", 0x2018 }, /* Open-single-quote. */
- { 3, "\xE2\x80\x99\x00", 0x2019 }, /* Close-single-quote. */
- { 4, "\xF0\xA3\x8E\xB4", 0x233B4 }, /* Example from RFC 3629. */
+ { 1, "\x20\x00\x00\x00", 0x0020 }, /* Space. */
+ { 2, "\xC2\xA9\x00\x00", 0x00A9 }, /* Copyright. */
+ { 3, "\xE2\x80\x98\x00", 0x2018 }, /* Open-single-quote. */
+ { 3, "\xE2\x80\x99\x00", 0x2019 }, /* Close-single-quote. */
+ { 4, "\xF0\xA3\x8E\xB4", 0x233B4 }, /* Example from RFC 3629. */
+ { 3, "\xED\x80\x80\x00", 0xD000 }, /* Valid 0xED prefixed codepoint. */
+ { 4, "\xF4\x8F\xBF\xBF", 0x10FFFF }, /* Highest valid RFC codepoint. */
{ 0, { 0, 0, 0, 0, 0 }, 0 }
};
static test_utf8_char const bad_chars[] = {
- "\x80\x00\x00\x00", "\xC0\x00\x00\x00", "\xE0\x00\x00\x00",
- "\xE0\x80\x80\x00", "\xF0\x80\x80\x80", { 0, 0, 0, 0, 0 }
+ "\x80\x00\x00\x00", /* Leading continuation byte. */
+ "\xC0\x80\x00\x00", /* Overlong encoding. */
+ "\xC1\x80\x00\x00", /* Overlong encoding. */
+ "\xC2\x00\x00\x00", /* Missing continuation byte. */
+ "\xE0\x00\x00\x00", /* Missing continuation bytes. */
+ "\xE0\x80\x80\x00", /* Overlong encoding. */
+ "\xF0\x80\x80\x80", /* Overlong encoding. */
+ "\xED\xA0\x80\x00", /* UTF-16 surrogate half. */
+ "\xED\xBF\xBF\x00", /* UTF-16 surrogate half. */
+ "\xF4\x90\x80\x80", /* Lowest out-of-range codepoint. */
+ "\xF5\x80\x80\x80", /* Prefix forces out-of-range codepoints. */
+ { 0, 0, 0, 0, 0 }
+};
+
+static char const* good_strings[] = { "", "ASCII", "\xC2\xA9 Kitware", 0 };
+
+static char const* bad_strings[] = {
+ "\xC0\x80", /* Modified UTF-8 for embedded 0-byte. */
+ 0
};
static void report_good(bool passed, test_utf8_char const c)
@@ -87,6 +121,46 @@ static bool decode_bad(test_utf8_char const s)
return true;
}
+static void report_valid(bool passed, char const* s)
+{
+ printf("%s: validity good ", passed ? "pass" : "FAIL");
+ byte_array_print(s);
+ printf(" (%s) ", s);
+}
+
+static void report_invalid(bool passed, char const* s)
+{
+ printf("%s: validity bad ", passed ? "pass" : "FAIL");
+ byte_array_print(s);
+ printf(" ");
+}
+
+static bool is_valid(const char* s)
+{
+ bool valid = cm_utf8_is_valid(s) != 0;
+ if (!valid) {
+ report_valid(false, s);
+ printf("expected valid, reported as invalid\n");
+ return false;
+ }
+ report_valid(true, s);
+ printf("valid as expected\n");
+ return true;
+}
+
+static bool is_invalid(const char* s)
+{
+ bool valid = cm_utf8_is_valid(s) != 0;
+ if (valid) {
+ report_invalid(false, s);
+ printf("expected invalid, reported as valid\n");
+ return false;
+ }
+ report_invalid(true, s);
+ printf("invalid as expected\n");
+ return true;
+}
+
int testUTF8(int /*unused*/, char* /*unused*/ [])
{
int result = 0;
@@ -94,11 +168,27 @@ int testUTF8(int /*unused*/, char* /*unused*/ [])
if (!decode_good(*e)) {
result = 1;
}
+ if (!is_valid(e->str)) {
+ result = 1;
+ }
}
for (test_utf8_char const* c = bad_chars; (*c)[0]; ++c) {
if (!decode_bad(*c)) {
result = 1;
}
+ if (!is_invalid(*c)) {
+ result = 1;
+ }
+ }
+ for (char const** s = good_strings; *s; ++s) {
+ if (!is_valid(*s)) {
+ result = 1;
+ }
+ }
+ for (char const** s = bad_strings; *s; ++s) {
+ if (!is_invalid(*s)) {
+ result = 1;
+ }
}
return result;
}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 01f8226..d793adf 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1421,6 +1421,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindDoxygen)
endif()
+ if(CMake_TEST_FindEnvModules)
+ add_subdirectory(FindEnvModules)
+ endif()
+
if(CMake_TEST_FindEXPAT)
add_subdirectory(FindEXPAT)
endif()
@@ -1445,6 +1449,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindGit)
endif()
+ if(CMake_TEST_FindGLEW)
+ add_subdirectory(FindGLEW)
+ endif()
+
if(CMake_TEST_FindGSL)
add_subdirectory(FindGSL)
endif()
diff --git a/Tests/FindEnvModules/CMakeLists.txt b/Tests/FindEnvModules/CMakeLists.txt
new file mode 100644
index 0000000..95b7d1d
--- /dev/null
+++ b/Tests/FindEnvModules/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_test(FindEnvModules.Test ${CMAKE_CMAKE_COMMAND}
+ -P ${CMAKE_CURRENT_LIST_DIR}/EnvModules.cmake
+)
diff --git a/Tests/FindEnvModules/EnvModules.cmake b/Tests/FindEnvModules/EnvModules.cmake
new file mode 100644
index 0000000..0c81bf2
--- /dev/null
+++ b/Tests/FindEnvModules/EnvModules.cmake
@@ -0,0 +1,35 @@
+find_package(EnvModules REQUIRED)
+message("module purge")
+env_module(COMMAND purge RESULT_VARIABLE ret_var)
+if(NOT ret_var EQUAL 0)
+ message(FATAL_ERROR "module(purge) returned ${ret_var}")
+endif()
+
+message("module avail")
+env_module_avail(avail_mods)
+foreach(mod IN LISTS avail_mods)
+ message(" ${mod}")
+endforeach()
+
+if(avail_mods)
+ list(GET avail_mods 0 mod0)
+ message("module load ${mod0}")
+ env_module(load ${mod0})
+
+ message("module list")
+ env_module_list(loaded_mods)
+ foreach(mod IN LISTS loaded_mods)
+ message(" ${mod}")
+ endforeach()
+
+ list(LENGTH loaded_mods num_loaded_mods)
+ message("Number of modules loaded: ${num_loaded_mods}")
+ if(NOT num_loaded_mods EQUAL 1)
+ message(FATAL_ERROR "Exactly 1 module should be loaded. Found ${num_loaded_mods}")
+ endif()
+
+ list(GET loaded_mods 0 mod0_actual)
+ if(NOT (mod0_actual MATCHES "^${mod0}"))
+ message(FATAL_ERROR "Loaded module does not match ${mod0}. Actual: ${mod0_actual}")
+ endif()
+endif()
diff --git a/Tests/FindGLEW/CMakeLists.txt b/Tests/FindGLEW/CMakeLists.txt
new file mode 100644
index 0000000..ff42bce
--- /dev/null
+++ b/Tests/FindGLEW/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindGLEW.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindGLEW/Test"
+ "${CMake_BINARY_DIR}/Tests/FindGLEW/Test"
+ ${build_generator_args}
+ --build-project TestFindGLEW
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindGLEW/Test/CMakeLists.txt b/Tests/FindGLEW/Test/CMakeLists.txt
new file mode 100644
index 0000000..954ee10
--- /dev/null
+++ b/Tests/FindGLEW/Test/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.1)
+project(TestFindGLEW LANGUAGES CXX)
+include(CTest)
+
+find_package(GLEW REQUIRED)
+
+add_executable(test_glew_shared_tgt main.cpp)
+target_link_libraries(test_glew_shared_tgt GLEW::GLEW)
+add_test(NAME test_glew_shared_tgt COMMAND test_glew_shared_tgt)
+
+add_executable(test_glew_generic_tgt main.cpp)
+target_link_libraries(test_glew_generic_tgt GLEW::glew)
+add_test(NAME test_glew_generic_tgt COMMAND test_glew_generic_tgt)
+
+add_executable(test_glew_var main.cpp)
+target_include_directories(test_glew_var PRIVATE ${GLEW_INCLUDE_DIRS})
+target_link_libraries(test_glew_var PRIVATE ${GLEW_LIBRARIES})
+add_test(NAME test_glew_var COMMAND test_glew_var)
diff --git a/Tests/FindGLEW/Test/main.cpp b/Tests/FindGLEW/Test/main.cpp
new file mode 100644
index 0000000..4a108ad
--- /dev/null
+++ b/Tests/FindGLEW/Test/main.cpp
@@ -0,0 +1,8 @@
+#include <GL/glew.h>
+
+int main()
+{
+ GLenum init_return = glewInit();
+
+ return (init_return == GLEW_OK);
+}
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 5b5c5a5..3deabd0 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -54,6 +54,14 @@ run_cmake_command(build-bad-dir
run_cmake_command(build-bad-generator
${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator)
+run_cmake_command(install-no-dir
+ ${CMAKE_COMMAND} --install)
+run_cmake_command(install-bad-dir
+ ${CMAKE_COMMAND} --install dir-does-not-exist)
+run_cmake_command(install-options-to-vars
+ ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars
+ --strip --prefix /var/test --config sample --component pack)
+
run_cmake_command(cache-bad-entry
${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-entry/)
run_cmake_command(cache-empty-entry
diff --git a/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake b/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake
new file mode 100644
index 0000000..fd4e67d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake
@@ -0,0 +1,15 @@
+if(CMAKE_INSTALL_PREFIX)
+ message("CMAKE_INSTALL_PREFIX is ${CMAKE_INSTALL_PREFIX}")
+endif()
+
+if(CMAKE_INSTALL_COMPONENT)
+ message("CMAKE_INSTALL_COMPONENT is ${CMAKE_INSTALL_COMPONENT}")
+endif()
+
+if(CMAKE_INSTALL_CONFIG_NAME)
+ message("CMAKE_INSTALL_CONFIG_NAME is ${CMAKE_INSTALL_CONFIG_NAME}")
+endif()
+
+if(CMAKE_INSTALL_DO_STRIP)
+ message("CMAKE_INSTALL_DO_STRIP is ${CMAKE_INSTALL_DO_STRIP}")
+endif()
diff --git a/Tests/RunCMake/CommandLine/install-bad-dir-result.txt b/Tests/RunCMake/CommandLine/install-bad-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-bad-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt b/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt
new file mode 100644
index 0000000..320aecc
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Error processing file:
diff --git a/Tests/RunCMake/CommandLine/install-no-dir-result.txt b/Tests/RunCMake/CommandLine/install-no-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-no-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt b/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt
new file mode 100644
index 0000000..d64f638
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt
@@ -0,0 +1 @@
+^Usage: cmake --install <dir> \[options\]
diff --git a/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt b/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt b/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt
new file mode 100644
index 0000000..f7b1583
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt
@@ -0,0 +1,4 @@
+CMAKE_INSTALL_PREFIX is /var/test
+CMAKE_INSTALL_COMPONENT is pack
+CMAKE_INSTALL_CONFIG_NAME is sample
+CMAKE_INSTALL_DO_STRIP is 1
diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
index 12635db..c8a3de9 100644
--- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
@@ -4,6 +4,7 @@ function(external_command_test NAME)
run_cmake_command(${NAME} ${CMAKE_COMMAND} -E ${ARGN})
endfunction()
+external_command_test(without-files tar cvf bad.tar)
external_command_test(bad-opt1 tar cvf bad.tar --bad)
external_command_test(bad-mtime1 tar cvf bad.tar --mtime=bad .)
external_command_test(bad-from1 tar cvf bad.tar --files-from=bad)
@@ -11,12 +12,13 @@ external_command_test(bad-from2 tar cvf bad.tar --files-from=.)
external_command_test(bad-from3 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from3.txt)
external_command_test(bad-from4 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from4.txt)
external_command_test(bad-from5 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from5.txt)
+external_command_test(bad-file tar cf bad.tar badfile.txt ${CMAKE_CURRENT_LIST_DIR}/test-file.txt)
external_command_test(end-opt1 tar cvf bad.tar -- --bad)
external_command_test(end-opt2 tar cvf bad.tar --)
-external_command_test(mtime tar cvf bad.tar "--mtime=1970-01-01 00:00:00 UTC")
-external_command_test(bad-format tar cvf bad.tar "--format=bad-format")
-external_command_test(zip-bz2 tar cvjf bad.tar "--format=zip")
-external_command_test(7zip-gz tar cvzf bad.tar "--format=7zip")
+external_command_test(mtime tar cvf bad.tar "--mtime=1970-01-01 00:00:00 UTC" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt)
+external_command_test(bad-format tar cvf bad.tar "--format=bad-format" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt)
+external_command_test(zip-bz2 tar cvjf bad.tar "--format=zip" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt)
+external_command_test(7zip-gz tar cvzf bad.tar "--format=7zip" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt)
run_cmake(7zip)
run_cmake(gnutar)
diff --git a/Tests/RunCMake/CommandLineTar/bad-file-result.txt b/Tests/RunCMake/CommandLineTar/bad-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/bad-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLineTar/bad-file-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-file-stderr.txt
new file mode 100644
index 0000000..1f9f748
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/bad-file-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Unable to read from file 'badfile.txt': .*
+CMake Error: Problem creating tar: bad.tar$
diff --git a/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt
index 1417d4d..fb0702a 100644
--- a/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt
+++ b/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt
@@ -1,2 +1,2 @@
-^CMake Error: archive_read_disk_entry_from_file 'does-not-exist':.*
+^CMake Error: Unable to read from file 'does-not-exist':.*
CMake Error: Problem creating tar: bad.tar$
diff --git a/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt
index 1417d4d..fb0702a 100644
--- a/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt
+++ b/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt
@@ -1,2 +1,2 @@
-^CMake Error: archive_read_disk_entry_from_file 'does-not-exist':.*
+^CMake Error: Unable to read from file 'does-not-exist':.*
CMake Error: Problem creating tar: bad.tar$
diff --git a/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt b/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt
index 1fddf6d..1342dc8 100644
--- a/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt
+++ b/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt
@@ -1,2 +1,2 @@
-^CMake Error: archive_read_disk_entry_from_file '--bad':.*
+^CMake Error: Unable to read from file '--bad':.*
CMake Error: Problem creating tar: bad.tar$
diff --git a/Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt b/Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt
new file mode 100644
index 0000000..70166f5
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt
@@ -0,0 +1 @@
+^tar: No files or directories specified
diff --git a/Tests/RunCMake/CommandLineTar/test-file.txt b/Tests/RunCMake/CommandLineTar/test-file.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/test-file.txt
diff --git a/Tests/RunCMake/CommandLineTar/without-files-stderr.txt b/Tests/RunCMake/CommandLineTar/without-files-stderr.txt
new file mode 100644
index 0000000..70166f5
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/without-files-stderr.txt
@@ -0,0 +1 @@
+^tar: No files or directories specified
diff --git a/Utilities/cmzstd/CMakeLists.txt b/Utilities/cmzstd/CMakeLists.txt
index b1399bd..8ed04d8 100644
--- a/Utilities/cmzstd/CMakeLists.txt
+++ b/Utilities/cmzstd/CMakeLists.txt
@@ -41,4 +41,7 @@ add_library(cmzstd STATIC
lib/dictBuilder/zdict.c
)
+# BMI2 instructions are not supported in older environments.
+set_property(TARGET cmzstd PROPERTY COMPILE_DEFINITIONS DYNAMIC_BMI2=0)
+
install(FILES LICENSE DESTINATION ${CMAKE_DOC_DIR}/cmzstd)
diff --git a/bootstrap b/bootstrap
index af05024..537b43b 100755
--- a/bootstrap
+++ b/bootstrap
@@ -304,7 +304,8 @@ CMAKE_CXX_SOURCES="\
cmFileCommand \
cmFileCopier \
cmFileInstaller \
- cmFileTimeComparison \
+ cmFileTime \
+ cmFileTimeCache \
cmFindBase \
cmFindCommon \
cmFindFileCommand \