Commit ba68f771 authored by Ken Martin's avatar Ken Martin

yikes added new custom command support

parent 4f55e487
......@@ -159,6 +159,12 @@ IF(BUILD_TESTING)
ADD_TEST(DumpDocumentation ${EXECUTABLE_OUTPUT_PATH}/DumpDocumentation
--all-for-coverage)
ADD_TEST(CustomCommand ${EXECUTABLE_OUTPUT_PATH}/cmaketest
${CMake_SOURCE_DIR}/Tests/CustomCommand
${CMake_BINARY_DIR}/Tests/CustomCommand
CustomCommand
${CMake_BINARY_DIR}/Tests/CustomCommand/bin)
ADD_TEST(SystemInformation ${EXECUTABLE_OUTPUT_PATH}/cmaketest
${CMake_SOURCE_DIR}/Tests/SystemInformation
${CMake_BINARY_DIR}/Tests/SystemInformation
......
......@@ -15,14 +15,14 @@
=========================================================================*/
#include "cmAddCustomCommandCommand.h"
#include "cmTarget.h"
// cmAddCustomCommandCommand
bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args)
{
/* Let's complain at the end of this function about the lack of a particular
arg. For the moment, let's say that COMMAND, TARGET are always
required.
arg. For the moment, let's say that COMMAND, and either TARGET or SOURCE
are required.
*/
if (args.size() < 4)
{
......@@ -30,15 +30,19 @@ bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args
return false;
}
std::string source, command, target, comment;
std::string source, command, target, comment, output, main_dependency;
std::vector<std::string> command_args, depends, outputs;
cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
enum tdoing {
doing_source,
doing_command,
doing_target,
doing_args,
doing_depends,
doing_main_dependency,
doing_output,
doing_outputs,
doing_comment,
doing_nothing
......@@ -58,6 +62,18 @@ bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args
{
doing = doing_command;
}
else if(copy == "PRE_BUILD")
{
cctype = cmTarget::PRE_BUILD;
}
else if(copy == "PRE_LINK")
{
cctype = cmTarget::PRE_LINK;
}
else if(copy == "POST_BUILD")
{
cctype = cmTarget::POST_BUILD;
}
else if(copy == "TARGET")
{
doing = doing_target;
......@@ -74,6 +90,14 @@ bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args
{
doing = doing_outputs;
}
else if (copy == "OUTPUT")
{
doing = doing_output;
}
else if (copy == "MAIN_DEPENDENCY")
{
doing = doing_main_dependency;
}
else if (copy == "COMMENT")
{
doing = doing_comment;
......@@ -85,6 +109,12 @@ bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args
case doing_source:
source = copy;
break;
case doing_output:
output = copy;
break;
case doing_main_dependency:
main_dependency = copy;
break;
case doing_command:
command = copy;
break;
......@@ -114,21 +144,36 @@ bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args
For the moment, let's say that COMMAND, TARGET are always
required.
*/
if(target.empty())
if (output.empty() && target.empty())
{
this->SetError("Wrong syntax. Empty TARGET.");
this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
return false;
}
// If source is empty, use the target
if(source.empty() && output.empty())
{
m_Makefile->AddCustomCommandToTarget(target.c_str(),
command.c_str(),
command_args,
cctype,
comment.c_str());
return true;
}
// If source is empty, use target as source, so that this command
// can be used to just attach a commmand to a target
if(source.empty())
// If target is empty, use the output
if(target.empty())
{
source = target;
m_Makefile->AddCustomCommandToOutput(output.c_str(),
command.c_str(),
command_args,
main_dependency.c_str(),
depends,
comment.c_str());
return true;
}
// otherwise backwards compatiblity mode
m_Makefile->AddCustomCommand(source.c_str(),
command.c_str(),
command_args,
......
......@@ -86,42 +86,69 @@ public:
virtual const char* GetFullDocumentation()
{
return
" ADD_CUSTOM_COMMAND(TARGET target\n"
" [SOURCE source]\n"
" [COMMAND command]\n"
"There are two main signatures for ADD_CUSTOM_COMMAND "
"The first signature is for adding a custom command "
"to a source file.\n"
" ADD_CUSTOM_COMMAND(OUTPUT result\n"
" COMMAND command\n"
" [ARGS [args...]]\n"
" [MAIN_DEPENDENCY depend]\n"
" [DEPENDS [depends...]]\n"
" [OUTPUTS [outputs...]]\n"
" [COMMENT comment])\n"
"This defines a new command that can be executed during the build "
"process. In makefile terms this creates a new target in the "
"following form:\n"
" OUTPUT1: SOURCE DEPENDS\n"
" COMAND ARGS\n"
" OUTPUT2: SOURCE DEPENDS\n"
" COMAND ARGS\n"
"The TARGET must be specified, but it is not the make target of the "
"build rule. It is the target (library, executable, or custom target) "
"that will use the output generated from this rule. This is necessary "
"to choose a project file in which to generate the rule for Visual "
"Studio.\n"
"Example of usage:\n"
" ADD_CUSTOM_COMMAND(\n"
" TARGET tiff\n"
" SOURCE ${TIFF_FAX_EXE}\n"
" COMMAND ${TIFF_FAX_EXE}\n"
" ARGS -c const ${TIFF_BINARY_DIR}/tif_fax3sm.c\n"
" OUTPUTS ${TIFF_BINARY_DIR}/tif_fax3sm.c\n"
" )\n"
"This will create custom target which will generate file tif_fax3sm.c "
"using command ${TIFF_FAX_EXE}. The rule will be executed as part of "
"building the tiff library because it includes tif_fax3sm.c as a "
"source file with the GENERATED property.";
" OUTPUT: MAIN_DEPENDENCY DEPENDS\n"
" COMMAND ARGS\n"
"\n"
"The second signature adds a custom command to a target "
"such as a library or executable. This is useful for "
"performing an operation before or after building the target "
"\n"
" ADD_CUSTOM_COMMAND(TARGET target\n"
" PRE_BUILD | PRE_LINK | POST_BUILD\n"
" COMMAND command\n"
" [ARGS [args...]]\n"
" [COMMENT comment])\n"
"This defines a new command that will be associated with "
"building the specified target. When the command will "
"happen is determined by whether you specify\n"
"PRE_BUILD - run before all other dependencies\n"
"PRE_LINK - run after other dependencies\n"
"POST_BUILD - run after the target has been built\n";
}
cmTypeMacro(cmAddCustomCommandCommand, cmCommand);
};
/*
target: normal depends
pre rules
normal rules
post rules
output1: source other depends
rule
output2: source other dpeends
rule
another option is
output1: depends
rule
output2: depends
rule
use case1 - an executable that depending on args create diff output files
*/
#endif
......@@ -45,14 +45,25 @@ bool cmAddCustomTargetCommand::InitialPass(std::vector<std::string> const& args)
command = *s;
++s;
}
for (;s != args.end(); ++s)
for (;s != args.end() && *s != "DEPENDS"; ++s)
{
arguments += cmSystemTools::EscapeSpaces(s->c_str());
arguments += " ";
}
std::vector<std::string> depends;
// skip depends keyword
if (s != args.end())
{
++s;
}
while (s != args.end())
{
depends.push_back(*s);
++s;
}
m_Makefile->AddUtilityCommand(args[0].c_str(),
command.c_str(),
arguments.c_str(), all);
arguments.c_str(), all, depends);
return true;
}
......
......@@ -64,7 +64,8 @@ public:
virtual const char* GetFullDocumentation()
{
return
" ADD_CUSTOM_TARGET(Name [ALL] [ command arg arg arg ... ])\n"
" ADD_CUSTOM_TARGET(Name [ALL] [ command arg arg arg ... ] "
" [DEPENDS depend depend depend ... ])\n"
"Adds a target with the given name that executes the given command "
"every time the target is built. If the ALL option is specified "
"it indicates that this target should be added to the default build "
......
......@@ -239,6 +239,56 @@ void cmAddCustomCommand(void *arg, const char* source,
mf->AddCustomCommand(source, command, args2, depends2, outputs2, target);
}
void cmAddCustomCommandToOutput(void *arg, const char* output,
const char* command,
int numArgs, const char **args,
const char* main_dependency,
int numDepends, const char **depends)
{
cmMakefile *mf = static_cast<cmMakefile *>(arg);
int i;
std::vector<std::string> args2;
for (i = 0; i < numArgs; ++i)
{
args2.push_back(args[i]);
}
std::vector<std::string> depends2;
for (i = 0; i < numDepends; ++i)
{
depends2.push_back(depends[i]);
}
mf->AddCustomCommandToOutput(output, command, args2, main_dependency,
depends2);
}
void cmAddCustomCommandToTarget(void *arg, const char* target,
const char* command,
int numArgs, const char **args,
int commandType)
{
cmMakefile *mf = static_cast<cmMakefile *>(arg);
int i;
std::vector<std::string> args2;
for (i = 0; i < numArgs; ++i)
{
args2.push_back(args[i]);
}
switch (commandType)
{
case CM_PRE_BUILD:
mf->AddCustomCommandToTarget(target, command, args2,
cmTarget::PRE_BUILD);
break;
case CM_PRE_LINK:
mf->AddCustomCommandToTarget(target, command, args2,
cmTarget::PRE_LINK);
break;
case CM_POST_BUILD:
mf->AddCustomCommandToTarget(target, command, args2,
cmTarget::POST_BUILD);
break;
}
}
void cmAddLinkLibraryForTarget(void *arg, const char *tgt, const char*value,
int libtype)
......@@ -546,5 +596,8 @@ cmCAPI cmStaticCAPI =
cmGetFilenamePath,
cmRemoveFile,
cmFree,
cmAddCustomCommandToOutput,
cmAddCustomCommandToTarget,
};
......@@ -145,6 +145,19 @@ typedef struct
void (*RemoveFile)(const char *f1);
void (*Free)(void *);
/*=========================================================================
The following are new functions added after 1.6
=========================================================================*/
void (*AddCustomCommandToOutput) (void *mf, const char* output,
const char* command,
int numArgs, const char **args,
const char* main_dependency,
int numDepends, const char **depends);
void (*AddCustomCommandToTarget) (void *mf, const char* target,
const char* command,
int numArgs, const char **args,
int commandType);
/* this is the end of the C function stub API structure */
} cmCAPI;
......@@ -176,6 +189,12 @@ define the different types of compiles a library may be
#define CM_LIBRARY_DEBUG 1
#define CM_LIBRARY_OPTIMIZED 2
/*=========================================================================
define the different types of custom commands for a target
=========================================================================*/
#define CM_PRE_BUILD 0
#define CM_PRE_LINK 1
#define CM_POST_BUILD 2
/*=========================================================================
Finally we define the key data structures and function prototypes
......
......@@ -20,47 +20,48 @@
/**
* The constructor
*/
cmCustomCommand::cmCustomCommand(const char *src, const char *command,
cmCustomCommand::cmCustomCommand(const char *command,
const char* arguments,
std::vector<std::string> dep,
std::vector<std::string> out):
m_Source(src),
const char *out):
m_Command(command),
m_Arguments(arguments),
m_Depends(dep),
m_Outputs(out)
m_Depends(dep)
{
if (out)
{
m_Output = out;
}
}
cmCustomCommand::cmCustomCommand(const char *command,
const char* arguments):
m_Command(command),
m_Arguments(arguments)
{
}
/**
* Copy constructor.
*/
cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
m_Source(r.m_Source),
m_Command(r.m_Command),
m_Arguments(r.m_Arguments),
m_Comment(r.m_Comment),
m_Depends(r.m_Depends),
m_Outputs(r.m_Outputs)
m_Output(r.m_Output)
{
}
void cmCustomCommand::ExpandVariables(const cmMakefile &mf)
{
mf.ExpandVariablesInString(m_Source);
mf.ExpandVariablesInString(m_Command);
mf.ExpandVariablesInString(m_Arguments);
mf.ExpandVariablesInString(m_Output);
for (std::vector<std::string>::iterator i = m_Depends.begin();
i != m_Depends.end(); ++i)
{
mf.ExpandVariablesInString(*i);
}
for (std::vector<std::string>::iterator i = m_Outputs.begin();
i != m_Outputs.end(); ++i)
{
mf.ExpandVariablesInString(*i);
}
}
......@@ -28,10 +28,13 @@ class cmMakefile;
class cmCustomCommand
{
public:
cmCustomCommand(const char *src, const char *command,
cmCustomCommand(const char *command,
const char* arguments,
std::vector<std::string> dep,
std::vector<std::string> out);
const char *out);
cmCustomCommand(const char *command,
const char* arguments);
cmCustomCommand() {};
cmCustomCommand(const cmCustomCommand& r);
/**
......@@ -40,12 +43,6 @@ public:
*/
void ExpandVariables(const cmMakefile &);
/**
* Return the name of the source file. I'm not sure if this is a full path or not.
*/
std::string GetSourceName() const {return m_Source;}
void SetSourceName(const char *name) {m_Source = name;}
///! Return the command to execute with arguments
std::string GetCommandAndArguments() const
{return m_Command + " " + m_Arguments;}
......@@ -54,7 +51,11 @@ public:
std::string GetCommand() const {return m_Command;}
void SetCommand(const char *cmd) {m_Command = cmd;}
///! Return the command to execute
///! Return the output
std::string GetOutput() const {return m_Output;}
void SetOutput(const char *cm) {m_Output = cm;}
///! Return the comment
std::string GetComment() const {return m_Comment;}
void SetComment(const char *cm) {m_Comment = cm;}
......@@ -68,19 +69,12 @@ public:
const std::vector<std::string> &GetDepends() const {return m_Depends;}
std::vector<std::string> &GetDepends() {return m_Depends;}
/**
* Return the vector that holds the list of outputs of this command
*/
const std::vector<std::string> &GetOutputs() const {return m_Outputs;}
std::vector<std::string> &GetOutputs() {return m_Outputs;}
private:
std::string m_Source;
std::string m_Command;
std::string m_Arguments;
std::string m_Comment;
std::string m_Output;
std::vector<std::string> m_Depends;
std::vector<std::string> m_Outputs;
};
......
......@@ -146,8 +146,9 @@ void cmGlobalVisualStudio6Generator::Generate()
{
// add a special target that depends on ALL projects for easy build
// of Debug only
std::vector<std::string> srcs;
m_LocalGenerators[0]->GetMakefile()->
AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false);
AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false,srcs);
// add the Run Tests command
this->SetupTests();
......@@ -235,8 +236,9 @@ void cmGlobalVisualStudio6Generator::SetupTests()
// If the file doesn't exist, then ENABLE_TESTING hasn't been run
if (cmSystemTools::FileExists(fname.c_str()))
{
std::vector<std::string> srcs;
m_LocalGenerators[0]->GetMakefile()->
AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false);
AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false,srcs);
}
}
}
......@@ -310,12 +312,13 @@ void cmGlobalVisualStudio6Generator::WriteDSWFile(std::ostream& fout)
// Write the project into the DSW file
if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
{
cmCustomCommand cc = l->second.GetCustomCommands()[0];
cmCustomCommand cc = l->second.GetPreLinkCommands()[0];
// dodgy use of the cmCustomCommand's members to store the
// arguments from the INCLUDE_EXTERNAL_MSPROJECT command
std::vector<std::string> stuff = cc.GetDepends();
std::vector<std::string> depends = cc.GetOutputs();
std::vector<std::string> depends;
depends.push_back(cc.GetOutput());
this->WriteExternalProject(fout, stuff[0].c_str(), stuff[1].c_str(), depends);
++si;
}
......
......@@ -109,12 +109,13 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile(std::ostream& fout)
// Write the project into the SLN file
if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
{
cmCustomCommand cc = l->second.GetCustomCommands()[0];
cmCustomCommand cc = l->second.GetPreLinkCommands()[0];
// dodgy use of the cmCustomCommand's members to store the
// arguments from the INCLUDE_EXTERNAL_MSPROJECT command
std::vector<std::string> stuff = cc.GetDepends();
std::vector<std::string> depends = cc.GetOutputs();
std::vector<std::string> depends;
depends.push_back(cc.GetOutput());
this->WriteExternalProject(fout, stuff[0].c_str(),
stuff[1].c_str(), depends);
++si;
......
......@@ -145,8 +145,9 @@ void cmGlobalVisualStudio7Generator::SetupTests()
// If the file doesn't exist, then ENABLE_TESTING hasn't been run
if (cmSystemTools::FileExists(fname.c_str()))
{
std::vector<std::string> srcs;
m_LocalGenerators[0]->GetMakefile()->
AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false);
AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false, srcs);
}
}
}
......@@ -223,8 +224,9 @@ void cmGlobalVisualStudio7Generator::Generate()
{
// add a special target that depends on ALL projects for easy build
// of Debug only
std::vector<std::string> srcs;
m_LocalGenerators[0]->GetMakefile()->
AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false);
AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false, srcs);
// add the Run Tests command
this->SetupTests();
......@@ -340,12 +342,13 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout)
// Write the project into the SLN file
if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
{
cmCustomCommand cc = l->second.GetCustomCommands()[0];
cmCustomCommand cc = l->second.GetPreLinkCommands()[0];
// dodgy use of the cmCustomCommand's members to store the
// arguments from the INCLUDE_EXTERNAL_MSPROJECT command
std::vector<std::string> stuff = cc.GetDepends();
std::vector<std::string> depends = cc.GetOutputs();
std::vector<std::string> depends;
depends.push_back(cc.GetOutput());
this->WriteExternalProject(fout, stuff[0].c_str(),
stuff[1].c_str(), depends);
++si;
......
This diff is collapsed.
......@@ -187,8 +187,12 @@ protected:
///! return true if the two paths are the same
virtual bool SamePath(const char* path1, const char* path2);
virtual std::string GetOutputExtension(const char* sourceExtension);
std::string CreateTargetRules(const cmTarget &target,
const char* targetName);
std::string CreatePreBuildRules(const cmTarget &target,
const char* targetName);
std::string CreatePreLinkRules(const cmTarget &target,
const char* targetName);
std::string CreatePostBuildRules(const cmTarget &target,
const char* targetName);
virtual std::string CreateMakeVariable(const char* s, const char* s2);
///! if the OS is case insensitive then return a lower case of the path.
......
This diff is collapsed.
......@@ -22,9 +22,8 @@
class cmMakeDepend;
class cmTarget;
class cmSourceFile;
// please remove me.... Yuck
#include "cmSourceGroup.h"
class cmSourceGroup;
class cmCustomCommand;
/** \class cmLocalVisualStudio6Generator
* \brief Write a LocalUnix makefiles.
......@@ -84,21 +83,17 @@ private:
const cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
void WriteDSPFooter(std::ostream& fout);
void AddDSPBuildRule(cmSourceGroup&);
void AddDSPBuildRule();
void WriteCustomRule(std::ostream& fout,
const char* source,
const char* command,
const char* comment,
const std::set<std::string>& depends,
const std::set<std::string>& outputs,
const std::vector<std::string>& depends,
const char* output,
const char* flags);
std::string CreateTargetRules(const cmTarget &target,
const char *libName);
std::string CombineCommands(const cmSourceGroup::Commands &commands,
cmSourceGroup::CommandFiles &totalCommand,
const char *source);
std::string m_IncludeOptions;
std::vector<std::string> m_Configurations;
};
......
This diff is collapsed.
......@@ -22,9 +22,8 @@
class cmMakeDepend;
class cmTarget;
class cmSourceFile;
// please remove me.... Yuck
#include "cmSourceGroup.h"
class cmCustomCommand;
class cmSourceGroup;
/** \class cmLocalVisualStudio7Generator
* \brief Write a LocalUnix makefiles.
......@@ -74,7 +73,7 @@ private:
void CreateSingleVCProj(const char *lname, cmTarget &tgt);
void WriteVCProjFile(std::ostream& fout, const char *libName,
cmTarget &tgt);
void AddVCProjBuildRule(cmSourceGroup&);
void AddVCProjBuildRule();
void WriteConfigurations(std::ostream& fout,
const char *libName,
const cmTarget &tgt);
......@@ -107,15 +106,12 @@ private:
const char* group,
const char* filter);
void WriteVCProjEndGroup(std::ostream& fout);
std::string CombineCommands(const cmSourceGroup::Commands &commands,
cmSourceGroup::CommandFiles &totalCommand,
const char *source);
void WriteCustomRule(std::ostream& fout,
const char* source,
const char* command,
const char* comment,
const std::set<std::string>& depends,
const std::set<std::string>& outputs,
const std::vector<std::string>& depends,
const char* output,
const char* extraFlags);
std::vector<std::string> m_CreatedProjectNames;
......
This diff is collapsed.
......@@ -118,6 +118,22 @@ public:
*/
void Print() const;
/**
* Add a custom command to the build.
*/
void AddCustomCommandToOutput(const char* output,
const char* command,
const std::vector<std::string>& commandArgs,
const char *main_dependency,
const std::vector<std::string>& depends,
const char *comment = 0,
bool replace = false);
void AddCustomCommandToTarget(const char* target,
const char* command,
const std::vector<std::string>& commandArgs,
cmTarget::CustomCommandType type,
const char *comment = 0);
/**
* Add a custom command to the build.
*/
......@@ -156,7 +172,8 @@ public:
void AddUtilityCommand(const char* utilityName,
const char* command,
const char* arguments,
bool all);
bool all,