summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2001-03-20 18:20:59 (GMT)
committerBrad King <brad.king@kitware.com>2001-03-20 18:20:59 (GMT)
commit8c087d0e7a2045fead07d3069eefddfa4c515179 (patch)
tree3ea3acebf9283f281e5753a15968bd13c8558da2 /Source
parent51ef865ef8c3b39e08ad627cb0effa35ca74955a (diff)
downloadCMake-8c087d0e7a2045fead07d3069eefddfa4c515179.zip
CMake-8c087d0e7a2045fead07d3069eefddfa4c515179.tar.gz
CMake-8c087d0e7a2045fead07d3069eefddfa4c515179.tar.bz2
ENH: Added SOURCE_GROUP command and corresponding support code. This command allows CMakeLists files to specify how sources are organized into groups in the generated DSP files and makefiles.
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLib.dsp4
-rw-r--r--Source/Makefile.in4
-rw-r--r--Source/cmCableCommand.cxx4
-rw-r--r--Source/cmCablePackageCommand.cxx12
-rw-r--r--Source/cmCommands.cxx2
-rw-r--r--Source/cmDSPMakefile.cxx208
-rw-r--r--Source/cmDSPMakefile.h11
-rw-r--r--Source/cmDSPWriter.cxx208
-rw-r--r--Source/cmDSPWriter.h11
-rw-r--r--Source/cmMakefile.cxx84
-rw-r--r--Source/cmMakefile.h42
-rw-r--r--Source/cmSourceGroup.cxx87
-rw-r--r--Source/cmSourceGroup.h94
-rw-r--r--Source/cmSourceGroupCommand.cxx31
-rw-r--r--Source/cmSourceGroupCommand.h84
-rw-r--r--Source/cmUnixMakefileGenerator.cxx60
-rw-r--r--Source/cmWrapTclCommand.cxx7
17 files changed, 721 insertions, 232 deletions
diff --git a/Source/CMakeLib.dsp b/Source/CMakeLib.dsp
index 9da72ea..2af4746 100644
--- a/Source/CMakeLib.dsp
+++ b/Source/CMakeLib.dsp
@@ -125,6 +125,10 @@ SOURCE=.\cmRegularExpression.cxx
# End Source File
# Begin Source File
+SOURCE=.\cmSourceGroup.cxx
+# End Source File
+# Begin Source File
+
SOURCE=.\cmSystemTools.cxx
# End Source File
# Begin Source File
diff --git a/Source/Makefile.in b/Source/Makefile.in
index fcaeb9a..352944e 100644
--- a/Source/Makefile.in
+++ b/Source/Makefile.in
@@ -22,7 +22,8 @@ cmSystemTools.o \
cmDirectory.o \
cmUnixMakefileGenerator.o \
cmCommands.o \
-cmCacheManager.o
+cmCacheManager.o \
+cmSourceGroup.o
DEPENDS = $(srcdir)/*.h ${CMAKE_CONFIG_DIR}/CMake/Source/cmConfigure.h
@@ -38,6 +39,7 @@ cmDirectory.o : $(DEPENDS)
cmUnixMakefileGenerator.o : $(DEPENDS)
cmCommands.o : $(DEPENDS)
cmCacheManager.o : $(DEPENDS)
+cmSourceGroup.o : $(DEPENDS)
diff --git a/Source/cmCableCommand.cxx b/Source/cmCableCommand.cxx
index f200037..8e23945 100644
--- a/Source/cmCableCommand.cxx
+++ b/Source/cmCableCommand.cxx
@@ -107,7 +107,7 @@ void cmCableCommand::SetupCableData()
std::vector<std::string> depends;
m_Makefile->AddCustomCommand(cMakeLists.c_str(),
- "cable_config.xml",
command.c_str(),
- depends);
+ depends,
+ "cable_config.xml");
}
diff --git a/Source/cmCablePackageCommand.cxx b/Source/cmCablePackageCommand.cxx
index 4c334a7..aca0612 100644
--- a/Source/cmCablePackageCommand.cxx
+++ b/Source/cmCablePackageCommand.cxx
@@ -60,17 +60,19 @@ bool cmCablePackageCommand::Invoke(std::vector<std::string>& args)
// files.
std::string command = "${CABLE}";
m_Makefile->ExpandVariablesInString(command);
- std::vector<std::string> depends;
+ std::vector<std::string> depends;
depends.push_back(command);
command += " cable_config.xml";
- std::string packageFile = "Cxx/"+m_PackageName+"_cxx.cxx";
+ std::vector<std::string> outputs;
+ outputs.push_back("Cxx/"+m_PackageName+"_cxx.cxx");
+ outputs.push_back("Cxx/"+m_PackageName+"_cxx.h");
- // A rule for the package's source file.
+ // A rule for the package's source files.
m_Makefile->AddCustomCommand("cable_config.xml",
- packageFile.c_str(),
command.c_str(),
- depends);
+ depends,
+ outputs);
return true;
}
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 7bdcaac..1debaa0 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -42,6 +42,7 @@
#include "cmBuildSharedLibrariesCommand.cxx"
#include "cmUtilitySourceCommand.cxx"
#include "cmIncludeRegularExpressionCommand.cxx"
+#include "cmSourceGroupCommand.cxx"
void GetPredefinedCommands(std::list<cmCommand*>& commands)
{
@@ -81,6 +82,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
commands.push_back(new cmBuildSharedLibrariesCommand);
commands.push_back(new cmUtilitySourceCommand);
commands.push_back(new cmIncludeRegularExpressionCommand);
+ commands.push_back(new cmSourceGroupCommand);
}
diff --git a/Source/cmDSPMakefile.cxx b/Source/cmDSPMakefile.cxx
index 10c9da8..31efded 100644
--- a/Source/cmDSPMakefile.cxx
+++ b/Source/cmDSPMakefile.cxx
@@ -170,42 +170,127 @@ void cmDSPMakefile::WriteDSPBuildRule(std::ostream& fout)
dsprule += " -B";
dsprule += m_Makefile->GetHomeOutputDirectory();
+ std::set<std::string> depends;
+ std::set<std::string> outputs;
+ outputs.insert(outputs.begin(), dspname);
+ fout << "# Begin Source File\n\n";
+ fout << "SOURCE=" << makefileIn.c_str() << "\n\n";
+ this->WriteCustomRule(fout, dsprule.c_str(), depends, outputs);
+ fout << "# End Source File\n";
+}
+
+
+void cmDSPMakefile::AddDSPBuildRule(cmSourceGroup& sourceGroup)
+{
+ std::string dspname = *(m_CreatedProjectNames.end()-1);
+ dspname += ".dsp";
+ std::string makefileIn = m_Makefile->GetStartDirectory();
+ makefileIn += "/";
+ makefileIn += "CMakeLists.txt";
+ std::string dsprule = m_Makefile->GetHomeDirectory();
+ dsprule += "/CMake/Source/CMakeSetupCMD ";
+ dsprule += makefileIn;
+ dsprule += " -DSP -H";
+ dsprule += m_Makefile->GetHomeDirectory();
+ dsprule += " -S";
+ dsprule += m_Makefile->GetStartDirectory();
+ dsprule += " -O";
+ dsprule += m_Makefile->GetStartOutputDirectory();
+ dsprule += " -B";
+ dsprule += m_Makefile->GetHomeOutputDirectory();
+
std::vector<std::string> depends;
- this->WriteCustomRule(fout, makefileIn.c_str(),
- dspname.c_str(),
- dsprule.c_str(),
- depends);
+ std::vector<std::string> outputs;
+ outputs.push_back(dspname);
+ sourceGroup.AddCustomCommand(makefileIn.c_str(), dsprule.c_str(),
+ depends, outputs);
}
+
void cmDSPMakefile::WriteDSPFile(std::ostream& fout)
{
+ // Write the DSP file's header.
this->WriteDSPHeader(fout);
- this->WriteDSPBeginGroup(fout, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
- this->WriteDSPBuildRules(fout,"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBeginGroup(fout, "Header Files", "h;hpp;hxx;hm;inl");
- this->WriteDSPBuildRules(fout,"h;hpp;hxx;hm;inl");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBeginGroup(fout, "XML Files", "xml");
- this->WriteDSPBuildRules(fout,"xml");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBeginGroup(fout, "Text Files", "txt");
- this->WriteDSPBuildRules(fout,"txt");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBuildRule(fout);
+
+ // We may be modifying the source groups temporarily, so make a copy.
+ std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
+
+ // Find the group in which the CMakeLists.txt source belongs, and add
+ // the rule to generate this DSP file.
+ 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 std::vector<std::string>& sources = sg->GetSources();
+ const cmSourceGroup::CustomCommands& customCommands = sg->GetCustomCommands();
+ // If the group is empty, don't write it at all.
+ if(sources.empty() && customCommands.empty())
+ { continue; }
+
+ // If the group has a name, write the header.
+ std::string name = sg->GetName();
+ if(name != "")
+ {
+ this->WriteDSPBeginGroup(fout, name.c_str(), "");
+ }
+
+ // Loop through each source in the source group.
+ for(std::vector<std::string>::const_iterator s = sources.begin();
+ s != sources.end(); ++s)
+ {
+ this->WriteDSPBuildRule(fout, s->c_str());
+ }
+
+ // Loop through each custom command in the source group.
+ for(cmSourceGroup::CustomCommands::const_iterator cc =
+ customCommands.begin(); cc != customCommands.end(); ++ cc)
+ {
+ std::string source = cc->first;
+ const cmSourceGroup::Commands& commands = cc->second;
+
+ fout << "# Begin Source File\n\n";
+ fout << "SOURCE=" << source << "\n\n";
+
+ // Loop through every command generating code from the current source.
+ for(cmSourceGroup::Commands::const_iterator c = commands.begin();
+ c != commands.end(); ++c)
+ {
+ std::string command = c->first;
+ const cmSourceGroup::CommandFiles& commandFiles = c->second;
+ this->WriteCustomRule(fout, command.c_str(), commandFiles.m_Depends,
+ commandFiles.m_Outputs);
+ }
+
+ fout << "# End Source File\n";
+ }
+
+ // If the group has a name, write the footer.
+ if(name != "")
+ {
+ this->WriteDSPEndGroup(fout);
+ }
+ }
+
+ // Write the DSP file's footer.
this->WriteDSPFooter(fout);
}
void cmDSPMakefile::WriteCustomRule(std::ostream& fout,
- const char* source,
- const char* result,
const char* command,
- std::vector<std::string>& depends)
+ const std::set<std::string>& depends,
+ const std::set<std::string>& outputs)
{
- fout << "# Begin Source File\n\n";
- fout << "SOURCE=" << source << "\n\n";
-
std::vector<std::string>::iterator i;
for(i = m_Configurations.begin(); i != m_Configurations.end(); ++i)
{
@@ -218,17 +303,27 @@ void cmDSPMakefile::WriteCustomRule(std::ostream& fout,
fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
}
fout << "# Begin Custom Build\n\n";
- fout << '\"' << result << "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\" ";
- for (int i = 0; i < depends.size(); i++)
+ fout << "BuildCommand = " << 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 << "\"" << depends[i].c_str() << "\" ";
+ fout << "\"" << output->c_str()
+ << "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
+ // Write out all the dependencies for this rule.
+ for(std::set<std::string>::const_iterator d = depends.begin();
+ d != depends.end(); ++d)
+ {
+ fout << " \"" << d->c_str() << "\"";
+ }
+ fout << "\n $(BuildCommand)\n\n";
}
- fout << "\n " << command << "\n\n";
+
fout << "# End Custom Build\n\n";
}
fout << "!ENDIF\n\n";
- fout << "# End Source File\n";
}
@@ -339,61 +434,6 @@ void cmDSPMakefile::WriteDSPFooter(std::ostream& fout)
}
}
-
-void cmDSPMakefile::WriteDSPBuildRules(std::ostream& fout, const char *ext)
-{
- // make a list if matching extentions
- std::vector<std::string> exts;
- std::string inExts = ext;
-
- std::string::size_type pos = inExts.find(';');
- std::string::size_type lastPos = 0;
- while (pos != std::string::npos)
- {
- std::string anExt = inExts.substr(lastPos, pos - lastPos);
- exts.push_back(anExt);
- lastPos = pos + 1;
- pos = inExts.find(';',lastPos);
- }
- exts.push_back(inExts.substr(lastPos,inExts.size() - lastPos));
-
- // loop over any classes
- std::vector<cmClassFile>& Classes = m_Makefile->GetClasses();
- for(int i = 0; i < Classes.size(); ++i)
- {
- if(!Classes[i].m_IsExecutable && !Classes[i].m_HeaderFileOnly)
- {
- // is this class of the appropriate type ?
- if (std::find(exts.begin(),exts.end(),Classes[i].m_ClassExtension)
- != exts.end())
- {
- this->WriteDSPBuildRule(fout, Classes[i].m_FullPath.c_str());
- }
- }
- }
- // loop over any custom commands
- std::vector<cmMakefile::customCommand>& ccoms =
- this->GetMakefile()->GetCustomCommands();
- int numCust = ccoms.size();
- for (int j = 0; j < numCust; j++)
- {
- cmMakefile::customCommand &cc = ccoms[j];
- // is the source of the command the correct type
- pos = cc.m_Source.rfind('.');
- if(pos != std::string::npos)
- {
- if (std::find(exts.begin(),exts.end(),
- cc.m_Source.substr(pos+1,cc.m_Source.size() - pos - 1))
- != exts.end())
- {
- this->WriteCustomRule(fout, cc.m_Source.c_str(),
- cc.m_Result.c_str(),
- cc.m_Command.c_str(),
- cc.m_Depends);
- }
- }
- }
-}
void cmDSPMakefile::WriteDSPBuildRule(std::ostream& fout, const char* path)
{
@@ -402,5 +442,3 @@ void cmDSPMakefile::WriteDSPBuildRule(std::ostream& fout, const char* path)
<< path << "\n";
fout << "# End Source File\n";
}
-
-
diff --git a/Source/cmDSPMakefile.h b/Source/cmDSPMakefile.h
index 0c4906b..f1a2003 100644
--- a/Source/cmDSPMakefile.h
+++ b/Source/cmDSPMakefile.h
@@ -75,15 +75,14 @@ private:
const char* filter);
void WriteDSPEndGroup(std::ostream& fout);
void WriteDSPHeader(std::ostream& fout);
- void WriteDSPBuildRules(std::ostream& fout, const char *extensions);
void WriteDSPBuildRule(std::ostream& fout, const char*);
- void WriteDSPFooter(std::ostream& fout);
void WriteDSPBuildRule(std::ostream& fout);
+ void WriteDSPFooter(std::ostream& fout);
+ void AddDSPBuildRule(cmSourceGroup&);
void WriteCustomRule(std::ostream& fout,
- const char* source,
- const char* result,
- const char* command,
- std::vector<std::string>& depends);
+ const char* command,
+ const std::set<std::string>& depends,
+ const std::set<std::string>& outputs);
std::string m_IncludeOptions;
std::string m_LibraryOptions;
diff --git a/Source/cmDSPWriter.cxx b/Source/cmDSPWriter.cxx
index 10c9da8..31efded 100644
--- a/Source/cmDSPWriter.cxx
+++ b/Source/cmDSPWriter.cxx
@@ -170,42 +170,127 @@ void cmDSPMakefile::WriteDSPBuildRule(std::ostream& fout)
dsprule += " -B";
dsprule += m_Makefile->GetHomeOutputDirectory();
+ std::set<std::string> depends;
+ std::set<std::string> outputs;
+ outputs.insert(outputs.begin(), dspname);
+ fout << "# Begin Source File\n\n";
+ fout << "SOURCE=" << makefileIn.c_str() << "\n\n";
+ this->WriteCustomRule(fout, dsprule.c_str(), depends, outputs);
+ fout << "# End Source File\n";
+}
+
+
+void cmDSPMakefile::AddDSPBuildRule(cmSourceGroup& sourceGroup)
+{
+ std::string dspname = *(m_CreatedProjectNames.end()-1);
+ dspname += ".dsp";
+ std::string makefileIn = m_Makefile->GetStartDirectory();
+ makefileIn += "/";
+ makefileIn += "CMakeLists.txt";
+ std::string dsprule = m_Makefile->GetHomeDirectory();
+ dsprule += "/CMake/Source/CMakeSetupCMD ";
+ dsprule += makefileIn;
+ dsprule += " -DSP -H";
+ dsprule += m_Makefile->GetHomeDirectory();
+ dsprule += " -S";
+ dsprule += m_Makefile->GetStartDirectory();
+ dsprule += " -O";
+ dsprule += m_Makefile->GetStartOutputDirectory();
+ dsprule += " -B";
+ dsprule += m_Makefile->GetHomeOutputDirectory();
+
std::vector<std::string> depends;
- this->WriteCustomRule(fout, makefileIn.c_str(),
- dspname.c_str(),
- dsprule.c_str(),
- depends);
+ std::vector<std::string> outputs;
+ outputs.push_back(dspname);
+ sourceGroup.AddCustomCommand(makefileIn.c_str(), dsprule.c_str(),
+ depends, outputs);
}
+
void cmDSPMakefile::WriteDSPFile(std::ostream& fout)
{
+ // Write the DSP file's header.
this->WriteDSPHeader(fout);
- this->WriteDSPBeginGroup(fout, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
- this->WriteDSPBuildRules(fout,"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBeginGroup(fout, "Header Files", "h;hpp;hxx;hm;inl");
- this->WriteDSPBuildRules(fout,"h;hpp;hxx;hm;inl");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBeginGroup(fout, "XML Files", "xml");
- this->WriteDSPBuildRules(fout,"xml");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBeginGroup(fout, "Text Files", "txt");
- this->WriteDSPBuildRules(fout,"txt");
- this->WriteDSPEndGroup(fout);
- this->WriteDSPBuildRule(fout);
+
+ // We may be modifying the source groups temporarily, so make a copy.
+ std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
+
+ // Find the group in which the CMakeLists.txt source belongs, and add
+ // the rule to generate this DSP file.
+ 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 std::vector<std::string>& sources = sg->GetSources();
+ const cmSourceGroup::CustomCommands& customCommands = sg->GetCustomCommands();
+ // If the group is empty, don't write it at all.
+ if(sources.empty() && customCommands.empty())
+ { continue; }
+
+ // If the group has a name, write the header.
+ std::string name = sg->GetName();
+ if(name != "")
+ {
+ this->WriteDSPBeginGroup(fout, name.c_str(), "");
+ }
+
+ // Loop through each source in the source group.
+ for(std::vector<std::string>::const_iterator s = sources.begin();
+ s != sources.end(); ++s)
+ {
+ this->WriteDSPBuildRule(fout, s->c_str());
+ }
+
+ // Loop through each custom command in the source group.
+ for(cmSourceGroup::CustomCommands::const_iterator cc =
+ customCommands.begin(); cc != customCommands.end(); ++ cc)
+ {
+ std::string source = cc->first;
+ const cmSourceGroup::Commands& commands = cc->second;
+
+ fout << "# Begin Source File\n\n";
+ fout << "SOURCE=" << source << "\n\n";
+
+ // Loop through every command generating code from the current source.
+ for(cmSourceGroup::Commands::const_iterator c = commands.begin();
+ c != commands.end(); ++c)
+ {
+ std::string command = c->first;
+ const cmSourceGroup::CommandFiles& commandFiles = c->second;
+ this->WriteCustomRule(fout, command.c_str(), commandFiles.m_Depends,
+ commandFiles.m_Outputs);
+ }
+
+ fout << "# End Source File\n";
+ }
+
+ // If the group has a name, write the footer.
+ if(name != "")
+ {
+ this->WriteDSPEndGroup(fout);
+ }
+ }
+
+ // Write the DSP file's footer.
this->WriteDSPFooter(fout);
}
void cmDSPMakefile::WriteCustomRule(std::ostream& fout,
- const char* source,
- const char* result,
const char* command,
- std::vector<std::string>& depends)
+ const std::set<std::string>& depends,
+ const std::set<std::string>& outputs)
{
- fout << "# Begin Source File\n\n";
- fout << "SOURCE=" << source << "\n\n";
-
std::vector<std::string>::iterator i;
for(i = m_Configurations.begin(); i != m_Configurations.end(); ++i)
{
@@ -218,17 +303,27 @@ void cmDSPMakefile::WriteCustomRule(std::ostream& fout,
fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
}
fout << "# Begin Custom Build\n\n";
- fout << '\"' << result << "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\" ";
- for (int i = 0; i < depends.size(); i++)
+ fout << "BuildCommand = " << 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 << "\"" << depends[i].c_str() << "\" ";
+ fout << "\"" << output->c_str()
+ << "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
+ // Write out all the dependencies for this rule.
+ for(std::set<std::string>::const_iterator d = depends.begin();
+ d != depends.end(); ++d)
+ {
+ fout << " \"" << d->c_str() << "\"";
+ }
+ fout << "\n $(BuildCommand)\n\n";
}
- fout << "\n " << command << "\n\n";
+
fout << "# End Custom Build\n\n";
}
fout << "!ENDIF\n\n";
- fout << "# End Source File\n";
}
@@ -339,61 +434,6 @@ void cmDSPMakefile::WriteDSPFooter(std::ostream& fout)
}
}
-
-void cmDSPMakefile::WriteDSPBuildRules(std::ostream& fout, const char *ext)
-{
- // make a list if matching extentions
- std::vector<std::string> exts;
- std::string inExts = ext;
-
- std::string::size_type pos = inExts.find(';');
- std::string::size_type lastPos = 0;
- while (pos != std::string::npos)
- {
- std::string anExt = inExts.substr(lastPos, pos - lastPos);
- exts.push_back(anExt);
- lastPos = pos + 1;
- pos = inExts.find(';',lastPos);
- }
- exts.push_back(inExts.substr(lastPos,inExts.size() - lastPos));
-
- // loop over any classes
- std::vector<cmClassFile>& Classes = m_Makefile->GetClasses();
- for(int i = 0; i < Classes.size(); ++i)
- {
- if(!Classes[i].m_IsExecutable && !Classes[i].m_HeaderFileOnly)
- {
- // is this class of the appropriate type ?
- if (std::find(exts.begin(),exts.end(),Classes[i].m_ClassExtension)
- != exts.end())
- {
- this->WriteDSPBuildRule(fout, Classes[i].m_FullPath.c_str());
- }
- }
- }
- // loop over any custom commands
- std::vector<cmMakefile::customCommand>& ccoms =
- this->GetMakefile()->GetCustomCommands();
- int numCust = ccoms.size();
- for (int j = 0; j < numCust; j++)
- {
- cmMakefile::customCommand &cc = ccoms[j];
- // is the source of the command the correct type
- pos = cc.m_Source.rfind('.');
- if(pos != std::string::npos)
- {
- if (std::find(exts.begin(),exts.end(),
- cc.m_Source.substr(pos+1,cc.m_Source.size() - pos - 1))
- != exts.end())
- {
- this->WriteCustomRule(fout, cc.m_Source.c_str(),
- cc.m_Result.c_str(),
- cc.m_Command.c_str(),
- cc.m_Depends);
- }
- }
- }
-}
void cmDSPMakefile::WriteDSPBuildRule(std::ostream& fout, const char* path)
{
@@ -402,5 +442,3 @@ void cmDSPMakefile::WriteDSPBuildRule(std::ostream& fout, const char* path)
<< path << "\n";
fout << "# End Source File\n";
}
-
-
diff --git a/Source/cmDSPWriter.h b/Source/cmDSPWriter.h
index 0c4906b..f1a2003 100644
--- a/Source/cmDSPWriter.h
+++ b/Source/cmDSPWriter.h
@@ -75,15 +75,14 @@ private:
const char* filter);
void WriteDSPEndGroup(std::ostream& fout);
void WriteDSPHeader(std::ostream& fout);
- void WriteDSPBuildRules(std::ostream& fout, const char *extensions);
void WriteDSPBuildRule(std::ostream& fout, const char*);
- void WriteDSPFooter(std::ostream& fout);
void WriteDSPBuildRule(std::ostream& fout);
+ void WriteDSPFooter(std::ostream& fout);
+ void AddDSPBuildRule(cmSourceGroup&);
void WriteCustomRule(std::ostream& fout,
- const char* source,
- const char* result,
- const char* command,
- std::vector<std::string>& depends);
+ const char* command,
+ const std::set<std::string>& depends,
+ const std::set<std::string>& outputs);
std::string m_IncludeOptions;
std::string m_LibraryOptions;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 8248f5e..87cc709 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -27,10 +27,14 @@
cmMakefile::cmMakefile()
{
// Setup the default include file regular expression.
+ // Should be changed to something like "\\.(h|hh|hpp|hxx)$" or "^.*$"
m_IncludeFileRegularExpression = "^itk|^vtk|^vnl|^vcl|^f2c";
m_DefineFlags = " ";
m_MakefileGenerator = 0;
+ this->AddSourceGroup("", "^.*$");
+ this->AddSourceGroup("Source Files", "\\.(cpp|C|c|cxx|rc|def|r|odl|idl|hpj|bat)$");
+ this->AddSourceGroup("Header Files", "\\.(h|hh|hpp|hxx|hm|inl)$");
this->AddDefaultCommands();
this->AddDefaultDefinitions();
}
@@ -249,21 +253,33 @@ void cmMakefile::GenerateMakefile()
void cmMakefile::AddClass(cmClassFile& cmfile)
{
m_Classes.push_back(cmfile);
-}
+ if(!cmfile.m_IsExecutable && !cmfile.m_HeaderFileOnly)
+ {
+ // Add the file to the list of sources.
+ std::string source = cmfile.m_FullPath;
+ cmSourceGroup& sourceGroup = this->FindSourceGroup(source.c_str());
+ sourceGroup.AddSource(source.c_str());
+ }
+}
+void cmMakefile::AddCustomCommand(const char* source,
+ const char* command,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& outputs)
+{
+ cmSourceGroup& sourceGroup = this->FindSourceGroup(source);
+ sourceGroup.AddCustomCommand(source, command, depends, outputs);
+}
void cmMakefile::AddCustomCommand(const char* source,
- const char* result,
- const char* command,
- std::vector<std::string>& depends)
+ const char* command,
+ const std::vector<std::string>& depends,
+ const char* output)
{
- cmMakefile::customCommand customCommand;
- customCommand.m_Source = source;
- customCommand.m_Result = result;
- customCommand.m_Command = command;
- customCommand.m_Depends = depends;
- m_CustomCommands.push_back(customCommand);
+ std::vector<std::string> outputs;
+ outputs.push_back(output);
+ this->AddCustomCommand(source, command, depends, outputs);
}
void cmMakefile::AddDefineFlag(const char* flag)
@@ -335,6 +351,25 @@ void cmMakefile::SetLibraryName(const char* l)
m_LibraryName = l;
}
+void cmMakefile::AddSourceGroup(const char* name, const char* regex)
+{
+ // First see if the group exists. If so, replace its regular expression.
+ for(std::vector<cmSourceGroup>::iterator sg = m_SourceGroups.begin();
+ sg != m_SourceGroups.end(); ++sg)
+ {
+ std::string sgName = sg->GetName();
+ if(sgName == name)
+ {
+ // We only want to set the regular expression. If there are already
+ // source files in the group, we don't want to remove them.
+ sg->SetGroupRegex(regex);
+ return;
+ }
+ }
+
+ // The group doesn't exist. Add it.
+ m_SourceGroups.push_back(cmSourceGroup(name, regex));
+}
void cmMakefile::AddExtraDirectory(const char* dir)
{
@@ -549,3 +584,32 @@ void cmMakefile::AddDefaultDefinitions()
this->AddDefinition("CMAKE_CFG_OUTDIR",".");
#endif
}
+
+/**
+ * Find a source group whose regular expression matches the filename
+ * part of the given source name. Search backward through the list of
+ * source groups, and take the first matching group found. This way
+ * non-inherited SOURCE_GROUP commands will have precedence over
+ * inherited ones.
+ */
+cmSourceGroup& cmMakefile::FindSourceGroup(const char* source)
+{
+ std::string file = source;
+ std::string::size_type pos = file.rfind('/');
+ if(pos != std::string::npos)
+ {
+ file = file.substr(pos, file.length()-pos);
+ }
+
+ for(std::vector<cmSourceGroup>::reverse_iterator sg = m_SourceGroups.rbegin();
+ sg != m_SourceGroups.rend(); ++sg)
+ {
+ if(sg->Matches(file.c_str()))
+ {
+ return *sg;
+ }
+ }
+
+ // Shouldn't get here, but just in case, return the default group.
+ return m_SourceGroups.front();
+}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 21ce96f..83e4fe6 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -19,6 +19,7 @@
#include "cmStandardIncludes.h"
#include "cmClassFile.h"
#include "cmSystemTools.h"
+#include "cmSourceGroup.h"
class cmCommand;
class cmMakefileGenerator;
@@ -74,9 +75,15 @@ public:
* Add a custom command to the build.
*/
void AddCustomCommand(const char* source,
- const char* result,
- const char* command,
- std::vector<std::string>& depends);
+ const char* command,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& outputs);
+
+ void AddCustomCommand(const char* source,
+ const char* command,
+ const std::vector<std::string>& depends,
+ const char* output);
+
/**
* Add a define flag to the build.
*/
@@ -147,6 +154,11 @@ public:
void AddClass(cmClassFile& );
/**
+ * Add a source group for consideration when adding a new source.
+ */
+ void AddSourceGroup(const char* name, const char* regex);
+
+ /**
* Add an auxiliary directory to the build.
*/
void AddExtraDirectory(const char* dir);
@@ -370,6 +382,12 @@ public:
{return m_UsedCommands;}
/**
+ * Get the vector source groups.
+ */
+ const std::vector<cmSourceGroup>& GetSourceGroups() const
+ { return m_SourceGroups; }
+
+ /**
* Dump documentation to a file. If 0 is returned, the
* operation failed.
*/
@@ -387,19 +405,7 @@ public:
/**
* Expand variables in the makefiles ivars such as link directories etc
*/
- void ExpandVariables();
-
- struct customCommand
- {
- std::string m_Source;
- std::string m_Result;
- std::string m_Command;
- std::vector<std::string> m_Depends;
- };
-
- std::vector<customCommand>& GetCustomCommands() {
- return m_CustomCommands; };
-
+ void ExpandVariables();
/** Recursivly read and create a cmMakefile object for
* all CMakeLists.txt files in the GetSubDirectories list.
@@ -440,7 +446,7 @@ protected:
std::vector<std::string> m_LinkLibrariesUnix;
std::string m_IncludeFileRegularExpression;
std::string m_DefineFlags;
- std::vector<customCommand> m_CustomCommands;
+ std::vector<cmSourceGroup> m_SourceGroups;
typedef std::map<std::string, cmCommand*> RegisteredCommandsMap;
typedef std::map<std::string, std::string> DefinitionMap;
DefinitionMap m_Definitions;
@@ -461,6 +467,8 @@ private:
void PrintStringVector(const char* s, std::vector<std::string>& v);
void AddDefaultCommands();
void AddDefaultDefinitions();
+
+ cmSourceGroup& FindSourceGroup(const char* source);
};
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
new file mode 100644
index 0000000..fc09631
--- /dev/null
+++ b/Source/cmSourceGroup.cxx
@@ -0,0 +1,87 @@
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+
+ Copyright (c) 2000 National Library of Medicine
+ All rights reserved.
+
+ See COPYRIGHT.txt for copyright details.
+
+=========================================================================*/
+#include "cmSourceGroup.h"
+
+
+/**
+ * The constructor initializes the group's regular expression.
+ */
+cmSourceGroup::cmSourceGroup(const char* name, const char* regex):
+ m_Name(name),
+ m_GroupRegex(regex)
+{
+}
+
+
+/**
+ * Copy constructor.
+ */
+cmSourceGroup::cmSourceGroup(const cmSourceGroup& r):
+ m_Name(r.m_Name),
+ m_GroupRegex(r.m_GroupRegex),
+ m_Sources(r.m_Sources),
+ m_CustomCommands(r.m_CustomCommands)
+{
+}
+
+
+/**
+ * Returns whether the given name matches the group's regular expression.
+ */
+bool cmSourceGroup::Matches(const char* name)
+{
+ return m_GroupRegex.find(name);
+}
+
+
+/**
+ * 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 char* source,
+ const char* command,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& outputs)
+{
+ CustomCommands::iterator s = m_CustomCommands.find(source);
+ if(s == m_CustomCommands.end())
+ {
+ // The source was not found. Add it with this command.
+ m_CustomCommands[source][command].m_Depends.insert(depends.begin(),
+ depends.end());
+ m_CustomCommands[source][command].m_Outputs.insert(outputs.begin(),
+ outputs.end());
+ return;
+ }
+
+ // The source already exists. See if the command exists.
+ Commands& commands = s->second;
+ Commands::iterator c = commands.find(command);
+ if(c == commands.end())
+ {
+ // The command did not exist. Add it.
+ commands[command].m_Depends.insert(depends.begin(), depends.end());
+ commands[command].m_Outputs.insert(outputs.begin(), outputs.end());
+ return;
+ }
+
+ // The command already exists for this source. Merge the sets.
+ CommandFiles& commandFiles = c->second;
+ commandFiles.m_Depends.insert(depends.begin(), depends.end());
+ commandFiles.m_Outputs.insert(outputs.begin(), outputs.end());
+}
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
new file mode 100644
index 0000000..bc8ec1c
--- /dev/null
+++ b/Source/cmSourceGroup.h
@@ -0,0 +1,94 @@
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+
+ Copyright (c) 2000 National Library of Medicine
+ All rights reserved.
+
+ See COPYRIGHT.txt for copyright details.
+
+=========================================================================*/
+#ifndef cmSourceGroup_h
+#define cmSourceGroup_h
+
+#include "cmStandardIncludes.h"
+#include "cmRegularExpression.h"
+#include <set>
+
+/** \class cmSourceGroup
+ * \brief Hold a group of sources as specified by a SOURCE_GROUP command.
+ *
+ * cmSourceGroup holds all the source files and corresponding commands
+ * for files matching the regular expression specified for the group.
+ */
+class cmSourceGroup
+{
+public:
+ cmSourceGroup(const char* name, const char* regex);
+ cmSourceGroup(const cmSourceGroup&);
+ ~cmSourceGroup() {}
+
+ struct CommandFiles
+ {
+ CommandFiles() {}
+ CommandFiles(const CommandFiles& r):
+ m_Outputs(r.m_Outputs), m_Depends(r.m_Depends) {}
+
+ std::set<std::string> m_Outputs;
+ std::set<std::string> m_Depends;
+ };
+
+ /**
+ * Map from command to its output/depends sets.
+ */
+ typedef std::map<std::string, CommandFiles> Commands;
+
+ /**
+ * Map from source to command map.
+ */
+ typedef std::map<std::string, Commands> CustomCommands;
+
+ bool Matches(const char* name);
+ void SetGroupRegex(const char* regex)
+ { m_GroupRegex.compile(regex); }
+ void AddSource(const char* name)
+ { m_Sources.push_back(name); }
+ void AddCustomCommand(const char* source,
+ const char* command,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& outputs);
+ const char* GetName() const
+ { return m_Name.c_str(); }
+ const std::vector<std::string>& GetSources() const
+ { return m_Sources; }
+ const CustomCommands& GetCustomCommands() const
+ { return m_CustomCommands; }
+
+private:
+ /**
+ * The name of the source group.
+ */
+ std::string m_Name;
+
+ /**
+ * The regular expression matching the files in the group.
+ */
+ cmRegularExpression m_GroupRegex;
+
+ /**
+ * The sources in this group that the compiler will know how to build.
+ */
+ std::vector<std::string> m_Sources;
+
+ /**
+ * The custom commands in this group and their corresponding sources.
+ */
+ CustomCommands m_CustomCommands;
+};
+
+#endif
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
new file mode 100644
index 0000000..4559e70
--- /dev/null
+++ b/Source/cmSourceGroupCommand.cxx
@@ -0,0 +1,31 @@
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+
+ Copyright (c) 2000 National Library of Medicine
+ All rights reserved.
+
+ See COPYRIGHT.txt for copyright details.
+
+=========================================================================*/
+#include "cmSourceGroupCommand.h"
+
+// cmSourceGroupCommand
+bool cmSourceGroupCommand::Invoke(std::vector<std::string>& args)
+{
+ if(args.size() != 2)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ m_Makefile->AddSourceGroup(args[0].c_str(), args[1].c_str());
+
+ return true;
+}
+
diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h
new file mode 100644
index 0000000..7a48a64
--- /dev/null
+++ b/Source/cmSourceGroupCommand.h
@@ -0,0 +1,84 @@
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+
+ Copyright (c) 2000 National Library of Medicine
+ All rights reserved.
+
+ See COPYRIGHT.txt for copyright details.
+
+=========================================================================*/
+#ifndef cmSourceGroupCommand_h
+#define cmSourceGroupCommand_h
+
+#include "cmStandardIncludes.h"
+#include "cmCommand.h"
+
+/** \class cmSourceGroupCommand
+ * \brief Adds a cmSourceGroup to the cmMakefile.
+ *
+ * cmSourceGroupCommand is used to define cmSourceGroups which split up
+ * source files in to named, organized groups in the generated makefiles.
+ */
+class cmSourceGroupCommand : public cmCommand
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmSourceGroupCommand;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool Invoke(std::vector<std::string>& args);
+
+ /**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual const char* GetName() {return "SOURCE_GROUP";}
+
+ /**
+ * This determines if the command gets propagated down
+ * to makefiles located in subdirectories.
+ */
+ virtual bool IsInherited()
+ {
+ return true;
+ }
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation()
+ {
+ return "Define a grouping for sources in the makefile.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation()
+ {
+ return
+ "SOURCE_GROUP(name regex)\n"
+ "Defines a new source group. Any file whose name matches the regular\n"
+ "expression will be placed in this group. The LAST regular expression\n"
+ "of all defined SOURCE_GROUPs that matches the file will be selected.";
+ }
+
+ cmTypeMacro(cmSourceGroupCommand, cmCommand);
+};
+
+
+
+#endif
diff --git a/Source/cmUnixMakefileGenerator.cxx b/Source/cmUnixMakefileGenerator.cxx
index 955b108..0128848 100644
--- a/Source/cmUnixMakefileGenerator.cxx
+++ b/Source/cmUnixMakefileGenerator.cxx
@@ -394,21 +394,57 @@ void cmUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout)
// Output each custom rule in the following format:
-// m_Result: m_Source m_Depends[0] m_Depends[1] ...
-// (tab) m_Command
+// output: source depends...
+// (tab) command...
void cmUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
{
- for(std::vector<cmMakefile::customCommand>::const_iterator c =
- m_Makefile->GetCustomCommands().begin();
- c != m_Makefile->GetCustomCommands().end(); ++c)
+ // Loop through every source group.
+ for(std::vector<cmSourceGroup>::const_iterator sg =
+ m_Makefile->GetSourceGroups().begin();
+ sg != m_Makefile->GetSourceGroups().end(); ++sg)
{
- fout << c->m_Result.c_str() << ": " << c->m_Source.c_str();
- for(std::vector<std::string>::const_iterator d = c->m_Depends.begin();
- d != c->m_Depends.end(); ++ d)
+ const cmSourceGroup::CustomCommands& customCommands = sg->GetCustomCommands();
+ if(customCommands.empty())
+ { continue; }
+
+ std::string name = sg->GetName();
+ if(name != "")
{
- fout << " " << d->c_str();
+ fout << "# Start of source group \"" << name.c_str() << "\"\n";
}
- fout << "\n\t" << c->m_Command.c_str() << "\n\n";
- }
-
+
+ // Loop through each source in the source group.
+ for(cmSourceGroup::CustomCommands::const_iterator cc =
+ customCommands.begin(); cc != customCommands.end(); ++ cc)
+ {
+ std::string source = cc->first;
+ const cmSourceGroup::Commands& commands = cc->second;
+ // Loop through every command generating code from the current source.
+ for(cmSourceGroup::Commands::const_iterator c = commands.begin();
+ c != commands.end(); ++c)
+ {
+ std::string command = c->first;
+ const cmSourceGroup::CommandFiles& commandFiles = c->second;
+ // 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)
+ {
+ fout << output->c_str() << ": " << source.c_str();
+ // Write 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)
+ {
+ fout << " " << d->c_str();
+ }
+ fout << "\n\t" << command.c_str() << "\n\n";
+ }
+ }
+ }
+ if(name != "")
+ {
+ fout << "# End of source group \"" << name.c_str() << "\"\n\n";
+ }
+ }
}
diff --git a/Source/cmWrapTclCommand.cxx b/Source/cmWrapTclCommand.cxx
index b6e3d40..522fe46 100644
--- a/Source/cmWrapTclCommand.cxx
+++ b/Source/cmWrapTclCommand.cxx
@@ -104,9 +104,10 @@ void cmWrapTclCommand::FinalPass()
std::string res = m_WrapClasses[classNum].m_ClassName + ".cxx";
std::string cmd = wtcl + " " + m_WrapHeaders[classNum] + " "
+ hints + (m_WrapClasses[classNum].m_AbstractClass ? " 0 " : " 1 ") + " > " + m_WrapClasses[classNum].m_ClassName + ".cxx";
- m_Makefile->AddCustomCommand(m_WrapHeaders[classNum].c_str(),
- res.c_str(),
- cmd.c_str(), depends);
+ m_Makefile->AddCustomCommand(m_WrapHeaders[classNum].c_str(),
+ cmd.c_str(),
+ depends,
+ res.c_str());
}
}