From 08b14163ee2cc9cced08d80b2c81b29c83072229 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 30 Mar 2006 13:33:48 -0500 Subject: [PATCH] ENH: Added named component installation implementation. Installation behavior should be unchanged unless -DCOMPONENT= is specified when cmake_install.cmake is invoked. --- Source/cmFileCommand.cxx | 32 +++++++++++ Source/cmGlobalGenerator.cxx | 8 +++ Source/cmGlobalGenerator.h | 5 ++ Source/cmInstallCommand.cxx | 88 ++++++++++++++++++++++++++--- Source/cmInstallCommand.h | 14 ++++- Source/cmInstallFilesGenerator.cxx | 10 +++- Source/cmInstallFilesGenerator.h | 5 +- Source/cmInstallGenerator.cxx | 5 ++ Source/cmInstallGenerator.h | 1 + Source/cmInstallTargetGenerator.cxx | 20 ++++--- Source/cmInstallTargetGenerator.h | 4 +- Source/cmLocalGenerator.cxx | 38 +++++++++++-- 12 files changed, 203 insertions(+), 27 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 588111bbe..408eec067 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -329,6 +329,7 @@ bool cmFileCommand::HandleInstallCommand( const char* destdir = cmSystemTools::GetEnv("DESTDIR"); + std::set components; std::vector files; int itype = cmTarget::INSTALL_FILES; @@ -367,6 +368,7 @@ bool cmFileCommand::HandleInstallCommand( bool in_files = false; bool in_properties = false; bool in_permissions = false; + bool in_components = false; bool use_given_permissions = false; mode_t permissions = 0; bool optional = false; @@ -380,6 +382,7 @@ bool cmFileCommand::HandleInstallCommand( in_files = false; in_properties = false; in_permissions = false; + in_components = false; } else if ( *cstr == "TYPE" && i < args.size()-1 ) { @@ -393,6 +396,7 @@ bool cmFileCommand::HandleInstallCommand( in_properties = false; in_files = false; in_permissions = false; + in_components = false; } else if ( *cstr == "RENAME" && i < args.size()-1 ) { @@ -401,12 +405,14 @@ bool cmFileCommand::HandleInstallCommand( in_properties = false; in_files = false; in_permissions = false; + in_components = false; } else if ( *cstr == "PROPERTIES" ) { in_properties = true; in_files = false; in_permissions = false; + in_components = false; } else if ( *cstr == "PERMISSIONS" ) { @@ -414,12 +420,21 @@ bool cmFileCommand::HandleInstallCommand( in_properties = false; in_files = false; in_permissions = true; + in_components = false; + } + else if ( *cstr == "COMPONENTS" ) + { + in_properties = false; + in_files = false; + in_permissions = false; + in_components = true; } else if ( *cstr == "FILES" && !in_files) { in_files = true; in_properties = false; in_permissions = false; + in_components = false; } else if ( in_properties && i < args.size()-1 ) { @@ -430,6 +445,10 @@ bool cmFileCommand::HandleInstallCommand( { files.push_back(*cstr); } + else if ( in_components ) + { + components.insert(*cstr); + } else if(in_permissions && args[i] == "OWNER_READ") { permissions |= mode_owner_read; @@ -488,6 +507,19 @@ bool cmFileCommand::HandleInstallCommand( return false; } + // Check for component-specific installation. + const char* cmake_install_component = + this->Makefile->GetDefinition("CMAKE_INSTALL_COMPONENT"); + if(cmake_install_component && *cmake_install_component) + { + // This install rule applies only if it is associated with the + // current component. + if(components.find(cmake_install_component) == components.end()) + { + return true; + } + } + int destDirLength = 0; if ( destdir && *destdir ) { diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 55929fea9..7f2ba800b 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -869,6 +869,14 @@ void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg) this->CMakeInstance->UpdateProgress("Configuring", prog); } +void cmGlobalGenerator::AddInstallComponent(const char* component) +{ + if(component && *component) + { + this->InstallComponents.insert(component); + } +} + cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator() { cmLocalGenerator *lg = new cmLocalGenerator; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 5836d7276..04906119a 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -121,6 +121,8 @@ public: g = this->LocalGenerators;} void AddLocalGenerator(cmLocalGenerator *lg); + + void AddInstallComponent(const char* component); static int s_TryCompileTimeout; @@ -198,6 +200,9 @@ protected: // map from project name to vector of local generators in that project std::map > ProjectMap; + // Set of named installation components requested by the project. + std::set InstallComponents; + private: // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index f02ba9894..f51fb28f5 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -99,6 +99,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) bool doing_targets = true; bool doing_destination = false; bool doing_permissions = false; + bool doing_component = false; bool archive_settings = true; bool library_settings = true; bool runtime_settings = true; @@ -109,6 +110,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) std::string archive_permissions; std::string library_permissions; std::string runtime_permissions; + std::string archive_component; + std::string library_component; + std::string runtime_component; for(unsigned int i=1; i < args.size(); ++i) { if(args[i] == "DESTINATION") @@ -117,6 +121,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_targets = false; doing_destination = true; doing_permissions = false; + doing_component = false; } else if(args[i] == "PERMISSIONS") { @@ -124,6 +129,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_targets = false; doing_destination = false; doing_permissions = true; + doing_component = false; + } + else if(args[i] == "COMPONENT") + { + // Switch to setting the component property. + doing_targets = false; + doing_destination = false; + doing_permissions = false; + doing_component = true; } else if(args[i] == "ARCHIVE") { @@ -131,6 +145,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_targets = false; doing_destination = false; doing_permissions = false; + doing_component = false; archive_settings = true; library_settings = false; runtime_settings = false; @@ -141,6 +156,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_targets = false; doing_destination = false; doing_permissions = false; + doing_component = false; archive_settings = false; library_settings = true; runtime_settings = false; @@ -151,6 +167,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_targets = false; doing_destination = false; doing_permissions = false; + doing_component = false; archive_settings = false; library_settings = false; runtime_settings = true; @@ -203,6 +220,23 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) } doing_destination = false; } + else if(doing_component) + { + // Set the component in the active set(s) of properties. + if(archive_settings) + { + archive_component = args[i]; + } + if(library_settings) + { + library_component = args[i]; + } + if(runtime_settings) + { + runtime_component = args[i]; + } + doing_component = false; + } else if(doing_permissions) { // Set the permissions in the active set(s) of properties. @@ -293,14 +327,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) // The import library uses the ARCHIVE properties. this->Makefile->AddInstallGenerator( new cmInstallTargetGenerator(target, archive_dest.c_str(), true, - archive_permissions.c_str())); + archive_permissions.c_str(), + archive_component.c_str())); } if(runtime_destination) { // The DLL uses the RUNTIME properties. this->Makefile->AddInstallGenerator( new cmInstallTargetGenerator(target, runtime_dest.c_str(), false, - runtime_permissions.c_str())); + runtime_permissions.c_str(), + runtime_component.c_str())); } #else // This is a non-DLL platform. @@ -309,7 +345,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) // The shared library uses the LIBRARY properties. this->Makefile->AddInstallGenerator( new cmInstallTargetGenerator(target, library_dest.c_str(), false, - library_permissions.c_str())); + library_permissions.c_str(), + library_component.c_str())); } else { @@ -329,7 +366,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) { this->Makefile->AddInstallGenerator( new cmInstallTargetGenerator(target, archive_dest.c_str(), false, - archive_permissions.c_str())); + archive_permissions.c_str(), + archive_component.c_str())); } else { @@ -348,7 +386,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) { this->Makefile->AddInstallGenerator( new cmInstallTargetGenerator(target, library_dest.c_str(), false, - library_permissions.c_str())); + library_permissions.c_str(), + library_component.c_str())); } else { @@ -367,7 +406,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) { this->Makefile->AddInstallGenerator( new cmInstallTargetGenerator(target, runtime_dest.c_str(), false, - runtime_permissions.c_str())); + runtime_permissions.c_str(), + runtime_component.c_str())); } else { @@ -386,6 +426,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) } } + // Tell the global generator about any installation component names + // specified. + this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->AddInstallComponent(archive_component.c_str()); + this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->AddInstallComponent(library_component.c_str()); + this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->AddInstallComponent(runtime_component.c_str()); + return true; } @@ -397,11 +446,13 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) bool doing_files = true; bool doing_destination = false; bool doing_permissions = false; + bool doing_component = false; bool doing_rename = false; std::vector files; const char* destination = 0; std::string rename; std::string permissions; + std::string component; for(unsigned int i=1; i < args.size(); ++i) { if(args[i] == "DESTINATION") @@ -410,6 +461,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) doing_files = false; doing_destination = true; doing_permissions = false; + doing_component = false; doing_rename = false; } else if(args[i] == "PERMISSIONS") @@ -418,6 +470,16 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) doing_files = false; doing_destination = false; doing_permissions = true; + doing_component = false; + doing_rename = false; + } + else if(args[i] == "COMPONENT") + { + // Switch to setting the component property. + doing_files = false; + doing_destination = false; + doing_permissions = false; + doing_component = true; doing_rename = false; } else if(args[i] == "RENAME") @@ -426,6 +488,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) doing_files = false; doing_destination = false; doing_permissions = false; + doing_component = false; doing_rename = true; } else if(doing_files) @@ -456,6 +519,11 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) destination = args[i].c_str(); doing_destination = false; } + else if(doing_component) + { + component = args[i]; + doing_component = false; + } else if(doing_permissions) { // Check the requested permission. @@ -512,7 +580,13 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) // Create the files install generator. this->Makefile->AddInstallGenerator( new cmInstallFilesGenerator(files, dest.c_str(), programs, - permissions.c_str(), rename.c_str())); + permissions.c_str(), component.c_str(), + rename.c_str())); + + // Tell the global generator about any installation component names + // specified. + this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->AddInstallComponent(component.c_str()); return true; } diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index e74d3b9fb..ea5e2010f 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -83,6 +83,11 @@ public: "SETUID, and SETGID. " "Permissions that do not make sense on certain platforms are ignored " "on those platforms. " + "The COMPONENT argument specifies an installation component name " + "with which the install rule is associated, such as \"runtime\" or " + "\"development\". During component-specific installation only " + "install rules associated with the given component name will be " + "executed. During a full installation all components are installed. " "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. " @@ -91,6 +96,7 @@ public: " INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME]\n" " [DESTINATION ]\n" " [PERMISSIONS permissions...]\n" + " [COMPONENT ]\n" " ] [...])\n" "The TARGETS form specifies rules for installing targets from a " "project. There are three kinds of target files that may be " @@ -131,7 +137,9 @@ public: "\n" "The FILES signature:\n" " INSTALL(FILES files... DESTINATION \n" - " [PERMISSIONS permissions...] [RENAME ])\n" + " [PERMISSIONS permissions...]\n" + " [COMPONENT ]\n" + " [RENAME ])\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 " @@ -139,7 +147,9 @@ public: "\n" "The PROGRAMS signature:\n" " INSTALL(PROGRAMS files... DESTINATION \n" - " [PERMISSIONS permissions...] [RENAME ])\n" + " [PERMISSIONS permissions...]\n" + " [COMPONENT ]\n" + " [RENAME ])\n" "The PROGRAMS form is identical to the FILES form except that the " "default permissions for the installed file mark it as executable. " "This form is intended to install programs that are not targets, " diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index ff32fe2bd..bf0d83079 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -22,9 +22,11 @@ cmInstallFilesGenerator ::cmInstallFilesGenerator(std::vector const& files, const char* dest, bool programs, - const char* permissions, const char* rename): + const char* permissions, + const char* component, + const char* rename): Files(files), Destination(dest), Programs(programs), - Permissions(permissions), Rename(rename) + Permissions(permissions), Component(component), Rename(rename) { } @@ -48,6 +50,8 @@ void cmInstallFilesGenerator::GenerateScript(std::ostream& os) ? cmTarget::INSTALL_PROGRAMS : cmTarget::INSTALL_FILES), fi->c_str(), not_optional, no_properties, - this->Permissions.c_str(), this->Rename.c_str()); + this->Permissions.c_str(), + this->Component.c_str(), + this->Rename.c_str()); } } diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index dc2094fc3..7732ff92a 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -27,7 +27,9 @@ class cmInstallFilesGenerator: public cmInstallGenerator public: cmInstallFilesGenerator(std::vector const& files, const char* dest, bool programs, - const char* permissions, const char* rename); + const char* permissions, + const char* component, + const char* rename); virtual ~cmInstallFilesGenerator(); protected: @@ -36,6 +38,7 @@ protected: std::string Destination; bool Programs; std::string Permissions; + std::string Component; std::string Rename; }; diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 3a7fd92ae..44b693652 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -54,6 +54,7 @@ void cmInstallGenerator::AddInstallRule(std::ostream& os, bool optional /* = false */, const char* properties /* = 0 */, const char* permissions /* = 0 */, + const char* component /* = 0 */, const char* rename /* = 0 */) { // Use the FILE command to install the file. @@ -86,5 +87,9 @@ void cmInstallGenerator::AddInstallRule(std::ostream& os, { os << " RENAME \"" << rename << "\""; } + if(component && *component) + { + os << " COMPONENTS \"" << component << "\""; + } os << " FILES \"" << file << "\")\n"; } diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 73aa4ff13..fee0d681e 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -38,6 +38,7 @@ public: const char* file, bool optional = false, const char* properties = 0, const char* permissions = 0, + const char* component = 0, const char* rename = 0); protected: diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 90b14a4be..690904a69 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -24,9 +24,9 @@ //---------------------------------------------------------------------------- cmInstallTargetGenerator ::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib, - const char* permissions): + const char* permissions, const char* component): Target(&t), Destination(dest), ImportLibrary(implib), - Permissions(permissions) + Permissions(permissions), Component(component) { this->Target->SetHaveInstallRule(true); } @@ -145,7 +145,7 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os) // Write code to install the target file. this->AddInstallRule(os, destination.c_str(), type, fromFile.c_str(), this->ImportLibrary, properties, - this->Permissions.c_str()); + this->Permissions.c_str(), this->Component.c_str()); // Fix the install_name settings in installed binaries. if(type == cmTarget::SHARED_LIBRARY || @@ -335,18 +335,24 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(std::ostream& os, // install_name value and references. if(!new_id.empty() || !install_name_remap.empty()) { - os << "EXECUTE_PROCESS(COMMAND install_name_tool"; + std::string component_test = + "NOT CMAKE_INSTALL_COMPONENT OR \"${CMAKE_INSTALL_COMPONENT}\" MATCHES \"^("; + component_test += this->Component; + component_test += ")$\""; + os << "IF(" << component_test << ")\n"; + os << " EXECUTE_PROCESS(COMMAND install_name_tool"; if(!new_id.empty()) { - os << "\n -id \"" << new_id << "\""; + os << "\n -id \"" << new_id << "\""; } for(std::map::const_iterator i = install_name_remap.begin(); i != install_name_remap.end(); ++i) { - os << "\n -change \"" << i->first << "\" \"" << i->second << "\""; + os << "\n -change \"" << i->first << "\" \"" << i->second << "\""; } - os << "\n \"" << destination << "/" + os << "\n \"" << destination << "/" << this->GetScriptReference(this->Target, "REMAPPED", true) << "\")\n"; + os << "ENDIF(" << component_test << ")\n"; } } diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 482e3f4db..7d88bdec6 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -28,7 +28,8 @@ class cmInstallTargetGenerator: public cmInstallGenerator { public: cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib, - const char* permissions = ""); + const char* permissions = "", + const char* component = ""); virtual ~cmInstallTargetGenerator(); protected: @@ -43,6 +44,7 @@ protected: std::string Destination; bool ImportLibrary; std::string Permissions; + std::string Component; }; #endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4f98ffb1d..af82c45e3 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -329,6 +329,19 @@ void cmLocalGenerator::GenerateInstallRules() "ENDIF(NOT CMAKE_INSTALL_CONFIG_NAME)\n" "\n"; + // Write support code for dealing with component-specific installs. + fout << + "# Set the component getting installed.\n" + "IF(NOT CMAKE_INSTALL_COMPONENT)\n" + " IF(COMPONENT)\n" + " MESSAGE(STATUS \"Install component: \\\"${COMPONENT}\\\"\")\n" + " SET(CMAKE_INSTALL_COMPONENT \"${COMPONENT}\")\n" + " ELSE(COMPONENT)\n" + " SET(CMAKE_INSTALL_COMPONENT)\n" + " ENDIF(COMPONENT)\n" + "ENDIF(NOT CMAKE_INSTALL_COMPONENT)\n" + "\n"; + // Ask each install generator to write its code. std::vector const& installers = this->Makefile->GetInstallGenerators(); @@ -358,10 +371,21 @@ void cmLocalGenerator::GenerateInstallRules() // Record the install manifest. if ( toplevel_install ) { - fout << "FILE(WRITE \"" << homedir.c_str() << "/install_manifest.txt\" " - << "\"\")" << std::endl; - fout << "FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})" << std::endl - << " FILE(APPEND \"" << homedir.c_str() << "/install_manifest.txt\" " + fout << + "IF(CMAKE_INSTALL_COMPONENT)\n" + " SET(CMAKE_INSTALL_MANIFEST \"install_manifest_" + "${CMAKE_INSTALL_COMPONENT}.txt\")\n" + "ELSE(CMAKE_INSTALL_COMPONENT)\n" + " SET(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n" + "ENDIF(CMAKE_INSTALL_COMPONENT)\n"; + fout + << "FILE(WRITE \"" + << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" " + << "\"\")" << std::endl; + fout + << "FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})" << std::endl + << " FILE(APPEND \"" + << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" " << "\"${file}\\n\")" << std::endl << "ENDFOREACH(file)" << std::endl; } @@ -1698,9 +1722,10 @@ cmLocalGenerator // Use a file install generator. const char* no_permissions = ""; const char* no_rename = ""; + const char* no_component = ""; cmInstallFilesGenerator g(l->second.GetSourceLists(), destination.c_str(), false, - no_permissions, no_rename); + no_permissions, no_component, no_rename); g.Generate(os, config, configurationTypes); } break; @@ -1709,9 +1734,10 @@ cmLocalGenerator // Use a file install generator. const char* no_permissions = ""; const char* no_rename = ""; + const char* no_component = ""; cmInstallFilesGenerator g(l->second.GetSourceLists(), destination.c_str(), true, - no_permissions, no_rename); + no_permissions, no_component, no_rename); g.Generate(os, config, configurationTypes); } break;