diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 0ba42d2eb..d270c77d3 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -151,6 +151,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) std::vector archive_configurations; std::vector library_configurations; std::vector runtime_configurations; + bool archive_optional = false; + bool library_optional = false; + bool runtime_optional = false; for(unsigned int i=1; i < args.size(); ++i) { if(args[i] == "DESTINATION") @@ -225,6 +228,27 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) library_settings = false; runtime_settings = true; } + else if(args[i] == "OPTIONAL") + { + // Set the optional property. + doing_targets = false; + doing_destination = false; + doing_permissions = false; + doing_component = false; + doing_configurations = false; + if(archive_settings) + { + archive_optional = true; + } + if(library_settings) + { + library_optional = true; + } + if(runtime_settings) + { + runtime_optional = true; + } + } else if(doing_targets) { // Lookup this target in the current directory. @@ -404,7 +428,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) new cmInstallTargetGenerator(target, archive_dest.c_str(), true, archive_permissions.c_str(), archive_configurations, - archive_component.c_str())); + archive_component.c_str(), + archive_optional)); } if(runtime_destination) { @@ -414,7 +439,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) false, runtime_permissions.c_str(), runtime_configurations, - runtime_component.c_str())); + runtime_component.c_str(), + runtime_optional)); } } else @@ -428,7 +454,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) false, library_permissions.c_str(), library_configurations, - library_component.c_str())); + library_component.c_str(), + library_optional)); } else { @@ -450,7 +477,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) new cmInstallTargetGenerator(target, archive_dest.c_str(), false, archive_permissions.c_str(), archive_configurations, - archive_component.c_str())); + archive_component.c_str(), + archive_optional)); } else { @@ -471,7 +499,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) new cmInstallTargetGenerator(target, library_dest.c_str(), false, library_permissions.c_str(), library_configurations, - library_component.c_str())); + library_component.c_str(), + library_optional)); } else { @@ -492,7 +521,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) new cmInstallTargetGenerator(target, runtime_dest.c_str(), false, runtime_permissions.c_str(), runtime_configurations, - runtime_component.c_str())); + runtime_component.c_str(), + runtime_optional)); } else { @@ -540,6 +570,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) std::string permissions; std::vector configurations; std::string component; + bool optional = false; for(unsigned int i=1; i < args.size(); ++i) { if(args[i] == "DESTINATION") @@ -592,6 +623,17 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) doing_component = false; doing_rename = true; } + else if(args[i] == "OPTIONAL") + { + // Set the optional property. + doing_files = false; + doing_destination = false; + doing_permissions = false; + doing_configurations = false; + doing_component = false; + doing_rename = false; + optional = true; + } else if(doing_files) { // Convert this file to a full path. @@ -686,7 +728,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) this->Makefile->AddInstallGenerator( new cmInstallFilesGenerator(files, dest.c_str(), programs, permissions.c_str(), configurations, - component.c_str(), rename.c_str())); + component.c_str(), rename.c_str(), + optional)); // Tell the global generator about any installation component names // specified. diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 79ed2cac6..afd66ea7c 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -93,6 +93,8 @@ public: "The RENAME argument specifies a name for an installed file that " "may be different from the original file. Renaming is allowed only " "when a single file is installed by the command. " + "The OPTIONAL argument specifies that it is not an error if the " + "file to be installed does not exist. " "\n" "The TARGETS signature:\n" " INSTALL(TARGETS targets...\n" @@ -101,6 +103,7 @@ public: " [PERMISSIONS permissions...]\n" " [CONFIGURATIONS [Debug|Release|...]]\n" " [COMPONENT ]\n" + " [OPTIONAL]\n" " ] [...])\n" "The TARGETS form specifies rules for installing targets from a " "project. There are three kinds of target files that may be " @@ -146,7 +149,7 @@ public: " [PERMISSIONS permissions...]\n" " [CONFIGURATIONS [Debug|Release|...]]\n" " [COMPONENT ]\n" - " [RENAME ])\n" + " [RENAME ] [OPTIONAL])\n" "The FILES form specifies rules for installing files for a " "project. File names given as relative paths are interpreted with " "respect to the current source directory. Files installed by this " @@ -158,7 +161,7 @@ public: " [PERMISSIONS permissions...]\n" " [CONFIGURATIONS [Debug|Release|...]]\n" " [COMPONENT ]\n" - " [RENAME ])\n" + " [RENAME ] [OPTIONAL])\n" "The PROGRAMS form is identical to the FILES form except that the " "default permissions for the installed file also include " "OWNER_EXECUTE, GROUP_EXECUTE, and WORLD_EXECUTE. " diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index fd857a507..075285c25 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -25,10 +25,11 @@ cmInstallFilesGenerator const char* file_permissions, std::vector const& configurations, const char* component, - const char* rename): + const char* rename, + bool optional): Files(files), Destination(dest), Programs(programs), FilePermissions(file_permissions), Configurations(configurations), - Component(component), Rename(rename) + Component(component), Rename(rename), Optional(optional) { } @@ -45,14 +46,13 @@ void cmInstallFilesGenerator::GenerateScript(std::ostream& os) for(std::vector::const_iterator fi = this->Files.begin(); fi != this->Files.end(); ++fi) { - bool not_optional = false; const char* no_properties = 0; const char* no_dir_permissions = 0; this->AddInstallRule(os, this->Destination.c_str(), (this->Programs ? cmTarget::INSTALL_PROGRAMS : cmTarget::INSTALL_FILES), fi->c_str(), - not_optional, no_properties, + this->Optional, no_properties, this->FilePermissions.c_str(), no_dir_permissions, this->Configurations, this->Component.c_str(), diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 400d29a79..4438ae7f2 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -30,7 +30,8 @@ public: const char* file_permissions, std::vector const& configurations, const char* component, - const char* rename); + const char* rename, + bool optional = false); virtual ~cmInstallFilesGenerator(); protected: @@ -42,6 +43,7 @@ protected: std::vector Configurations; std::string Component; std::string Rename; + bool Optional; }; #endif diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 1e99cd91c..61536c8b6 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -27,10 +27,10 @@ cmInstallTargetGenerator ::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib, const char* file_permissions, std::vector const& configurations, - const char* component): + const char* component, bool optional): Target(&t), Destination(dest), ImportLibrary(implib), FilePermissions(file_permissions), Configurations(configurations), - Component(component) + Component(component), Optional(optional) { this->Target->SetHaveInstallRule(true); } @@ -162,8 +162,9 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os) // Write code to install the target file. const char* no_dir_permissions = 0; const char* no_rename = 0; + bool optional = this->Optional | this->ImportLibrary; this->AddInstallRule(os, destination.c_str(), type, fromFile.c_str(), - this->ImportLibrary, properties, + optional, properties, this->FilePermissions.c_str(), no_dir_permissions, this->Configurations, this->Component.c_str(), diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 63eea304d..77f9fec46 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -32,7 +32,8 @@ public: const char* file_permissions = "", std::vector const& configurations = std::vector(), - const char* component = "" + const char* component = "", + bool optional = false ); virtual ~cmInstallTargetGenerator(); @@ -50,6 +51,7 @@ protected: std::string FilePermissions; std::vector Configurations; std::string Component; + bool Optional; }; #endif diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index a99f6d32f..564b4fa5a 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -166,6 +166,9 @@ ELSE(STAGE2) ) INSTALL_FILES(/MyTest/include FILES lib3.h) + # Test optional installation. + INSTALL(FILES does_not_exist.h DESTINATION MyTest/include/foo OPTIONAL) + # Test configuration-specific installation. INSTALL(FILES lib1.h RENAME lib1release.h CONFIGURATIONS Release DESTINATION MyTest/include/Release diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index a99f6d32f..564b4fa5a 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/Tests/SimpleInstallS2/CMakeLists.txt @@ -166,6 +166,9 @@ ELSE(STAGE2) ) INSTALL_FILES(/MyTest/include FILES lib3.h) + # Test optional installation. + INSTALL(FILES does_not_exist.h DESTINATION MyTest/include/foo OPTIONAL) + # Test configuration-specific installation. INSTALL(FILES lib1.h RENAME lib1release.h CONFIGURATIONS Release DESTINATION MyTest/include/Release