diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2001-01-05 16:41:20 (GMT) |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2001-01-05 16:41:20 (GMT) |
commit | c54a05bfc799f3e88459956ec37698bab22c27f9 (patch) | |
tree | 400b2eb0b6853952a4faa8c0fc41b90eb06deaec /Source/cmMakefile.cxx | |
parent | d888b5e39d4e01af538b48ad16c2a6a474de34a0 (diff) | |
download | CMake-c54a05bfc799f3e88459956ec37698bab22c27f9.zip CMake-c54a05bfc799f3e88459956ec37698bab22c27f9.tar.gz CMake-c54a05bfc799f3e88459956ec37698bab22c27f9.tar.bz2 |
ENH: rework cmake, added ruleMaker classes and changed the syntax of the CMakeLists.txt files.
Diffstat (limited to 'Source/cmMakefile.cxx')
-rw-r--r-- | Source/cmMakefile.cxx | 488 |
1 files changed, 311 insertions, 177 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 426f956..d93fe1a 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1,225 +1,359 @@ -#ifdef _MSC_VER -#pragma warning ( disable : 4786 ) -#endif #include "cmMakefile.h" +#include "cmRuleMaker.h" +#include "cmStandardIncludes.h" #include "cmClassFile.h" #include "cmDirectory.h" #include "cmSystemTools.h" -#include <fstream> -#include <iostream> +#include "cmMakefileGenerator.h" +#include "cmAbstractFilesRule.h" +#include "cmAddTargetRule.h" +#include "cmAuxSourceDirectoryRule.h" +#include "cmExecutablesRule.h" +#include "cmFindIncludeRule.h" +#include "cmFindLibraryRule.h" +#include "cmFindProgramRule.h" +#include "cmIncludeDirectoryRule.h" +#include "cmLibraryRule.h" +#include "cmLinkDirectoriesRule.h" +#include "cmLinkLibrariesRule.h" +#include "cmProjectRule.h" +#include "cmSourceFilesRule.h" +#include "cmSourceFilesRequireRule.h" +#include "cmSubdirRule.h" +#include "cmUnixDefinesRule.h" +#include "cmUnixLibrariesRule.h" +#include "cmWin32DefinesRule.h" +#include "cmWin32LibrariesRule.h" +#include "cmTestsRule.h" // default is not to be building executables cmMakefile::cmMakefile() { + m_DefineFlags = " "; m_Executables = false; + m_MakefileGenerator = 0; + this->AddDefaultRules(); +} + +void cmMakefile::AddDefaultRules() +{ + this->AddRuleMaker(new cmAbstractFilesRule); + this->AddRuleMaker(new cmAddTargetRule); + this->AddRuleMaker(new cmAuxSourceDirectoryRule); + this->AddRuleMaker(new cmExecutablesRule); + this->AddRuleMaker(new cmFindIncludeRule); + this->AddRuleMaker(new cmFindLibraryRule); + this->AddRuleMaker(new cmFindProgramRule); + this->AddRuleMaker(new cmIncludeDirectoryRule); + this->AddRuleMaker(new cmLibraryRule); + this->AddRuleMaker(new cmLinkDirectoriesRule); + this->AddRuleMaker(new cmLinkLibrariesRule); + this->AddRuleMaker(new cmProjectRule); + this->AddRuleMaker(new cmSourceFilesRule); + this->AddRuleMaker(new cmSourceFilesRequireRule); + this->AddRuleMaker(new cmSubdirRule); + this->AddRuleMaker(new cmUnixLibrariesRule); + this->AddRuleMaker(new cmUnixDefinesRule); + this->AddRuleMaker(new cmWin32LibrariesRule); + this->AddRuleMaker(new cmWin32DefinesRule); + this->AddRuleMaker(new cmTestsRule); +#ifdef _WIN32 + this->AddDefinition("WIN32", "1"); +#else + this->AddDefinition("UNIX", "1"); +#endif + // Cygwin is more like unix so enable the unix rules +#if defined(__CYGWIN__) + this->AddDefinition("UNIX", "1"); +#endif +} + + +cmMakefile::~cmMakefile() +{ + for(int i=0; i < m_UsedRuleMakers.size(); i++) + { + delete m_UsedRuleMakers[i]; + } + for(StringRuleMakerMap::iterator j = m_RuleMakers.begin(); + j != m_RuleMakers.end(); ++j) + { + delete (*j).second; + } + delete m_MakefileGenerator; +} + +void cmMakefile::PrintStringVector(const char* s, std::vector<std::string>& v) +{ + std::cout << s << ": ( \n"; + for(std::vector<std::string>::iterator i = v.begin(); + i != v.end(); ++i) + { + std::cout << (*i).c_str() << " "; + } + std::cout << " )\n"; } // call print on all the classes in the makefile void cmMakefile::Print() { - for(int i = 0; i < m_Classes.size(); i++) + std::cout << "classes:\n"; + for(unsigned int i = 0; i < m_Classes.size(); i++) m_Classes[i].Print(); + std::cout << " m_OutputDirectory; " << + m_OutputDirectory.c_str() << std::endl; + std::cout << " m_OutputHomeDirectory; " << + m_OutputHomeDirectory.c_str() << std::endl; + std::cout << " m_cmHomeDirectory; " << + m_cmHomeDirectory.c_str() << std::endl; + std::cout << " m_cmCurrentDirectory; " << + m_cmCurrentDirectory.c_str() << std::endl; + std::cout << " m_LibraryName; " << m_LibraryName.c_str() << std::endl; + std::cout << " m_ProjectName; " << m_ProjectName.c_str() << std::endl; + this->PrintStringVector("m_SubDirectories ", m_SubDirectories); + this->PrintStringVector("m_MakeVerbatim ", m_MakeVerbatim); + this->PrintStringVector("m_IncludeDirectories;", m_IncludeDirectories); + this->PrintStringVector("m_LinkDirectories", m_LinkDirectories); + this->PrintStringVector("m_LinkLibraries", m_LinkLibraries); + this->PrintStringVector("m_LinkLibrariesWin32", m_LinkLibrariesWin32); + this->PrintStringVector("m_LinkLibrariesUnix", m_LinkLibrariesUnix); } // Parse the given CMakeLists.txt file into a list of classes. -bool cmMakefile::ReadMakefile(const char* filename) +bool cmMakefile::ReadMakefile(const char* filename, bool inheriting) { - m_BuildFlags.SetSourceHomeDirectory(this->GetHomeDirectory()); - m_BuildFlags.SetStartDirectory(this->GetCurrentDirectory()); - m_BuildFlags.ParseDirectories(); - m_BuildFlags.ExpandVaribles(this); - + // If not being called from ParseDirectory which + // sets the inheriting flag, then parse up the + // tree and collect inherited parameters + if(!inheriting) + { + cmSystemTools::ConvertToUnixSlashes(m_cmCurrentDirectory); + m_SourceHomeDirectory = m_cmHomeDirectory; + cmSystemTools::ConvertToUnixSlashes(m_SourceHomeDirectory); + this->ParseDirectory(m_cmCurrentDirectory.c_str()); + } + // Now read the input file std::ifstream fin(filename); if(!fin) { - std::cerr << "error can not open file " << filename << std::endl; + cmSystemTools::Error("error can not open file ", filename); return false; } - char inbuffer[2048]; - while ( fin.getline(inbuffer, 2047 ) ) + std::string name; + std::vector<std::string> arguments; + while ( fin ) { - std::string line = inbuffer; - cmClassFile file; - std::string::size_type pos = line.find("SOURCE_FILES"); - if((pos != std::string::npos) && (pos == 0 ) ) - { - if(line.find("\\") != std::string::npos) - { - this->ReadClasses(fin, false); - } - } -#ifdef _WIN32 - else if(line.find("WIN32_SOURCE_FILES") != std::string::npos) - { - if(line.find("\\") != std::string::npos) - { - this->ReadClasses(fin, false); - } - } -#else - else if(line.find("UNIX_SOURCE_FILES") != std::string::npos) - { - if(line.find("\\") != std::string::npos) - { - this->ReadClasses(fin, false); - } - } -#endif - else if(line.find("ABSTRACT_CLASSES") != std::string::npos) + if(cmSystemTools::ParseFunction(fin, name, arguments) ) { - if(line.find("\\") != std::string::npos) - { - this->ReadClasses(fin, true); - } - } - else if(line.find("AUX_SOURCE_DIRECTORY") != std::string::npos) - { - this->ReadTemplateInstanceDirectory(line); - } - else if(line.find("SUBDIRS") != std::string::npos) - { - if(line.find("\\") != std::string::npos) - { - cmSystemTools::ReadList(m_SubDirectories, fin); - } - } - else if(line.find("EXECUTABLES") != std::string::npos || line.find("TESTS") != std::string::npos ) - { - if(line.find("\\") != std::string::npos) - { - this->ReadClasses(fin, false); - m_Executables = true; - } - } - else if(line.find("BEGIN MAKE VERBATIM") != std::string::npos) - { - char inbuffer[2048]; - bool done = false; - m_MakeVerbatim.push_back("# Begin CMakeLists Verbatim\n"); - while(!done) + // Special rule that needs to be removed when + // ADD_RULE is implemented + if(name == "VERBATIM") { - fin.getline(inbuffer, 2047); - m_MakeVerbatim.push_back(inbuffer); - if((m_MakeVerbatim.end()-1)->find("END MAKE VERBATIM") - != std::string::npos ) + if(!inheriting) { - done = true; - *(m_MakeVerbatim.end()-1) = "# End CMakeLists VERBATIM\n\n"; + m_MakeVerbatim = arguments; + } + } + else + { + StringRuleMakerMap::iterator pos = m_RuleMakers.find(name); + if(pos != m_RuleMakers.end()) + { + cmRuleMaker* rm = (*pos).second; + cmRuleMaker* usedMaker = rm->Clone(); + usedMaker->SetMakefile(this); + usedMaker->LoadCache(); + m_UsedRuleMakers.push_back(usedMaker); + if(usedMaker->GetEnabled()) + { + // if not running in inherit mode or + // if the rule is inherited then Invoke it. + if(!inheriting || usedMaker->IsInherited()) + { + if(!usedMaker->Invoke(arguments)) + { + cmSystemTools::Error(usedMaker->GetError()); + } + } + } + } + else + { + cmSystemTools::Error("unknown CMake function", name.c_str()); } } - } - else if(line.find("LIBRARY") != std::string::npos) - { - std::string libname = cmSystemTools::ExtractVariable("LIBRARY", - line.c_str()); - this->SetLibraryName(libname.c_str()); - } - else if(line.find("PROJECT") != std::string::npos) - { - std::string libname = cmSystemTools::ExtractVariable("PROJECT", - line.c_str()); - this->SetProjectName(libname.c_str()); } } return true; } -// Read a list from the Makefile stream -void cmMakefile::ReadClasses(std::ifstream& fin, - bool abstract) -{ - char inbuffer[2048]; - bool done = false; - while (!done) - { - // read a line from the makefile - fin.getline(inbuffer, 2047); - // convert to a string class - std::string classname = inbuffer; - // if the line does not end in \ then we are at the - // end of the list - if(classname.find('\\') == std::string::npos) - { - done = true; - } - // remove extra spaces and \ from the class name - classname = cmSystemTools::CleanUpName(classname.c_str()); - - // if this is not an abstract list then add new class - // to the list of classes in this makefile - if(!abstract) - { - cmClassFile file; - file.SetName(classname.c_str(), this->GetCurrentDirectory()); - file.m_AbstractClass = false; - m_Classes.push_back(file); - } - else - { - // if this is an abstract list, then look - // for an existing class and set it to abstract - for(int i = 0; i < m_Classes.size(); i++) - { - if(m_Classes[i].m_ClassName == classname) - { - m_Classes[i].m_AbstractClass = true; - break; - } - } - } +void cmMakefile::AddRuleMaker(cmRuleMaker* wg) +{ + std::string name = wg->GetName(); + m_RuleMakers.insert( StringRuleMakerMap::value_type(name, wg)); +} + + // Set the make file +void cmMakefile::SetMakefileGenerator(cmMakefileGenerator* mf) +{ + delete m_MakefileGenerator; + m_MakefileGenerator = mf; +} + + // Generate the output file +void cmMakefile::GenerateMakefile() +{ + // do all the variable expansions here + this->ExpandVaribles(); + // set the makefile on the generator + m_MakefileGenerator->SetMakefile(this); + // give all the rules a chance to do something + // after the file has been parsed before generation + for(std::vector<cmRuleMaker*>::iterator i = m_UsedRuleMakers.begin(); + i != m_UsedRuleMakers.end(); ++i) + { + (*i)->FinalPass(); } + // now do the generation + m_MakefileGenerator->GenerateMakefile(); } -// Find all of the files in dir as specified from this line: -// AUX_SOURCE_DIRECTORY = dir -// Add all the files to the m_Classes array. +void cmMakefile::AddClass(cmClassFile& cmfile) +{ + m_Classes.push_back(cmfile); +} + + + +void cmMakefile::AddCustomRule(const char* source, + const char* result, + const char* command, + std::vector<std::string>& depends) +{ + cmMakefile::customRule rule; + rule.m_Source = source; + rule.m_Result = result; + rule.m_Command = command; + rule.m_Depends = depends; + m_CustomRules.push_back(rule); +} + +void cmMakefile::AddDefineFlag(const char* flag) +{ + m_DefineFlags += " "; + m_DefineFlags += flag; +} + +void cmMakefile::AddExecutable(cmClassFile& cf) +{ + m_Classes.push_back(cf); + m_Executables = true; +} + +void cmMakefile::AddLinkLibrary(const char* lib) +{ + m_LinkLibraries.push_back(lib); +} + +void cmMakefile::AddLinkDirectory(const char* dir) +{ + m_LinkDirectories.push_back(dir); +} + +void cmMakefile::AddSubDirectory(const char* sub) +{ + m_SubDirectories.push_back(sub); +} + +void cmMakefile::AddIncludeDirectory(const char* inc) +{ + m_IncludeDirectories.push_back(inc); +} + +void cmMakefile::AddDefinition(const char* name, const char* value) +{ + m_Definitions.insert(DefinitionMap::value_type(name, value)); +} + +void cmMakefile::SetProjectName(const char* p) +{ + m_ProjectName = p; +} + +void cmMakefile::SetLibraryName(const char* l) +{ + m_LibraryName = l; +} + + +void cmMakefile::AddExtraDirectory(const char* dir) +{ + m_AuxSourceDirectories.push_back(dir); +} -void cmMakefile::ReadTemplateInstanceDirectory(std::string& line) + +// Go until directory == m_cmHomeDirectory +// 1. fix slashes +// 2. peal off /dir until home found, go no higher +void cmMakefile::ParseDirectory(const char* dir) { - std::string::size_type start = line.find("="); - if(start != std::string::npos) + std::string listsFile = dir; + listsFile += "/CMakeLists.txt"; + if(cmSystemTools::FileExists(listsFile.c_str())) { - std::string templateDirectory = line.substr(start+1, line.size()); - templateDirectory = cmSystemTools::CleanUpName(templateDirectory.c_str()); - m_TemplateDirectories.push_back(templateDirectory); - std::string tdir = this->GetCurrentDirectory(); - tdir += "/"; - tdir += templateDirectory; - // Load all the files in the directory - cmDirectory dir; - if(dir.Load(tdir.c_str())) - { - int numfiles = dir.GetNumberOfFiles(); - for(int i =0; i < numfiles; ++i) - { - std::string file = dir.GetFile(i); - // ignore files less than f.cxx in length - if(file.size() > 4) - { - // Remove the extension - std::string::size_type dotpos = file.rfind("."); - file = file.substr(0, dotpos); - std::string fullname = templateDirectory; - fullname += "/"; - fullname += file; - // add the file as a class file so - // depends can be done - cmClassFile cmfile; - cmfile.SetName(fullname.c_str(), this->GetCurrentDirectory()); - cmfile.m_AbstractClass = false; - m_Classes.push_back(cmfile); - } - } - } - else - { - std::cerr << "Warning can not open template instance directory " - << templateDirectory.c_str() << std::endl; - } + this->ReadMakefile(listsFile.c_str(), true); + } + if(m_SourceHomeDirectory == dir) + { + return; + } + + std::string dotdotDir = dir; + std::string::size_type pos = dotdotDir.rfind('/'); + if(pos != std::string::npos) + { + dotdotDir = dotdotDir.substr(0, pos); + this->ParseDirectory(dotdotDir.c_str()); } } +// expance CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the +// include and library directories. + +void cmMakefile::ExpandVaribles() +{ + // Now replace varibles + std::vector<std::string>::iterator j, begin, end; + begin = m_IncludeDirectories.begin(); + end = m_IncludeDirectories.end(); + for(j = begin; j != end; ++j) + { + cmSystemTools::ReplaceString(*j, "${CMAKE_BINARY_DIR}", + this->GetOutputHomeDirectory() ); + cmSystemTools::ReplaceString(*j, "${CMAKE_SOURCE_DIR}", + this->GetHomeDirectory() ); + } + begin = m_LinkDirectories.begin(); + end = m_LinkDirectories.end(); + for(j = begin; j != end; ++j) + { + cmSystemTools::ReplaceString(*j, "${CMAKE_BINARY_DIR}", + this->GetOutputHomeDirectory() ); + cmSystemTools::ReplaceString(*j, "${CMAKE_SOURCE_DIR}", + this->GetHomeDirectory() ); + } +} + +const char* cmMakefile::GetDefinition(const char* name) +{ + DefinitionMap::iterator pos = m_Definitions.find(name); + if(pos != m_Definitions.end()) + { + return (*pos).second.c_str(); + } + return 0; +} |