summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/file.rst11
-rw-r--r--Help/release/dev/file-size.rst5
-rw-r--r--Source/cmFileCommand.cxx32
-rw-r--r--Source/cmFileCommand.h1
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/file/SIZE-error-does-not-exist-result.txt1
-rw-r--r--Tests/RunCMake/file/SIZE-error-does-not-exist-stderr.txt5
-rw-r--r--Tests/RunCMake/file/SIZE-error-does-not-exist.cmake3
-rw-r--r--Tests/RunCMake/file/SIZE.cmake9
9 files changed, 69 insertions, 0 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst
index f5279c0..26a9ae2 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -25,6 +25,7 @@ Synopsis
file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...])
file(`MAKE_DIRECTORY`_ [<dir>...])
file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...])
+ file(`SIZE`_ <filename> <out-var>)
`Path Conversion`_
file(`RELATIVE_PATH`_ <out-var> <directory> <file>)
@@ -333,6 +334,16 @@ and ``NO_SOURCE_PERMISSIONS`` is default.
Installation scripts generated by the :command:`install` command
use this signature (with some undocumented options for internal use).
+.. _SIZE:
+
+.. code-block:: cmake
+
+ file(SIZE <filename> <variable>)
+
+Determine the file size of the ``<filename>`` and put the result in
+``<variable>`` variable. Requires that ``<filename>`` is a valid path
+pointing to a file and is readable.
+
Path Conversion
^^^^^^^^^^^^^^^
diff --git a/Help/release/dev/file-size.rst b/Help/release/dev/file-size.rst
new file mode 100644
index 0000000..4f0e196
--- /dev/null
+++ b/Help/release/dev/file-size.rst
@@ -0,0 +1,5 @@
+file-size
+---------
+
+* The :command:`file` command gained a ``SIZE`` mode to get the size
+ of a file on disk.
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index fa2a3e1..73ff5a1 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -177,6 +177,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "LOCK") {
return this->HandleLockCommand(args);
}
+ if (subCommand == "SIZE") {
+ return this->HandleSizeCommand(args);
+ }
std::string e = "does not recognize sub-command " + subCommand;
this->SetError(e);
@@ -3606,3 +3609,32 @@ bool cmFileCommand::HandleTimestampCommand(
return true;
}
+
+bool cmFileCommand::HandleSizeCommand(std::vector<std::string> const& args)
+{
+ if (args.size() != 3) {
+ std::ostringstream e;
+ e << args[0] << " requires a file name and output variable";
+ this->SetError(e.str());
+ return false;
+ }
+
+ unsigned int argsIndex = 1;
+
+ const std::string& filename = args[argsIndex++];
+
+ const std::string& outputVariable = args[argsIndex++];
+
+ if (!cmSystemTools::FileExists(filename, true)) {
+ std::ostringstream e;
+ e << "SIZE requested of path that is not readable " << filename;
+ this->SetError(e.str());
+ return false;
+ }
+
+ this->Makefile->AddDefinition(
+ outputVariable,
+ std::to_string(cmSystemTools::FileLength(filename)).c_str());
+
+ return true;
+}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 719dca2..01e007d 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -59,6 +59,7 @@ protected:
bool HandleTimestampCommand(std::vector<std::string> const& args);
bool HandleGenerateCommand(std::vector<std::string> const& args);
bool HandleLockCommand(std::vector<std::string> const& args);
+ bool HandleSizeCommand(std::vector<std::string> const& args);
private:
void AddEvaluationFile(const std::string& inputName,
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index b383230..b9d76bf 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -36,6 +36,8 @@ run_cmake(READ_ELF)
run_cmake(GLOB)
run_cmake(GLOB_RECURSE)
run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS)
+run_cmake(SIZE)
+run_cmake(SIZE-error-does-not-exist)
# tests are valid both for GLOB and GLOB_RECURSE
run_cmake(GLOB-sort-dedup)
diff --git a/Tests/RunCMake/file/SIZE-error-does-not-exist-result.txt b/Tests/RunCMake/file/SIZE-error-does-not-exist-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/SIZE-error-does-not-exist-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/SIZE-error-does-not-exist-stderr.txt b/Tests/RunCMake/file/SIZE-error-does-not-exist-stderr.txt
new file mode 100644
index 0000000..b797a41
--- /dev/null
+++ b/Tests/RunCMake/file/SIZE-error-does-not-exist-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at SIZE-error-does-not-exist.cmake:[0-9]+ \(file\):
+ file SIZE requested of path that is not readable
+ /a/file/that/does-not-exist
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file/SIZE-error-does-not-exist.cmake b/Tests/RunCMake/file/SIZE-error-does-not-exist.cmake
new file mode 100644
index 0000000..edcc222
--- /dev/null
+++ b/Tests/RunCMake/file/SIZE-error-does-not-exist.cmake
@@ -0,0 +1,3 @@
+set(file "/a/file/that/does-not-exist")
+
+file(SIZE "${file}" CALCULATED_SIZE)
diff --git a/Tests/RunCMake/file/SIZE.cmake b/Tests/RunCMake/file/SIZE.cmake
new file mode 100644
index 0000000..4d9dbd2
--- /dev/null
+++ b/Tests/RunCMake/file/SIZE.cmake
@@ -0,0 +1,9 @@
+set(file "${CMAKE_CURRENT_BINARY_DIR}/a-test-file")
+
+file(WRITE "${file}" "test")
+
+file(SIZE "${file}" CALCULATED_SIZE)
+
+if (NOT CALCULATED_SIZE EQUAL 4)
+ message(FATAL_ERROR "Unexpected file size")
+endif()