install: Add CMAKE_INSTALL_MESSAGE variable (#13761)

Create a variable to allow users to control which installation
messages are printed.  In particular, provide a "LAZY" setting
that prints "Installing" messages but not "Up-to-date" messages.
This is desirable for incremental re-installations.

Suggested-by: J Decker <d3ck0r@gmail.com>
This commit is contained in:
Brad King 2014-06-24 11:18:43 -04:00
parent ec7cf7ea13
commit c9568de52c
15 changed files with 113 additions and 8 deletions

View File

@ -298,6 +298,7 @@ See the :command:`install(DIRECTORY)` command for documentation of
permissions, ``PATTERN``, ``REGEX``, and ``EXCLUDE`` options. permissions, ``PATTERN``, ``REGEX``, and ``EXCLUDE`` options.
The ``INSTALL`` signature differs slightly from ``COPY``: it prints The ``INSTALL`` signature differs slightly from ``COPY``: it prints
status messages, and ``NO_SOURCE_PERMISSIONS`` is default. status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable),
and ``NO_SOURCE_PERMISSIONS`` is default.
Installation scripts generated by the :command:`install` command Installation scripts generated by the :command:`install` command
use this signature (with some undocumented options for internal use). use this signature (with some undocumented options for internal use).

View File

@ -59,6 +59,10 @@ signatures that specify them. The common options are:
Specify that it is not an error if the file to be installed does Specify that it is not an error if the file to be installed does
not exist. not exist.
Command signatures that install files may print messages during
installation. Use the :variable:`CMAKE_INSTALL_MESSAGE` variable
to control which messages are printed.
Installing Targets Installing Targets
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^

View File

@ -128,6 +128,7 @@ Variables that Change Behavior
/variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE /variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE
/variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE /variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
/variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME /variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME
/variable/CMAKE_INSTALL_MESSAGE
/variable/CMAKE_INSTALL_PREFIX /variable/CMAKE_INSTALL_PREFIX
/variable/CMAKE_LIBRARY_PATH /variable/CMAKE_LIBRARY_PATH
/variable/CMAKE_MFC_FLAG /variable/CMAKE_MFC_FLAG

View File

@ -0,0 +1,5 @@
install-messages
----------------
* The :variable:`CMAKE_INSTALL_MESSAGE` variable was introduced to
optionally reduce output installation.

View File

@ -0,0 +1,30 @@
CMAKE_INSTALL_MESSAGE
---------------------
Specify verbosity of installation script code generated by the
:command:`install` command (using the :command:`file(INSTALL)` command).
For paths that are newly installed or updated, installation
may print lines like::
-- Installing: /some/destination/path
For paths that are already up to date, installation may print
lines like::
-- Up-to-date: /some/destination/path
The ``CMAKE_INSTALL_MESSAGE`` variable may be set to control
which messages are printed:
``ALWAYS``
Print both ``Installing`` and ``Up-to-date`` messages.
``LAZY``
Print ``Installing`` but not ``Up-to-date`` messages.
``NEVER``
Print neither ``Installing`` nor ``Up-to-date`` messages.
Other values have undefined behavior and may not be diagnosed.
If this variable is not set, the default behavior is ``ALWAYS``.

View File

