diff options
author | Brad King <brad.king@kitware.com> | 2022-11-18 14:28:33 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2022-11-18 14:28:46 (GMT) |
commit | 7be4574790c4f6430bfcb34c4e1aa45bfd5c2ec2 (patch) | |
tree | a459e895428c9d82e32e3c96d853c097601a09ca /Source | |
parent | e558beeef6004a82ecef5627daf82bfff551bf80 (diff) | |
parent | 6e3e8827faf0bf2363ecf9035b5573e715e52fb2 (diff) | |
download | CMake-7be4574790c4f6430bfcb34c4e1aa45bfd5c2ec2.zip CMake-7be4574790c4f6430bfcb34c4e1aa45bfd5c2ec2.tar.gz CMake-7be4574790c4f6430bfcb34c4e1aa45bfd5c2ec2.tar.bz2 |
Merge topic 'refactor-cmDocumentation'
6e3e8827fa Refactor: `cmGlobalGeneratorFactory::GetDocumentation` returns entry
e99a4acbcd cmGlobalGeneratorFactory.h: Simplify returning default values
7daadd304f cmake.cxx: Simplify `cmake::AppendExtraGeneratorsDocumentation()`
df2047c2ac cpack.cxx: Optimize calls to `std::osteam::operator<<`
f6180485bb cpack.cxx: Eliminate redundant `if`
d7c183f35c cpack.cxx: Deduplicate "Generators" section creation code
9c06f0dd71 cmake.cxx: Move `static` functions to an anonymous namespace
69918b07e1 cmDocumentationEntry: Drop all user provided ctors for C++ >= 14
...
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !7605
Diffstat (limited to 'Source')
42 files changed, 663 insertions, 802 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c268a92..c0709c6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -196,7 +196,6 @@ add_library( cmDependsCompiler.h cmDocumentation.cxx cmDocumentationFormatter.cxx - cmDocumentationSection.cxx cmDynamicLoader.cxx cmDynamicLoader.h cmELF.h diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index f06946b..c228f07 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -5,10 +5,12 @@ #include <cstddef> #include <functional> #include <iostream> +#include <iterator> #include <map> #include <memory> #include <sstream> #include <string> +#include <type_traits> #include <utility> #include <vector> @@ -25,7 +27,6 @@ #include "cmConsoleBuf.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" -#include "cmDocumentationFormatter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" @@ -36,19 +37,14 @@ #include "cmake.h" namespace { -const char* cmDocumentationName[][2] = { - { nullptr, " cpack - Packaging driver provided by CMake." }, - { nullptr, nullptr } +const cmDocumentationEntry cmDocumentationName = { + {}, + " cpack - Packaging driver provided by CMake." }; -const char* cmDocumentationUsage[][2] = { - // clang-format off - { nullptr, " cpack [options]" }, - { nullptr, nullptr } - // clang-format on -}; +const cmDocumentationEntry cmDocumentationUsage = { {}, " cpack [options]" }; -const char* cmDocumentationOptions[][2] = { +const cmDocumentationEntry cmDocumentationOptions[14] = { { "-G <generators>", "Override/define CPACK_GENERATOR" }, { "-C <Configuration>", "Specify the project configuration" }, { "-D <var>=<value>", "Set a CPack variable." }, @@ -62,14 +58,30 @@ const char* cmDocumentationOptions[][2] = { { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" }, { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" }, { "--preset", "Read arguments from a package preset" }, - { "--list-presets", "List available package presets" }, - { nullptr, nullptr } + { "--list-presets", "List available package presets" } }; void cpackProgressCallback(const std::string& message, float /*unused*/) { - std::cout << "-- " << message << std::endl; + std::cout << "-- " << message << '\n'; } + +std::vector<cmDocumentationEntry> makeGeneratorDocs( + const cmCPackGeneratorFactory& gf) +{ + const auto& generators = gf.GetGeneratorsList(); + + std::vector<cmDocumentationEntry> docs; + docs.reserve(generators.size()); + + std::transform( + generators.cbegin(), generators.cend(), std::back_inserter(docs), + [](const std::decay<decltype(generators)>::type::value_type& gen) { + return cmDocumentationEntry{ gen.first, gen.second }; + }); + return docs; +} + } // namespace // this is CPack. @@ -101,8 +113,7 @@ int main(int argc, char const* const* argv) if (cmSystemTools::GetCurrentWorkingDirectory().empty()) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Current working directory cannot be established." - << std::endl); + "Current working directory cannot be established.\n"); return 1; } @@ -129,14 +140,14 @@ int main(int argc, char const* const* argv) auto const verboseLambda = [&log](const std::string&, cmake*, cmMakefile*) -> bool { log.SetVerbose(true); - cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose" << std::endl); + cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose\n"); return true; }; auto const debugLambda = [&log](const std::string&, cmake*, cmMakefile*) -> bool { log.SetDebug(true); - cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl); + cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug\n"); return true; }; @@ -194,26 +205,25 @@ int main(int argc, char const* const* argv) CommandArgument::setToValue(preset) }, CommandArgument{ "--list-presets", CommandArgument::Values::Zero, CommandArgument::setToTrue(listPresets) }, - CommandArgument{ - "-D", CommandArgument::Values::One, - [&log, &definitions](const std::string& arg, cmake*, - cmMakefile*) -> bool { - std::string value = arg; - size_t pos = value.find_first_of('='); - if (pos == std::string::npos) { - cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Please specify CPack definitions as: KEY=VALUE" - << std::endl); - return false; - } - std::string key = value.substr(0, pos); - value.erase(0, pos + 1); - definitions[key] = value; - cmCPack_Log(&log, cmCPackLog::LOG_DEBUG, - "Set CPack variable: " << key << " to \"" << value << "\"" - << std::endl); - return true; - } }, + CommandArgument{ "-D", CommandArgument::Values::One, + [&log, &definitions](const std::string& arg, cmake*, + cmMakefile*) -> bool { + std::string value = arg; + size_t pos = value.find_first_of('='); + if (pos == std::string::npos) { + cmCPack_Log( + &log, cmCPackLog::LOG_ERROR, + "Please specify CPack definitions as: KEY=VALUE\n"); + return false; + } + std::string key = value.substr(0, pos); + value.erase(0, pos + 1); + definitions[key] = value; + cmCPack_Log(&log, cmCPackLog::LOG_DEBUG, + "Set CPack variable: " << key << " to \"" + << value << "\"\n"); + return true; + } }, }; cmake cminst(cmake::RoleScript, cmState::CPack); @@ -262,8 +272,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Could not read presets from " << workingDirectory << ": " - << cmCMakePresetsGraph::ResultToString(result) - << std::endl); + << cmCMakePresetsGraph::ResultToString(result) << '\n'); return 1; } @@ -276,7 +285,7 @@ int main(int argc, char const* const* argv) if (presetPair == presetsGraph.PackagePresets.end()) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "No such package preset in " << workingDirectory << ": \"" - << preset << '"' << std::endl); + << preset << "\"\n"); presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); return 1; } @@ -284,8 +293,7 @@ int main(int argc, char const* const* argv) if (presetPair->second.Unexpanded.Hidden) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use hidden package preset in " - << workingDirectory << ": \"" << preset << '"' - << std::endl); + << workingDirectory << ": \"" << preset << "\"\n"); presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); return 1; } @@ -294,7 +302,7 @@ int main(int argc, char const* const* argv) if (!expandedPreset) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Could not evaluate package preset \"" - << preset << "\": Invalid macro expansion" << std::endl); + << preset << "\": Invalid macro expansion\n"); presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); return 1; } @@ -302,8 +310,7 @@ int main(int argc, char const* const* argv) if (!expandedPreset->ConditionResult) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use disabled package preset in " - << workingDirectory << ": \"" << preset << '"' - << std::endl); + << workingDirectory << ": \"" << preset << "\"\n"); presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); return 1; } @@ -320,7 +327,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "No such configure preset in " << workingDirectory << ": \"" - << expandedPreset->ConfigurePreset << '"' << std::endl); + << expandedPreset->ConfigurePreset << "\"\n"); presetsGraph.PrintConfigurePresetList(); return 1; } @@ -329,7 +336,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use hidden configure preset in " << workingDirectory << ": \"" - << expandedPreset->ConfigurePreset << '"' << std::endl); + << expandedPreset->ConfigurePreset << "\"\n"); presetsGraph.PrintConfigurePresetList(); return 1; } @@ -339,7 +346,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Could not evaluate configure preset \"" << expandedPreset->ConfigurePreset - << "\": Invalid macro expansion" << std::endl); + << "\": Invalid macro expansion\n"); return 1; } @@ -395,7 +402,7 @@ int main(int argc, char const* const* argv) } cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, - "Read CPack config file: " << cpackConfigFile << std::endl); + "Read CPack config file: " << cpackConfigFile << '\n'); bool cpackConfigFileSpecified = true; if (cpackConfigFile.empty()) { @@ -423,7 +430,7 @@ int main(int argc, char const* const* argv) globalMF.GetModulesFile("CMakeDetermineSystem.cmake"); if (!globalMF.ReadListFile(systemFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Error reading CMakeDetermineSystem.cmake" << std::endl); + "Error reading CMakeDetermineSystem.cmake\n"); return 1; } @@ -431,8 +438,7 @@ int main(int argc, char const* const* argv) globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake"); if (!globalMF.ReadListFile(systemFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Error reading CMakeSystemSpecificInformation.cmake" - << std::endl); + "Error reading CMakeSystemSpecificInformation.cmake\n"); return 1; } @@ -444,17 +450,17 @@ int main(int argc, char const* const* argv) cpackConfigFile = cmSystemTools::CollapseFullPath(cpackConfigFile); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack configuration file: " << cpackConfigFile - << std::endl); + << '\n'); if (!globalMF.ReadListFile(cpackConfigFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Problem reading CPack config file: \"" - << cpackConfigFile << "\"" << std::endl); + "Problem reading CPack config file: \"" << cpackConfigFile + << "\"\n"); return 1; } } else if (cpackConfigFileSpecified) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot find CPack config file: \"" << cpackConfigFile - << "\"" << std::endl); + << "\"\n"); return 1; } @@ -503,17 +509,17 @@ int main(int argc, char const* const* argv) cmValue genList = globalMF.GetDefinition("CPACK_GENERATOR"); if (!genList) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "CPack generator not specified" << std::endl); + "CPack generator not specified\n"); } else { std::vector<std::string> generatorsVector = cmExpandedList(*genList); for (std::string const& gen : generatorsVector) { cmMakefile::ScopePushPop raii(&globalMF); cmMakefile* mf = &globalMF; cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, - "Specified generator: " << gen << std::endl); + "Specified generator: " << gen << '\n'); if (!mf->GetDefinition("CPACK_PACKAGE_NAME")) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "CPack project name not specified" << std::endl); + "CPack project name not specified" << '\n'); parsed = false; } if (parsed && @@ -522,13 +528,11 @@ int main(int argc, char const* const* argv) mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR") && mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")))) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "CPack project version not specified" - << std::endl - << "Specify CPACK_PACKAGE_VERSION, or " - "CPACK_PACKAGE_VERSION_MAJOR, " - "CPACK_PACKAGE_VERSION_MINOR, and " - "CPACK_PACKAGE_VERSION_PATCH." - << std::endl); + "CPack project version not specified\n" + "Specify CPACK_PACKAGE_VERSION, or " + "CPACK_PACKAGE_VERSION_MAJOR, " + "CPACK_PACKAGE_VERSION_MINOR, and " + "CPACK_PACKAGE_VERSION_PATCH.\n"); parsed = false; } if (parsed) { @@ -539,19 +543,12 @@ int main(int argc, char const* const* argv) cpackGenerator->SetTraceExpand(cminst.GetTraceExpand()); } else { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Could not create CPack generator: " << gen - << std::endl); + "Could not create CPack generator: " << gen << '\n'); // Print out all the valid generators cmDocumentation generatorDocs; - std::vector<cmDocumentationEntry> v; - for (auto const& g : generators.GetGeneratorsList()) { - cmDocumentationEntry e; - e.Name = g.first; - e.Brief = g.second; - v.push_back(std::move(e)); - } - generatorDocs.SetSection("Generators", v); - std::cerr << "\n"; + generatorDocs.SetSection("Generators", + makeGeneratorDocs(generators)); + std::cerr << '\n'; generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr); parsed = false; @@ -559,8 +556,7 @@ int main(int argc, char const* const* argv) if (parsed && !cpackGenerator->Initialize(gen, mf)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Cannot initialize the generator " << gen - << std::endl); + "Cannot initialize the generator " << gen << '\n'); parsed = false; } @@ -573,17 +569,16 @@ int main(int argc, char const* const* argv) "Please specify build tree of the project that uses CMake " "using CPACK_INSTALL_CMAKE_PROJECTS, specify " "CPACK_INSTALL_COMMANDS, CPACK_INSTALL_SCRIPT, or " - "CPACK_INSTALLED_DIRECTORIES." - << std::endl); + "CPACK_INSTALLED_DIRECTORIES.\n"); parsed = false; } if (parsed) { cmValue projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: " << cpackGenerator->GetNameOfClass() - << std::endl); + << '\n'); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, - "For project: " << *projName << std::endl); + "For project: " << *projName << '\n'); cmValue projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION"); if (!projVersion) { @@ -594,7 +589,7 @@ int main(int argc, char const* const* argv) cmValue projVersionPatch = mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH"); std::ostringstream ostr; - ostr << *projVersionMajor << "." << *projVersionMinor << "." + ostr << *projVersionMajor << "." << *projVersionMinor << '.' << *projVersionPatch; mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str()); } @@ -603,7 +598,7 @@ int main(int argc, char const* const* argv) if (!res) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Error when generating package: " << *projName - << std::endl); + << '\n'); return 1; } } @@ -618,27 +613,13 @@ int main(int argc, char const* const* argv) */ if (help) { // Construct and print requested documentation. - doc.SetName("cpack"); doc.SetSection("Name", cmDocumentationName); doc.SetSection("Usage", cmDocumentationUsage); doc.PrependSection("Options", cmDocumentationOptions); - - std::vector<cmDocumentationEntry> v; - for (auto const& g : generators.GetGeneratorsList()) { - cmDocumentationEntry e; - e.Name = g.first; - e.Brief = g.second; - v.push_back(std::move(e)); - } - doc.SetSection("Generators", v); - - return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; - } - - if (cmSystemTools::GetErrorOccurredFlag()) { - return 1; + doc.SetSection("Generators", makeGeneratorDocs(generators)); + return !doc.PrintRequestedDocumentation(std::cout); } - return 0; + return int(cmSystemTools::GetErrorOccurredFlag()); } diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 70ed648..18c1a80 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -16,45 +16,38 @@ #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" #include "cmDocumentation.h" -#include "cmDocumentationEntry.h" // IWYU pragma: keep +#include "cmDocumentationEntry.h" #include "cmMessageMetadata.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -static const char* cmDocumentationName[][2] = { - { nullptr, " ccmake - Curses Interface for CMake." }, - { nullptr, nullptr } +namespace { +const cmDocumentationEntry cmDocumentationName = { + {}, + " ccmake - Curses Interface for CMake." }; -static const char* cmDocumentationUsage[][2] = { - { nullptr, +const cmDocumentationEntry cmDocumentationUsage[2] = { + { {}, " ccmake <path-to-source>\n" " ccmake <path-to-existing-build>" }, - { nullptr, + { {}, "Specify a source directory to (re-)generate a build system for " "it in the current working directory. Specify an existing build " "directory to re-generate its build system." }, - { nullptr, nullptr } }; -static const char* cmDocumentationUsageNote[][2] = { - { nullptr, "Run 'ccmake --help' for more information." }, - { nullptr, nullptr } +const cmDocumentationEntry cmDocumentationUsageNote = { + {}, + "Run 'ccmake --help' for more information." }; -static const char* cmDocumentationOptions[][2] = { - CMAKE_STANDARD_OPTIONS_TABLE, - { nullptr, nullptr } -}; - -cmCursesForm* cmCursesForm::CurrentForm = nullptr; - #ifndef _WIN32 extern "C" { -static void onsig(int /*unused*/) +void onsig(int /*unused*/) { if (cmCursesForm::CurrentForm) { cmCursesForm::CurrentForm->HandleResize(); @@ -63,6 +56,9 @@ static void onsig(int /*unused*/) } } #endif // _WIN32 +} // anonymous namespace + +cmCursesForm* cmCursesForm::CurrentForm = nullptr; int main(int argc, char const* const* argv) { @@ -89,8 +85,8 @@ int main(int argc, char const* const* argv) doc.AppendSection("Usage", cmDocumentationUsageNote); } doc.AppendSection("Generators", generators); - doc.PrependSection("Options", cmDocumentationOptions); - return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; + doc.PrependSection("Options", cmake::CMAKE_STANDARD_OPTIONS_TABLE); + return !doc.PrintRequestedDocumentation(std::cout); } bool debug = false; diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 591b793..50e8e3a 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -22,26 +22,27 @@ #include "cmSystemTools.h" // IWYU pragma: keep #include "cmake.h" -static const char* cmDocumentationName[][2] = { { nullptr, - " cmake-gui - CMake GUI." }, - { nullptr, nullptr } }; - -static const char* cmDocumentationUsage[][2] = { - { nullptr, - " cmake-gui [options]\n" - " cmake-gui [options] <path-to-source>\n" - " cmake-gui [options] <path-to-existing-build>\n" - " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n" - " cmake-gui [options] --browse-manual\n" }, - { nullptr, nullptr } +namespace { +const cmDocumentationEntry cmDocumentationName = { + {}, + " cmake-gui - CMake GUI." }; -static const char* cmDocumentationOptions[][2] = { +const cmDocumentationEntry cmDocumentationUsage = { + {}, + " cmake-gui [options]\n" + " cmake-gui [options] <path-to-source>\n" + " cmake-gui [options] <path-to-existing-build>\n" + " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n" + " cmake-gui [options] --browse-manual" +}; + +const cmDocumentationEntry cmDocumentationOptions[3] = { { "-S <path-to-source>", "Explicitly specify a source directory." }, { "-B <path-to-build>", "Explicitly specify a build directory." }, - { "--preset=<preset>", "Specify a configure preset." }, - { nullptr, nullptr } + { "--preset=<preset>", "Specify a configure preset." } }; +} // anonymous namespace #if defined(Q_OS_MAC) static int cmOSXInstall(std::string dir); @@ -91,7 +92,7 @@ int main(int argc, char** argv) doc.AppendSection("Generators", generators); doc.PrependSection("Options", cmDocumentationOptions); - return (doc.PrintRequestedDocumentation(std::cout) ? 0 : 1); + return !doc.PrintRequestedDocumentation(std::cout); } #if defined(Q_OS_MAC) @@ -252,6 +253,7 @@ int main(int argc, char** argv) # include <unistd.h> # include "cm_sys_stat.h" + static bool cmOSXInstall(std::string const& dir, std::string const& tool) { if (tool.empty()) { @@ -277,6 +279,7 @@ static bool cmOSXInstall(std::string const& dir, std::string const& tool) << "': " << strerror(err) << "\n"; return false; } + static int cmOSXInstall(std::string dir) { if (!cmHasLiteralSuffix(dir, "/")) { diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index d466a12..77c5295 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -16,7 +16,8 @@ #include "cmSystemTools.h" #include "cmVersion.h" -static const char* cmDocumentationStandardOptions[][2] = { +namespace { +const cmDocumentationEntry cmDocumentationStandardOptions[20] = { { "-h,-H,--help,-help,-usage,/?", "Print usage information and exit." }, { "--version,-version,/V [<file>]", "Print version number and exit." }, { "--help-full [<file>]", "Print all help manuals and exit." }, @@ -42,22 +43,27 @@ static const char* cmDocumentationStandardOptions[][2] = { { "--help-variable var [<file>]", "Print help for one variable and exit." }, { "--help-variable-list [<file>]", "List variables with help available and exit." }, - { "--help-variables [<file>]", "Print cmake-variables manual and exit." }, - { nullptr, nullptr } + { "--help-variables [<file>]", "Print cmake-variables manual and exit." } }; -static const char* cmDocumentationCPackGeneratorsHeader[][2] = { - { nullptr, "The following generators are available on this platform:" }, - { nullptr, nullptr } +const cmDocumentationEntry cmDocumentationCPackGeneratorsHeader = { + {}, + "The following generators are available on this platform:" }; -static const char* cmDocumentationCMakeGeneratorsHeader[][2] = { - { nullptr, - "The following generators are available on this platform (* marks " - "default):" }, - { nullptr, nullptr } +const cmDocumentationEntry cmDocumentationCMakeGeneratorsHeader = { + {}, + "The following generators are available on this platform (* marks " + "default):" }; +bool isOption(const char* arg) +{ + return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) || + (strcmp(arg, "/?") == 0)); +} +} // anonymous namespace + cmDocumentation::cmDocumentation() { this->addCommonStandardDocSections(); @@ -148,14 +154,6 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) return result; } -#define GET_OPT_ARGUMENT(target) \ - do { \ - if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \ - (target) = argv[i + 1]; \ - i = i + 1; \ - }; \ - } while (false) - void cmDocumentation::WarnFormFromFilename( cmDocumentation::RequestedHelpItem& request, bool& result) { @@ -217,6 +215,14 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, return true; } + auto get_opt_argument = [=](const int nextIdx, std::string& target) -> bool { + if ((nextIdx < argc) && !isOption(argv[nextIdx])) { + target = argv[nextIdx]; + return true; + } + return false; + }; + // Search for supported help options. bool result = false; @@ -230,7 +236,7 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, (strcmp(argv[i], "/?") == 0) || (strcmp(argv[i], "-usage") == 0) || (strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-H") == 0)) { help.HelpType = cmDocumentation::Help; - GET_OPT_ARGUMENT(help.Argument); + i += int(get_opt_argument(i + 1, help.Argument)); help.Argument = cmSystemTools::LowerCase(help.Argument); // special case for single command if (!help.Argument.empty()) { @@ -239,25 +245,25 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, } else if (strcmp(argv[i], "--help-properties") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-properties.7"; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-policies") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-policies.7"; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-variables") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-variables.7"; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-modules") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-modules.7"; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-custom-modules") == 0) { - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); cmSystemTools::Message( "Warning: --help-custom-modules no longer supported"); if (help.Filename.empty()) { @@ -271,83 +277,79 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, } else if (strcmp(argv[i], "--help-commands") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-commands.7"; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-compatcommands") == 0) { - GET_OPT_ARGUMENT(help.Filename); cmSystemTools::Message( "Warning: --help-compatcommands no longer supported"); return true; } else if (strcmp(argv[i], "--help-full") == 0) { help.HelpType = cmDocumentation::Full; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-html") == 0) { - GET_OPT_ARGUMENT(help.Filename); cmSystemTools::Message("Warning: --help-html no longer supported"); return true; } else if (strcmp(argv[i], "--help-man") == 0) { - GET_OPT_ARGUMENT(help.Filename); cmSystemTools::Message("Warning: --help-man no longer supported"); return true; } else if (strcmp(argv[i], "--help-command") == 0) { help.HelpType = cmDocumentation::OneCommand; - GET_OPT_ARGUMENT(help.Argument); - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Argument)); + i += int(get_opt_argument(i + 1, help.Filename)); help.Argument = cmSystemTools::LowerCase(help.Argument); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-module") == 0) { help.HelpType = cmDocumentation::OneModule; - GET_OPT_ARGUMENT(help.Argument); - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Argument)); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-property") == 0) { help.HelpType = cmDocumentation::OneProperty; - GET_OPT_ARGUMENT(help.Argument); - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Argument)); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-policy") == 0) { help.HelpType = cmDocumentation::OnePolicy; - GET_OPT_ARGUMENT(help.Argument); - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Argument)); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-variable") == 0) { help.HelpType = cmDocumentation::OneVariable; - GET_OPT_ARGUMENT(help.Argument); - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Argument)); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-manual") == 0) { help.HelpType = cmDocumentation::OneManual; - GET_OPT_ARGUMENT(help.Argument); - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Argument)); + i += int(get_opt_argument(i + 1, help.Filename)); this->WarnFormFromFilename(help, result); } else if (strcmp(argv[i], "--help-command-list") == 0) { help.HelpType = cmDocumentation::ListCommands; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } else if (strcmp(argv[i], "--help-module-list") == 0) { help.HelpType = cmDocumentation::ListModules; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } else if (strcmp(argv[i], "--help-property-list") == 0) { help.HelpType = cmDocumentation::ListProperties; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } else if (strcmp(argv[i], "--help-variable-list") == 0) { help.HelpType = cmDocumentation::ListVariables; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } else if (strcmp(argv[i], "--help-policy-list") == 0) { help.HelpType = cmDocumentation::ListPolicies; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } else if (strcmp(argv[i], "--help-manual-list") == 0) { help.HelpType = cmDocumentation::ListManuals; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } else if (strcmp(argv[i], "--copyright") == 0) { - GET_OPT_ARGUMENT(help.Filename); cmSystemTools::Message("Warning: --copyright no longer supported"); return true; } else if ((strcmp(argv[i], "--version") == 0) || (strcmp(argv[i], "-version") == 0) || (strcmp(argv[i], "/V") == 0)) { help.HelpType = cmDocumentation::Version; - GET_OPT_ARGUMENT(help.Filename); + i += int(get_opt_argument(i + 1, help.Filename)); } if (help.HelpType != None) { // This is a help option. See if there is a file name given. @@ -369,56 +371,12 @@ void cmDocumentation::SetSection(const char* name, this->SectionAtName(name) = std::move(section); } -void cmDocumentation::SetSection(const char* name, - std::vector<cmDocumentationEntry>& docs) -{ - cmDocumentationSection sec{ name }; - sec.Append(docs); - this->SetSection(name, std::move(sec)); -} - -void cmDocumentation::SetSection(const char* name, const char* docs[][2]) -{ - cmDocumentationSection sec{ name }; - sec.Append(docs); - this->SetSection(name, std::move(sec)); -} - -void cmDocumentation::SetSections( - std::map<std::string, cmDocumentationSection> sections) -{ - for (auto& s : sections) { - this->SetSection(s.first.c_str(), std::move(s.second)); - } -} cmDocumentationSection& cmDocumentation::SectionAtName(const char* name) { return this->AllSections.emplace(name, cmDocumentationSection{ name }) .first->second; } -void cmDocumentation::PrependSection(const char* name, const char* docs[][2]) -{ - this->SectionAtName(name).Prepend(docs); -} - -void cmDocumentation::PrependSection(const char* name, - std::vector<cmDocumentationEntry>& docs) -{ - this->SectionAtName(name).Prepend(docs); -} - -void cmDocumentation::AppendSection(const char* name, const char* docs[][2]) -{ - this->SectionAtName(name).Append(docs); -} - -void cmDocumentation::AppendSection(const char* name, - std::vector<cmDocumentationEntry>& docs) -{ - this->SectionAtName(name).Append(docs); -} - void cmDocumentation::AppendSection(const char* name, cmDocumentationEntry& docs) { @@ -465,7 +423,7 @@ void cmDocumentation::PrintNames(std::ostream& os, std::string const& pattern) } std::sort(names.begin(), names.end()); for (std::string const& n : names) { - os << n << "\n"; + os << n << '\n'; } } @@ -501,7 +459,7 @@ bool cmDocumentation::PrintHelpOneManual(std::ostream& os) // Argument was not a manual. Complain. os << "Argument \"" << this->CurrentArgument << "\" to --help-manual is not an available manual. " - << "Use --help-manual-list to see all available manuals.\n"; + "Use --help-manual-list to see all available manuals.\n"; return false; } @@ -520,7 +478,7 @@ bool cmDocumentation::PrintHelpOneCommand(std::ostream& os) // Argument was not a command. Complain. os << "Argument \"" << this->CurrentArgument << "\" to --help-command is not a CMake command. " - << "Use --help-command-list to see all commands.\n"; + "Use --help-command-list to see all commands.\n"; return false; } @@ -553,7 +511,7 @@ bool cmDocumentation::PrintHelpListModules(std::ostream& os) } std::sort(modules.begin(), modules.end()); for (std::string const& m : modules) { - os << m << "\n"; + os << m << '\n'; } return true; } @@ -567,7 +525,7 @@ bool cmDocumentation::PrintHelpOneProperty(std::ostream& os) // Argument was not a property. Complain. os << "Argument \"" << this->CurrentArgument << "\" to --help-property is not a CMake property. " - << "Use --help-property-list to see all properties.\n"; + "Use --help-property-list to see all properties.\n"; return false; } @@ -601,7 +559,6 @@ bool cmDocumentation::PrintHelpListGenerators(std::ostream& os) { const auto si = this->AllSections.find("Generators"); if (si != this->AllSections.end()) { - this->Formatter.SetIndent(" "); this->Formatter.PrintSection(os, si->second); } return true; @@ -616,7 +573,7 @@ bool cmDocumentation::PrintHelpOneVariable(std::ostream& os) // Argument was not a variable. Complain. os << "Argument \"" << this->CurrentArgument << "\" to --help-variable is not a defined variable. " - << "Use --help-variable-list to see all defined variables.\n"; + "Use --help-variable-list to see all defined variables.\n"; return false; } @@ -662,12 +619,6 @@ const char* cmDocumentation::GetNameString() const return "CMake"; } -bool cmDocumentation::IsOption(const char* arg) const -{ - return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) || - (strcmp(arg, "/?") == 0)); -} - bool cmDocumentation::PrintOldCustomModules(std::ostream& os) { // CheckOptions abuses the Argument field to give us the file name. @@ -691,7 +642,7 @@ bool cmDocumentation::PrintOldCustomModules(std::ostream& os) } else if ((ext.length() == 2) && (ext[1] >= '1') && (ext[1] <= '9')) { /* clang-format off */ os << - ".TH " << name << " " << ext[1] << " \"" << + ".TH " << name << ' ' << ext[1] << " \"" << cmSystemTools::GetCurrentDateTime("%B %d, %Y") << "\" \"cmake " << cmVersion::GetCMakeVersion() << "\"\n" ".SH NAME\n" @@ -704,7 +655,7 @@ bool cmDocumentation::PrintOldCustomModules(std::ostream& os) ; /* clang-format on */ } else { - os << name << "\n\n" << summary << "\n" << detail; + os << name << "\n\n" << summary << '\n' << detail; } return true; } diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 313be32..6930986 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> #include <string> +#include <utility> #include <vector> #include "cmDocumentationFormatter.h" @@ -15,9 +16,33 @@ struct cmDocumentationEntry; /** Class to generate documentation. */ -class cmDocumentation : public cmDocumentationEnums +class cmDocumentation { public: + /** Types of help provided. */ + enum Type + { + None, + Version, + Usage, + Help, + Full, + ListManuals, + ListCommands, + ListModules, + ListProperties, + ListVariables, + ListPolicies, + ListGenerators, + OneManual, + OneCommand, + OneModule, + OneProperty, + OneVariable, + OnePolicy, + OldCustomModules + }; + cmDocumentation(); /** @@ -50,19 +75,26 @@ public: /** Set a section of the documentation. Typical sections include Name, Usage, Description, Options */ void SetSection(const char* sectionName, cmDocumentationSection section); - void SetSection(const char* sectionName, - std::vector<cmDocumentationEntry>& docs); - void SetSection(const char* sectionName, const char* docs[][2]); - void SetSections(std::map<std::string, cmDocumentationSection> sections); + template <typename Iterable> + void SetSection(const char* sectionName, const Iterable& docs) + { + cmDocumentationSection sec{ sectionName }; + sec.Append(docs); + this->SetSection(sectionName, std::move(sec)); + } /** Add the documentation to the beginning/end of the section */ - void PrependSection(const char* sectionName, const char* docs[][2]); - void PrependSection(const char* sectionName, - std::vector<cmDocumentationEntry>& docs); + template <typename Iterable> + void PrependSection(const char* sectionName, const Iterable& docs) + { + this->SectionAtName(sectionName).Prepend(docs); + } void PrependSection(const char* sectionName, cmDocumentationEntry& docs); - void AppendSection(const char* sectionName, const char* docs[][2]); - void AppendSection(const char* sectionName, - std::vector<cmDocumentationEntry>& docs); + template <typename Iterable> + void AppendSection(const char* sectionName, const Iterable& docs) + { + this->SectionAtName(sectionName).Append(docs); + } void AppendSection(const char* sectionName, cmDocumentationEntry& docs); /** Add common (to all tools) documentation section(s) */ @@ -102,7 +134,6 @@ private: bool PrintOldCustomModules(std::ostream& os); const char* GetNameString() const; - bool IsOption(const char* arg) const; bool ShowGenerators; @@ -114,7 +145,7 @@ private: struct RequestedHelpItem { - cmDocumentationEnums::Type HelpType = None; + Type HelpType = None; std::string Filename; std::string Argument; }; diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h index 89a2899..d971836 100644 --- a/Source/cmDocumentationEntry.h +++ b/Source/cmDocumentationEntry.h @@ -9,26 +9,15 @@ /** Standard documentation entry for cmDocumentation's formatting. */ struct cmDocumentationEntry { - std::string Name; - std::string Brief; - char CustomNamePrefix = ' '; - cmDocumentationEntry() = default; - cmDocumentationEntry(const char* doc[2]) - { - if (doc[0]) { - this->Name = doc[0]; - } - if (doc[1]) { - this->Brief = doc[1]; - } - } - cmDocumentationEntry(const char* n, const char* b) +#if __cplusplus <= 201103L + cmDocumentationEntry(const std::string& name, const std::string& brief) + : Name{ name } + , Brief{ brief } { - if (n) { - this->Name = n; - } - if (b) { - this->Brief = b; - } } +#endif + + std::string Name = {}; + std::string Brief = {}; + char CustomNamePrefix = ' '; }; diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx index 732637e..70ba1fc 100644 --- a/Source/cmDocumentationFormatter.cxx +++ b/Source/cmDocumentationFormatter.cxx @@ -2,7 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDocumentationFormatter.h" -#include <cstring> +#include <algorithm> +#include <cassert> #include <iomanip> #include <ostream> #include <string> @@ -11,178 +12,207 @@ #include "cmDocumentationEntry.h" #include "cmDocumentationSection.h" -cmDocumentationFormatter::cmDocumentationFormatter() = default; - -cmDocumentationFormatter::~cmDocumentationFormatter() = default; +namespace { +const char* skipSpaces(const char* ptr) +{ + assert(ptr); + for (; *ptr == ' '; ++ptr) { + ; + } + return ptr; +} +const char* skipToSpace(const char* ptr) +{ + assert(ptr); + for (; *ptr && (*ptr != '\n') && (*ptr != ' '); ++ptr) { + ; + } + return ptr; +} +} void cmDocumentationFormatter::PrintFormatted(std::ostream& os, - const char* text) + std::string const& text) const { - if (!text) { + if (text.empty()) { return; } - const char* ptr = text; - while (*ptr) { - // Any ptrs starting in a space are treated as preformatted text. - std::string preformatted; - while (*ptr == ' ') { - for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) { - preformatted.append(1, ch); - } - if (*ptr) { - ++ptr; - preformatted.append(1, '\n'); - } - } - if (!preformatted.empty()) { - this->PrintPreformatted(os, preformatted.c_str()); + + struct Buffer + { + // clang-format off + using PrinterFn = void (cmDocumentationFormatter::*)( + std::ostream&, std::string const& + ) const; + // clang-format on + std::string collected; + const PrinterFn printer; + }; + // const auto NORMAL_IDX = 0u; + const auto PREFORMATTED_IDX = 1u; + const auto HANDLERS_SIZE = 2u; + Buffer buffers[HANDLERS_SIZE] = { + { {}, &cmDocumentationFormatter::PrintParagraph }, + { {}, &cmDocumentationFormatter::PrintPreformatted } + }; + + const auto padding = std::string(this->TextIndent, ' '); + + for (std::size_t pos = 0u, eol = 0u; pos < text.size(); pos = eol) { + const auto current_idx = std::size_t(text[pos] == ' '); + // size_t(!bool(current_idx)) + const auto other_idx = current_idx ^ 1u; + + // Flush the other buffer if anything has been collected + if (!buffers[other_idx].collected.empty()) { + // NOTE Whatever the other index is, the current buffered + // string expected to be empty. + assert(buffers[current_idx].collected.empty()); + + (this->*buffers[other_idx].printer)(os, buffers[other_idx].collected); + buffers[other_idx].collected.clear(); } - // Other ptrs are treated as paragraphs. - std::string paragraph; - for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) { - paragraph.append(1, ch); + // ATTENTION The previous implementation had called `PrintParagraph()` + // **for every processed (char by char) input line**. + // The method unconditionally append the `\n' character after the + // printed text. To keep the backward-compatible behavior it's needed to + // add the '\n' character to the previously collected line... + if (!buffers[current_idx].collected.empty() && + current_idx != PREFORMATTED_IDX) { + buffers[current_idx].collected += '\n'; } - if (*ptr) { - ++ptr; - paragraph.append(1, '\n'); + + // Lookup EOL + eol = text.find('\n', pos); + if (current_idx == PREFORMATTED_IDX) { + buffers[current_idx].collected.append(padding); } - if (!paragraph.empty()) { - this->PrintParagraph(os, paragraph.c_str()); + buffers[current_idx].collected.append( + text, pos, eol == std::string::npos ? eol : ++eol - pos); + } + + for (auto& buf : buffers) { + if (!buf.collected.empty()) { + (this->*buf.printer)(os, buf.collected); } } } void cmDocumentationFormatter::PrintPreformatted(std::ostream& os, - const char* text) + std::string const& text) const { - bool newline = true; - for (const char* ptr = text; *ptr; ++ptr) { - if (newline && *ptr != '\n') { - os << this->TextIndent; - newline = false; - } - os << *ptr; - if (*ptr == '\n') { - newline = true; - } - } - os << "\n"; + os << text << '\n'; } void cmDocumentationFormatter::PrintParagraph(std::ostream& os, - const char* text) + std::string const& text) const { - os << this->TextIndent; + if (this->TextIndent) { + os << std::string(this->TextIndent, ' '); + } this->PrintColumn(os, text); - os << "\n"; -} - -void cmDocumentationFormatter::SetIndent(const char* indent) -{ - this->TextIndent = indent; + os << '\n'; } -void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text) +void cmDocumentationFormatter::PrintColumn(std::ostream& os, + std::string const& text) const { // Print text arranged in an indented column of fixed width. - const char* l = text; - long column = 0; bool newSentence = false; bool firstLine = true; - int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent)); - // Loop until the end of the text. - while (*l) { - // Parse the next word. - const char* r = l; - while (*r && (*r != '\n') && (*r != ' ')) { - ++r; - } + assert(this->TextIndent < this->TextWidth); + const std::ptrdiff_t width = this->TextWidth - this->TextIndent; + std::ptrdiff_t column = 0; + // Loop until the end of the text. + for (const char *l = text.c_str(), *r = skipToSpace(text.c_str()); *l; + l = skipSpaces(r), r = skipToSpace(l)) { // Does it fit on this line? - if (r - l < (width - column - (newSentence ? 1 : 0))) { + if (r - l < width - column - std::ptrdiff_t(newSentence)) { // Word fits on this line. if (r > l) { if (column) { // Not first word on line. Separate from the previous word // by a space, or two if this is a new sentence. - if (newSentence) { - os << " "; - column += 2; - } else { - os << " "; - column += 1; - } - } else { + os << &(" "[std::size_t(!newSentence)]); + column += 1u + std::ptrdiff_t(newSentence); + } else if (!firstLine && this->TextIndent) { // First word on line. Print indentation unless this is the // first line. - os << (firstLine ? "" : this->TextIndent); + os << std::string(this->TextIndent, ' '); } // Print the word. - os.write(l, static_cast<long>(r - l)); + os.write(l, r - l); newSentence = (*(r - 1) == '.'); } if (*r == '\n') { // Text provided a newline. Start a new line. - os << "\n"; + os << '\n'; ++r; column = 0; firstLine = false; } else { // No provided newline. Continue this line. - column += static_cast<long>(r - l); + column += r - l; } } else { // Word does not fit on this line. Start a new line. - os << "\n"; + os << '\n'; firstLine = false; if (r > l) { - os << this->TextIndent; - os.write(l, static_cast<long>(r - l)); - column = static_cast<long>(r - l); + os << std::string(this->TextIndent, ' '); + os.write(l, r - l); + column = r - l; newSentence = (*(r - 1) == '.'); } else { column = 0; } } - // Move to beginning of next word. Skip over whitespace. - l = r; - while (*l == ' ') { - ++l; - } } } void cmDocumentationFormatter::PrintSection( std::ostream& os, cmDocumentationSection const& section) { - os << section.GetName() << "\n"; + const std::size_t PREFIX_SIZE = + sizeof(cmDocumentationEntry::CustomNamePrefix) + 1u; + // length of the "= " literal (see below) + const std::size_t SUFFIX_SIZE = 2u; + // legacy magic number ;-) + const std::size_t NAME_SIZE = 29u; + + const std::size_t PADDING_SIZE = PREFIX_SIZE + SUFFIX_SIZE; + const std::size_t TITLE_SIZE = NAME_SIZE + PADDING_SIZE; + + const auto savedIndent = this->TextIndent; - const std::vector<cmDocumentationEntry>& entries = section.GetEntries(); - for (cmDocumentationEntry const& entry : entries) { + os << section.GetName() << '\n'; + + for (cmDocumentationEntry const& entry : section.GetEntries()) { if (!entry.Name.empty()) { - os << std::setw(2) << std::left << entry.CustomNamePrefix << entry.Name; - this->TextIndent = " "; - int align = static_cast<int>(strlen(this->TextIndent)) - 4; - for (int i = static_cast<int>(entry.Name.size()); i < align; ++i) { - os << " "; - } - if (entry.Name.size() > strlen(this->TextIndent) - 4) { - os << "\n"; - os.write(this->TextIndent, strlen(this->TextIndent) - 2); + this->TextIndent = TITLE_SIZE; + os << std::setw(PREFIX_SIZE) << std::left << entry.CustomNamePrefix + << std::setw(int(std::max(NAME_SIZE, entry.Name.size()))) + << entry.Name; + if (entry.Name.size() > NAME_SIZE) { + os << '\n' << std::setw(int(this->TextIndent - PREFIX_SIZE)) << ' '; } os << "= "; - this->PrintColumn(os, entry.Brief.c_str()); - os << "\n"; + this->PrintColumn(os, entry.Brief); + os << '\n'; } else { - os << "\n"; - this->TextIndent = ""; - this->PrintFormatted(os, entry.Brief.c_str()); + os << '\n'; + this->TextIndent = 0u; + this->PrintFormatted(os, entry.Brief); } } - os << "\n"; + + os << '\n'; + + this->TextIndent = savedIndent; } diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h index cb3038a..e269f6a 100644 --- a/Source/cmDocumentationFormatter.h +++ b/Source/cmDocumentationFormatter.h @@ -5,40 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> - -/** This is just a helper class to make it build with MSVC 6.0. -Actually the enums and internal classes could directly go into -cmDocumentation, but then MSVC6 complains in RequestedHelpItem that -cmDocumentation is an undefined type and so it doesn't know the enums. -Moving the enums to a class which is then already completely parsed helps -against this. */ -class cmDocumentationEnums -{ -public: - /** Types of help provided. */ - enum Type - { - None, - Version, - Usage, - Help, - Full, - ListManuals, - ListCommands, - ListModules, - ListProperties, - ListVariables, - ListPolicies, - ListGenerators, - OneManual, - OneCommand, - OneModule, - OneProperty, - OneVariable, - OnePolicy, - OldCustomModules - }; -}; +#include <string> class cmDocumentationSection; @@ -46,18 +13,15 @@ class cmDocumentationSection; class cmDocumentationFormatter { public: - cmDocumentationFormatter(); - virtual ~cmDocumentationFormatter(); - void PrintFormatted(std::ostream& os, const char* text); - - virtual void PrintSection(std::ostream& os, - cmDocumentationSection const& section); - virtual void PrintPreformatted(std::ostream& os, const char* text); - virtual void PrintParagraph(std::ostream& os, const char* text); - void PrintColumn(std::ostream& os, const char* text); - void SetIndent(const char* indent); + void SetIndent(std::size_t indent) { this->TextIndent = indent; } + void PrintFormatted(std::ostream& os, std::string const& text) const; + void PrintSection(std::ostream& os, cmDocumentationSection const& section); private: - int TextWidth = 77; - const char* TextIndent = ""; + void PrintPreformatted(std::ostream& os, std::string const&) const; + void PrintParagraph(std::ostream& os, std::string const&) const; + void PrintColumn(std::ostream& os, std::string const&) const; + + std::size_t TextWidth = 77u; + std::size_t TextIndent = 0u; }; diff --git a/Source/cmDocumentationSection.cxx b/Source/cmDocumentationSection.cxx deleted file mode 100644 index 439da1b..0000000 --- a/Source/cmDocumentationSection.cxx +++ /dev/null @@ -1,28 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmDocumentationSection.h" - -void cmDocumentationSection::Append(const char* data[][2]) -{ - int i = 0; - while (data[i][1]) { - this->Entries.emplace_back(data[i][0], data[i][1]); - data += 1; - } -} - -void cmDocumentationSection::Prepend(const char* data[][2]) -{ - std::vector<cmDocumentationEntry> tmp; - int i = 0; - while (data[i][1]) { - tmp.emplace_back(data[i][0], data[i][1]); - data += 1; - } - this->Entries.insert(this->Entries.begin(), tmp.begin(), tmp.end()); -} - -void cmDocumentationSection::Append(const char* n, const char* b) -{ - this->Entries.emplace_back(n, b); -} diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index 276e520..b5e24fe 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -4,11 +4,10 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <iterator> #include <string> #include <vector> -#include <cmext/algorithm> - #include "cmDocumentationEntry.h" // Low-level interface for custom documents: @@ -45,21 +44,20 @@ public: { this->Entries.push_back(entry); } - void Append(const std::vector<cmDocumentationEntry>& entries) + + template <typename Iterable> + void Append(const Iterable& entries) { - cm::append(this->Entries, entries); + this->Entries.insert(std::end(this->Entries), std::begin(entries), + std::end(entries)); } - /** Append an entry to this section using NULL terminated chars */ - void Append(const char* [][2]); - void Append(const char* n, const char* b); - /** prepend some documentation to this section */ - void Prepend(const char* [][2]); - void Prepend(const std::vector<cmDocumentationEntry>& entries) + template <typename Iterable> + void Prepend(const Iterable& entries) { - this->Entries.insert(this->Entries.begin(), entries.begin(), - entries.end()); + this->Entries.insert(std::begin(this->Entries), std::begin(entries), + std::end(entries)); } private: diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 776ee40..2fd7f8a 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -60,11 +60,10 @@ cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(cmMakefile* mf) return std::unique_ptr<cmLocalGenerator>(std::move(lg)); } -void cmGlobalBorlandMakefileGenerator::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalBorlandMakefileGenerator::GetDocumentation() { - entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName(); - entry.Brief = "Generates Borland makefiles."; + return { cmGlobalBorlandMakefileGenerator::GetActualName(), + "Generates Borland makefiles." }; } std::vector<cmGlobalGenerator::GeneratedMakeCommand> diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index a280b81..049d6ba 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -13,7 +13,6 @@ class cmLocalGenerator; class cmMakefile; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalBorlandMakefileGenerator * \brief Write a Borland makefiles. @@ -38,7 +37,7 @@ public: static std::string GetActualName() { return "Borland Makefiles"; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); //! Create a local generator appropriate to this Global Generator std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index d6ababb..a935079 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -4,6 +4,10 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmDocumentationEntry.h" // IWYU pragma: export + +// TODO The following headers are parts of the `cmGlobalGeneratorFactory` +// public API, so could be defined as export to IWYU #include <string> #include <vector> @@ -11,7 +15,6 @@ class cmGlobalGenerator; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalGeneratorFactory * \brief Responable for creating cmGlobalGenerator instances @@ -28,7 +31,7 @@ public: const std::string& n, bool allowArch, cmake* cm) const = 0; /** Get the documentation entry for this factory */ - virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0; + virtual cmDocumentationEntry GetDocumentation() const = 0; /** Get the names of the current registered generators */ virtual std::vector<std::string> GetGeneratorNames() const = 0; @@ -47,7 +50,7 @@ public: virtual std::string GetDefaultPlatformName() const = 0; }; -template <class T> +template <typename T> class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory { public: @@ -62,21 +65,19 @@ public: } /** Get the documentation entry for this factory */ - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - T::GetDocumentation(entry); + return T::GetDocumentation(); } /** Get the names of the current registered generators */ std::vector<std::string> GetGeneratorNames() const override { - std::vector<std::string> names; - names.push_back(T::GetActualName()); - return names; + return { T::GetActualName() }; } std::vector<std::string> GetGeneratorNamesWithPlatform() const override { - return std::vector<std::string>(); + return {}; } /** Determine whether or not this generator supports toolsets */ @@ -89,8 +90,8 @@ public: std::vector<std::string> GetKnownPlatforms() const override { // default is no platform supported - return std::vector<std::string>(); + return {}; } - std::string GetDefaultPlatformName() const override { return std::string(); } + std::string GetDefaultPlatformName() const override { return {}; } }; diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 9c334a5..18c48d7 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -15,7 +15,6 @@ #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" -#include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGhsMultiGpj.h" @@ -58,11 +57,12 @@ cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmMakefile* mf) cm::make_unique<cmLocalGhsMultiGenerator>(this, mf)); } -void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalGhsMultiGenerator::GetDocumentation() { - entry.Name = GetActualName(); - entry.Brief = - "Generates Green Hills MULTI files (experimental, work-in-progress)."; + return { + GetActualName(), + "Generates Green Hills MULTI files (experimental, work-in-progress)." + }; } void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index aa68d3b..4a79610 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -18,7 +18,6 @@ class cmGeneratorTarget; class cmLocalGenerator; class cmMakefile; class cmake; -struct cmDocumentationEntry; class cmGlobalGhsMultiGenerator : public cmGlobalGenerator { @@ -46,7 +45,7 @@ public: std::string GetName() const override { return GetActualName(); } /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); /** * Utilized by the generator factory to determine if this generator diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index 1a625cc..f1d4d09 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -6,7 +6,6 @@ #include <cmext/algorithm> -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" @@ -36,11 +35,10 @@ void cmGlobalJOMMakefileGenerator::EnableLanguage( this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } -void cmGlobalJOMMakefileGenerator::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalJOMMakefileGenerator::GetDocumentation() { - entry.Name = cmGlobalJOMMakefileGenerator::GetActualName(); - entry.Brief = "Generates JOM makefiles."; + return { cmGlobalJOMMakefileGenerator::GetActualName(), + "Generates JOM makefiles." }; } void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os, diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index 332d1cf..5e74875 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -13,7 +13,6 @@ class cmMakefile; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalJOMMakefileGenerator * \brief Write a JOM makefiles. @@ -39,7 +38,7 @@ public: static std::string GetActualName() { return "NMake Makefiles JOM"; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index d4ff1e0..e543aea 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -4,7 +4,6 @@ #include "cmsys/FStream.hxx" -#include "cmDocumentationEntry.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -53,9 +52,8 @@ void cmGlobalMSYSMakefileGenerator::EnableLanguage( } } -void cmGlobalMSYSMakefileGenerator::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalMSYSMakefileGenerator::GetDocumentation() { - entry.Name = cmGlobalMSYSMakefileGenerator::GetActualName(); - entry.Brief = "Generates MSYS makefiles."; + return { cmGlobalMSYSMakefileGenerator::GetActualName(), + "Generates MSYS makefiles." }; } diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h index 586487f..a8516a4 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.h +++ b/Source/cmGlobalMSYSMakefileGenerator.h @@ -11,7 +11,6 @@ class cmMakefile; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalMSYSMakefileGenerator * \brief Write a NMake makefiles. @@ -36,7 +35,7 @@ public: static std::string GetActualName() { return "MSYS Makefiles"; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index 5a7edae..a0a52d3 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalMinGWMakefileGenerator.h" -#include "cmDocumentationEntry.h" #include "cmMakefile.h" #include "cmState.h" #include "cmSystemTools.h" @@ -19,9 +18,8 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm) cm->GetState()->SetMinGWMake(true); } -void cmGlobalMinGWMakefileGenerator::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalMinGWMakefileGenerator::GetDocumentation() { - entry.Name = cmGlobalMinGWMakefileGenerator::GetActualName(); - entry.Brief = "Generates a make file for use with mingw32-make."; + return { cmGlobalMinGWMakefileGenerator::GetActualName(), + "Generates a make file for use with mingw32-make." }; } diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index 92d495c..b39db03 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -11,7 +11,6 @@ class cmMakefile; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalMinGWMakefileGenerator * \brief Write a NMake makefiles. @@ -35,5 +34,5 @@ public: static std::string GetActualName() { return "MinGW Makefiles"; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); }; diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index eabacf6..cb53850 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -8,7 +8,6 @@ #include "cmsys/RegularExpression.hxx" -#include "cmDocumentationEntry.h" #include "cmDuration.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -80,11 +79,10 @@ void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures() cmSystemTools::OP_LESS, this->NMakeVersion, "9"); } -void cmGlobalNMakeMakefileGenerator::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalNMakeMakefileGenerator::GetDocumentation() { - entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName(); - entry.Brief = "Generates NMake makefiles."; + return { cmGlobalNMakeMakefileGenerator::GetActualName(), + "Generates NMake makefiles." }; } void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice( @@ -128,12 +126,8 @@ void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os, if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { // nmake does not support parallel build level // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx - - /* clang-format off */ - os << - "Warning: NMake does not support parallel builds. " - "Ignoring parallel build command line option.\n"; - /* clang-format on */ + os << "Warning: NMake does not support parallel builds. " + "Ignoring parallel build command line option.\n"; } this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice( diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index b3574eb..436ebca 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -15,7 +15,6 @@ class cmMakefile; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalNMakeMakefileGenerator * \brief Write a NMake makefiles. @@ -45,7 +44,7 @@ public: } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 395372b..aa1ded0 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -25,7 +25,6 @@ #include "cmsys/FStream.hxx" #include "cmCxxModuleMapper.h" -#include "cmDocumentationEntry.h" #include "cmFileSet.h" #include "cmFortranParser.h" #include "cmGeneratedFileStream.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. @@ -3211,10 +3210,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( diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index dac1c52..1628349 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -35,7 +35,6 @@ class cmMakefile; class cmOutputConverter; class cmStateDirectory; class cmake; -struct cmDocumentationEntry; /** * \class cmGlobalNinjaGenerator @@ -193,7 +192,7 @@ public: /** Get encoding used by generator for ninja files */ codecvt::Encoding GetMakefileEncoding() const override; - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); void EnableLanguage(std::vector<std::string> const& languages, cmMakefile* mf, bool optional) override; @@ -656,7 +655,7 @@ public: new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>()); } - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); std::string GetName() const override { diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index bf9e40e..70a9d3e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -11,7 +11,6 @@ #include <cmext/algorithm> #include <cmext/memory> -#include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -71,11 +70,10 @@ cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmMakefile* mf) cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf)); } -void cmGlobalUnixMakefileGenerator3::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalUnixMakefileGenerator3::GetDocumentation() { - entry.Name = cmGlobalUnixMakefileGenerator3::GetActualName(); - entry.Brief = "Generates standard UNIX makefiles."; + return { cmGlobalUnixMakefileGenerator3::GetActualName(), + "Generates standard UNIX makefiles." }; } void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory( diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 92e567a..214ba2a 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -24,7 +24,6 @@ class cmLocalUnixMakefileGenerator3; class cmMakefile; class cmMakefileTargetGenerator; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalUnixMakefileGenerator3 * \brief Write a Unix makefiles. @@ -101,7 +100,7 @@ public: bool SupportsCustomCommandDepfile() const override { return true; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( cmMakefile* mf) override; diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index c53ddf5..75e3df8 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -7,7 +7,6 @@ #include <utility> #include <vector> -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" @@ -74,11 +73,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(std::move(ret)); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs11generatorName) + " [arch]"; - entry.Brief = "Deprecated. Generates Visual Studio 2012 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; + return { std::string(vs11generatorName) + " [arch]", + "Deprecated. Generates Visual Studio 2012 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"." }; } std::vector<std::string> GetGeneratorNames() const override diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index 600ee0a..7e56a78 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -6,7 +6,6 @@ #include <sstream> #include <vector> -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" @@ -62,11 +61,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs12generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2013 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; + return { std::string(vs12generatorName) + " [arch]", + "Generates Visual Studio 2013 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"." }; } std::vector<std::string> GetGeneratorNames() const override diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 9f94cca..0e05083 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -7,7 +7,6 @@ #include <cm/vector> -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" @@ -64,11 +63,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs14generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2015 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; + return { std::string(vs14generatorName) + " [arch]", + "Generates Visual Studio 2015 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"." }; } std::vector<std::string> GetGeneratorNames() const override diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index e03e665..cd0b114 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -6,7 +6,6 @@ #include <utility> #include <vector> -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" @@ -62,11 +61,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(std::move(ret)); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs9generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2008 project files. " - "Optional [arch] can be \"Win64\" or \"IA64\"."; + return { std::string(vs9generatorName) + " [arch]", + "Generates Visual Studio 2008 project files. " + "Optional [arch] can be \"Win64\" or \"IA64\"." }; } std::vector<std::string> GetGeneratorNames() const override diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index be318c1..ee24f05 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -14,7 +14,6 @@ #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmGlobalGeneratorFactory.h" #include "cmMakefile.h" @@ -255,11 +254,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs15generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2017 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; + return { std::string(vs15generatorName) + " [arch]", + "Generates Visual Studio 2017 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"." }; } std::vector<std::string> GetGeneratorNames() const override @@ -351,11 +350,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs16generatorName); - entry.Brief = "Generates Visual Studio 2019 project files. " - "Use -A option to specify architecture."; + return { std::string(vs16generatorName), + "Generates Visual Studio 2019 project files. " + "Use -A option to specify architecture." }; } std::vector<std::string> GetGeneratorNames() const override @@ -416,11 +415,11 @@ public: return std::unique_ptr<cmGlobalGenerator>(); } - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - entry.Name = std::string(vs17generatorName); - entry.Brief = "Generates Visual Studio 2022 project files. " - "Use -A option to specify architecture."; + return { std::string(vs17generatorName), + "Generates Visual Studio 2022 project files. " + "Use -A option to specify architecture." }; } std::vector<std::string> GetGeneratorNames() const override diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx index fb2a8b6..ed44e6b 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.cxx +++ b/Source/cmGlobalWatcomWMakeGenerator.cxx @@ -4,7 +4,6 @@ #include <ostream> -#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" @@ -54,11 +53,10 @@ bool cmGlobalWatcomWMakeGenerator::SetSystemName(std::string const& s, return this->cmGlobalUnixMakefileGenerator3::SetSystemName(s, mf); } -void cmGlobalWatcomWMakeGenerator::GetDocumentation( - cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalWatcomWMakeGenerator::GetDocumentation() { - entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName(); - entry.Brief = "Generates Watcom WMake makefiles."; + return { cmGlobalWatcomWMakeGenerator::GetActualName(), + "Generates Watcom WMake makefiles." }; } std::vector<cmGlobalGenerator::GeneratedMakeCommand> diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index eb93934..5579120 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -15,7 +15,6 @@ class cmMakefile; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalWatcomWMakeGenerator * \brief Write a NMake makefiles. @@ -39,7 +38,7 @@ public: static std::string GetActualName() { return "Watcom WMake"; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); /** Tell the generator about the target system. */ bool SetSystemName(std::string const& s, cmMakefile* mf) override; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 62e5a1e..0e94de5 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -24,7 +24,6 @@ #include "cmCustomCommandGenerator.h" #include "cmCustomCommandLines.h" #include "cmCustomCommandTypes.h" -#include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -149,9 +148,9 @@ public: std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( const std::string& name, bool allowArch, cmake* cm) const override; - void GetDocumentation(cmDocumentationEntry& entry) const override + cmDocumentationEntry GetDocumentation() const override { - cmGlobalXCodeGenerator::GetDocumentation(entry); + return cmGlobalXCodeGenerator::GetDocumentation(); } std::vector<std::string> GetGeneratorNames() const override @@ -4864,10 +4863,10 @@ std::string cmGlobalXCodeGenerator::ExpandCFGIntDir( return tmp; } -void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry) +cmDocumentationEntry cmGlobalXCodeGenerator::GetDocumentation() { - entry.Name = cmGlobalXCodeGenerator::GetActualName(); - entry.Brief = "Generate Xcode project files."; + return { cmGlobalXCodeGenerator::GetActualName(), + "Generate Xcode project files." }; } std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake( diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 9ae75fb..856852b 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -14,6 +14,7 @@ #include <cm/optional> #include <cm/string_view> +#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmTransformDepfile.h" #include "cmValue.h" @@ -28,7 +29,6 @@ class cmMakefile; class cmSourceFile; class cmSourceGroup; class cmake; -struct cmDocumentationEntry; /** \class cmGlobalXCodeGenerator * \brief Write a Unix makefiles. @@ -54,7 +54,7 @@ public: static std::string GetActualName() { return "Xcode"; } /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); + static cmDocumentationEntry GetDocumentation(); //! Create a local generator appropriate to this Global Generator std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index 333003b..ff513be 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -107,8 +107,8 @@ static void printMessageText(std::ostream& msg, std::string const& text) { msg << ":\n"; cmDocumentationFormatter formatter; - formatter.SetIndent(" "); - formatter.PrintFormatted(msg, text.c_str()); + formatter.SetIndent(2u); + formatter.PrintFormatted(msg, text); } static void displayMessage(MessageType t, std::ostringstream& msg) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 36c0089..befcb55 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -40,7 +40,6 @@ #include "cmCommands.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" -#include "cmDocumentationFormatter.h" #include "cmDuration.h" #include "cmExternalMakefileProjectGenerator.h" #include "cmFileTimeCache.h" @@ -150,21 +149,136 @@ auto IgnoreAndTrueLambda = [](std::string const&, cmake*) -> bool { using CommandArgument = cmCommandLineArgument<bool(std::string const& value, cmake* state)>; -} // namespace - -static bool cmakeCheckStampFile(const std::string& stampName); -static bool cmakeCheckStampList(const std::string& stampList); - #ifndef CMAKE_BOOTSTRAP -static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, - void* ctx, const char* /*unused*/, - const cmMakefile* /*unused*/) +void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, + void* ctx, const char* /*unused*/, + const cmMakefile* /*unused*/) { cmake* cm = reinterpret_cast<cmake*>(ctx); cm->MarkCliAsUsed(variable); } #endif +bool cmakeCheckStampFile(const std::string& stampName) +{ + // The stamp file does not exist. Use the stamp dependencies to + // determine whether it is really out of date. This works in + // conjunction with cmLocalVisualStudio7Generator to avoid + // repeatedly re-running CMake when the user rebuilds the entire + // solution. + std::string stampDepends = cmStrCat(stampName, ".depend"); +#if defined(_WIN32) || defined(__CYGWIN__) + cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary); +#else + cmsys::ifstream fin(stampDepends.c_str()); +#endif + if (!fin) { + // The stamp dependencies file cannot be read. Just assume the + // build system is really out of date. + std::cout << "CMake is re-running because " << stampName + << " dependency file is missing.\n"; + return false; + } + + // Compare the stamp dependencies against the dependency file itself. + { + cmFileTimeCache ftc; + std::string dep; + while (cmSystemTools::GetLineFromStream(fin, dep)) { + int result; + if (!dep.empty() && dep[0] != '#' && + (!ftc.Compare(stampDepends, dep, &result) || result < 0)) { + // The stamp depends file is older than this dependency. The + // build system is really out of date. + /* clang-format off */ + std::cout << "CMake is re-running because " << stampName + << " is out-of-date.\n" + " the file '" << dep << "'\n" + " is newer than '" << stampDepends << "'\n" + " result='" << result << "'\n"; + /* clang-format on */ + return false; + } + } + } + + // The build system is up to date. The stamp file has been removed + // by the VS IDE due to a "rebuild" request. Restore it atomically. + std::ostringstream stampTempStream; + stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed(); + std::string stampTemp = stampTempStream.str(); + { + // TODO: Teach cmGeneratedFileStream to use a random temp file (with + // multiple tries in unlikely case of conflict) and use that here. + cmsys::ofstream stamp(stampTemp.c_str()); + stamp << "# CMake generation timestamp file for this directory.\n"; + } + std::string err; + if (cmSystemTools::RenameFile(stampTemp, stampName, + cmSystemTools::Replace::Yes, &err) == + cmSystemTools::RenameResult::Success) { + // CMake does not need to re-run because the stamp file is up-to-date. + return true; + } + cmSystemTools::RemoveFile(stampTemp); + cmSystemTools::Error( + cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err)); + return false; +} + +bool cmakeCheckStampList(const std::string& stampList) +{ + // If the stamp list does not exist CMake must rerun to generate it. + if (!cmSystemTools::FileExists(stampList)) { + std::cout << "CMake is re-running because generate.stamp.list " + "is missing.\n"; + return false; + } + cmsys::ifstream fin(stampList.c_str()); + if (!fin) { + std::cout << "CMake is re-running because generate.stamp.list " + "could not be read.\n"; + return false; + } + + // Check each stamp. + std::string stampName; + while (cmSystemTools::GetLineFromStream(fin, stampName)) { + if (!cmakeCheckStampFile(stampName)) { + return false; + } + } + return true; +} + +} // namespace + +cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[18] = { + { "-S <path-to-source>", "Explicitly specify a source directory." }, + { "-B <path-to-build>", "Explicitly specify a build directory." }, + { "-C <initial-cache>", "Pre-load a script to populate the cache." }, + { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, + { "-U <globbing_expr>", "Remove matching entries from CMake cache." }, + { "-G <generator-name>", "Specify a build system generator." }, + { "-T <toolset-name>", "Specify toolset name if supported by generator." }, + { "-A <platform-name>", "Specify platform name if supported by generator." }, + { "--toolchain <file>", "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." }, + { "--install-prefix <directory>", + "Specify install directory [CMAKE_INSTALL_PREFIX]." }, + { "-Wdev", "Enable developer warnings." }, + { "-Wno-dev", "Suppress developer warnings." }, + { "-Werror=dev", "Make developer warnings errors." }, + { "-Wno-error=dev", "Make developer warnings not errors." }, + { "-Wdeprecated", "Enable deprecation warnings." }, + { "-Wno-deprecated", "Suppress deprecation warnings." }, + { "-Werror=deprecated", + "Make deprecated macro and function warnings " + "errors." }, + { "-Wno-error=deprecated", + "Make deprecated macro and function warnings " + "not errors." } +}; + cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind) : CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory()) , FileTimeCache(cm::make_unique<cmFileTimeCache>()) @@ -1008,7 +1122,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) std::cout << "Running with debug output on for the 'find' commands " "for package(s)"; for (auto const& v : find_pkgs) { - std::cout << " " << v; + std::cout << ' ' << v; state->SetDebugFindOutputPkgs(v); } std::cout << ".\n"; @@ -1021,7 +1135,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) std::vector<std::string> find_vars(cmTokenize(value, ",")); std::cout << "Running with debug output on for the variable(s)"; for (auto const& v : find_vars) { - std::cout << " " << v; + std::cout << ' ' << v; state->SetDebugFindOutputVars(v); } std::cout << ".\n"; @@ -1082,7 +1196,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) [](std::string const&, cmake* state) -> bool { std::cout << "Not searching for unused variables given on the " - << "command line.\n"; + "command line.\n"; state->SetWarnUnusedCli(false); return true; } }, @@ -1090,7 +1204,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) "--check-system-vars", CommandArgument::Values::Zero, [](std::string const&, cmake* state) -> bool { std::cout << "Also check system files when warning about unused and " - << "uninitialized variables.\n"; + "uninitialized variables.\n"; state->SetCheckSystemVars(true); return true; } }, @@ -1098,7 +1212,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) "--compile-no-warning-as-error", CommandArgument::Values::Zero, [](std::string const&, cmake* state) -> bool { std::cout << "Ignoring COMPILE_WARNING_AS_ERROR target property and " - << "CMAKE_COMPILE_WARNING_AS_ERROR variable.\n"; + "CMAKE_COMPILE_WARNING_AS_ERROR variable.\n"; state->SetIgnoreWarningAsError(true); return true; } } @@ -1497,7 +1611,7 @@ void cmake::SetTraceFile(const std::string& file) cmSystemTools::Error(ss.str()); return; } - std::cout << "Trace will be written to " << file << "\n"; + std::cout << "Trace will be written to " << file << '\n'; } void cmake::PrintTraceFormatVersion() @@ -2020,12 +2134,10 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) } std::vector<SaveCacheEntry> saved; std::ostringstream warning; - /* clang-format off */ warning << "You have changed variables that require your cache to be deleted.\n" - << "Configure will be re-run and you may have to reset some variables.\n" - << "The following variables have changed:\n"; - /* clang-format on */ + "Configure will be re-run and you may have to reset some variables.\n" + "The following variables have changed:\n"; for (auto i = argsSplit.begin(); i != argsSplit.end(); ++i) { SaveCacheEntry save; save.key = *i; @@ -2033,9 +2145,9 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) i++; if (i != argsSplit.end()) { save.value = *i; - warning << *i << "\n"; + warning << *i << '\n'; } else { - warning << "\n"; + warning << '\n'; i -= 1; } cmValue existingValue = this->State->GetCacheEntryValue(save.key); @@ -2437,7 +2549,7 @@ void cmake::CreateDefaultGlobalGenerator() auto gen = this->EvaluateDefaultGlobalGenerator(); #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) // This print could be unified for all platforms - std::cout << "-- Building for: " << gen->GetName() << "\n"; + std::cout << "-- Building for: " << gen->GetName() << '\n'; #endif this->SetGlobalGenerator(std::move(gen)); } @@ -2596,7 +2708,7 @@ int cmake::Generate() } this->GlobalGenerator->Generate(); if (!this->GraphVizFile.empty()) { - std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl; + std::cout << "Generate graphviz: " << this->GraphVizFile << '\n'; this->GenerateGraphViz(this->GraphVizFile); } if (this->WarnUnusedCli) { @@ -2837,17 +2949,15 @@ void cmake::AppendGlobalGeneratorsDocumentation( std::vector<cmDocumentationEntry>& v) { const auto defaultGenerator = this->EvaluateDefaultGlobalGenerator(); - const std::string defaultName = defaultGenerator->GetName(); - bool foundDefaultOne = false; + const auto defaultName = defaultGenerator->GetName(); + auto foundDefaultOne = false; for (const auto& g : this->Generators) { - cmDocumentationEntry e; - g->GetDocumentation(e); - if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) { - e.CustomNamePrefix = '*'; + v.emplace_back(g->GetDocumentation()); + if (!foundDefaultOne && cmHasPrefix(v.back().Name, defaultName)) { + v.back().CustomNamePrefix = '*'; foundDefaultOne = true; } - v.push_back(std::move(e)); } } @@ -2860,21 +2970,14 @@ void cmake::AppendExtraGeneratorsDocumentation( // Aliases: for (std::string const& a : eg->Aliases) { - cmDocumentationEntry e; - e.Name = a; - e.Brief = doc; - v.push_back(std::move(e)); + v.emplace_back(cmDocumentationEntry{ a, doc }); } // Full names: - const std::vector<std::string> generators = - eg->GetSupportedGlobalGenerators(); - for (std::string const& g : generators) { - cmDocumentationEntry e; - e.Name = - cmExternalMakefileProjectGenerator::CreateFullGeneratorName(g, name); - e.Brief = doc; - v.push_back(std::move(e)); + for (std::string const& g : eg->GetSupportedGlobalGenerators()) { + v.emplace_back(cmDocumentationEntry{ + cmExternalMakefileProjectGenerator::CreateFullGeneratorName(g, name), + doc }); } } } @@ -2893,7 +2996,7 @@ void cmake::PrintGeneratorList() cmDocumentation doc; auto generators = this->GetGeneratorsDocumentation(); doc.AppendSection("Generators", generators); - std::cerr << "\n"; + std::cerr << '\n'; doc.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr); #endif } @@ -2945,7 +3048,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake missing file: " << this->CheckBuildSystemArgument - << "\n"; + << '\n'; cmSystemTools::Stdout(msg.str()); } return 1; @@ -2965,7 +3068,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument - << "\n"; + << '\n'; cmSystemTools::Stdout(msg.str()); } // There was an error reading the file. Just rerun. @@ -2996,9 +3099,8 @@ int cmake::CheckBuildSystem() for (std::string const& p : products) { if (!(cmSystemTools::FileExists(p) || cmSystemTools::FileIsSymlink(p))) { if (verbose) { - std::ostringstream msg; - msg << "Re-run cmake, missing byproduct: " << p << "\n"; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout( + cmStrCat("Re-run cmake, missing byproduct: ", p, '\n')); } return 1; } @@ -3063,7 +3165,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake file: " << out_oldest - << " older than: " << dep_newest << "\n"; + << " older than: " << dep_newest << '\n'; cmSystemTools::Stdout(msg.str()); } return 1; @@ -3239,7 +3341,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) // permissions are questionable or some other process has deleted the // directory std::cerr << "Failed to change to directory " << destPath << " : " - << std::strerror(workdir.GetLastResult()) << std::endl; + << std::strerror(workdir.GetLastResult()) << '\n'; return 1; } std::vector<std::string> args2; @@ -3276,96 +3378,6 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) return 0; } -static bool cmakeCheckStampFile(const std::string& stampName) -{ - // The stamp file does not exist. Use the stamp dependencies to - // determine whether it is really out of date. This works in - // conjunction with cmLocalVisualStudio7Generator to avoid - // repeatedly re-running CMake when the user rebuilds the entire - // solution. - std::string stampDepends = cmStrCat(stampName, ".depend"); -#if defined(_WIN32) || defined(__CYGWIN__) - cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary); -#else - cmsys::ifstream fin(stampDepends.c_str()); -#endif - if (!fin) { - // The stamp dependencies file cannot be read. Just assume the - // build system is really out of date. - std::cout << "CMake is re-running because " << stampName - << " dependency file is missing.\n"; - return false; - } - - // Compare the stamp dependencies against the dependency file itself. - { - cmFileTimeCache ftc; - std::string dep; - while (cmSystemTools::GetLineFromStream(fin, dep)) { - int result; - if (!dep.empty() && dep[0] != '#' && - (!ftc.Compare(stampDepends, dep, &result) || result < 0)) { - // The stamp depends file is older than this dependency. The - // build system is really out of date. - std::cout << "CMake is re-running because " << stampName - << " is out-of-date.\n"; - std::cout << " the file '" << dep << "'\n"; - std::cout << " is newer than '" << stampDepends << "'\n"; - std::cout << " result='" << result << "'\n"; - return false; - } - } - } - - // The build system is up to date. The stamp file has been removed - // by the VS IDE due to a "rebuild" request. Restore it atomically. - std::ostringstream stampTempStream; - stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed(); - std::string stampTemp = stampTempStream.str(); - { - // TODO: Teach cmGeneratedFileStream to use a random temp file (with - // multiple tries in unlikely case of conflict) and use that here. - cmsys::ofstream stamp(stampTemp.c_str()); - stamp << "# CMake generation timestamp file for this directory.\n"; - } - std::string err; - if (cmSystemTools::RenameFile(stampTemp, stampName, - cmSystemTools::Replace::Yes, &err) == - cmSystemTools::RenameResult::Success) { - // CMake does not need to re-run because the stamp file is up-to-date. - return true; - } - cmSystemTools::RemoveFile(stampTemp); - cmSystemTools::Error( - cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err)); - return false; -} - -static bool cmakeCheckStampList(const std::string& stampList) -{ - // If the stamp list does not exist CMake must rerun to generate it. - if (!cmSystemTools::FileExists(stampList)) { - std::cout << "CMake is re-running because generate.stamp.list " - << "is missing.\n"; - return false; - } - cmsys::ifstream fin(stampList.c_str()); - if (!fin) { - std::cout << "CMake is re-running because generate.stamp.list " - << "could not be read.\n"; - return false; - } - - // Check each stamp. - std::string stampName; - while (cmSystemTools::GetLineFromStream(fin, stampName)) { - if (!cmakeCheckStampFile(stampName)) { - return false; - } - } - return true; -} - void cmake::IssueMessage(MessageType t, std::string const& text, cmListFileBacktrace const& backtrace) const { diff --git a/Source/cmake.h b/Source/cmake.h index 6b585a1..325c0c5 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -18,6 +18,7 @@ #include <cm/string_view> #include <cmext/string_view> +#include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" #include "cmListFileCache.h" @@ -45,7 +46,6 @@ class cmMakefile; class cmMessenger; class cmVariableWatch; struct cmBuildOptions; -struct cmDocumentationEntry; /** \brief Represents a cmake invocation. * @@ -793,37 +793,10 @@ private: #if !defined(CMAKE_BOOTSTRAP) std::unique_ptr<cmMakefileProfilingData> ProfilingOutput; #endif -}; -#define CMAKE_STANDARD_OPTIONS_TABLE \ - { "-S <path-to-source>", "Explicitly specify a source directory." }, \ - { "-B <path-to-build>", "Explicitly specify a build directory." }, \ - { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \ - { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \ - { "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \ - { "-G <generator-name>", "Specify a build system generator." }, \ - { "-T <toolset-name>", \ - "Specify toolset name if supported by generator." }, \ - { "-A <platform-name>", \ - "Specify platform name if supported by generator." }, \ - { "--toolchain <file>", \ - "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." }, \ - { "--install-prefix <directory>", \ - "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \ - { "-Wdev", "Enable developer warnings." }, \ - { "-Wno-dev", "Suppress developer warnings." }, \ - { "-Werror=dev", "Make developer warnings errors." }, \ - { "-Wno-error=dev", "Make developer warnings not errors." }, \ - { "-Wdeprecated", "Enable deprecation warnings." }, \ - { "-Wno-deprecated", "Suppress deprecation warnings." }, \ - { "-Werror=deprecated", \ - "Make deprecated macro and function warnings " \ - "errors." }, \ - { \ - "-Wno-error=deprecated", \ - "Make deprecated macro and function warnings " \ - "not errors." \ - } +public: + static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[18]; +}; #define FOR_EACH_C90_FEATURE(F) F(c_function_prototypes) diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 9f23667..a155787 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -24,7 +24,7 @@ #include "cmBuildOptions.h" #include "cmCommandLineArgument.h" #include "cmConsoleBuf.h" -#include "cmDocumentationEntry.h" // IWYU pragma: keep +#include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageMetadata.h" @@ -46,30 +46,28 @@ namespace { #ifndef CMAKE_BOOTSTRAP -const char* cmDocumentationName[][2] = { - { nullptr, " cmake - Cross-Platform Makefile Generator." }, - { nullptr, nullptr } +const cmDocumentationEntry cmDocumentationName = { + {}, + " cmake - Cross-Platform Makefile Generator." }; -const char* cmDocumentationUsage[][2] = { - { nullptr, +const cmDocumentationEntry cmDocumentationUsage[2] = { + { {}, " cmake [options] <path-to-source>\n" " cmake [options] <path-to-existing-build>\n" " cmake [options] -S <path-to-source> -B <path-to-build>" }, - { nullptr, + { {}, "Specify a source directory to (re-)generate a build system for " "it in the current working directory. Specify an existing build " - "directory to re-generate its build system." }, - { nullptr, nullptr } + "directory to re-generate its build system." } }; -const char* cmDocumentationUsageNote[][2] = { - { nullptr, "Run 'cmake --help' for more information." }, - { nullptr, nullptr } +const cmDocumentationEntry cmDocumentationUsageNote = { + {}, + "Run 'cmake --help' for more information." }; -const char* cmDocumentationOptions[][2] = { - CMAKE_STANDARD_OPTIONS_TABLE, +const cmDocumentationEntry cmDocumentationOptions[31] = { { "--preset <preset>,--preset=<preset>", "Specify a configure preset." }, { "--list-presets[=<type>]", "List available presets." }, { "-E", "CMake command mode." }, @@ -113,15 +111,12 @@ const char* cmDocumentationOptions[][2] = { { "--compile-no-warning-as-error", "Ignore COMPILE_WARNING_AS_ERROR property and " "CMAKE_COMPILE_WARNING_AS_ERROR variable." }, -# if !defined(CMAKE_BOOTSTRAP) { "--profiling-format=<fmt>", "Output data for profiling CMake scripts. Supported formats: " "google-trace" }, { "--profiling-output=<file>", "Select an output path for the profiling data enabled through " - "--profiling-format." }, -# endif - { nullptr, nullptr } + "--profiling-format." } }; #endif @@ -228,8 +223,9 @@ int do_cmake(int ac, char const* const* av) } doc.AppendSection("Generators", generators); doc.PrependSection("Options", cmDocumentationOptions); + doc.PrependSection("Options", cmake::CMAKE_STANDARD_OPTIONS_TABLE); - return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; + return !doc.PrintRequestedDocumentation(std::cout); } #else if (ac == 1) { diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 363f473..fa38a65 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -11,21 +11,21 @@ #include "cmCTest.h" #include "cmConsoleBuf.h" #include "cmDocumentation.h" +#include "cmDocumentationEntry.h" #include "cmSystemTools.h" #include "CTest/cmCTestLaunch.h" #include "CTest/cmCTestScriptHandler.h" -static const char* cmDocumentationName[][2] = { - { nullptr, " ctest - Testing driver provided by CMake." }, - { nullptr, nullptr } +namespace { +const cmDocumentationEntry cmDocumentationName = { + {}, + " ctest - Testing driver provided by CMake." }; -static const char* cmDocumentationUsage[][2] = { { nullptr, - " ctest [options]" }, - { nullptr, nullptr } }; +const cmDocumentationEntry cmDocumentationUsage = { {}, " ctest [options]" }; -static const char* cmDocumentationOptions[][2] = { +const cmDocumentationEntry cmDocumentationOptions[74] = { { "--preset <preset>, --preset=<preset>", "Read arguments from a test preset." }, { "--list-presets", "List available test presets." }, @@ -155,9 +155,9 @@ static const char* cmDocumentationOptions[][2] = { { "--no-compress-output", "Do not compress test output when submitting." }, { "--print-labels", "Print all available test labels." }, { "--no-tests=<[error|ignore]>", - "Regard no tests found either as 'error' or 'ignore' it." }, - { nullptr, nullptr } + "Regard no tests found either as 'error' or 'ignore' it." } }; +} // anonymous namespace // this is a test driver program for cmCTest. int main(int argc, char const* const* argv) @@ -186,8 +186,7 @@ int main(int argc, char const* const* argv) if (cmSystemTools::GetCurrentWorkingDirectory().empty()) { cmCTestLog(&inst, ERROR_MESSAGE, - "Current working directory cannot be established." - << std::endl); + "Current working directory cannot be established.\n"); return 1; } @@ -199,10 +198,9 @@ int main(int argc, char const* const* argv) cmSystemTools::FileExists("DartTestfile.txt"))) { if (argc == 1) { cmCTestLog(&inst, ERROR_MESSAGE, - "*********************************" - << std::endl - << "No test configuration file found!" << std::endl - << "*********************************" << std::endl); + "*********************************\n" + "No test configuration file found!\n" + "*********************************\n"); } cmDocumentation doc; doc.addCTestStandardDocSections(); @@ -216,7 +214,7 @@ int main(int argc, char const* const* argv) doc.SetSection("Name", cmDocumentationName); doc.SetSection("Usage", cmDocumentationUsage); doc.PrependSection("Options", cmDocumentationOptions); - return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; + return !doc.PrintRequestedDocumentation(std::cout); } } |