summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorKen Martin <ken.martin@kitware.com>2003-06-03 14:30:23 (GMT)
committerKen Martin <ken.martin@kitware.com>2003-06-03 14:30:23 (GMT)
commitba68f771b369e65476e7ce12aa8dd1cf18d7f529 (patch)
tree4580bb0cd83663ac32e7234b47f1a03881a2b709 /Source
parent4f55e4870d0dea6f700943ccd4bac958c478cff4 (diff)
downloadCMake-ba68f771b369e65476e7ce12aa8dd1cf18d7f529.zip
CMake-ba68f771b369e65476e7ce12aa8dd1cf18d7f529.tar.gz
CMake-ba68f771b369e65476e7ce12aa8dd1cf18d7f529.tar.bz2
yikes added new custom command support
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt6
-rw-r--r--Source/cmAddCustomCommandCommand.cxx69
-rw-r--r--Source/cmAddCustomCommandCommand.h77
-rw-r--r--Source/cmAddCustomTargetCommand.cxx15
-rw-r--r--Source/cmAddCustomTargetCommand.h3
-rw-r--r--Source/cmCPluginAPI.cxx53
-rw-r--r--Source/cmCPluginAPI.h19
-rw-r--r--Source/cmCustomCommand.cxx29
-rw-r--r--Source/cmCustomCommand.h28
-rw-r--r--Source/cmGlobalVisualStudio6Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx5
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx11
-rw-r--r--Source/cmLocalUnixMakefileGenerator.cxx328
-rw-r--r--Source/cmLocalUnixMakefileGenerator.h8
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx367
-rw-r--r--Source/cmLocalVisualStudio6Generator.h15
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx427
-rw-r--r--Source/cmLocalVisualStudio7Generator.h14
-rw-r--r--Source/cmMakefile.cxx297
-rw-r--r--Source/cmMakefile.h43
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx81
-rw-r--r--Source/cmSourceFile.h20
-rw-r--r--Source/cmSourceGroup.cxx98
-rw-r--r--Source/cmSourceGroup.h52
-rw-r--r--Source/cmSystemTools.cxx19
-rw-r--r--Source/cmSystemTools.h3
-rw-r--r--Source/cmTarget.h20
27 files changed, 1296 insertions, 822 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index bbfaf53..a707b55 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -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
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index a0a017d..d1de845 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -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,
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index fe46f0e..218b676 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -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
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 77ab3ef..8ab470c 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -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;
}
diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h
index 37f8537..778cc73 100644
--- a/Source/cmAddCustomTargetCommand.h
+++ b/Source/cmAddCustomTargetCommand.h
@@ -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 "
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 4bec426..90be276 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -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,
};
diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h
index da1f6f3..311e6ab 100644
--- a/Source/cmCPluginAPI.h
+++ b/Source/cmCPluginAPI.h
@@ -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
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index d8fafe4..378505e 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -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);
- }
}
-
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 9085177..79206ac 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -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;
};
diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx
index 0a204cf..2189679 100644
--- a/Source/cmGlobalVisualStudio6Generator.cxx
+++ b/Source/cmGlobalVisualStudio6Generator.cxx
@@ -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;
}
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index d38c300..4564901 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -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;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 037e34a..c7d0324 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -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;
diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx
index 5dab6a3..7b25c72 100644
--- a/Source/cmLocalUnixMakefileGenerator.cxx
+++ b/Source/cmLocalUnixMakefileGenerator.cxx
@@ -422,7 +422,8 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
for(std::vector<cmSourceFile*>::iterator i = classes.begin();
i != classes.end(); i++)
{
- if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY"))
+ if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+ !(*i)->GetCustomCommand())
{
std::string outExt(
this->GetOutputExtension((*i)->GetSourceExtension().c_str()));
@@ -439,7 +440,8 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
for(std::vector<cmSourceFile*>::iterator i = classes.begin();
i != classes.end(); i++)
{
- if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY"))
+ if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+ !(*i)->GetCustomCommand())
{
std::string outExt(this->GetOutputExtension((*i)->GetSourceExtension().c_str()));
if(outExt.size())
@@ -676,31 +678,77 @@ void cmLocalUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
}
}
+std::string cmLocalUnixMakefileGenerator::CreatePreBuildRules(
+ const cmTarget &target, const char* targetName)
+{
+ std::string customRuleCode = "";
+ bool initNext = false;
+ for (std::vector<cmCustomCommand>::const_iterator cr =
+ target.GetPreBuildCommands().begin();
+ cr != target.GetPreBuildCommands().end(); ++cr)
+ {
+ cmCustomCommand cc(*cr);
+ cc.ExpandVariables(*m_Makefile);
+ if(initNext)
+ {
+ customRuleCode += "\n\t";
+ }
+ else
+ {
+ initNext = true;
+ }
+ std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
+ customRuleCode += command + " " + cc.GetArguments();
+ }
+ return customRuleCode;
+}
-std::string cmLocalUnixMakefileGenerator::CreateTargetRules(const cmTarget &target,
- const char* targetName)
+std::string cmLocalUnixMakefileGenerator::CreatePreLinkRules(
+ const cmTarget &target, const char* targetName)
{
std::string customRuleCode = "";
bool initNext = false;
for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetCustomCommands().begin();
- cr != target.GetCustomCommands().end(); ++cr)
+ target.GetPreLinkCommands().begin();
+ cr != target.GetPreLinkCommands().end(); ++cr)
{
cmCustomCommand cc(*cr);
cc.ExpandVariables(*m_Makefile);
- if (cc.GetSourceName() == targetName)
+ if(initNext)
{
- if(initNext)
- {
- customRuleCode += "\n\t";
- }
- else
- {
- initNext = true;
- }
- std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
- customRuleCode += command + " " + cc.GetArguments();
+ customRuleCode += "\n\t";
+ }
+ else
+ {
+ initNext = true;
}
+ std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
+ customRuleCode += command + " " + cc.GetArguments();
+ }
+ return customRuleCode;
+}
+
+std::string cmLocalUnixMakefileGenerator::CreatePostBuildRules(
+ const cmTarget &target, const char* targetName)
+{
+ std::string customRuleCode = "";
+ bool initNext = false;
+ for (std::vector<cmCustomCommand>::const_iterator cr =
+ target.GetPostBuildCommands().begin();
+ cr != target.GetPostBuildCommands().end(); ++cr)
+ {
+ cmCustomCommand cc(*cr);
+ cc.ExpandVariables(*m_Makefile);
+ if(initNext)
+ {
+ customRuleCode += "\n\t";
+ }
+ else
+ {
+ initNext = true;
+ }
+ std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str());
+ customRuleCode += command + " " + cc.GetArguments();
}
return customRuleCode;
}
@@ -848,9 +896,21 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
// expand multi-command semi-colon separated lists
// of commands into separate commands
std::vector<std::string> commands;
+ // collect custom commands for this target and add them to the list
+ std::string customCommands = this->CreatePreBuildRules(t, name);
+ if(customCommands.size() > 0)
+ {
+ commands.push_back(customCommands);
+ }
+ // collect custom commands for this target and add them to the list
+ customCommands = this->CreatePreLinkRules(t, name);
+ if(customCommands.size() > 0)
+ {
+ commands.push_back(customCommands);
+ }
cmSystemTools::ExpandList(rules, commands);
// collect custom commands for this target and add them to the list
- std::string customCommands = this->CreateTargetRules(t, name);
+ customCommands = this->CreatePostBuildRules(t, name);
if(customCommands.size() > 0)
{
commands.push_back(customCommands);
@@ -1072,8 +1132,18 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
std::string comment = "executable";
std::vector<std::string> commands;
+ std::string customCommands = this->CreatePreBuildRules(t, name);
+ if(customCommands.size() > 0)
+ {
+ commands.push_back(customCommands.c_str());
+ }
+ customCommands = this->CreatePreLinkRules(t, name);
+ if(customCommands.size() > 0)
+ {
+ commands.push_back(customCommands.c_str());
+ }
cmSystemTools::ExpandList(rules, commands);
- std::string customCommands = this->CreateTargetRules(t, name);
+ customCommands = this->CreatePostBuildRules(t, name);
if(customCommands.size() > 0)
{
commands.push_back(customCommands.c_str());
@@ -1127,8 +1197,18 @@ void cmLocalUnixMakefileGenerator::OutputUtilityRule(std::ostream& fout,
const char* name,
const cmTarget &t)
{
- std::string customCommands = this->CreateTargetRules(t, name);
const char* cc = 0;
+ std::string customCommands = this->CreatePreBuildRules(t, name);
+ std::string customCommands2 = this->CreatePreLinkRules(t, name);
+ if(customCommands2.size() > 0)
+ {
+ customCommands += customCommands2;
+ }
+ customCommands2 = this->CreatePostBuildRules(t, name);
+ if(customCommands2.size() > 0)
+ {
+ customCommands += customCommands2;
+ }
if(customCommands.size() > 0)
{
cc = customCommands.c_str();
@@ -1136,7 +1216,7 @@ void cmLocalUnixMakefileGenerator::OutputUtilityRule(std::ostream& fout,
std::string comment = "Utility";
std::string depends;
std::string replaceVars;
- const std::vector<cmCustomCommand> &ccs = t.GetCustomCommands();
+ const std::vector<cmCustomCommand> &ccs = t.GetPostBuildCommands();
for(std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
i != ccs.end(); ++i)
{
@@ -1513,6 +1593,17 @@ void cmLocalUnixMakefileGenerator::OutputExeDepend(std::ostream& fout,
exepath += cmSystemTools::GetExecutableExtension();
fout << cmSystemTools::ConvertToOutputPath(exepath.c_str()) << " ";
}
+ // if it isn't in the cache, it might still be a utility target
+ // so check for that
+ else
+ {
+ std::map<cmStdString, cmTarget>& targets = m_Makefile->GetTargets();
+ if (targets.find(name) != targets.end())
+ {
+ fout << name << " ";
+ }
+ }
+
}
@@ -1707,9 +1798,6 @@ void cmLocalUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout)
SubDirectories);
}
-
-
-
// Output the depend information for all the classes
// in the makefile. These would have been generated
// by the class cmMakeDepend GenerateMakefile
@@ -1821,126 +1909,76 @@ void cmLocalUnixMakefileGenerator::OutputCheckDepends(std::ostream& fout)
// (tab) command...
void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
{
- // We may be modifying the source groups temporarily, so make a copy.
- std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
+ // we cannot provide multiple rules for a single output
+ // so we will keep track of outputs to make sure we don't write
+ // two rules. First found wins
+ std::set<std::string> processedOutputs;
- const cmTargets &tgts = m_Makefile->GetTargets();
- for(cmTargets::const_iterator tgt = tgts.begin();
- tgt != tgts.end(); ++tgt)
- {
- // add any custom rules to the source groups
- for (std::vector<cmCustomCommand>::const_iterator cr =
- tgt->second.GetCustomCommands().begin();
- cr != tgt->second.GetCustomCommands().end(); ++cr)
- {
- // if the source for the custom command is the same name
- // as the target, then to not create a rule in the makefile for
- // the custom command, as the command will be fired when the other target
- // is built.
- if ( cr->GetSourceName().compare(tgt->first) !=0)
- {
- cmSourceGroup& sourceGroup =
- m_Makefile->FindSourceGroup(cr->GetSourceName().c_str(),
- sourceGroups);
- cmCustomCommand cc(*cr);
- cc.ExpandVariables(*m_Makefile);
- sourceGroup.AddCustomCommand(cc);
- }
- }
- }
-
- // Loop through every source group.
- for(std::vector<cmSourceGroup>::const_iterator sg =
- sourceGroups.begin(); sg != sourceGroups.end(); ++sg)
+ // first output all custom rules
+ const std::vector<cmSourceFile*>& sources = m_Makefile->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
+ i != sources.end(); ++i)
{
- const cmSourceGroup::BuildRules& buildRules = sg->GetBuildRules();
- if(buildRules.empty())
- { continue; }
-
- std::string name = sg->GetName();
- if(name != "")
+ if ((*i)->GetCustomCommand())
{
- fout << "# Start of source group \"" << name.c_str() << "\"\n";
- }
-
- // Loop through each source in the source group.
- for(cmSourceGroup::BuildRules::const_iterator cc =
- buildRules.begin(); cc != buildRules.end(); ++ cc)
- {
- std::string source = cc->first;
- const cmSourceGroup::Commands& commands = cc->second.m_Commands;
- // Loop through every command generating code from the current source.
- for(cmSourceGroup::Commands::const_iterator c = commands.begin();
- c != commands.end(); ++c)
+ cmCustomCommand *c = (*i)->GetCustomCommand();
+ // escape spaces and convert to native slashes path for
+ // the command
+ const char* comment = c->GetComment().c_str();
+ std::string command = c->GetCommand();
+ cmSystemTools::ReplaceString(command, "/./", "/");
+ command = cmSystemTools::ConvertToOutputPath(command.c_str());
+ command += " ";
+ // now add the arguments
+ command += c->GetArguments();
+ std::string depends;
+ // Collect out all the dependencies for this rule.
+ for(std::vector<std::string>::const_iterator d =
+ c->GetDepends().begin();
+ d != c->GetDepends().end(); ++d)
{
- // escape spaces and convert to native slashes path for
- // the command
- const char* comment = c->second.m_Comment.c_str();
- std::string command = c->second.m_Command;
- cmSystemTools::ReplaceString(command, "/./", "/");
- command = cmSystemTools::ConvertToOutputPath(command.c_str());
- command += " ";
- // now add the arguments
- command += c->second.m_Arguments;
- const cmSourceGroup::CommandFiles& commandFiles = c->second;
- // if the command has no outputs, then it is a utility command
- // with no outputs
- if(commandFiles.m_Outputs.size() == 0)
- {
- std::string depends;
- // collect out all the dependencies for this rule.
- for(std::set<std::string>::const_iterator d =
- commandFiles.m_Depends.begin();
- d != commandFiles.m_Depends.end(); ++d)
- {
- std::string dep = *d;
- cmSystemTools::ReplaceString(dep, "/./", "/");
- cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
- dep = cmSystemTools::ConvertToOutputPath(dep.c_str());
- depends += " ";
- depends += dep;
- }
- // output rule
- this->OutputMakeRule(fout,
- (*comment?comment:"Custom command"),
- source.c_str(),
- depends.c_str(),
- command.c_str());
- }
- // Write a rule for every output generated by this command.
- for(std::set<std::string>::const_iterator output =
- commandFiles.m_Outputs.begin();
- output != commandFiles.m_Outputs.end(); ++output)
+ std::string dep = *d;
+ m_Makefile->ExpandVariablesInString(dep);
+
+ // watch for target dependencies,
+ std::string libPath = dep + "_CMAKE_PATH";
+ const char* cacheValue = m_Makefile->GetDefinition(libPath.c_str());
+ if (cacheValue)
{
- std::string src = cmSystemTools::ConvertToOutputPath(source.c_str());
- std::string depends;
- depends += src;
- // Collect out all the dependencies for this rule.
- for(std::set<std::string>::const_iterator d =
- commandFiles.m_Depends.begin();
- d != commandFiles.m_Depends.end(); ++d)
+ libPath = cacheValue;
+ if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH") &&
+ m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")[0] != '\0')
{
- std::string dep = *d;
- cmSystemTools::ReplaceString(dep, "/./", "/");
- cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
- dep = cmSystemTools::ConvertToOutputPath(dep.c_str());
- depends += " ";
- depends += dep;
- }
- // output rule
- this->OutputMakeRule(fout,
- (*comment?comment:"Custom command"),
- output->c_str(),
- depends.c_str(),
- command.c_str());
+ libPath = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
+ }
+ libPath += "/";
+ libPath += dep;
+ libPath += cmSystemTools::GetExecutableExtension();
+ dep = libPath;
}
+ cmSystemTools::ReplaceString(dep, "/./", "/");
+ cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
+ dep = cmSystemTools::ConvertToOutputPath(dep.c_str());
+ depends += " ";
+ depends += dep;
+ }
+ // output rule
+ if (processedOutputs.find(c->GetOutput()) == processedOutputs.end())
+ {
+ this->OutputMakeRule(fout,
+ (*comment?comment:"Custom command"),
+ c->GetOutput().c_str(),
+ depends.c_str(),
+ command.c_str());
+ processedOutputs.insert(c->GetOutput());
+ }
+ else
+ {
+ cmSystemTools::Error("An output was found with multiple rules on how to build it for output: ",
+ c->GetOutput().c_str());
}
}
- if(name != "")
- {
- fout << "# End of source group \"" << name.c_str() << "\"\n\n";
- }
- }
+ }
}
std::string
@@ -2185,7 +2223,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
// collect up all the sources
std::string allsources;
std::map<cmStdString, cmTarget>& targets = m_Makefile->GetTargets();
- for(std::map<cmStdString, cmTarget>::const_iterator target = targets.begin();
+ for(std::map<cmStdString,cmTarget>::const_iterator target = targets.begin();
target != targets.end(); ++target)
{
// Iterate over every source for this target.
@@ -2501,11 +2539,13 @@ void cmLocalUnixMakefileGenerator::OutputSourceObjectBuildRules(std::ostream& fo
exportsDef = "-D"+ export_symbol;
}
// Iterate over every source for this target.
- const std::vector<cmSourceFile*>& sources = target->second.GetSourceFiles();
+ const std::vector<cmSourceFile*>& sources =
+ target->second.GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
- if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
+ if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+ !(*source)->GetCustomCommand())
{
std::string shortName;
std::string sourceName;
@@ -2513,11 +2553,15 @@ void cmLocalUnixMakefileGenerator::OutputSourceObjectBuildRules(std::ostream& fo
// directory, we want to use the relative path for the
// filename of the object file. Otherwise, we will use just
// the filename portion.
- if((cmSystemTools::GetFilenamePath((*source)->GetFullPath()).find(m_Makefile->GetCurrentDirectory()) == 0)
- || (cmSystemTools::GetFilenamePath((*source)->GetFullPath()).find(m_Makefile->
- GetCurrentOutputDirectory()) == 0))
+ if((cmSystemTools::GetFilenamePath(
+ (*source)->GetFullPath()).find(
+ m_Makefile->GetCurrentDirectory()) == 0)
+ || (cmSystemTools::GetFilenamePath(
+ (*source)->GetFullPath()).find(
+ m_Makefile->GetCurrentOutputDirectory()) == 0))
{
- sourceName = (*source)->GetSourceName()+"."+(*source)->GetSourceExtension();
+ sourceName = (*source)->GetSourceName()+"."+
+ (*source)->GetSourceExtension();
shortName = (*source)->GetSourceName();
// The path may be relative. See if a directory needs to be
diff --git a/Source/cmLocalUnixMakefileGenerator.h b/Source/cmLocalUnixMakefileGenerator.h
index f3ebd9e..b4fc54e 100644
--- a/Source/cmLocalUnixMakefileGenerator.h
+++ b/Source/cmLocalUnixMakefileGenerator.h
@@ -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.
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 5355e3a..5b001a2 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -20,6 +20,7 @@
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmCacheManager.h"
+#include <queue>
cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator()
{
@@ -74,6 +75,9 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
// clear project names
m_CreatedProjectNames.clear();
+ // expand vars for custom commands
+ m_Makefile->ExpandVariablesInCustomCommands();
+
// build any targets
cmTargets &tgts = m_Makefile->GetTargets();
for(cmTargets::iterator l = tgts.begin();
@@ -154,7 +158,7 @@ void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname, cmTarget
}
-void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmSourceGroup& sourceGroup)
+void cmLocalVisualStudio6Generator::AddDSPBuildRule()
{
std::string dspname = *(m_CreatedProjectNames.end()-1);
if(dspname == "ALL_BUILD")
@@ -169,20 +173,28 @@ void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmSourceGroup& sourceGroup)
std::string dsprule = "${CMAKE_COMMAND}";
m_Makefile->ExpandVariablesInString(dsprule);
dsprule = cmSystemTools::ConvertToOutputPath(dsprule.c_str());
- std::string args = makefileIn;
- args += " -H";
+ std::vector<std::string> argv;
+ argv.push_back(makefileIn);
+ makefileIn = m_Makefile->GetStartDirectory();
+ makefileIn += "/";
+ makefileIn += "CMakeLists.txt";
+ std::string args;
+ args = "-H";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeDirectory());
- args += " -S";
+ argv.push_back(args);
+ args = "-S";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartDirectory());
- args += " -O";
+ argv.push_back(args);
+ args = "-O";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartOutputDirectory());
- args += " -B";
+ argv.push_back(args);
+ args = "-B";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory());
- m_Makefile->ExpandVariablesInString(args);
+ argv.push_back(args);
std::string configFile =
m_Makefile->GetDefinition("CMAKE_ROOT");
@@ -201,14 +213,9 @@ void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmSourceGroup& sourceGroup)
{
listFiles.push_back(configFile);
}
-
- std::vector<std::string> outputs;
- outputs.push_back(dspname);
- cmCustomCommand cc(makefileIn.c_str(), dsprule.c_str(),
- args.c_str(),
- listFiles,
- outputs);
- sourceGroup.AddCustomCommand(cc);
+ m_Makefile->AddCustomCommandToOutput(dspname.c_str(), dsprule.c_str(),
+ argv, makefileIn.c_str(), listFiles,
+ NULL, true);
}
@@ -219,8 +226,87 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
// We may be modifying the source groups temporarily, so make a copy.
std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
+ // if we should add regen rule then...
+ const char *suppRegenRule =
+ m_Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
+ if (!cmSystemTools::IsOn(suppRegenRule))
+ {
+ this->AddDSPBuildRule();
+ }
+
// get the classes from the source lists then add them to the groups
- std::vector<cmSourceFile*> classes = target.GetSourceFiles();
+ std::vector<cmSourceFile*> & classes = target.GetSourceFiles();
+ // use a deck to keep track of processed source files
+ std::queue<std::string> srcFilesToProcess;
+ std::string name;
+ for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
+ i != classes.end(); ++i)
+ {
+ name = (*i)->GetSourceName();
+ if ((*i)->GetSourceExtension() != "rule")
+ {
+ name += ".";
+ name += (*i)->GetSourceExtension();
+ }
+ srcFilesToProcess.push(name);
+ }
+ name = libName;
+ name += ".dsp.cmake";
+ srcFilesToProcess.push(name);
+ // add in the library depends for cusotm targets
+ if (target.GetType() == cmTarget::UTILITY)
+ {
+ cmCustomCommand &c = target.GetPostBuildCommands()[0];
+ for (std::vector<std::string>::iterator i = c.GetDepends().begin();
+ i != c.GetDepends().end(); ++i)
+ {
+ srcFilesToProcess.push(*i);
+ }
+ }
+ while (!srcFilesToProcess.empty())
+ {
+ // is this source the output of a custom command
+ cmSourceFile* outsf =
+ m_Makefile->GetSourceFileWithOutput(srcFilesToProcess.front().c_str());
+ if (outsf)
+ {
+ // is it not already in the target?
+ if (std::find(classes.begin(),classes.end(),outsf) == classes.end())
+ {
+ // then add the source to this target and add it to the queue
+ classes.push_back(outsf);
+ std::string name = outsf->GetSourceName();
+ if (outsf->GetSourceExtension() != "rule")
+ {
+ name += ".";
+ name += outsf->GetSourceExtension();
+ }
+ srcFilesToProcess.push(name);
+ }
+ // add its dependencies to the list to check
+ unsigned int i;
+ for (i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i)
+ {
+ std::string dep = cmSystemTools::GetFilenameName(
+ outsf->GetCustomCommand()->GetDepends()[i]);
+ // watch for target dependencies,
+ std::string libPath = dep + "_CMAKE_PATH";
+ const char* cacheValue = m_Makefile->GetDefinition(libPath.c_str());
+ if (cacheValue)
+ {
+ // add the depend as a utility on the target
+ target.AddUtility(dep.c_str());
+ }
+ else
+ {
+ srcFilesToProcess.push(dep);
+ }
+ }
+ }
+ // finished with this SF move to the next
+ srcFilesToProcess.pop();
+ }
+
for(std::vector<cmSourceFile*>::iterator i = classes.begin();
i != classes.end(); i++)
{
@@ -231,49 +317,20 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
sourceGroup.AddSource(source.c_str(), *i);
}
- // add any custom rules to the source groups
- for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetCustomCommands().begin();
- cr != target.GetCustomCommands().end(); ++cr)
- {
- cmSourceGroup& sourceGroup =
- m_Makefile->FindSourceGroup(cr->GetSourceName().c_str(),
- sourceGroups);
- cmCustomCommand cc(*cr);
- cc.ExpandVariables(*m_Makefile);
- sourceGroup.AddCustomCommand(cc);
- }
-
// Write the DSP file's header.
this->WriteDSPHeader(fout, libName, target, sourceGroups);
- // if we should add regen rule then...
- const char *suppRegenRule =
- m_Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
-
- // Find the group in which the CMakeLists.txt source belongs, and add
- // the rule to generate this DSP file.
- if (!cmSystemTools::IsOn(suppRegenRule))
- {
- for(std::vector<cmSourceGroup>::reverse_iterator sg = sourceGroups.rbegin();
- sg != sourceGroups.rend(); ++sg)
- {
- if(sg->Matches("CMakeLists.txt"))
- {
- this->AddDSPBuildRule(*sg);
- break;
- }
- }
- }
-
// Loop through every source group.
for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
sg != sourceGroups.end(); ++sg)
{
- const cmSourceGroup::BuildRules& buildRules = sg->GetBuildRules();
+ const std::vector<const cmSourceFile *> &sourceFiles =
+ sg->GetSourceFiles();
// If the group is empty, don't write it at all.
- if(buildRules.empty())
- { continue; }
+ if(sourceFiles.empty())
+ {
+ continue;
+ }
// If the group has a name, write the header.
std::string name = sg->GetName();
@@ -282,37 +339,32 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
this->WriteDSPBeginGroup(fout, name.c_str(), "");
}
- // Loop through each build rule in the source group.
- for(cmSourceGroup::BuildRules::const_iterator cc =
- buildRules.begin(); cc != buildRules.end(); ++ cc)
+ // Loop through each source in the source group.
+ for(std::vector<const cmSourceFile *>::const_iterator sf =
+ sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
{
- std::string source = cc->first;
- const cmSourceGroup::Commands& commands = cc->second.m_Commands;
- std::vector<std::string> depends;
+ std::string source = (*sf)->GetFullPath();
+ const cmCustomCommand *command =
+ (*sf)->GetCustomCommand();
std::string compileFlags;
- if(cc->second.m_SourceFile)
+ std::vector<std::string> depends;
+ const char* cflags = (*sf)->GetProperty("COMPILE_FLAGS");
+ if(cflags)
{
- // Check for extra compiler flags.
- const char* cflags = cc->second.m_SourceFile->GetProperty("COMPILE_FLAGS");
- if(cflags)
- {
- compileFlags = cflags;
- }
- if(cmSystemTools::GetFileFormat(
- cc->second.m_SourceFile->GetSourceExtension().c_str())
- == cmSystemTools::CXX_FILE_FORMAT)
- {
- // force a C++ file type
- compileFlags += " /TP ";
- }
-
- // Check for extra object-file dependencies.
- const char* dependsValue =
- cc->second.m_SourceFile->GetProperty("OBJECT_DEPENDS");
- if(dependsValue)
- {
- cmSystemTools::ExpandListArgument(dependsValue, depends);
- }
+ compileFlags = cflags;
+ }
+ if(cmSystemTools::GetFileFormat((*sf)->GetSourceExtension().c_str())
+ == cmSystemTools::CXX_FILE_FORMAT)
+ {
+ // force a C++ file type
+ compileFlags += " /TP ";
+ }
+
+ // Check for extra object-file dependencies.
+ const char* dependsValue = (*sf)->GetProperty("OBJECT_DEPENDS");
+ if(dependsValue)
+ {
+ cmSystemTools::ExpandListArgument(dependsValue, depends);
}
if (source != libName || target.GetType() == cmTarget::UTILITY)
{
@@ -334,18 +386,20 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
}
fout << "\n";
}
- if (!commands.empty())
+ if (command)
{
- cmSourceGroup::CommandFiles totalCommand;
std::string totalCommandStr;
- totalCommandStr = this->CombineCommands(commands, totalCommand,
- source.c_str());
- const char* comment = totalCommand.m_Comment.c_str();
+ totalCommandStr =
+ cmSystemTools::ConvertToOutputPath(command->GetCommand().c_str());
+ totalCommandStr += " ";
+ totalCommandStr += command->GetArguments();
+ totalCommandStr += "\n";
+ const char* comment = command->GetComment().c_str();
const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
this->WriteCustomRule(fout, source.c_str(), totalCommandStr.c_str(),
(*comment?comment:"Custom Rule"),
- totalCommand.m_Depends,
- totalCommand.m_Outputs, flags);
+ command->GetDepends(),
+ command->GetOutput().c_str(), flags);
}
else if(compileFlags.size())
{
@@ -384,8 +438,8 @@ void cmLocalVisualStudio6Generator::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
)
{
@@ -406,7 +460,7 @@ void cmLocalVisualStudio6Generator::WriteCustomRule(std::ostream& fout,
}
// Write out the dependencies for the rule.
fout << "USERDEP__HACK=";
- for(std::set<std::string>::const_iterator d = depends.begin();
+ for(std::vector<std::string>::const_iterator d = depends.begin();
d != depends.end(); ++d)
{
fout << "\\\n\t" <<
@@ -417,21 +471,16 @@ void cmLocalVisualStudio6Generator::WriteCustomRule(std::ostream& fout,
fout << "# PROP Ignore_Default_Tool 1\n";
fout << "# Begin Custom Build - Building " << comment
<< " $(InputPath)\n\n";
- if(outputs.size() == 0)
+ if(output == 0)
{
fout << source << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
fout << command << "\n\n";
}
// Write a rule for every output generated by this command.
- for(std::set<std::string>::const_iterator output = outputs.begin();
- output != outputs.end(); ++output)
- {
- fout << cmSystemTools::ConvertToOutputPath(output->c_str())
- << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
- fout << command << "\n\n";
- }
-
+ fout << cmSystemTools::ConvertToOutputPath(output)
+ << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
+ fout << command << "\n\n";
fout << "# End Custom Build\n\n";
}
@@ -544,46 +593,6 @@ void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
}
}
-std::string
-cmLocalVisualStudio6Generator::CombineCommands(const cmSourceGroup::Commands &commands,
- cmSourceGroup::CommandFiles &totalCommand,
- const char *source)
-
-{
- // Loop through every custom command generating code from the
- // current source.
- // build up the depends and outputs and commands
- std::string totalCommandStr = "";
- std::string temp;
- for(cmSourceGroup::Commands::const_iterator c = commands.begin();
- c != commands.end(); ++c)
- {
- totalCommandStr += "\n\t";
- temp= c->second.m_Command;
- temp = cmSystemTools::ConvertToOutputPath(temp.c_str());
- totalCommandStr += temp;
- totalCommandStr += " ";
- totalCommandStr += c->second.m_Arguments;
- totalCommand.Merge(c->second);
- totalCommand.m_Comment = c->second.m_Comment.c_str();
- }
- // Create a dummy file with the name of the source if it does
- // not exist
- if(totalCommand.m_Outputs.empty())
- {
- std::string dummyFile = m_Makefile->GetStartOutputDirectory();
- dummyFile += "/";
- dummyFile += source;
- if(!cmSystemTools::FileExists(dummyFile.c_str()))
- {
- std::ofstream fout(dummyFile.c_str());
- fout << "Dummy file created by cmake as unused source for utility command.\n";
- }
- }
- return totalCommandStr;
-}
-
-
// look for custom rules on a target and collect them together
std::string
cmLocalVisualStudio6Generator::CreateTargetRules(const cmTarget &target,
@@ -591,39 +600,85 @@ cmLocalVisualStudio6Generator::CreateTargetRules(const cmTarget &target,
{
std::string customRuleCode = "";
- if (target.GetType() >= cmTarget::UTILITY)
+ if (target.GetType() > cmTarget::UTILITY)
{
return customRuleCode;
}
+
+ // are there any rules?
+ if (target.GetPreBuildCommands().size() +
+ target.GetPreLinkCommands().size() +
+ target.GetPostBuildCommands().size() == 0)
+ {
+ return customRuleCode;
+ }
+
+ customRuleCode = "# Begin Special Build Tool\n";
- // Find the group in which the lix exe custom rules belong
+ // Do the PreBuild and PreLink (VS6 does not support both)
bool init = false;
for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetCustomCommands().begin();
- cr != target.GetCustomCommands().end(); ++cr)
+ target.GetPreBuildCommands().begin();
+ cr != target.GetPreBuildCommands().end(); ++cr)
{
cmCustomCommand cc(*cr);
cc.ExpandVariables(*m_Makefile);
- if (cc.GetSourceName() == libName)
+ if (!init)
{
- if (!init)
- {
- // header stuff
- customRuleCode = "# Begin Special Build Tool\nPostBuild_Cmds=";
- init = true;
- }
- else
- {
- customRuleCode += "\t";
- }
- customRuleCode += cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()) + " " + cc.GetArguments();
+ // header stuff
+ customRuleCode = "PreLink_Cmds=";
+ init = true;
+ }
+ else
+ {
+ customRuleCode += "\t";
+ }
+ customRuleCode += cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()) + " " + cc.GetArguments();
+ }
+
+ for (std::vector<cmCustomCommand>::const_iterator cr =
+ target.GetPreLinkCommands().begin();
+ cr != target.GetPreLinkCommands().end(); ++cr)
+ {
+ cmCustomCommand cc(*cr);
+ cc.ExpandVariables(*m_Makefile);
+ if (!init)
+ {
+ // header stuff
+ customRuleCode = "PreLink_Cmds=";
+ init = true;
+ }
+ else
+ {
+ customRuleCode += "\t";
}
+ customRuleCode += cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()) + " " + cc.GetArguments();
}
- if (init)
+ // do the post build rules
+ init = false;
+ for (std::vector<cmCustomCommand>::const_iterator cr =
+ target.GetPostBuildCommands().begin();
+ cr != target.GetPostBuildCommands().end(); ++cr)
{
- customRuleCode += "\n# End Special Build Tool\n";
+ cmCustomCommand cc(*cr);
+ cc.ExpandVariables(*m_Makefile);
+ if (!init)
+ {
+ // header stuff
+ customRuleCode = "PostBuild_Cmds=";
+ init = true;
+ }
+ else
+ {
+ customRuleCode += "\t";
+ }
+ customRuleCode +=
+ cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()) +
+ " " + cc.GetArguments();
}
+
+ customRuleCode += "\n# End Special Build Tool\n";
return customRuleCode;
}
diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h
index c3b2001..f4cee58 100644
--- a/Source/cmLocalVisualStudio6Generator.h
+++ b/Source/cmLocalVisualStudio6Generator.h
@@ -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;
};
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index ee7225b..2aced52 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -21,6 +21,7 @@
#include "cmSourceFile.h"
#include "cmCacheManager.h"
#include "cmake.h"
+#include <queue>
cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator()
{
@@ -85,6 +86,9 @@ void cmLocalVisualStudio7Generator::OutputVCProjFile()
// clear project names
m_CreatedProjectNames.clear();
+ // expand vars for custom commands
+ m_Makefile->ExpandVariablesInCustomCommands();
+
// build any targets
cmTargets &tgts = m_Makefile->GetTargets();
for(cmTargets::iterator l = tgts.begin();
@@ -127,7 +131,7 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(const char *lname, cmTarg
}
-void cmLocalVisualStudio7Generator::AddVCProjBuildRule(cmSourceGroup& sourceGroup)
+void cmLocalVisualStudio7Generator::AddVCProjBuildRule()
{
std::string dspname = *(m_CreatedProjectNames.end()-1);
if(dspname == "ALL_BUILD")
@@ -142,22 +146,29 @@ void cmLocalVisualStudio7Generator::AddVCProjBuildRule(cmSourceGroup& sourceGrou
std::string dsprule = "${CMAKE_COMMAND}";
m_Makefile->ExpandVariablesInString(dsprule);
dsprule = cmSystemTools::ConvertToOutputPath(dsprule.c_str());
- std::string args = makefileIn;
- args += " -H";
+ std::vector<std::string> argv;
+ argv.push_back(makefileIn);
+ makefileIn = m_Makefile->GetStartDirectory();
+ makefileIn += "/";
+ makefileIn += "CMakeLists.txt";
+ std::string args;
+ args = "-H";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeDirectory());
- args += " -S";
- args +=
+ argv.push_back(args);
+ args = "-S";
+ args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartDirectory());
- args += " -O";
+ argv.push_back(args);
+ args = "-O";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartOutputDirectory());
- args += " -B";
+ argv.push_back(args);
+ args = "-B";
args +=
cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory());
- args += "";
- m_Makefile->ExpandVariablesInString(args);
-
+ argv.push_back(args);
+
std::string configFile =
m_Makefile->GetDefinition("CMAKE_ROOT");
configFile += "/Templates/CMakeWindowsSystemConfig.cmake";
@@ -175,14 +186,9 @@ void cmLocalVisualStudio7Generator::AddVCProjBuildRule(cmSourceGroup& sourceGrou
{
listFiles.push_back(configFile);
}
-
- std::vector<std::string> outputs;
- outputs.push_back(dspname);
- cmCustomCommand cc(makefileIn.c_str(), dsprule.c_str(),
- args.c_str(),
- listFiles,
- outputs);
- sourceGroup.AddCustomCommand(cc);
+ m_Makefile->AddCustomCommandToOutput(dspname.c_str(), dsprule.c_str(),
+ argv, makefileIn.c_str(), listFiles,
+ NULL, true);
}
@@ -359,10 +365,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
}
fout << "\"\n/>\n";
fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"/>\n";
- fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"";
this->OutputTargetRules(fout, target, libName);
- fout << "/>\n";
- fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"/>\n";
this->OutputBuildTool(fout, configName, libName, target);
fout << "\t\t</Configuration>\n";
}
@@ -635,18 +638,104 @@ void cmLocalVisualStudio7Generator::OutputDefineFlags(std::ostream& fout)
}
void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
- const char *libName,
- cmTarget &target)
+ const char *libName,
+ cmTarget &target)
{
// get the configurations
std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>(m_GlobalGenerator)->GetConfigurations();
+ static_cast<cmGlobalVisualStudio7Generator *>
+ (m_GlobalGenerator)->GetConfigurations();
+ // if we should add regen rule then...
+ const char *suppRegenRule =
+ m_Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
+ if (!cmSystemTools::IsOn(suppRegenRule))
+ {
+ this->AddVCProjBuildRule();
+ }
+
// We may be modifying the source groups temporarily, so make a copy.
std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
// get the classes from the source lists then add them to the groups
- std::vector<cmSourceFile*> const& classes = target.GetSourceFiles();
+ std::vector<cmSourceFile*> & classes = target.GetSourceFiles();
+ // use a deck to keep track of processed source files
+ std::queue<std::string> srcFilesToProcess;
+ std::string name;
+ for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
+ i != classes.end(); ++i)
+ {
+ std::string name = (*i)->GetSourceName();
+ if ((*i)->GetSourceExtension() != "rule")
+ {
+ name += ".";
+ name += (*i)->GetSourceExtension();
+ }
+ srcFilesToProcess.push(name);
+ }
+ // add in the project file itself
+ name = libName;
+ name += ".vcproj.cmake";
+ srcFilesToProcess.push(name);
+ // add in the library depends for cusotm targets
+ if (target.GetType() == cmTarget::UTILITY)
+ {
+ cmCustomCommand &c = target.GetPostBuildCommands()[0];
+ for (std::vector<std::string>::iterator i = c.GetDepends().begin();
+ i != c.GetDepends().end(); ++i)
+ {
+ srcFilesToProcess.push(*i);
+ }
+ }
+ while (!srcFilesToProcess.empty())
+ {
+ // is this source the output of a custom command
+ cmSourceFile* outsf =
+ m_Makefile->GetSourceFileWithOutput(srcFilesToProcess.front().c_str());
+ if (outsf)
+ {
+ // is it not already in the target?
+ if (std::find(classes.begin(),classes.end(),outsf) == classes.end())
+ {
+ // then add the source to this target and add it to the queue
+ classes.push_back(outsf);
+ std::string name = outsf->GetSourceName();
+ if (outsf->GetSourceExtension() != "rule")
+ {
+ name += ".";
+ name += outsf->GetSourceExtension();
+ }
+ srcFilesToProcess.push(name);
+ }
+ // add its dependencies to the list to check
+ unsigned int i;
+ for (i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i)
+ {
+ std::string dep = cmSystemTools::GetFilenameName(
+ outsf->GetCustomCommand()->GetDepends()[i]);
+ if (cmSystemTools::GetFilenameLastExtension(dep) == ".exe")
+ {
+ dep = cmSystemTools::GetFilenameWithoutLastExtension(dep);
+ }
+ // watch for target dependencies,
+ std::string libPath = dep + "_CMAKE_PATH";
+ const char* cacheValue = m_Makefile->GetDefinition(libPath.c_str());
+ if (cacheValue)
+ {
+ // add the depend as a utility on the target
+ target.AddUtility(dep.c_str());
+ }
+ else
+ {
+ srcFilesToProcess.push(dep);
+ }
+ }
+ }
+ // finished with this SF move to the next
+ srcFilesToProcess.pop();
+ }
+
+ // get the classes from the source lists then add them to the groups
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++)
{
@@ -656,23 +745,9 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
{
m_ModuleDefinitionFile = (*i)->GetFullPath();
}
-
- cmSourceGroup& sourceGroup = m_Makefile->FindSourceGroup(source.c_str(),
- sourceGroups);
- sourceGroup.AddSource(source.c_str(), *i);
- }
-
- // add any custom rules to the source groups
- for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetCustomCommands().begin();
- cr != target.GetCustomCommands().end(); ++cr)
- {
cmSourceGroup& sourceGroup =
- m_Makefile->FindSourceGroup(cr->GetSourceName().c_str(),
- sourceGroups);
- cmCustomCommand cc(*cr);
- cc.ExpandVariables(*m_Makefile);
- sourceGroup.AddCustomCommand(cc);
+ m_Makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ sourceGroup.AddSource(source.c_str(), *i);
}
// open the project
@@ -682,34 +757,18 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
fout << "\t<Files>\n";
- // if we should add regen rule then...
- const char *suppRegenRule =
- m_Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
-
- // Find the group in which the CMakeLists.txt source belongs, and add
- // the rule to generate this VCProj file.
- if (!cmSystemTools::IsOn(suppRegenRule))
- {
- for(std::vector<cmSourceGroup>::reverse_iterator sg =
- sourceGroups.rbegin();
- sg != sourceGroups.rend(); ++sg)
- {
- if(sg->Matches("CMakeLists.txt"))
- {
- this->AddVCProjBuildRule(*sg);
- break;
- }
- }
- }
// Loop through every source group.
for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
sg != sourceGroups.end(); ++sg)
{
- const cmSourceGroup::BuildRules& buildRules = sg->GetBuildRules();
+ const std::vector<const cmSourceFile *> &sourceFiles =
+ sg->GetSourceFiles();
// If the group is empty, don't write it at all.
- if(buildRules.empty())
- { continue; }
+ if(sourceFiles.empty())
+ {
+ continue;
+ }
// If the group has a name, write the header.
std::string name = sg->GetName();
@@ -718,45 +777,41 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
this->WriteVCProjBeginGroup(fout, name.c_str(), "");
}
- // Loop through each build rule in the source group.
- for(cmSourceGroup::BuildRules::const_iterator cc =
- buildRules.begin(); cc != buildRules.end(); ++ cc)
+ // Loop through each source in the source group.
+ for(std::vector<const cmSourceFile *>::const_iterator sf =
+ sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
{
- std::string source = cc->first;
- const cmSourceGroup::Commands& commands = cc->second.m_Commands;
+ std::string source = (*sf)->GetFullPath();
+ const cmCustomCommand *command = (*sf)->GetCustomCommand();
std::string compileFlags;
std::string additionalDeps;
- if(cc->second.m_SourceFile)
+
+ // Check for extra compiler flags.
+ const char* cflags = (*sf)->GetProperty("COMPILE_FLAGS");
+ if(cflags)
{
- // Check for extra compiler flags.
- const char* cflags = cc->second.m_SourceFile->GetProperty("COMPILE_FLAGS");
- if(cflags)
- {
- compileFlags = cc->second.m_SourceFile->GetProperty("COMPILE_FLAGS");
- }
- if(cmSystemTools::GetFileFormat(
- cc->second.m_SourceFile->GetSourceExtension().c_str())
- == cmSystemTools::CXX_FILE_FORMAT)
- {
- // force a C++ file type
- compileFlags += " /TP ";
- }
- // Check for extra object-file dependencies.
- const char* deps =
- cc->second.m_SourceFile->GetProperty("OBJECT_DEPENDS");
- if(deps)
+ compileFlags = cflags;
+ }
+ if(cmSystemTools::GetFileFormat((*sf)->GetSourceExtension().c_str())
+ == cmSystemTools::CXX_FILE_FORMAT)
+ {
+ // force a C++ file type
+ compileFlags += " /TP ";
+ }
+ // Check for extra object-file dependencies.
+ const char* deps = (*sf)->GetProperty("OBJECT_DEPENDS");
+ if(deps)
+ {
+ std::vector<std::string> depends;
+ cmSystemTools::ExpandListArgument(deps, depends);
+ if(!depends.empty())
{
- std::vector<std::string> depends;
- cmSystemTools::ExpandListArgument(deps, depends);
- if(!depends.empty())
+ std::vector<std::string>::iterator i = depends.begin();
+ additionalDeps = this->ConvertToXMLOutputPath(i->c_str());
+ for(++i;i != depends.end(); ++i)
{
- std::vector<std::string>::iterator i = depends.begin();
- additionalDeps = this->ConvertToXMLOutputPath(i->c_str());
- for(++i;i != depends.end(); ++i)
- {
- additionalDeps += ";";
- additionalDeps += this->ConvertToXMLOutputPath(i->c_str());
- }
+ additionalDeps += ";";
+ additionalDeps += this->ConvertToXMLOutputPath(i->c_str());
}
}
}
@@ -767,18 +822,20 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
// Tell MS-Dev what the source is. If the compiler knows how to
// build it, then it will.
fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
- if (!commands.empty())
+ if (command)
{
- cmSourceGroup::CommandFiles totalCommand;
std::string totalCommandStr;
- totalCommandStr = this->CombineCommands(commands, totalCommand,
- source.c_str());
- const char* comment = totalCommand.m_Comment.c_str();
+ totalCommandStr =
+ cmSystemTools::ConvertToOutputPath(command->GetCommand().c_str());
+ totalCommandStr += " ";
+ totalCommandStr += command->GetArguments();
+ totalCommandStr += "\n";
+ const char* comment = command->GetComment().c_str();
const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
this->WriteCustomRule(fout, source.c_str(), totalCommandStr.c_str(),
(*comment?comment:"Custom Rule"),
- totalCommand.m_Depends,
- totalCommand.m_Outputs, flags);
+ command->GetDepends(),
+ command->GetOutput().c_str(), flags);
}
else if(compileFlags.size() || additionalDeps.length())
{
@@ -820,13 +877,14 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
}
-void cmLocalVisualStudio7Generator::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 char* compileFlags)
+void cmLocalVisualStudio7Generator::
+WriteCustomRule(std::ostream& fout,
+ const char* source,
+ const char* command,
+ const char* comment,
+ const std::vector<std::string>& depends,
+ const char *output,
+ const char* compileFlags)
{
std::string cmd = command;
cmSystemTools::ReplaceString(cmd, "\"", "&quot;");
@@ -847,17 +905,13 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(std::ostream& fout,
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"VCCustomBuildTool\"\n"
<< "\t\t\t\t\tDescription=\"Building " << comment;
- std::set<std::string>::const_iterator it;
- for ( it = outputs.begin(); it != outputs.end(); it ++ )
- {
- fout << " " << *it;
- }
+ fout << " " << output;
fout << "\"\n"
<< "\t\t\t\t\tCommandLine=\"" << cmd << "\n\"\n"
<< "\t\t\t\t\tAdditionalDependencies=\"";
// Write out the dependencies for the rule.
std::string temp;
- for(std::set<std::string>::const_iterator d = depends.begin();
+ for(std::vector<std::string>::const_iterator d = depends.begin();
d != depends.end(); ++d)
{
fout << this->ConvertToXMLOutputPath(d->c_str())
@@ -865,26 +919,14 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(std::ostream& fout,
}
fout << "\"\n";
fout << "\t\t\t\t\tOutputs=\"";
- if(outputs.size() == 0)
+ if(output == 0)
{
fout << source << "_force";
}
bool first = true;
- // Write a rule for every output generated by this command.
- for(std::set<std::string>::const_iterator output = outputs.begin();
- output != outputs.end(); ++output)
- {
- if(!first)
- {
- fout << ";";
- }
- else
- {
- first = false;
- }
- fout << this->ConvertToXMLOutputPathSingle(output->c_str());
- }
+ // Write a rule for the output generated by this command.
+ fout << this->ConvertToXMLOutputPathSingle(output);
fout << "\"/>\n";
fout << "\t\t\t\t</FileConfiguration>\n";
}
@@ -907,85 +949,90 @@ void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout)
}
-
-
-
-std::string
-cmLocalVisualStudio7Generator::CombineCommands(
- const cmSourceGroup::Commands &commands,
- cmSourceGroup::CommandFiles &totalCommand,
- const char *source)
-
+// look for custom rules on a target and collect them together
+void cmLocalVisualStudio7Generator::OutputTargetRules(std::ostream& fout,
+ const cmTarget &target,
+ const char *libName)
{
- // Loop through every custom command generating code from the
- // current source.
- // build up the depends and outputs and commands
- std::string totalCommandStr = "";
- std::string temp;
- for(cmSourceGroup::Commands::const_iterator c = commands.begin();
- c != commands.end(); ++c)
+ if (target.GetType() > cmTarget::UTILITY)
{
- temp=
- cmSystemTools::ConvertToOutputPath(c->second.m_Command.c_str());
- totalCommandStr += temp;
- totalCommandStr += " ";
- totalCommandStr += c->second.m_Arguments;
- totalCommandStr += "\n";
- totalCommand.Merge(c->second);
- totalCommand.m_Comment = c->second.m_Comment.c_str();
- }
- // Create a dummy file with the name of the source if it does
- // not exist
- if(totalCommand.m_Outputs.empty())
- {
- std::string dummyFile = m_Makefile->GetStartOutputDirectory();
- dummyFile += "/";
- dummyFile += source;
- if(!cmSystemTools::FileExists(dummyFile.c_str()))
+ return;
+ }
+
+ // add the pre build rules
+ fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"";
+ bool init = false;
+ for (std::vector<cmCustomCommand>::const_iterator cr =
+ target.GetPreBuildCommands().begin();
+ cr != target.GetPreBuildCommands().end(); ++cr)
+ {
+ cmCustomCommand cc(*cr);
+ cc.ExpandVariables(*m_Makefile);
+ if(!init)
{
- std::ofstream fout(dummyFile.c_str());
- fout << "Dummy file created by cmake as unused source for utility command.\n";
+ fout << "\nCommandLine=\"";
+ init = true;
}
+ std::string args = cc.GetArguments();
+ cmSystemTools::ReplaceString(args, "\"", "&quot;");
+ fout << this->ConvertToXMLOutputPath(cc.GetCommand().c_str()) << " " <<
+ args << "\n";
}
- return totalCommandStr;
-}
-
-
-// look for custom rules on a target and collect them together
+ if (init)
+ {
+ fout << "\"";
+ }
+ fout << "/>\n";
-void cmLocalVisualStudio7Generator::OutputTargetRules(std::ostream& fout,
- const cmTarget &target,
- const char *libName)
-{
- if (target.GetType() >= cmTarget::UTILITY)
+ // add the pre Link rules
+ fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"";
+ init = false;
+ for (std::vector<cmCustomCommand>::const_iterator cr =
+ target.GetPreLinkCommands().begin();
+ cr != target.GetPreLinkCommands().end(); ++cr)
{
- return;
+ cmCustomCommand cc(*cr);
+ cc.ExpandVariables(*m_Makefile);
+ if(!init)
+ {
+ fout << "\nCommandLine=\"";
+ init = true;
+ }
+ std::string args = cc.GetArguments();
+ cmSystemTools::ReplaceString(args, "\"", "&quot;");
+ fout << this->ConvertToXMLOutputPath(cc.GetCommand().c_str()) << " " <<
+ args << "\n";
+ }
+ if (init)
+ {
+ fout << "\"";
}
+ fout << "/>\n";
- // Find the group in which the lix exe custom rules belong
- bool init = false;
+ // add the PostBuild rules
+ fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"";
+ init = false;
for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetCustomCommands().begin();
- cr != target.GetCustomCommands().end(); ++cr)
+ target.GetPostBuildCommands().begin();
+ cr != target.GetPostBuildCommands().end(); ++cr)
{
cmCustomCommand cc(*cr);
cc.ExpandVariables(*m_Makefile);
- if (cc.GetSourceName() == libName)
+ if(!init)
{
- if(!init)
- {
- fout << "\nCommandLine=\"";
- init = true;
- }
- std::string args = cc.GetArguments();
- cmSystemTools::ReplaceString(args, "\"", "&quot;");
- fout << this->ConvertToXMLOutputPath(cc.GetCommand().c_str()) << " " << args << "\n";
+ fout << "\nCommandLine=\"";
+ init = true;
}
+ std::string args = cc.GetArguments();
+ cmSystemTools::ReplaceString(args, "\"", "&quot;");
+ fout << this->ConvertToXMLOutputPath(cc.GetCommand().c_str()) << " " <<
+ args << "\n";
}
if (init)
{
fout << "\"";
}
+ fout << "/>\n";
}
void
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 9469c5f..df711b7 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -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;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index a71de1b..661841b 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -65,6 +65,7 @@ cmMakefile::cmMakefile()
this->AddSourceGroup("Source Files",
"\\.(C|M|c|c\\+\\+|cc|cpp|cxx|m|mm|rc|def|r|odl|idl|hpj|bat)$");
this->AddSourceGroup("Header Files", "\\.(h|h\\+\\+|hm|hpp|hxx|in|txx|inl)$");
+ this->AddSourceGroup("CMake Rules", "\\.rule$");
this->AddDefaultDefinitions();
}
@@ -169,7 +170,7 @@ void cmMakefile::Print() const
for( std::vector<cmSourceGroup>::const_iterator i = m_SourceGroups.begin();
i != m_SourceGroups.end(); ++i)
{
- i->Print();
+ std::cout << "Source Group: " << i->GetName() << std::endl;
}
}
@@ -441,6 +442,7 @@ void cmMakefile::ConfigureFinalPass()
}
+// this is the old style signature, we convert to new style
void cmMakefile::AddCustomCommand(const char* source,
const char* command,
const std::vector<std::string>& commandArgs,
@@ -449,13 +451,137 @@ void cmMakefile::AddCustomCommand(const char* source,
const char *target,
const char *comment)
{
+ if (strcmp(source,target))
+ {
+ // what a pain, for backwards compatibility we will try to
+ // convert this to an output based rule... so for each output..
+ for(std::vector<std::string>::const_iterator d = outputs.begin();
+ d != outputs.end(); ++d)
+ {
+ this->AddCustomCommandToOutput(d->c_str(), command, commandArgs,
+ source, depends, comment);
+ // add the output to the target?
+ std::string sname = *d;
+ sname += ".rule";
+ if (!this->GetSource(sname.c_str()))
+ {
+ m_Targets[target].GetSourceLists().push_back(source);
+ }
+ }
+ }
+ else
+ {
+ this->AddCustomCommandToTarget(target, command, commandArgs,
+ cmTarget::POST_BUILD,
+ comment);
+ }
+}
+
+void cmMakefile::AddCustomCommand(const char* source,
+ const char* command,
+ const std::vector<std::string>& commandArgs,
+ const std::vector<std::string>& depends,
+ const char* output,
+ const char *target)
+{
+ std::vector<std::string> outputs;
+ outputs.push_back(output);
+ this->AddCustomCommand(source, command, commandArgs, depends,
+ outputs, target);
+}
+
+void cmMakefile::
+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,
+ bool replace)
+{
+ cmSourceFile *file = 0;
+ std::string outName = output;
+ outName += ".rule";
+
+ // OK this rule will be placed on a generated output file unless the main
+ // depednency was specified.
+ if (main_dependency && main_dependency[0] != '\0')
+ {
+ file = this->GetSource(main_dependency);
+ if (file && file->GetCustomCommand() && !replace)
+ {
+ // generate a source instead
+ file = 0;
+ }
+ else
+ {
+ file = this->GetOrCreateSource(main_dependency);
+ }
+ }
+
+ if (!file)
+ {
+ file = this->GetSource(outName.c_str());
+ if (file && file->GetCustomCommand() && !replace)
+ {
+ cmSystemTools::Error("Attempt to add a custom rule to an output that already has a custom rule. For output: ", output);
+ return;
+ }
+ // create a cmSourceFile for the output
+ file = this->GetOrCreateSource(outName.c_str(), true);
+ // always mark as generated
+ file->SetProperty("GENERATED","1");
+ }
+
+ // always create the output and mark it generated
+ cmSourceFile *out = this->GetOrCreateSource(output, true);
+ out->SetProperty("GENERATED","1");
+
+ // process the command
+ std::string expandC = command;
+ this->ExpandVariablesInString(expandC);
+ std::string c = cmSystemTools::EscapeSpaces(expandC.c_str());
+
+ std::string combinedArgs;
+ unsigned int i;
+ for (i = 0; i < commandArgs.size(); ++i)
+ {
+ expandC = commandArgs[i].c_str();
+ this->ExpandVariablesInString(expandC);
+ combinedArgs += cmSystemTools::EscapeSpaces(expandC.c_str());
+ combinedArgs += " ";
+ }
+ std::vector<std::string> depends2(depends);
+ if (main_dependency && main_dependency[0] != '\0')
+ {
+ depends2.push_back(main_dependency);
+ }
+ cmCustomCommand *cc =
+ new cmCustomCommand(c.c_str(),combinedArgs.c_str(),depends2, output);
+ if ( comment && comment[0] )
+ {
+ cc->SetComment(comment);
+ }
+ if (file->GetCustomCommand())
+ {
+ delete file->GetCustomCommand();
+ }
+ file->SetCustomCommand(cc);
+}
+
+void cmMakefile::
+AddCustomCommandToTarget(const char* target, const char* command,
+ const std::vector<std::string>& commandArgs,
+ cmTarget::CustomCommandType type,
+ const char *comment)
+{
// find the target,
if (m_Targets.find(target) != m_Targets.end())
{
std::string expandC = command;
this->ExpandVariablesInString(expandC);
std::string c = cmSystemTools::EscapeSpaces(expandC.c_str());
-
+
std::string combinedArgs;
unsigned int i;
@@ -467,12 +593,23 @@ void cmMakefile::AddCustomCommand(const char* source,
combinedArgs += " ";
}
- cmCustomCommand cc(source,c.c_str(),combinedArgs.c_str(),depends,outputs);
+ cmCustomCommand cc(c.c_str(),combinedArgs.c_str());
if ( comment && comment[0] )
{
cc.SetComment(comment);
}
- m_Targets[target].GetCustomCommands().push_back(cc);
+ switch (type)
+ {
+ case cmTarget::PRE_BUILD:
+ m_Targets[target].GetPreBuildCommands().push_back(cc);
+ break;
+ case cmTarget::PRE_LINK:
+ m_Targets[target].GetPreLinkCommands().push_back(cc);
+ break;
+ case cmTarget::POST_BUILD:
+ m_Targets[target].GetPostBuildCommands().push_back(cc);
+ break;
+ }
std::string cacheCommand = command;
this->ExpandVariablesInString(cacheCommand);
if(this->GetCacheManager()->GetCacheValue(cacheCommand.c_str()))
@@ -483,18 +620,6 @@ void cmMakefile::AddCustomCommand(const char* source,
}
}
-void cmMakefile::AddCustomCommand(const char* source,
- const char* command,
- const std::vector<std::string>& commandArgs,
- const std::vector<std::string>& depends,
- const char* output,
- const char *target)
-{
- std::vector<std::string> outputs;
- outputs.push_back(output);
- this->AddCustomCommand(source, command, commandArgs, depends, outputs, target);
-}
-
void cmMakefile::AddDefineFlag(const char* flag)
{
m_DefineFlags += " ";
@@ -799,11 +924,12 @@ void cmMakefile::AddExecutable(const char *exeName,
void cmMakefile::AddUtilityCommand(const char* utilityName,
const char* command,
const char* arguments,
- bool all)
+ bool all,
+ const std::vector<std::string> &depends)
{
std::vector<std::string> empty;
this->AddUtilityCommand(utilityName,command,arguments,all,
- empty,empty);
+ depends, empty);
}
void cmMakefile::AddUtilityCommand(const char* utilityName,
@@ -816,11 +942,54 @@ void cmMakefile::AddUtilityCommand(const char* utilityName,
cmTarget target;
target.SetType(cmTarget::UTILITY);
target.SetInAll(all);
- cmCustomCommand cc(utilityName, command, arguments, dep, out);
- target.GetCustomCommands().push_back(cc);
+ if (out.size() > 1)
+ {
+ cmSystemTools::Error(
+ "Utility targets can only have one output. For utilityNamed: ",
+ utilityName);
+ return;
+ }
+ if (out.size())
+ {
+ cmCustomCommand cc(command, arguments, dep, out[0].c_str());
+ target.GetPostBuildCommands().push_back(cc);
+ }
+ else
+ {
+ cmCustomCommand cc(command, arguments, dep, NULL);
+ target.GetPostBuildCommands().push_back(cc);
+ }
m_Targets.insert(cmTargets::value_type(utilityName,target));
}
+cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
+{
+ std::string name = cname;
+
+ // look through all the source files that have custom commands
+ // and see if the custom command has the passed source file as an output
+ // keep in mind the possible .rule extension that may be tacked on
+ for(std::vector<cmSourceFile*>::const_iterator i = m_SourceFiles.begin();
+ i != m_SourceFiles.end(); ++i)
+ {
+ // does this source file have a custom command?
+ if ((*i)->GetCustomCommand())
+ {
+ // is the output of the custom command match the source files name
+ std::string out = (*i)->GetCustomCommand()->GetOutput();
+ if (out.rfind(name) != out.npos &&
+ out.rfind(name) == out.size() - name.size())
+ {
+ return *i;
+ }
+ }
+ }
+
+ // otherwise return NULL
+ return NULL;
+}
+
+
cmSourceGroup* cmMakefile::GetSourceGroup(const char* name)
{
// First see if the group exists. If so, replace its regular expression.
@@ -946,6 +1115,19 @@ void cmMakefile::ExpandVariables()
}
}
+void cmMakefile::ExpandVariablesInCustomCommands()
+{
+ for(std::vector<cmSourceFile*>::iterator i = m_SourceFiles.begin();
+ i != m_SourceFiles.end(); ++i)
+ {
+ cmCustomCommand *cc = (*i)->GetCustomCommand();
+ if (cc)
+ {
+ cc->ExpandVariables(*this);
+ }
+ }
+}
+
bool cmMakefile::IsOn(const char* name) const
{
const char* value = this->GetDefinition(name);
@@ -1254,7 +1436,7 @@ cmMakefile::FindSourceGroup(const char* source,
std::string::size_type pos = file.rfind('/');
if(pos != std::string::npos)
{
- file = file.substr(pos, file.length()-pos);
+ file = file.substr(pos+1);
}
for(std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
@@ -1402,11 +1584,11 @@ cmSourceFile* cmMakefile::GetSource(const char* sourceName) const
{
std::string s = cmSystemTools::GetFilenameName(sourceName);
std::string ext;
- std::string::size_type pos = s.rfind('.');
- if(pos != std::string::npos)
+ ext = cmSystemTools::GetFilenameLastExtension(s);
+ s = s.substr(0, s.length()-ext.length());
+ if ( ext.length() && ext[0] == '.' )
{
- ext = s.substr(pos+1, s.size() - pos-1);
- s = s.substr(0, pos);
+ ext = ext.substr(1);
}
for(std::vector<cmSourceFile*>::const_iterator i = m_SourceFiles.begin();
i != m_SourceFiles.end(); ++i)
@@ -1422,8 +1604,71 @@ cmSourceFile* cmMakefile::GetSource(const char* sourceName) const
return 0;
}
+cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName,
+ bool generated)
+{
+ // check to see if it exists
+ cmSourceFile* ret = this->GetSource(sourceName);
+ if (ret)
+ {
+ return ret;
+ }
+
+ // we must create one
+ std::string newfile = sourceName;
+ cmSourceFile file;
+ std::string path = cmSystemTools::GetFilenamePath(newfile);
+ if(generated)
+ {
+ std::string ext = cmSystemTools::GetFilenameLastExtension(newfile);
+ std::string name_no_ext = cmSystemTools::GetFilenameName(newfile.c_str());
+ name_no_ext = name_no_ext.substr(0, name_no_ext.length()-ext.length());
+ if ( ext.length() && ext[0] == '.' )
+ {
+ ext = ext.substr(1);
+ }
+ if((path.size() && path[0] == '/') ||
+ (path.size() > 1 && path[1] == ':'))
+ {
+ file.SetName(name_no_ext.c_str(), path.c_str(), ext.c_str(), false);
+ }
+ else
+ {
+ file.SetName(name_no_ext.c_str(), this->GetCurrentOutputDirectory(),
+ ext.c_str(), false);
+ }
+ }
+ else
+ {
+ // if this is a full path then
+ if((path.size() && path[0] == '/') ||
+ (path.size() > 1 && path[1] == ':'))
+ {
+ file.SetName(cmSystemTools::GetFilenameName(newfile.c_str()).c_str(),
+ path.c_str(),
+ this->GetSourceExtensions(),
+ this->GetHeaderExtensions());
+ }
+ else
+ {
+ file.SetName(newfile.c_str(), this->GetCurrentDirectory(),
+ this->GetSourceExtensions(),
+ this->GetHeaderExtensions());
+ }
+ }
+ // add the source file to the makefile
+ this->AddSource(file);
+ ret = this->GetSource(sourceName);
+ if (!ret)
+ {
+ cmSystemTools::Error(
+ "CMake failed to properly look up cmSourceFile: ", sourceName);
+ int i = *(int *)0x0;
+ }
+ return ret;
+}
-
+
cmSourceFile* cmMakefile::AddSource(cmSourceFile const&sf)
{
// check to see if it exists
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 3180847..93d02c8 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -121,6 +121,22 @@ public:
/**
* 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.
+ */
void AddCustomCommand(const char* source,
const char* command,
const std::vector<std::string>& commandArgs,
@@ -156,7 +172,8 @@ public:
void AddUtilityCommand(const char* utilityName,
const char* command,
const char* arguments,
- bool all);
+ bool all,
+ const std::vector<std::string> &depends);
void AddUtilityCommand(const char* utilityName,
const char* command,
const char* arguments,
@@ -417,6 +434,14 @@ public:
cmSourceFile* GetSource(const char* sourceName) const;
///! Add a new cmSourceFile to the list of sources for this makefile.
cmSourceFile* AddSource(cmSourceFile const&);
+
+ /** Get a cmSourceFile pointer for a given source name, if the name is
+ * not found, then create the source file and return it. generated
+ * indicates if it is a generated file, this is used in determining
+ * how to create the source file instance e.g. name
+ */
+ cmSourceFile* GetOrCreateSource(const char* sourceName,
+ bool generated = false);
/**
* Obtain a list of auxiliary source directories.
@@ -508,7 +533,8 @@ public:
* Expand variables in the makefiles ivars such as link directories etc
*/
void ExpandVariables();
-
+ void ExpandVariablesInCustomCommands();
+
/**
* find what source group this source is in
*/
@@ -559,6 +585,19 @@ public:
*/
cmake *GetCMakeInstance() const;
+ /**
+ * Get all the source files this makefile knows about
+ */
+ const std::vector<cmSourceFile*> &GetSourceFiles() const
+ {return m_SourceFiles;}
+ std::vector<cmSourceFile*> &GetSourceFiles() {return m_SourceFiles;}
+
+ /**
+ * Is there a source file that has the provided source file as an output?
+ * if so then return it
+ */
+ cmSourceFile *GetSourceFileWithOutput(const char *outName);
+
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(const char* name, cmTarget& target);
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index e57cfa6..65e85fe 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.cxx
+++ b/Source/cmSetSourceFilesPropertiesCommand.cxx
@@ -29,6 +29,7 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
// first collect up the list of files
std::vector<std::string> propertyPairs;
bool doingFiles = true;
+ bool generated = false;
int numFiles = 0;
std::vector<std::string>::const_iterator j;
for(j= args.begin(); j != args.end();++j)
@@ -49,6 +50,7 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
else if(*j == "GENERATED")
{
doingFiles = false;
+ generated = true;
propertyPairs.push_back("GENERATED");
propertyPairs.push_back("1");
}
@@ -84,7 +86,18 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
while (j != args.end())
{
propertyPairs.push_back(*j);
- ++j;
+ if(*j == "GENERATED")
+ {
+ ++j;
+ if(j != args.end() && cmSystemTools::IsOn(j->c_str()))
+ {
+ generated = true;
+ }
+ }
+ else
+ {
+ ++j;
+ }
if(j == args.end())
{
this->SetError("called with incorrect number of arguments.");
@@ -112,67 +125,13 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
unsigned int k;
for(i = 0; i < numFiles; ++i)
{
- // if the file is already in the makefile just set properites on it
- cmSourceFile* sf = m_Makefile->GetSource(args[i].c_str());
- if(sf)
+ // get the source file
+ cmSourceFile* sf =
+ m_Makefile->GetOrCreateSource(args[i].c_str(), generated);
+ // now loop through all the props and set them
+ for (k = 0; k < propertyPairs.size(); k = k + 2)
{
- // now loop through all the props and set them
- for (k = 0; k < propertyPairs.size(); k = k + 2)
- {
- sf->SetProperty(propertyPairs[k].c_str(),propertyPairs[k+1].c_str());
- }
- }
- // if file is not already in the makefile, then add it
- else
- {
- std::string newfile = args[i];
- cmSourceFile file;
- std::string path = cmSystemTools::GetFilenamePath(newfile);
- // now loop through all the props and set them
- for (k = 0; k < propertyPairs.size(); k = k + 2)
- {
- file.SetProperty(propertyPairs[k].c_str(),propertyPairs[k+1].c_str());
- }
- if(file.GetPropertyAsBool("GENERATED"))
- {
- std::string ext = cmSystemTools::GetFilenameExtension(newfile);
- std::string name_no_ext = cmSystemTools::GetFilenameName(newfile.c_str());
- name_no_ext = name_no_ext.substr(0, name_no_ext.length()-ext.length());
- if ( ext.length() && ext[0] == '.' )
- {
- ext = ext.substr(1);
- }
- if((path.size() && path[0] == '/') ||
- (path.size() > 1 && path[1] == ':'))
- {
- file.SetName(name_no_ext.c_str(), path.c_str(), ext.c_str(), false);
- }
- else
- {
- file.SetName(name_no_ext.c_str(), m_Makefile->GetCurrentOutputDirectory(),
- ext.c_str(), false);
- }
- }
- else
- {
- // if this is a full path then
- if((path.size() && path[0] == '/') ||
- (path.size() > 1 && path[1] == ':'))
- {
- file.SetName(cmSystemTools::GetFilenameName(newfile.c_str()).c_str(),
- path.c_str(),
- m_Makefile->GetSourceExtensions(),
- m_Makefile->GetHeaderExtensions());
- }
- else
- {
- file.SetName(newfile.c_str(), m_Makefile->GetCurrentDirectory(),
- m_Makefile->GetSourceExtensions(),
- m_Makefile->GetHeaderExtensions());
- }
- }
- // add the source file to the makefile
- m_Makefile->AddSource(file);
+ sf->SetProperty(propertyPairs[k].c_str(),propertyPairs[k+1].c_str());
}
}
return true;
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index e04a856..d6d1744 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -18,6 +18,7 @@
#define cmSourceFile_h
#include "cmStandardIncludes.h"
+#include "cmCustomCommand.h"
/** \class cmSourceFile
* \brief Represent a class loaded from a makefile.
@@ -34,6 +35,11 @@ public:
*/
cmSourceFile()
{
+ m_CustomCommand = 0;
+ }
+ ~cmSourceFile()
+ {
+ if (m_CustomCommand) { delete m_CustomCommand; }
}
/**
@@ -46,6 +52,15 @@ public:
const std::vector<std::string>& headerExts);
/**
+ * Get the list of the custom commands for this source file
+ */
+ const cmCustomCommand *GetCustomCommand() const
+ {return m_CustomCommand;}
+ cmCustomCommand *GetCustomCommand() {return m_CustomCommand;}
+ void SetCustomCommand(cmCustomCommand *cc)
+ { m_CustomCommand = cc;}
+
+ /**
* Set the name of the file, given the directory the file should be in. IN
* this version the extension is provided in the call. This is useful for
* generated files that do not exist prior to the build.
@@ -77,8 +92,7 @@ public:
void SetSourceName(const char *name) {m_SourceName = name;}
/**
- * The file name associated with stripped off directory and extension.
- * (In most cases this is the name of the class.)
+ * The file extension associated with source file
*/
const std::string &GetSourceExtension() const {return m_SourceExtension;}
void SetSourceExtension(const char *name) {m_SourceExtension = name;}
@@ -90,8 +104,8 @@ public:
std::vector<std::string> &GetDepends() {return m_Depends;}
private:
-
std::map<cmStdString,cmStdString> m_Properties;
+ cmCustomCommand *m_CustomCommand;
std::string m_FullPath;
std::string m_SourceName;
std::string m_SourceExtension;
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index 081f299..8815e30 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -33,7 +33,7 @@ cmSourceGroup::cmSourceGroup(const char* name, const char* regex):
cmSourceGroup::cmSourceGroup(const cmSourceGroup& r):
m_Name(r.m_Name),
m_GroupRegex(r.m_GroupRegex),
- m_BuildRules(r.m_BuildRules)
+ m_SourceFiles(r.m_SourceFiles)
{
}
@@ -52,100 +52,6 @@ bool cmSourceGroup::Matches(const char* name)
*/
void cmSourceGroup::AddSource(const char* name, const cmSourceFile* sf)
{
- BuildRules::iterator s = m_BuildRules.find(name);
- if(s == m_BuildRules.end())
- {
- SourceAndCommands sc;
- sc.m_SourceFile = sf;
- // The source was not found. Add it with no commands.
- m_BuildRules[name] = sc;
- return;
- }
+ m_SourceFiles.push_back(sf);
}
-
-/**
- * Add a source and corresponding custom command to the group. If the
- * source already exists, the command will be added to its set of commands.
- * If the command also already exists, the given dependencies and outputs
- * are added to it.
- */
-void cmSourceGroup::AddCustomCommand(const cmCustomCommand &cmd)
-{
- std::string commandAndArgs = cmd.GetCommandAndArguments();
- BuildRules::iterator s = m_BuildRules.find(cmd.GetSourceName());
- if(s == m_BuildRules.end())
- {
- // The source was not found. Add it with this command.
- CommandFiles& cmdFiles =
- m_BuildRules[cmd.GetSourceName()].m_Commands[commandAndArgs];
- cmdFiles.m_Command = cmd.GetCommand();
- cmdFiles.m_Comment = cmd.GetComment();
- cmdFiles.m_Arguments = cmd.GetArguments();
- cmdFiles.m_Depends.insert(cmd.GetDepends().begin(),cmd.GetDepends().end());
- cmdFiles.m_Outputs.insert(cmd.GetOutputs().begin(),cmd.GetOutputs().end());
- return;
- }
-
- // The source already exists. See if the command exists.
- Commands& commands = s->second.m_Commands;
- Commands::iterator c = commands.find(commandAndArgs);
- if(c == commands.end())
- {
- // The command did not exist. Add it.
- commands[commandAndArgs].m_Command = cmd.GetCommand();
- commands[commandAndArgs].m_Comment = cmd.GetComment();
- commands[commandAndArgs].m_Arguments = cmd.GetArguments();
- commands[commandAndArgs].m_Depends.insert(cmd.GetDepends().begin(),
- cmd.GetDepends().end());
- commands[commandAndArgs].m_Outputs.insert(cmd.GetOutputs().begin(),
- cmd.GetOutputs().end());
- return;
- }
-
- // The command already exists for this source. Merge the sets.
- CommandFiles& commandFiles = c->second;
- commandFiles.m_Depends.insert(cmd.GetDepends().begin(),
- cmd.GetDepends().end());
- commandFiles.m_Outputs.insert(cmd.GetOutputs().begin(),
- cmd.GetOutputs().end());
-}
-
-void cmSourceGroup::Print() const
-{
- std::cout << "cmSourceGroup: " << m_Name.c_str() << "\n";
- for(BuildRules::const_iterator i = m_BuildRules.begin();
- i != m_BuildRules.end(); ++i)
- {
- std::cout << "BuildRule: " << i->first.c_str() << "\n";
- for(Commands::const_iterator j = i->second.m_Commands.begin();
- j != i->second.m_Commands.end(); ++j)
- {
- std::cout << "FullCommand: " << j->first.c_str() << "\n";
- std::cout << "Command: " << j->second.m_Command.c_str() << "\n";
- std::cout << "Arguments: " << j->second.m_Arguments.c_str() << "\n";
- std::cout << "Command Outputs "
- << static_cast<int>(j->second.m_Outputs.size()) << "\n";
- std::cout << "Command Depends "
- << static_cast<int>(j->second.m_Depends.size()) << "\n";
- }
- }
-}
-
-
-void cmSourceGroup::CommandFiles::Merge(const CommandFiles &r)
-{
- std::set<std::string>::const_iterator dep = r.m_Depends.begin();
- std::set<std::string>::const_iterator out = r.m_Outputs.begin();
- for (;dep != r.m_Depends.end(); ++dep)
- {
- this->m_Depends.insert(*dep);
- }
- for (;out != r.m_Outputs.end(); ++out)
- {
- this->m_Outputs.insert(*out);
- }
-}
-
-
-
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index 6c3fe4d..0dbd8cc 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -19,7 +19,6 @@
#include "cmStandardIncludes.h"
#include "cmRegularExpression.h"
-#include "cmCustomCommand.h"
class cmSourceFile;
/** \class cmSourceGroup
@@ -35,47 +34,20 @@ public:
cmSourceGroup(const cmSourceGroup&);
~cmSourceGroup() {}
- struct CommandFiles
- {
- CommandFiles() {}
- CommandFiles(const CommandFiles& r):
- m_Comment(r.m_Comment), m_Outputs(r.m_Outputs), m_Depends(r.m_Depends) {}
-
- void Merge(const CommandFiles &r);
-
- std::string m_Command;
- std::string m_Arguments;
- std::string m_Comment;
- std::set<std::string> m_Outputs;
- std::set<std::string> m_Depends;
- };
-
- /**
- * Map from command to its output/depends sets.
- */
- typedef std::map<cmStdString, CommandFiles> Commands;
-
- struct SourceAndCommands
- {
- SourceAndCommands(): m_SourceFile(0) {}
- const cmSourceFile* m_SourceFile;
- Commands m_Commands;
- };
- /**
- * Map from source to command map.
- */
- typedef std::map<cmStdString, SourceAndCommands> BuildRules;
-
- bool Matches(const char* name);
void SetGroupRegex(const char* regex)
{ m_GroupRegex.compile(regex); }
void AddSource(const char* name, const cmSourceFile*);
- void AddCustomCommand(const cmCustomCommand &cmd);
const char* GetName() const
{ return m_Name.c_str(); }
- const BuildRules& GetBuildRules() const
- { return m_BuildRules; }
- void Print() const;
+ bool Matches(const char *);
+
+ /**
+ * Get the list of the source files used by this target
+ */
+ const std::vector<const cmSourceFile*> &GetSourceFiles() const
+ {return m_SourceFiles;}
+ std::vector<const cmSourceFile*> &GetSourceFiles() {return m_SourceFiles;}
+
private:
/**
* The name of the source group.
@@ -88,11 +60,9 @@ private:
cmRegularExpression m_GroupRegex;
/**
- * Map from source name to the commands to build from the source.
- * Some commands may build from files that the compiler also knows how to
- * build.
+ * vector of all source files in this source group
*/
- BuildRules m_BuildRules;
+ std::vector<const cmSourceFile*> m_SourceFiles;
};
#endif
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 46bcabd..0ef39fd 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1932,6 +1932,25 @@ std::string cmSystemTools::GetFilenameExtension(const std::string& filename)
}
}
+/**
+ * Return file extension of a full filename (dot included).
+ * Warning: this is the shortest extension (for example: .tar.gz)
+ */
+std::string
+cmSystemTools::GetFilenameLastExtension(const std::string& filename)
+{
+ std::string name = cmSystemTools::GetFilenameName(filename);
+ std::string::size_type dot_pos = name.rfind(".");
+ if(dot_pos != std::string::npos)
+ {
+ return name.substr(dot_pos);
+ }
+ else
+ {
+ return "";
+ }
+}
+
/**
* Return file name without extension of a full filename (i.e. without path).
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 24ac737..8317e64 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -284,6 +284,9 @@ public:
///! return file extension of a full filename (dot included).
static std::string GetFilenameExtension(const std::string&);
+ ///! return file extension of a full filename (dot included).
+ static std::string GetFilenameLastExtension(const std::string&);
+
///! return file name without extension of a full filename.
static std::string GetFilenameWithoutExtension(const std::string&);
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 14ee770..89dac6a 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -34,6 +34,8 @@ public:
SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, INSTALL_FILES,
INSTALL_PROGRAMS };
+ enum CustomCommandType { PRE_BUILD, PRE_LINK, POST_BUILD };
+
/**
* Return the type of target.
*/
@@ -57,8 +59,18 @@ public:
/**
* Get the list of the custom commands for this target
*/
- const std::vector<cmCustomCommand> &GetCustomCommands() const {return m_CustomCommands;}
- std::vector<cmCustomCommand> &GetCustomCommands() {return m_CustomCommands;}
+ const std::vector<cmCustomCommand> &GetPreBuildCommands() const
+ {return m_PreBuildCommands;}
+ std::vector<cmCustomCommand> &GetPreBuildCommands()
+ {return m_PreBuildCommands;}
+ const std::vector<cmCustomCommand> &GetPreLinkCommands() const
+ {return m_PreLinkCommands;}
+ std::vector<cmCustomCommand> &GetPreLinkCommands()
+ {return m_PreLinkCommands;}
+ const std::vector<cmCustomCommand> &GetPostBuildCommands() const
+ {return m_PostBuildCommands;}
+ std::vector<cmCustomCommand> &GetPostBuildCommands()
+ {return m_PostBuildCommands;}
/**
* Get the list of the source lists used by this target
@@ -186,7 +198,9 @@ private:
private:
- std::vector<cmCustomCommand> m_CustomCommands;
+ std::vector<cmCustomCommand> m_PreBuildCommands;
+ std::vector<cmCustomCommand> m_PreLinkCommands;
+ std::vector<cmCustomCommand> m_PostBuildCommands;
std::vector<std::string> m_SourceLists;
TargetType m_TargetType;
std::vector<cmSourceFile*> m_SourceFiles;