diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2020-08-26 12:33:18 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2020-09-08 16:33:57 (GMT) |
commit | be36266dabee16d17a4f2e71fa9d05f8ef4769ce (patch) | |
tree | 57d4da5efc5b6b4dc8837acb63dcb471fd8266b5 | |
parent | 503d0f80e1ccafa8352145b1a733dd41751dcd7f (diff) | |
download | CMake-be36266dabee16d17a4f2e71fa9d05f8ef4769ce.zip CMake-be36266dabee16d17a4f2e71fa9d05f8ef4769ce.tar.gz CMake-be36266dabee16d17a4f2e71fa9d05f8ef4769ce.tar.bz2 |
file(): Add REAL_PATH sub-command
-rw-r--r-- | Help/command/file.rst | 14 | ||||
-rw-r--r-- | Help/command/get_filename_component.rst | 5 | ||||
-rw-r--r-- | Help/release/dev/file-REAL_PATH.rst | 5 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 46 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH-no-base-dir-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt | 2 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH-no-base-dir.cmake | 2 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH-unexpected-arg-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH-unexpected-arg-stderr.txt | 2 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH-unexpected-arg.cmake | 2 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH.cmake | 14 | ||||
-rw-r--r-- | Tests/RunCMake/file/RunCMakeTest.cmake | 3 |
12 files changed, 95 insertions, 2 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst index f4a817e..d77ad2d 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -49,6 +49,7 @@ Synopsis file(`CHMOD_RECURSE`_ <files>... <directories>... PERMISSIONS <permissions>... [...]) `Path Conversion`_ + file(`REAL_PATH`_ <path> <out-var> [BASE_DIRECTORY <dir>]) file(`RELATIVE_PATH`_ <out-var> <directory> <file>) file({`TO_CMAKE_PATH`_ | `TO_NATIVE_PATH`_} <path> <out-var>) @@ -806,6 +807,19 @@ the ``<directories>..`` recursively. Path Conversion ^^^^^^^^^^^^^^^ +.. _REAL_PATH: + +.. code-block:: cmake + + file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>]) + +Compute the absolute path to an existing file or directory with symlinks +resolved. + +If the provided ``<path>`` is a relative path, it is evaluated relative to the +given base directory ``<dir>``. If no base directory is provided, the default +base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`. + .. _RELATIVE_PATH: .. code-block:: cmake diff --git a/Help/command/get_filename_component.rst b/Help/command/get_filename_component.rst index 9d33a0a..e8c68b2 100644 --- a/Help/command/get_filename_component.rst +++ b/Help/command/get_filename_component.rst @@ -46,8 +46,9 @@ cache. .. note:: - All previous sub-commands, except ``REALPATH``, has been superseded by - :command:`cmake_path` command. + All previous sub-commands has been superseded by + :command:`cmake_path` command, except ``REALPATH`` now offered by + :ref:`file(REAL_PATH) <REAL_PATH>` command. .. code-block:: cmake diff --git a/Help/release/dev/file-REAL_PATH.rst b/Help/release/dev/file-REAL_PATH.rst new file mode 100644 index 0000000..32768ca --- /dev/null +++ b/Help/release/dev/file-REAL_PATH.rst @@ -0,0 +1,5 @@ +file-REAL_PATH +-------------- + +* The :command:`file` gained sub-command `REAL_PATH` to compute a path with + symlinks resolved. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index cdb1492..84639a7 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -28,6 +28,7 @@ #include "cmAlgorithms.h" #include "cmArgumentParser.h" +#include "cmCMakePath.h" #include "cmCryptoHash.h" #include "cmExecutionStatus.h" #include "cmFSPermissions.h" @@ -1234,6 +1235,50 @@ bool HandleInstallCommand(std::vector<std::string> const& args, return installer.Run(args); } +bool HandleRealPathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 3) { + status.SetError("REAL_PATH requires a path and an output variable"); + return false; + } + + struct Arguments + { + std::string BaseDirectory; + }; + static auto const parser = cmArgumentParser<Arguments>{}.Bind( + "BASE_DIRECTORY"_s, &Arguments::BaseDirectory); + + std::vector<std::string> unparsedArguments; + std::vector<std::string> keywordsMissingValue; + std::vector<std::string> parsedKeywords; + auto arguments = + parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments, + &keywordsMissingValue, &parsedKeywords); + + if (!unparsedArguments.empty()) { + status.SetError("REAL_PATH called with unexpected arguments"); + return false; + } + if (!keywordsMissingValue.empty()) { + status.SetError("BASE_DIRECTORY requires a value"); + return false; + } + + if (parsedKeywords.empty()) { + arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); + } + + cmCMakePath path(args[1]); + path = path.Absolute(arguments.BaseDirectory).Normal(); + auto realPath = cmSystemTools::GetRealPath(path.GenericString()); + + status.GetMakefile().AddDefinition(args[2], realPath); + + return true; +} + bool HandleRelativePathCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -3360,6 +3405,7 @@ bool cmFileCommand(std::vector<std::string> const& args, { "RPATH_CHECK"_s, HandleRPathCheckCommand }, { "RPATH_REMOVE"_s, HandleRPathRemoveCommand }, { "READ_ELF"_s, HandleReadElfCommand }, + { "REAL_PATH"_s, HandleRealPathCommand }, { "RELATIVE_PATH"_s, HandleRelativePathCommand }, { "TO_CMAKE_PATH"_s, HandleCMakePathCommand }, { "TO_NATIVE_PATH"_s, HandleNativePathCommand }, diff --git a/Tests/RunCMake/file/REAL_PATH-no-base-dir-result.txt b/Tests/RunCMake/file/REAL_PATH-no-base-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH-no-base-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt new file mode 100644 index 0000000..7c58aeb --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\): + file BASE_DIRECTORY requires a value diff --git a/Tests/RunCMake/file/REAL_PATH-no-base-dir.cmake b/Tests/RunCMake/file/REAL_PATH-no-base-dir.cmake new file mode 100644 index 0000000..132aee6 --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH-no-base-dir.cmake @@ -0,0 +1,2 @@ + +file(REAL_PATH "some-path" real_path BASE_DIRECTORY) diff --git a/Tests/RunCMake/file/REAL_PATH-unexpected-arg-result.txt b/Tests/RunCMake/file/REAL_PATH-unexpected-arg-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH-unexpected-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/REAL_PATH-unexpected-arg-stderr.txt b/Tests/RunCMake/file/REAL_PATH-unexpected-arg-stderr.txt new file mode 100644 index 0000000..301db75 --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH-unexpected-arg-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at REAL_PATH-unexpected-arg.cmake:[0-9]+ \(file\): + file REAL_PATH called with unexpected arguments diff --git a/Tests/RunCMake/file/REAL_PATH-unexpected-arg.cmake b/Tests/RunCMake/file/REAL_PATH-unexpected-arg.cmake new file mode 100644 index 0000000..144f30b --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH-unexpected-arg.cmake @@ -0,0 +1,2 @@ + +file(REAL_PATH "some-path" real_path extra_arg) diff --git a/Tests/RunCMake/file/REAL_PATH.cmake b/Tests/RunCMake/file/REAL_PATH.cmake new file mode 100644 index 0000000..be25706 --- /dev/null +++ b/Tests/RunCMake/file/REAL_PATH.cmake @@ -0,0 +1,14 @@ + +file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt") +file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym") +file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC) + +file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path) +if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") +endif() + +file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") +if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 8d84943..22813eb 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -72,6 +72,9 @@ if(NOT WIN32 OR CYGWIN) run_cmake(READ_SYMLINK-noexist) run_cmake(READ_SYMLINK-notsymlink) run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) + run_cmake(REAL_PATH-unexpected-arg) + run_cmake(REAL_PATH-no-base-dir) + run_cmake(REAL_PATH) endif() if(RunCMake_GENERATOR MATCHES "Ninja") |