CMake/Source/cmMakefile.cxx

278 lines
6.6 KiB
C++

#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif
#include "cmMakefile.h"
#include "cmClassFile.h"
#include "cmDirectory.h"
#include <fstream>
#include <iostream>
// remove extra spaces and the "\" character from the name
// of the class as it is in the CMakeLists.txt
inline std::string CleanUpName(const char* name)
{
std::string className = name;
size_t i =0;
while(className[i] == ' ')
{
i++;
}
if(i)
{
className = className.substr(i, className.size());
}
size_t pos = className.find('\\');
if(pos != std::string::npos)
{
className = className.substr(0, pos);
}
pos = className.find(' ');
if(pos != std::string::npos)
{
className = className.substr(0, pos);
}
return className;
}
// default is not to be building executables
cmMakefile::cmMakefile()
{
m_Executables = false;
}
// call print on all the classes in the makefile
void cmMakefile::Print()
{
for(int i = 0; i < m_Classes.size(); i++)
m_Classes[i].Print();
}
// Parse the given CMakeLists.txt file into a list of classes.
bool cmMakefile::ReadMakefile(const char* filename)
{
std::cerr << "reading makefile " << filename << std::endl;
std::ifstream fin(filename);
if(!fin)
{
std::cerr << "error can not open file " << filename << std::endl;
return false;
}
char inbuffer[2048];
while ( fin.getline(inbuffer, 2047 ) )
{
std::string line = inbuffer;
cmClassFile file;
if(line.find("COMPILE_CLASSES") != std::string::npos)
{
if(line.find("\\") != std::string::npos)
{
this->ReadClasses(fin, false);
}
}
#ifdef _WIN32
else if(line.find("WIN32_CLASSES") != std::string::npos)
{
if(line.find("\\") != std::string::npos)
{
this->ReadClasses(fin, false);
}
}
#else
else if(line.find("UNIX_CLASSES") != std::string::npos)
{
if(line.find("\\") != std::string::npos)
{
this->ReadClasses(fin, false);
}
}
#endif
else if(line.find("ABSTRACT_CLASSES") != std::string::npos)
{
if(line.find("\\") != std::string::npos)
{
this->ReadClasses(fin, true);
}
}
else if(line.find("TEMPLATE_INSTANCE_DIRECTORY") != std::string::npos)
{
this->ReadTemplateInstanceDirectory(line);
}
else if(line.find("SUBDIRS") != std::string::npos)
{
if(line.find("\\") != std::string::npos)
{
this->ReadSubdirs(fin);
}
}
else if(line.find("EXECUTABLES") != 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)
{
fin.getline(inbuffer, 2047);
m_MakeVerbatim.push_back(inbuffer);
if((m_MakeVerbatim.end()-1)->find("END MAKE VERBATIM")
!= std::string::npos )
{
done = true;
*(m_MakeVerbatim.end()-1) = "# End CMakeLists VERBATIM\n\n";
}
}
}
else if(line.find("ME") != std::string::npos)
{
size_t mestart = line.find("ME");
size_t start = line.find("=");
if(start != std::string::npos && start > mestart )
{
start++;
while(line[start] == ' ' && start < line.size())
{
start++;
}
size_t end = line.size()-1;
while(line[end] == ' ' && end > start)
{
end--;
}
this->SetLibraryName(line.substr(start, end).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 = 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::ReadTemplateInstanceDirectory(std::string& line)
{
std::string::size_type start = line.find("=");
if(start != std::string::npos)
{
std::string dirname = line.substr(start+1, line.size());
dirname = CleanUpName(dirname.c_str());
std::string tdir = this->GetCurrentDirectory();
tdir += "/";
tdir += dirname;
// 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 = dirname;
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 << "Error can not open template instance directory "
<< dirname.c_str() << std::endl;
}
}
}
// Read a list of subdirectories from the stream
void cmMakefile::ReadSubdirs(std::ifstream& fin)
{
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 dir = inbuffer;
// if the line does not end in \ then we are at the
// end of the list
if(dir.find('\\') == std::string::npos)
{
done = true;
}
// remove extra spaces and \ from the class name
dir = CleanUpName(dir.c_str());
m_SubDirectories.push_back(dir);
}
}