summaryrefslogtreecommitdiffstats
path: root/Source/cmakemain.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmakemain.cxx')
-rw-r--r--Source/cmakemain.cxx220
1 files changed, 181 insertions, 39 deletions
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index a83f7dc..d70c9d9 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -23,6 +23,7 @@
# include "cmsys/ConsoleBuf.hxx"
#endif
+#include <cassert>
#include <ctype.h>
#include <iostream>
#include <string.h>
@@ -54,29 +55,38 @@ static const char* cmDocumentationUsageNote[][2] = {
# define CMAKE_BUILD_OPTIONS \
" <dir> = Project binary directory to be built.\n" \
- " -j [<jobs>] --parallel [<jobs>] = Build in parallel using\n" \
- " the given number of jobs. If <jobs> is omitted\n" \
- " the native build tool's default number is used.\n" \
+ " --parallel [<jobs>], -j [<jobs>]\n" \
+ " = Build in parallel using the given number of jobs. \n" \
+ " If <jobs> is omitted the native build tool's \n" \
+ " default number is used.\n" \
" The CMAKE_BUILD_PARALLEL_LEVEL environment " \
"variable\n" \
" specifies a default parallel level when this " \
"option\n" \
" is not given.\n" \
- " --target <tgt> = Build <tgt> instead of default targets.\n" \
- " May only be specified once.\n" \
+ " --target <tgt>..., -t <tgt>... \n" \
+ " = Build <tgt> instead of default targets.\n" \
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
" --clean-first = Build target 'clean' first, then build.\n" \
" (To clean only, use --target 'clean'.)\n" \
- " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \
- " -v --verbose = Enable verbose output - if supported - including\n" \
+ " --verbose, -v = Enable verbose output - if supported - including\n" \
" the build commands to be executed. \n" \
" -- = Pass remaining options to the native tool.\n"
+# define CMAKE_INSTALL_OPTIONS \
+ " <dir> = Project binary directory to install.\n" \
+ " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
+ " --component <comp> = Component-based install. Only install <comp>.\n" \
+ " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n" \
+ " --strip = Performing install/strip.\n" \
+ " -v --verbose = Enable verbose output.\n"
+
static const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
{ "-E", "CMake command mode." },
{ "-L[A][H]", "List non-advanced cached variables." },
{ "--build <dir>", "Build a CMake-generated project binary tree." },
+ { "--install <dir>", "Install a CMake-generated project binary tree." },
{ "--open <dir>", "Open generated project in the associated application." },
{ "-N", "View mode only." },
{ "-P <file>", "Process script mode." },
@@ -115,6 +125,7 @@ static int do_command(int ac, char const* const* av)
int do_cmake(int ac, char const* const* av);
static int do_build(int ac, char const* const* av);
+static int do_install(int ac, char const* const* av);
static int do_open(int ac, char const* const* av);
static cmMakefile* cmakemainGetMakefile(cmake* cm)
@@ -142,20 +153,21 @@ static std::string cmakemainGetStack(cmake* cm)
return msg;
}
-static void cmakemainMessageCallback(const char* m, const char* /*unused*/,
- cmake* cm)
+static void cmakemainMessageCallback(const std::string& m,
+ const char* /*unused*/, cmake* cm)
{
std::cerr << m << cmakemainGetStack(cm) << std::endl << std::flush;
}
-static void cmakemainProgressCallback(const char* m, float prog, cmake* cm)
+static void cmakemainProgressCallback(const std::string& m, float prog,
+ cmake* cm)
{
cmMakefile* mf = cmakemainGetMakefile(cm);
std::string dir;
- if ((mf) && (strstr(m, "Configuring") == m) && (prog < 0)) {
+ if (mf && cmHasLiteralPrefix(m, "Configuring") && (prog < 0)) {
dir = " ";
dir += mf->GetCurrentSourceDirectory();
- } else if ((mf) && (strstr(m, "Generating") == m)) {
+ } else if (mf && cmHasLiteralPrefix(m, "Generating")) {
dir = " ";
dir += mf->GetCurrentBinaryDirectory();
}
@@ -188,6 +200,9 @@ int main(int ac, char const* const* av)
if (strcmp(av[1], "--build") == 0) {
return do_build(ac, av);
}
+ if (strcmp(av[1], "--install") == 0) {
+ return do_install(ac, av);
+ }
if (strcmp(av[1], "--open") == 0) {
return do_open(ac, av);
}
@@ -319,10 +334,11 @@ int do_cmake(int ac, char const* const* av)
cmake cm(role, mode);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
- cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
- });
- cm.SetProgressCallback([&cm](const char* msg, float prog) {
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
});
cm.SetWorkingMode(workingMode);
@@ -393,13 +409,14 @@ static int do_build(int ac, char const* const* av)
return -1;
#else
int jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
- std::string target;
+ std::vector<std::string> targets;
std::string config = "Debug";
std::string dir;
std::vector<std::string> nativeOptions;
- bool clean = false;
+ bool cleanFirst = false;
+ bool foundClean = false;
+ bool foundNonClean = false;
bool verbose = cmSystemTools::HasEnv("VERBOSE");
- bool hasTarget = false;
enum Doing
{
@@ -419,25 +436,21 @@ static int do_build(int ac, char const* const* av)
if (jobs < 0) {
dir.clear();
}
+ doing = DoingNone;
} else if (cmHasLiteralPrefix(av[i], "--parallel")) {
const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr);
jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1);
if (jobs < 0) {
dir.clear();
}
- } else if (strcmp(av[i], "--target") == 0) {
- if (!hasTarget) {
- doing = DoingTarget;
- hasTarget = true;
- } else {
- std::cerr << "'--target' may not be specified more than once.\n\n";
- dir.clear();
- break;
- }
+ doing = DoingNone;
+ } else if ((strcmp(av[i], "--target") == 0) ||
+ (strcmp(av[i], "-t") == 0)) {
+ doing = DoingTarget;
} else if (strcmp(av[i], "--config") == 0) {
doing = DoingConfig;
} else if (strcmp(av[i], "--clean-first") == 0) {
- clean = true;
+ cleanFirst = true;
doing = DoingNone;
} else if ((strcmp(av[i], "--verbose") == 0) ||
(strcmp(av[i], "-v") == 0)) {
@@ -454,8 +467,23 @@ static int do_build(int ac, char const* const* av)
doing = DoingNone;
break;
case DoingTarget:
- target = av[i];
- doing = DoingNone;
+ if (strlen(av[i]) == 0) {
+ std::cerr << "Warning: Argument number " << i
+ << " after --target option is empty." << std::endl;
+ } else {
+ targets.emplace_back(av[i]);
+ if (strcmp(av[i], "clean") == 0) {
+ foundClean = true;
+ } else {
+ foundNonClean = true;
+ }
+ }
+ if (foundClean && foundNonClean) {
+ std::cerr << "Error: Building 'clean' and other targets together "
+ "is not supported."
+ << std::endl;
+ dir.clear();
+ }
break;
case DoingConfig:
config = av[i];
@@ -499,13 +527,126 @@ static int do_build(int ac, char const* const* av)
}
cmake cm(cmake::RoleInternal, cmState::Project);
- cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
});
- cm.SetProgressCallback([&cm](const char* msg, float prog) {
+ return cm.Build(jobs, dir, targets, config, nativeOptions, cleanFirst,
+ verbose);
+#endif
+}
+
+static int do_install(int ac, char const* const* av)
+{
+#ifndef CMAKE_BUILD_WITH_CMAKE
+ std::cerr << "This cmake does not support --install\n";
+ return -1;
+#else
+ assert(1 < ac);
+
+ std::string config;
+ std::string component;
+ std::string prefix;
+ std::string dir;
+ bool strip = false;
+ bool verbose = cmSystemTools::HasEnv("VERBOSE");
+
+ enum Doing
+ {
+ DoingNone,
+ DoingDir,
+ DoingConfig,
+ DoingComponent,
+ DoingPrefix,
+ };
+
+ Doing doing = DoingDir;
+
+ for (int i = 2; i < ac; ++i) {
+ if (strcmp(av[i], "--config") == 0) {
+ doing = DoingConfig;
+ } else if (strcmp(av[i], "--component") == 0) {
+ doing = DoingComponent;
+ } else if (strcmp(av[i], "--prefix") == 0) {
+ doing = DoingPrefix;
+ } else if (strcmp(av[i], "--strip") == 0) {
+ strip = true;
+ doing = DoingNone;
+ } else if ((strcmp(av[i], "--verbose") == 0) ||
+ (strcmp(av[i], "-v") == 0)) {
+ verbose = true;
+ doing = DoingNone;
+ } else {
+ switch (doing) {
+ case DoingDir:
+ dir = cmSystemTools::CollapseFullPath(av[i]);
+ doing = DoingNone;
+ break;
+ case DoingConfig:
+ config = av[i];
+ doing = DoingNone;
+ break;
+ case DoingComponent:
+ component = av[i];
+ doing = DoingNone;
+ break;
+ case DoingPrefix:
+ prefix = av[i];
+ doing = DoingNone;
+ break;
+ default:
+ std::cerr << "Unknown argument " << av[i] << std::endl;
+ dir.clear();
+ break;
+ }
+ }
+ }
+
+ if (dir.empty()) {
+ std::cerr << "Usage: cmake --install <dir> "
+ "[options]\nOptions:\n" CMAKE_INSTALL_OPTIONS;
+ return 1;
+ }
+
+ cmake cm(cmake::RoleScript, cmState::Script);
+
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
});
- return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.SetDebugOutputOn(verbose);
+ cm.SetWorkingMode(cmake::SCRIPT_MODE);
+
+ std::vector<std::string> args{ av[0] };
+
+ if (!prefix.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_PREFIX=" + prefix);
+ }
+
+ if (!component.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_COMPONENT=" + component);
+ }
+
+ if (strip) {
+ args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1");
+ }
+
+ if (!config.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config);
+ }
+
+ args.emplace_back("-P");
+ args.emplace_back(dir + "/cmake_install.cmake");
+
+ return cm.Run(args) ? 1 : 0;
#endif
}
@@ -541,10 +682,11 @@ static int do_open(int ac, char const* const* av)
}
cmake cm(cmake::RoleInternal, cmState::Unknown);
- cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
- });
- cm.SetProgressCallback([&cm](const char* msg, float prog) {
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
});
return cm.Open(dir, false) ? 0 : 1;