summaryrefslogtreecommitdiffstats
path: root/Source/cmcmd.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmcmd.cxx')
-rw-r--r--Source/cmcmd.cxx306
1 files changed, 203 insertions, 103 deletions
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 28fcd27..3ea2186 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -15,15 +15,16 @@
#include "cmGlobalGenerator.h"
#include "cmQtAutoGenerators.h"
#include "cmVersion.h"
+#include "cmAlgorithms.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
-# include <cmsys/Terminal.h>
#endif
#include <cmsys/Directory.hxx>
#include <cmsys/Process.h>
#include <cmsys/FStream.hxx>
+#include <cmsys/Terminal.h>
#if defined(CMAKE_HAVE_VS_GENERATORS)
#include "cmCallVisualStudioMacro.h"
@@ -210,30 +211,99 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 0;
}
- // Echo string
- else if (args[1] == "echo" )
+ // run include what you use command and then run the compile
+ // command. This is an internal undocumented option and should
+ // only be used by CMake itself when running iwyu.
+ else if (args[1] == "__run_iwyu")
{
- unsigned int cc;
- const char* space = "";
- for ( cc = 2; cc < args.size(); cc ++ )
+ if (args.size() < 3)
{
- std::cout << space << args[cc];
- space = " ";
+ std::cerr << "__run_iwyu Usage: -E __run_iwyu [--iwyu=/path/iwyu]"
+ " -- compile command\n";
+ return 1;
}
- std::cout << std::endl;
+ bool doing_options = true;
+ std::vector<std::string> orig_cmd;
+ std::string iwyu;
+ for (std::string::size_type cc = 2; cc < args.size(); cc ++)
+ {
+ std::string const& arg = args[cc];
+ if (arg == "--")
+ {
+ doing_options = false;
+ }
+ else if (doing_options && cmHasLiteralPrefix(arg, "--iwyu="))
+ {
+ iwyu = arg.substr(7);
+ }
+ else if (doing_options)
+ {
+ std::cerr << "__run_iwyu given unknown argument: " << arg << "\n";
+ return 1;
+ }
+ else
+ {
+ orig_cmd.push_back(arg);
+ }
+ }
+ if (iwyu.empty())
+ {
+ std::cerr << "__run_iwyu missing --iwyu=\n";
+ return 1;
+ }
+ if (orig_cmd.empty())
+ {
+ std::cerr << "__run_iwyu missing compile command after --\n";
+ return 1;
+ }
+
+ // Construct the iwyu command line by taking what was given
+ // and adding all the arguments we give to the compiler.
+ std::vector<std::string> iwyu_cmd;
+ cmSystemTools::ExpandListArgument(iwyu, iwyu_cmd, true);
+ iwyu_cmd.insert(iwyu_cmd.end(), orig_cmd.begin()+1, orig_cmd.end());
+
+ // Run the iwyu command line. Capture its stderr and hide its stdout.
+ int ret = 0;
+ std::string stdErr;
+ if(!cmSystemTools::RunSingleCommand(iwyu_cmd, 0, &stdErr, &ret,
+ 0, cmSystemTools::OUTPUT_NONE))
+ {
+ std::cerr << "Error running '" << iwyu_cmd[0] << "': "
+ << stdErr << "\n";
+ return 1;
+ }
+
+ // Warn if iwyu reported anything.
+ if(stdErr.find("should remove these lines:") != stdErr.npos
+ || stdErr.find("should add these lines:") != stdErr.npos)
+ {
+ std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
+ << stdErr << "\n";
+ }
+
+ // Now run the real compiler command and return its result value.
+ if(!cmSystemTools::RunSingleCommand(orig_cmd, 0, &stdErr, &ret, 0,
+ cmSystemTools::OUTPUT_PASSTHROUGH))
+ {
+ std::cerr << "Error running '" << orig_cmd[0] << "': "
+ << stdErr << "\n";
+ return 1;
+ }
+ return ret;
+ }
+
+ // Echo string
+ else if (args[1] == "echo" )
+ {
+ std::cout << cmJoin(cmRange(args).advance(2), " ") << std::endl;
return 0;
}
// Echo string no new line
else if (args[1] == "echo_append" )
{
- unsigned int cc;
- const char* space = "";
- for ( cc = 2; cc < args.size(); cc ++ )
- {
- std::cout << space << args[cc];
- space = " ";
- }
+ std::cout << cmJoin(cmRange(args).advance(2), " ");
return 0;
}
@@ -279,7 +349,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
std::vector<std::string> cmd(ai, ae);
int retval;
if(cmSystemTools::RunSingleCommand(
- cmd, 0, &retval, NULL, cmSystemTools::OUTPUT_PASSTHROUGH))
+ cmd, 0, 0, &retval, NULL, cmSystemTools::OUTPUT_PASSTHROUGH))
{
return retval;
}
@@ -287,8 +357,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
- // Command to create a symbolic link. Fails on platforms not
- // supporting them.
else if (args[1] == "environment" )
{
std::vector<std::string> env = cmSystemTools::GetEnvironmentVariables();
@@ -352,8 +420,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
{
for (std::string::size_type cc = 2; cc < args.size(); cc ++)
{
- // Complain if the file could not be removed, still exists,
- // and the -f option was not given.
if(!cmSystemTools::Touch(args[cc], true))
{
return 1;
@@ -406,12 +472,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Clock command
else if (args[1] == "time" && args.size() > 2)
{
- std::string command = args[2];
- for (std::string::size_type cc = 3; cc < args.size(); cc ++)
- {
- command += " ";
- command += args[cc];
- }
+ std::string command = cmJoin(cmRange(args).advance(2), " ");
clock_t clock_start, clock_finish;
time_t time_start, time_finish;
@@ -419,7 +480,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
time(&time_start);
clock_start = clock();
int ret =0;
- cmSystemTools::RunSingleCommand(command.c_str(), 0, &ret);
+ cmSystemTools::RunSingleCommand(command.c_str(), 0, 0, &ret);
clock_finish = clock();
time(&time_finish);
@@ -472,18 +533,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
- std::string command = "\"";
- command += args[3];
- command += "\"";
- for (std::string::size_type cc = 4; cc < args.size(); cc ++)
- {
- command += " \"";
- command += args[cc];
- command += "\"";
- }
+ std::string command = cmWrap('"', cmRange(args).advance(3), '"', " ");
int retval = 0;
int timeout = 0;
- if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, &retval,
+ if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, 0, &retval,
directory.c_str(), cmSystemTools::OUTPUT_NORMAL, timeout) )
{
return retval;
@@ -534,48 +587,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Command to report progress for a build
else if (args[1] == "cmake_progress_report" && args.size() >= 3)
{
- std::string dirName = args[2];
- dirName += "/Progress";
- std::string fName;
- FILE *progFile;
-
- // read the count
- fName = dirName;
- fName += "/count.txt";
- progFile = cmsys::SystemTools::Fopen(fName,"r");
- int count = 0;
- if (!progFile)
- {
- return 0;
- }
- else
- {
- if (1!=fscanf(progFile,"%i",&count))
- {
- cmSystemTools::Message("Could not read from progress file.");
- }
- fclose(progFile);
- }
- unsigned int i;
- for (i = 3; i < args.size(); ++i)
- {
- fName = dirName;
- fName += "/";
- fName += args[i];
- progFile = cmsys::SystemTools::Fopen(fName,"w");
- if (progFile)
- {
- fprintf(progFile,"empty");
- fclose(progFile);
- }
- }
- int fileNum = static_cast<int>
- (cmsys::Directory::GetNumberOfFilesInDirectory(dirName));
- if (count > 0)
- {
- // print the progress
- fprintf(stdout,"[%3i%%] ",((fileNum-3)*100)/count);
- }
+ // This has been superseded by cmake_echo_color --progress-*
+ // options. We leave it here to avoid errors if somehow this
+ // is invoked by an existing makefile without regenerating.
return 0;
}
@@ -710,16 +724,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir);
startOutDir = cmSystemTools::CollapseFullPath(startOutDir);
cm.SetHomeDirectory(homeDir);
- cm.SetStartDirectory(startDir);
cm.SetHomeOutputDirectory(homeOutDir);
- cm.SetStartOutputDirectory(startOutDir);
if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen))
{
cm.SetGlobalGenerator(ggd);
- cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
- lgd->GetMakefile()->SetStartDirectory(startDir);
- lgd->GetMakefile()->SetStartOutputDirectory(startOutDir);
- lgd->GetMakefile()->MakeStartDirectoriesCurrent();
+ cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->MakeLocalGenerator());
+ lgd->GetMakefile()->SetCurrentSourceDirectory(startDir);
+ lgd->GetMakefile()->SetCurrentBinaryDirectory(startOutDir);
// Actually scan dependencies.
return lgd->UpdateDependencies(depInfo.c_str(),
@@ -753,12 +764,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
{
return cmcmd::VisualStudioLink(args, 2);
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
// Internal CMake color makefile support.
else if (args[1] == "cmake_echo_color")
{
return cmcmd::ExecuteEchoColor(args);
}
+#ifdef CMAKE_BUILD_WITH_CMAKE
else if (args[1] == "cmake_autogen" && args.size() >= 4)
{
cmQtAutoGenerators autogen;
@@ -771,10 +782,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Tar files
else if (args[1] == "tar" && args.size() > 3)
{
+ const char* knownFormats[] =
+ {
+ "7zip",
+ "gnutar",
+ "pax",
+ "paxr",
+ "zip"
+ };
+
std::string flags = args[2];
std::string outFile = args[3];
std::vector<std::string> files;
std::string mtime;
+ std::string format;
bool doing_options = true;
for (std::string::size_type cc = 4; cc < args.size(); cc ++)
{
@@ -797,6 +818,19 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
}
+ else if (cmHasLiteralPrefix(arg, "--format="))
+ {
+ format = arg.substr(9);
+ bool isKnown = std::find(cmArrayBegin(knownFormats),
+ cmArrayEnd(knownFormats), format) != cmArrayEnd(knownFormats);
+
+ if(!isKnown)
+ {
+ cmSystemTools::Error("Unknown -E tar --format= argument: ",
+ format.c_str());
+ return 1;
+ }
+ }
else
{
cmSystemTools::Error("Unknown option to -E tar: ", arg.c_str());
@@ -827,7 +861,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
compress = cmSystemTools::TarCompressGZip;
++nCompress;
}
- if ( nCompress > 1 )
+ if ( (format == "7zip" || format == "zip") && nCompress > 0 )
+ {
+ cmSystemTools::Error("Can not use compression flags with format: ",
+ format.c_str());
+ return 1;
+ }
+ else if ( nCompress > 1 )
{
cmSystemTools::Error("Can only compress a tar file one way; "
"at most one flag of z, j, or J may be used");
@@ -849,7 +889,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
else if ( flags.find_first_of('c') != flags.npos )
{
if ( !cmSystemTools::CreateTar(
- outFile.c_str(), files, compress, verbose, mtime) )
+ outFile.c_str(), files, compress, verbose, mtime, format) )
{
cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
return 1;
@@ -987,7 +1027,65 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link)
}
//----------------------------------------------------------------------------
-#ifdef CMAKE_BUILD_WITH_CMAKE
+static void cmcmdProgressReport(std::string const& dir,
+ std::string const& num)
+{
+ std::string dirName = dir;
+ dirName += "/Progress";
+ std::string fName;
+ FILE *progFile;
+
+ // read the count
+ fName = dirName;
+ fName += "/count.txt";
+ progFile = cmsys::SystemTools::Fopen(fName,"r");
+ int count = 0;
+ if (!progFile)
+ {
+ return;
+ }
+ else
+ {
+ if (1!=fscanf(progFile,"%i",&count))
+ {
+ cmSystemTools::Message("Could not read from progress file.");
+ }
+ fclose(progFile);
+ }
+ const char* last = num.c_str();
+ for(const char* c = last;; ++c)
+ {
+ if (*c == ',' || *c == '\0')
+ {
+ if (c != last)
+ {
+ fName = dirName;
+ fName += "/";
+ fName.append(last, c-last);
+ progFile = cmsys::SystemTools::Fopen(fName,"w");
+ if (progFile)
+ {
+ fprintf(progFile,"empty");
+ fclose(progFile);
+ }
+ }
+ if(*c == '\0')
+ {
+ break;
+ }
+ last = c + 1;
+ }
+ }
+ int fileNum = static_cast<int>
+ (cmsys::Directory::GetNumberOfFilesInDirectory(dirName));
+ if (count > 0)
+ {
+ // print the progress
+ fprintf(stdout,"[%3i%%] ",((fileNum-3)*100)/count);
+ }
+}
+
+//----------------------------------------------------------------------------
int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
{
// The arguments are
@@ -997,6 +1095,7 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
bool enabled = true;
int color = cmsysTerminal_Color_Normal;
bool newline = true;
+ std::string progressDir;
for(unsigned int i=2; i < args.size(); ++i)
{
if(args[i].find("--switch=") == 0)
@@ -1015,6 +1114,18 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
}
}
}
+ else if(cmHasLiteralPrefix(args[i], "--progress-dir="))
+ {
+ progressDir = args[i].substr(15);
+ }
+ else if(cmHasLiteralPrefix(args[i], "--progress-num="))
+ {
+ if (!progressDir.empty())
+ {
+ std::string const& progressNum = args[i].substr(15);
+ cmcmdProgressReport(progressDir, progressNum);
+ }
+ }
else if(args[i] == "--normal")
{
color = cmsysTerminal_Color_Normal;
@@ -1073,12 +1184,6 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
return 0;
}
-#else
-int cmcmd::ExecuteEchoColor(std::vector<std::string>&)
-{
- return 1;
-}
-#endif
//----------------------------------------------------------------------------
int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
@@ -1318,18 +1423,13 @@ bool cmcmd::RunCommand(const char* comment,
if(verbose)
{
std::cout << comment << ":\n";
- for(std::vector<std::string>::iterator i = command.begin();
- i != command.end(); ++i)
- {
- std::cout << *i << " ";
- }
- std::cout << "\n";
+ std::cout << cmJoin(command, " ") << "\n";
}
std::string output;
int retCode =0;
// use rc command to create .res file
cmSystemTools::RunSingleCommand(command,
- &output,
+ &output, &output,
&retCode, 0, cmSystemTools::OUTPUT_NONE);
// always print the output of the command, unless
// it is the dumb rc command banner, but if the command