diff options
Diffstat (limited to 'Source/cmSetPropertyCommand.cxx')
-rw-r--r-- | Source/cmSetPropertyCommand.cxx | 197 |
1 files changed, 184 insertions, 13 deletions
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 4dbbbd7..07cb7c9 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -43,7 +43,9 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, - bool appendMode, bool remove); + bool appendMode, bool remove, + const std::vector<cmMakefile*>& directory_makefiles, + bool source_file_paths_should_be_absolute); bool HandleSource(cmSourceFile* sf, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, bool appendMode, bool remove); @@ -74,6 +76,131 @@ bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, bool appendMode, bool remove); } +namespace SetPropertyCommand { +bool HandleSourceFileDirectoryScopes( + cmExecutionStatus& status, std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories, + std::vector<cmMakefile*>& directory_makefiles) +{ + cmMakefile* current_dir_mf = &status.GetMakefile(); + if (!source_file_directories.empty()) { + for (const std::string& dir_path : source_file_directories) { + const std::string absolute_dir_path = cmSystemTools::CollapseFullPath( + dir_path, current_dir_mf->GetCurrentSourceDirectory()); + cmMakefile* dir_mf = + status.GetMakefile().GetGlobalGenerator()->FindMakefile( + absolute_dir_path); + if (!dir_mf) { + status.SetError(cmStrCat("given non-existent DIRECTORY ", dir_path)); + return false; + } + directory_makefiles.push_back(dir_mf); + } + } else if (!source_file_target_directories.empty()) { + for (const std::string& target_name : source_file_target_directories) { + cmTarget* target = current_dir_mf->FindTargetToUse(target_name); + if (!target) { + status.SetError(cmStrCat( + "given non-existent target for DIRECTORY_TARGET ", target_name)); + return false; + } + cmProp target_source_dir = target->GetProperty("SOURCE_DIR"); + cmMakefile* target_dir_mf = + status.GetMakefile().GetGlobalGenerator()->FindMakefile( + *target_source_dir); + directory_makefiles.push_back(target_dir_mf); + } + } else { + directory_makefiles.push_back(current_dir_mf); + } + return true; +} + +bool HandleSourceFileDirectoryScopeValidation( + cmExecutionStatus& status, bool source_file_directory_option_enabled, + bool source_file_target_option_enabled, + std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories) +{ + // Validate source file directory scopes. + if (source_file_directory_option_enabled && + source_file_directories.empty()) { + std::string errors = "called with incorrect number of arguments " + "no value provided to the DIRECTORY option"; + status.SetError(errors); + return false; + } + if (source_file_target_option_enabled && + source_file_target_directories.empty()) { + std::string errors = "called with incorrect number of arguments " + "no value provided to the TARGET_DIRECTORY option"; + status.SetError(errors); + return false; + } + return true; +} + +bool HandleAndValidateSourceFileDirectortoryScopes( + cmExecutionStatus& status, bool source_file_directory_option_enabled, + bool source_file_target_option_enabled, + std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories, + std::vector<cmMakefile*>& source_file_directory_makefiles) +{ + bool scope_options_valid = + SetPropertyCommand::HandleSourceFileDirectoryScopeValidation( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories); + if (!scope_options_valid) { + return false; + } + + scope_options_valid = SetPropertyCommand::HandleSourceFileDirectoryScopes( + status, source_file_directories, source_file_target_directories, + source_file_directory_makefiles); + return scope_options_valid; +} + +std::string MakeSourceFilePathAbsoluteIfNeeded( + cmExecutionStatus& status, const std::string& source_file_path, + const bool needed) +{ + if (!needed) { + return source_file_path; + } + const std::string absolute_file_path = cmSystemTools::CollapseFullPath( + source_file_path, status.GetMakefile().GetCurrentSourceDirectory()); + return absolute_file_path; +} + +void MakeSourceFilePathsAbsoluteIfNeeded( + cmExecutionStatus& status, + std::vector<std::string>& source_files_absolute_paths, + std::vector<std::string>::const_iterator files_it_begin, + std::vector<std::string>::const_iterator files_it_end, const bool needed) +{ + + // Make the file paths absolute, so that relative source file paths are + // picked up relative to the command calling site, regardless of the + // directory scope. + std::vector<std::string>::difference_type num_files = + files_it_end - files_it_begin; + source_files_absolute_paths.reserve(num_files); + + if (!needed) { + source_files_absolute_paths.assign(files_it_begin, files_it_end); + return; + } + + for (; files_it_begin != files_it_end; ++files_it_begin) { + const std::string absolute_file_path = + MakeSourceFilePathAbsoluteIfNeeded(status, *files_it_begin, true); + source_files_absolute_paths.push_back(absolute_file_path); + } +} +} + bool cmSetPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -114,13 +241,20 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, std::string propertyName; std::string propertyValue; + std::vector<std::string> source_file_directories; + std::vector<std::string> source_file_target_directories; + bool source_file_directory_option_enabled = false; + bool source_file_target_option_enabled = false; + // Parse the rest of the arguments up to the values. enum Doing { DoingNone, DoingNames, DoingProperty, - DoingValues + DoingValues, + DoingSourceDirectory, + DoingSourceTargetDirectory }; Doing doing = DoingNames; const char* sep = ""; @@ -137,8 +271,20 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, appendMode = true; remove = false; appendAsString = true; + } else if (doing == DoingNames && scope == cmProperty::SOURCE_FILE && + arg == "DIRECTORY") { + doing = DoingSourceDirectory; + source_file_directory_option_enabled = true; + } else if (doing == DoingNames && scope == cmProperty::SOURCE_FILE && + arg == "TARGET_DIRECTORY") { + doing = DoingSourceTargetDirectory; + source_file_target_option_enabled = true; } else if (doing == DoingNames) { names.insert(arg); + } else if (doing == DoingSourceDirectory) { + source_file_directories.push_back(arg); + } else if (doing == DoingSourceTargetDirectory) { + source_file_target_directories.push_back(arg); } else if (doing == DoingProperty) { propertyName = arg; doing = DoingValues; @@ -159,6 +305,18 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, return false; } + std::vector<cmMakefile*> source_file_directory_makefiles; + bool file_scopes_handled = + SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories, source_file_directory_makefiles); + if (!file_scopes_handled) { + return false; + } + bool source_file_paths_should_be_absolute = + source_file_directory_option_enabled || source_file_target_option_enabled; + // Dispatch property setting. switch (scope) { case cmProperty::GLOBAL: @@ -172,7 +330,9 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, appendAsString, appendMode, remove); case cmProperty::SOURCE_FILE: return HandleSourceMode(status, names, propertyName, propertyValue, - appendAsString, appendMode, remove); + appendAsString, appendMode, remove, + source_file_directory_makefiles, + source_file_paths_should_be_absolute); case cmProperty::TEST: return HandleTestMode(status, names, propertyName, propertyValue, appendAsString, appendMode, remove); @@ -315,21 +475,32 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, - bool appendMode, bool remove) + bool appendMode, bool remove, + const std::vector<cmMakefile*>& directory_makefiles, + const bool source_file_paths_should_be_absolute) { - for (std::string const& name : names) { - // Get the source file. - if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) { - if (!HandleSource(sf, propertyName, propertyValue, appendAsString, - appendMode, remove)) { + std::vector<std::string> files_absolute; + std::vector<std::string> unique_files(names.begin(), names.end()); + SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded( + status, files_absolute, unique_files.begin(), unique_files.end(), + source_file_paths_should_be_absolute); + + for (const auto mf : directory_makefiles) { + for (std::string const& name : files_absolute) { + // Get the source file. + if (cmSourceFile* sf = mf->GetOrCreateSource(name)) { + if (!HandleSource(sf, propertyName, propertyValue, appendAsString, + appendMode, remove)) { + return false; + } + } else { + status.SetError(cmStrCat( + "given SOURCE name that could not be found or created: ", name)); return false; } - } else { - status.SetError(cmStrCat( - "given SOURCE name that could not be found or created: ", name)); - return false; } } + return true; } |