diff options
Diffstat (limited to 'Source/cmGlobalNinjaGenerator.cxx')
| -rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 422 |
1 files changed, 37 insertions, 385 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 077de42..c24b1e3 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -25,8 +25,7 @@ #include "cmsys/FStream.hxx" #include "cmCxxModuleMapper.h" -#include "cmDocumentationEntry.h" -#include "cmFileSet.h" +#include "cmDyndepCollation.h" #include "cmFortranParser.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpressionEvaluationFile.h" @@ -554,10 +553,10 @@ codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const return this->NinjaExpectedEncoding; } -void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalNinjaGenerator::GetDocumentation() { - entry.Name = cmGlobalNinjaGenerator::GetActualName(); - entry.Brief = "Generates build.ninja files."; + return { cmGlobalNinjaGenerator::GetActualName(), + "Generates build.ninja files." }; } // Implemented in all cmGlobaleGenerator sub-classes. @@ -592,7 +591,9 @@ void cmGlobalNinjaGenerator::Generate() this->TargetAll = this->NinjaOutputPath("all"); this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt"); this->DisableCleandead = false; - this->DiagnosedCxxModuleSupport = false; + this->DiagnosedCxxModuleNinjaSupport = false; + this->ClangTidyExportFixesDirs.clear(); + this->ClangTidyExportFixesFiles.clear(); this->PolicyCMP0058 = this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus( @@ -633,6 +634,8 @@ void cmGlobalNinjaGenerator::Generate() { this->CleanMetaData(); } + + this->RemoveUnknownClangTidyExportFixesFiles(); } void cmGlobalNinjaGenerator::CleanMetaData() @@ -851,18 +854,12 @@ bool cmGlobalNinjaGenerator::CheckLanguages( bool cmGlobalNinjaGenerator::CheckCxxModuleSupport() { - bool const diagnose = !this->DiagnosedCxxModuleSupport && - !this->CMakeInstance->GetIsInTryCompile(); - if (diagnose) { - this->DiagnosedCxxModuleSupport = true; - this->GetCMakeInstance()->IssueMessage( - MessageType::AUTHOR_WARNING, - "C++20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP " - "is experimental. It is meant only for compiler developers to try."); - } + this->CxxModuleSupportCheck(); if (this->NinjaSupportsDyndeps) { return true; } + bool const diagnose = !this->DiagnosedCxxModuleNinjaSupport && + !this->CMakeInstance->GetIsInTryCompile(); if (diagnose) { std::ostringstream e; /* clang-format off */ @@ -1171,7 +1168,8 @@ void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName, } void cmGlobalNinjaGenerator::AddCXXCompileCommand( - const std::string& commandLine, const std::string& sourceFile) + const std::string& commandLine, const std::string& sourceFile, + const std::string& objPath) { // Compute Ninja's build file path. std::string buildFileDir = @@ -1205,7 +1203,9 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand( << R"( "command": ")" << cmGlobalGenerator::EscapeJSON(commandLine) << "\",\n" << R"( "file": ")" - << cmGlobalGenerator::EscapeJSON(sourceFileName) << "\"\n" + << cmGlobalGenerator::EscapeJSON(sourceFileName) << "\",\n" + << R"( "output": ")" + << cmGlobalGenerator::EscapeJSON(objPath) << "\"\n" << "}"; /* clang-format on */ } @@ -1254,7 +1254,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends) const { - // for frameworks, we want the real name, not smple name + // for frameworks, we want the real name, not sample name // frameworks always appear versioned, and the build.ninja // will always attempt to manage symbolic links instead // of letting cmOSXBundleGenerator do it. @@ -2098,6 +2098,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) } std::vector<std::string> byproducts; + byproducts.reserve(this->CrossConfigs.size()); for (auto const& config : this->CrossConfigs) { byproducts.push_back( this->BuildAlias(GetByproductsForCleanTargetName(), config)); @@ -2472,45 +2473,6 @@ cm::optional<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran( } } -struct CxxModuleFileSet -{ - std::string Name; - std::string RelativeDirectory; - std::string SourcePath; - std::string Type; - cmFileSetVisibility Visibility; - cm::optional<std::string> Destination; -}; - -struct CxxModuleBmiInstall -{ - std::string Component; - std::string Destination; - bool ExcludeFromAll; - bool Optional; - std::string Permissions; - std::string MessageLevel; - std::string ScriptLocation; -}; - -struct CxxModuleExport -{ - std::string Name; - std::string Destination; - std::string Prefix; - std::string CxxModuleInfoDir; - std::string Namespace; - bool Install; -}; - -struct cmGlobalNinjaGenerator::CxxModuleExportInfo -{ - std::map<std::string, CxxModuleFileSet> ObjectToFileSet; - cm::optional<CxxModuleBmiInstall> BmiInstallation; - std::vector<CxxModuleExport> Exports; - std::string Config; -}; - bool cmGlobalNinjaGenerator::WriteDyndepFile( std::string const& dir_top_src, std::string const& dir_top_bld, std::string const& dir_cur_src, std::string const& dir_cur_bld, @@ -2518,7 +2480,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( std::string const& module_dir, std::vector<std::string> const& linked_target_dirs, std::string const& arg_lang, std::string const& arg_modmapfmt, - CxxModuleExportInfo const& export_info) + cmCxxModuleExportInfo const& export_info) { // Setup path conversions. { @@ -2610,6 +2572,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( cm::optional<CxxModuleMapFormat> modmap_fmt; if (arg_modmapfmt.empty()) { // nothing to do. + } else if (arg_modmapfmt == "clang") { + modmap_fmt = CxxModuleMapFormat::Clang; } else if (arg_modmapfmt == "gcc") { modmap_fmt = CxxModuleMapFormat::Gcc; } else if (arg_modmapfmt == "msvc") { @@ -2753,279 +2717,18 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( cmGeneratedFileStream tmf(target_mods_file); tmf << target_module_info; - bool result = true; - - // Fortran doesn't support any of the file-set or BMI installation considered - // below. - if (arg_lang != "Fortran"_s) { - // Prepare the export information blocks. - std::string const config_upper = - cmSystemTools::UpperCase(export_info.Config); - std::vector<std::pair<std::unique_ptr<cmGeneratedFileStream>, - CxxModuleExport const*>> - exports; - for (auto const& exp : export_info.Exports) { - std::unique_ptr<cmGeneratedFileStream> properties; - - std::string const export_dir = - cmStrCat(exp.Prefix, '/', exp.CxxModuleInfoDir, '/'); - std::string const property_file_path = cmStrCat( - export_dir, "target-", exp.Name, '-', export_info.Config, ".cmake"); - properties = cm::make_unique<cmGeneratedFileStream>(property_file_path); - - // Set up the preamble. - *properties << "set_property(TARGET \"" << exp.Namespace << exp.Name - << "\"\n" - << " PROPERTY IMPORTED_CXX_MODULES_" << config_upper - << '\n'; - - exports.emplace_back(std::move(properties), &exp); + cmDyndepMetadataCallbacks cb; + cb.ModuleFile = + [mod_files](std::string const& name) -> cm::optional<std::string> { + auto m = mod_files.find(name); + if (m != mod_files.end()) { + return m->second; } + return {}; + }; - std::unique_ptr<cmGeneratedFileStream> bmi_install_script; - if (export_info.BmiInstallation) { - bmi_install_script = cm::make_unique<cmGeneratedFileStream>( - export_info.BmiInstallation->ScriptLocation); - } - - auto cmEscape = [](cm::string_view str) { - return cmOutputConverter::EscapeForCMake( - str, cmOutputConverter::WrapQuotes::NoWrap); - }; - auto install_destination = - [&cmEscape](std::string const& dest) -> std::pair<bool, std::string> { - if (cmSystemTools::FileIsFullPath(dest)) { - return std::make_pair(true, cmEscape(dest)); - } - return std::make_pair(false, - cmStrCat("${_IMPORT_PREFIX}/", cmEscape(dest))); - }; - - // public/private requirement tracking. - std::set<std::string> private_modules; - std::map<std::string, std::set<std::string>> public_source_requires; - - for (cmScanDepInfo const& object : objects) { - // Convert to forward slashes. - auto output_path = object.PrimaryOutput; -# ifdef _WIN32 - cmSystemTools::ConvertToUnixSlashes(output_path); -# endif - // Find the fileset for this object. - auto fileset_info_itr = export_info.ObjectToFileSet.find(output_path); - bool const has_provides = !object.Provides.empty(); - if (fileset_info_itr == export_info.ObjectToFileSet.end()) { - // If it provides anything, it should have a `CXX_MODULES` or - // `CXX_MODULE_INTERNAL_PARTITIONS` type and be present. - if (has_provides) { - // Take the first module provided to provide context. - auto const& provides = object.Provides[0]; - char const* ok_types = "`CXX_MODULES`"; - if (provides.LogicalName.find(':') != std::string::npos) { - ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if " - "it is not `export`ed)"; - } - cmSystemTools::Error( - cmStrCat("Output ", object.PrimaryOutput, " provides the `", - provides.LogicalName, - "` module but it is not found in a `FILE_SET` of type ", - ok_types)); - result = false; - } - - // This object file does not provide anything, so nothing more needs to - // be done. - continue; - } - - auto const& file_set = fileset_info_itr->second; - - // Verify the fileset type for the object. - if (file_set.Type == "CXX_MODULES"_s) { - if (!has_provides) { - cmSystemTools::Error(cmStrCat( - "Output ", object.PrimaryOutput, - " is of type `CXX_MODULES` but does not provide a module")); - result = false; - continue; - } - } else if (file_set.Type == "CXX_MODULE_INTERNAL_PARTITIONS"_s) { - if (!has_provides) { - cmSystemTools::Error(cmStrCat( - "Source ", file_set.SourcePath, - " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not " - "provide a module")); - result = false; - continue; - } - auto const& provides = object.Provides[0]; - if (provides.LogicalName.find(':') == std::string::npos) { - cmSystemTools::Error(cmStrCat( - "Source ", file_set.SourcePath, - " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not " - "provide a module partition")); - result = false; - continue; - } - } else if (file_set.Type == "CXX_MODULE_HEADERS"_s) { - // TODO. - } else { - if (has_provides) { - auto const& provides = object.Provides[0]; - char const* ok_types = "`CXX_MODULES`"; - if (provides.LogicalName.find(':') != std::string::npos) { - ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if " - "it is not `export`ed)"; - } - cmSystemTools::Error(cmStrCat( - "Source ", file_set.SourcePath, " provides the `", - provides.LogicalName, "` C++ module but is of type `", - file_set.Type, "` module but must be of type ", ok_types)); - result = false; - } - - // Not a C++ module; ignore. - continue; - } - - if (!cmFileSetVisibilityIsForInterface(file_set.Visibility)) { - // Nothing needs to be conveyed about non-`PUBLIC` modules. - for (auto const& p : object.Provides) { - private_modules.insert(p.LogicalName); - } - continue; - } - - // The module is public. Record what it directly requires. - { - auto& reqs = public_source_requires[file_set.SourcePath]; - for (auto const& r : object.Requires) { - reqs.insert(r.LogicalName); - } - } - - // Write out properties and install rules for any exports. - for (auto const& p : object.Provides) { - bool bmi_dest_is_abs = false; - std::string bmi_destination; - if (export_info.BmiInstallation) { - auto dest = - install_destination(export_info.BmiInstallation->Destination); - bmi_dest_is_abs = dest.first; - bmi_destination = cmStrCat(dest.second, '/'); - } - - std::string install_bmi_path; - std::string build_bmi_path; - auto m = mod_files.find(p.LogicalName); - if (m != mod_files.end()) { - install_bmi_path = - cmStrCat(bmi_destination, - cmEscape(cmSystemTools::GetFilenameName(m->second))); - build_bmi_path = cmEscape(m->second); - } - - for (auto const& exp : exports) { - std::string iface_source; - if (exp.second->Install && file_set.Destination) { - auto dest = install_destination(*file_set.Destination); - iface_source = cmStrCat( - dest.second, '/', cmEscape(file_set.RelativeDirectory), - cmEscape(cmSystemTools::GetFilenameName(file_set.SourcePath))); - } else { - iface_source = cmEscape(file_set.SourcePath); - } - - std::string bmi_path; - if (exp.second->Install && export_info.BmiInstallation) { - bmi_path = install_bmi_path; - } else if (!exp.second->Install) { - bmi_path = build_bmi_path; - } - - if (iface_source.empty()) { - // No destination for the C++ module source; ignore this property - // value. - continue; - } - - *exp.first << " \"" << cmEscape(p.LogicalName) << '=' - << iface_source; - if (!bmi_path.empty()) { - *exp.first << ',' << bmi_path; - } - *exp.first << "\"\n"; - } - - if (bmi_install_script) { - auto const& bmi_install = *export_info.BmiInstallation; - - *bmi_install_script << "if (CMAKE_INSTALL_COMPONENT STREQUAL \"" - << cmEscape(bmi_install.Component) << '\"'; - if (!bmi_install.ExcludeFromAll) { - *bmi_install_script << " OR NOT CMAKE_INSTALL_COMPONENT"; - } - *bmi_install_script << ")\n"; - *bmi_install_script << " file(INSTALL\n" - " DESTINATION \""; - if (!bmi_dest_is_abs) { - *bmi_install_script << "${CMAKE_INSTALL_PREFIX}/"; - } - *bmi_install_script << cmEscape(bmi_install.Destination) - << "\"\n" - " TYPE FILE\n"; - if (bmi_install.Optional) { - *bmi_install_script << " OPTIONAL\n"; - } - if (!bmi_install.MessageLevel.empty()) { - *bmi_install_script << " " << bmi_install.MessageLevel << "\n"; - } - if (!bmi_install.Permissions.empty()) { - *bmi_install_script << " PERMISSIONS" << bmi_install.Permissions - << "\n"; - } - *bmi_install_script << " FILES \"" << m->second << "\")\n"; - if (bmi_dest_is_abs) { - *bmi_install_script - << " list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n" - " \"" - << cmEscape(cmSystemTools::GetFilenameName(m->second)) - << "\")\n" - " if (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n" - " message(WARNING\n" - " \"ABSOLUTE path INSTALL DESTINATION : " - "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n" - " endif ()\n" - " if (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n" - " message(FATAL_ERROR\n" - " \"ABSOLUTE path INSTALL DESTINATION forbidden (by " - "caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n" - " endif ()\n"; - } - *bmi_install_script << "endif ()\n"; - } - } - } - - // Add trailing parenthesis for the `set_property` call. - for (auto const& exp : exports) { - *exp.first << ")\n"; - } - - // Check that public sources only require public modules. - for (auto const& pub_reqs : public_source_requires) { - for (auto const& req : pub_reqs.second) { - if (private_modules.count(req)) { - cmSystemTools::Error(cmStrCat( - "Public C++ module source `", pub_reqs.first, "` requires the `", - req, "` C++ module which is provided by a private source")); - result = false; - } - } - } - } - - return result; + return cmDyndepCollation::WriteDyndepMetadata(arg_lang, objects, export_info, + cb); } int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, @@ -3099,58 +2802,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, } } - cmGlobalNinjaGenerator::CxxModuleExportInfo export_info; - export_info.Config = tdi["config"].asString(); - if (export_info.Config.empty()) { - export_info.Config = "noconfig"; - } - Json::Value const& tdi_exports = tdi["exports"]; - if (tdi_exports.isArray()) { - for (auto const& tdi_export : tdi_exports) { - CxxModuleExport exp; - exp.Install = tdi_export["install"].asBool(); - exp.Name = tdi_export["export-name"].asString(); - exp.Destination = tdi_export["destination"].asString(); - exp.Prefix = tdi_export["export-prefix"].asString(); - exp.CxxModuleInfoDir = tdi_export["cxx-module-info-dir"].asString(); - exp.Namespace = tdi_export["namespace"].asString(); - - export_info.Exports.push_back(exp); - } - } - auto const& bmi_installation = tdi["bmi-installation"]; - if (bmi_installation.isObject()) { - CxxModuleBmiInstall bmi_install; - - bmi_install.Component = bmi_installation["component"].asString(); - bmi_install.Destination = bmi_installation["destination"].asString(); - bmi_install.ExcludeFromAll = bmi_installation["exclude-from-all"].asBool(); - bmi_install.Optional = bmi_installation["optional"].asBool(); - bmi_install.Permissions = bmi_installation["permissions"].asString(); - bmi_install.MessageLevel = bmi_installation["message-level"].asString(); - bmi_install.ScriptLocation = - bmi_installation["script-location"].asString(); - - export_info.BmiInstallation = bmi_install; - } - Json::Value const& tdi_cxx_modules = tdi["cxx-modules"]; - if (tdi_cxx_modules.isObject()) { - for (auto i = tdi_cxx_modules.begin(); i != tdi_cxx_modules.end(); ++i) { - CxxModuleFileSet& fsi = export_info.ObjectToFileSet[i.key().asString()]; - auto const& tdi_cxx_module_info = *i; - fsi.Name = tdi_cxx_module_info["name"].asString(); - fsi.RelativeDirectory = - tdi_cxx_module_info["relative-directory"].asString(); - fsi.SourcePath = tdi_cxx_module_info["source"].asString(); - fsi.Type = tdi_cxx_module_info["type"].asString(); - fsi.Visibility = cmFileSetVisibilityFromName( - tdi_cxx_module_info["visibility"].asString(), nullptr); - auto const& tdi_fs_dest = tdi_cxx_module_info["destination"]; - if (tdi_fs_dest.isString()) { - fsi.Destination = tdi_fs_dest.asString(); - } - } - } + auto export_info = cmDyndepCollation::ParseExportInfo(tdi); cmake cm(cmake::RoleInternal, cmState::Unknown); cm.SetHomeDirectory(dir_top_src); @@ -3160,7 +2812,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, !cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile( dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis, module_dir, linked_target_dirs, arg_lang, arg_modmapfmt, - export_info)) { + *export_info)) { return 1; } return 0; @@ -3208,10 +2860,10 @@ cmGlobalNinjaMultiGenerator::cmGlobalNinjaMultiGenerator(cmake* cm) cm->GetState()->SetNinjaMulti(true); } -void cmGlobalNinjaMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalNinjaMultiGenerator::GetDocumentation() { - entry.Name = cmGlobalNinjaMultiGenerator::GetActualName(); - entry.Brief = "Generates build-<Config>.ninja files."; + return { cmGlobalNinjaMultiGenerator::GetActualName(), + "Generates build-<Config>.ninja files." }; } std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir( |