@ -26,7 +26,7 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false) const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false)
{ {
cmInstallGenerator::MessageLevel message = cmInstallGenerator::MessageLevel message =
cmInstallGenerator::MessageDefault; cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
return new cmInstallTargetGenerator(target, args.GetDestination().c_str(), return new cmInstallTargetGenerator(target, args.GetDestination().c_str(),
impLib, args.GetPermissions().c_str(), impLib, args.GetPermissions().c_str(),
args.GetConfigurations(), args.GetComponent().c_str(), args.GetConfigurations(), args.GetComponent().c_str(),
@ -40,7 +40,7 @@ static cmInstallFilesGenerator* CreateInstallFilesGenerator(
const cmInstallCommandArguments& args, bool programs) const cmInstallCommandArguments& args, bool programs)
{ {
cmInstallGenerator::MessageLevel message = cmInstallGenerator::MessageLevel message =
cmInstallGenerator::MessageDefault; cmInstallGenerator::SelectMessageLevel(mf);
return new cmInstallFilesGenerator(mf, return new cmInstallFilesGenerator(mf,
absFiles, args.GetDestination().c_str(), absFiles, args.GetDestination().c_str(),
programs, args.GetPermissions().c_str(), programs, args.GetPermissions().c_str(),
@ -1215,7 +1215,7 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
} }
cmInstallGenerator::MessageLevel message = cmInstallGenerator::MessageLevel message =
cmInstallGenerator::MessageDefault; cmInstallGenerator::SelectMessageLevel(this->Makefile);
// Create the directory install generator. // Create the directory install generator.
this->Makefile->AddInstallGenerator( this->Makefile->AddInstallGenerator(
@ -1344,7 +1344,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
} }
cmInstallGenerator::MessageLevel message = cmInstallGenerator::MessageLevel message =
cmInstallGenerator::MessageDefault; cmInstallGenerator::SelectMessageLevel(this->Makefile);
// Create the export install generator. // Create the export install generator.
cmInstallExportGenerator* exportGenerator = cmInstallExportGenerator* exportGenerator =

View File

@ -133,7 +133,7 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
"CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
std::vector<std::string> no_configurations; std::vector<std::string> no_configurations;
cmInstallGenerator::MessageLevel message = cmInstallGenerator::MessageLevel message =
cmInstallGenerator::MessageDefault; cmInstallGenerator::SelectMessageLevel(this->Makefile);
this->Makefile->AddInstallGenerator( this->Makefile->AddInstallGenerator(
new cmInstallFilesGenerator(this->Makefile, this->Files, new cmInstallFilesGenerator(this->Makefile, this->Files,
destination.c_str(), false, destination.c_str(), false,

View File

@ -11,6 +11,7 @@
============================================================================*/ ============================================================================*/
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -98,6 +99,13 @@ void cmInstallGenerator
{ {
os << " OPTIONAL"; os << " OPTIONAL";
} }
switch(this->Message)
{
case MessageDefault: break;
case MessageAlways: os << " MESSAGE_ALWAYS"; break;
case MessageLazy: os << " MESSAGE_LAZY"; break;
case MessageNever: os << " MESSAGE_NEVER"; break;
}
if(permissions_file && *permissions_file) if(permissions_file && *permissions_file)
{ {
os << " PERMISSIONS" << permissions_file; os << " PERMISSIONS" << permissions_file;
@ -182,3 +190,23 @@ std::string cmInstallGenerator::GetInstallDestination() const
result += this->Destination; result += this->Destination;
return result; return result;
} }
//----------------------------------------------------------------------------
cmInstallGenerator::MessageLevel
cmInstallGenerator::SelectMessageLevel(cmMakefile* mf)
{
std::string m = mf->GetSafeDefinition("CMAKE_INSTALL_MESSAGE");
if(m == "ALWAYS")
{
return MessageAlways;
}
if(m == "LAZY")
{
return MessageLazy;
}
if(m == "NEVER")
{
return MessageNever;
}
return MessageDefault;
}

View File

@ -16,6 +16,7 @@
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmLocalGenerator; class cmLocalGenerator;
class cmMakefile;
/** \class cmInstallGenerator /** \class cmInstallGenerator
* \brief Support class for generating install scripts. * \brief Support class for generating install scripts.
@ -27,6 +28,9 @@ public:
enum MessageLevel enum MessageLevel
{ {
MessageDefault, MessageDefault,
MessageAlways,
MessageLazy,
MessageNever
}; };
cmInstallGenerator(const char* destination, cmInstallGenerator(const char* destination,
@ -56,6 +60,9 @@ public:
/** Test if this generator installs something for a given configuration. */ /** Test if this generator installs something for a given configuration. */
bool InstallsForConfig(const std::string& config); bool InstallsForConfig(const std::string& config);
/** Select message level from CMAKE_INSTALL_MESSAGE. */
static MessageLevel SelectMessageLevel(cmMakefile* mf);
protected: protected:
virtual void GenerateScript(std::ostream& os); virtual void GenerateScript(std::ostream& os);

View File

@ -94,7 +94,7 @@ void cmInstallProgramsCommand::FinalPass()
"CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
std::vector<std::string> no_configurations; std::vector<std::string> no_configurations;
cmInstallGenerator::MessageLevel message = cmInstallGenerator::MessageLevel message =
cmInstallGenerator::MessageDefault; cmInstallGenerator::SelectMessageLevel(this->Makefile);
this->Makefile->AddInstallGenerator( this->Makefile->AddInstallGenerator(
new cmInstallFilesGenerator(this->Makefile, this->Files, new cmInstallFilesGenerator(this->Makefile, this->Files,
destination.c_str(), true, destination.c_str(), true,

View File

@ -3004,7 +3004,7 @@ public:
cmInstallTargetGeneratorLocal(cmTarget& t, const char* dest, bool implib): cmInstallTargetGeneratorLocal(cmTarget& t, const char* dest, bool implib):
cmInstallTargetGenerator( cmInstallTargetGenerator(
t, dest, implib, "", std::vector<std::string>(), "Unspecified", t, dest, implib, "", std::vector<std::string>(), "Unspecified",
MessageDefault, cmInstallGenerator::SelectMessageLevel(t.GetMakefile()),
false) {} false) {}
}; };

View File

@ -0,0 +1,24 @@
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/prefix)
execute_process(COMMAND ${CMAKE_COMMAND} -P ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake
OUTPUT_VARIABLE out ERROR_VARIABLE err)
set(expect "
-- Installing: [^\n]*/prefix/dir\r?
-- Installing: [^\n]*/prefix/dir/empty.txt\r?
")
if(NOT out MATCHES "${expect}")
string(REGEX REPLACE "\n" "\n " out " ${out}")
set(RunCMake_TEST_FAILED
"${RunCMake_TEST_FAILED}First install did not say 'Installing' as expected:\n${out}")
endif()
set(f ${RunCMake_TEST_BINARY_DIR}/prefix/dir/empty.txt)
if(NOT EXISTS "${f}")
set(RunCMake_TEST_FAILED
"${RunCMake_TEST_FAILED}File was not installed:\n ${f}\n")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -P ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake
OUTPUT_VARIABLE out ERROR_VARIABLE err)
if(out MATCHES "(Installing|Up-to-date)")
string(REGEX REPLACE "\n" "\n " out " ${out}")
set(RunCMake_TEST_FAILED
"${RunCMake_TEST_FAILED}Second install was not silent as expected:\n${out}")
endif()

View File

@ -0,0 +1,3 @@
set(CMAKE_INSTALL_MESSAGE "LAZY")
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/prefix")
install(DIRECTORY dir/ DESTINATION dir)

View File

@ -1,2 +1,3 @@
set(CMAKE_INSTALL_MESSAGE "ALWAYS")
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/prefix") set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/prefix")
install(DIRECTORY dir/ DESTINATION dir) install(DIRECTORY dir/ DESTINATION dir)

View File

@ -1,5 +1,6 @@
include(RunCMake) include(RunCMake)
run_cmake(DIRECTORY-message) run_cmake(DIRECTORY-message)
run_cmake(DIRECTORY-message-lazy)
run_cmake(SkipInstallRulesWarning) run_cmake(SkipInstallRulesWarning)
run_cmake(SkipInstallRulesNoWarning1) run_cmake(SkipInstallRulesNoWarning1)
run_cmake(SkipInstallRulesNoWarning2) run_cmake(SkipInstallRulesNoWarning2)