Generate MinGW makefile in the backend.

svn path=/branches/xmlbuildsystem/; revision=12837
This commit is contained in:
Casper Hornstrup 2005-01-05 20:59:10 +00:00
parent 222bde955c
commit 1568981925
12 changed files with 127 additions and 75 deletions

View file

@ -7,6 +7,7 @@
#include <assert.h> #include <assert.h>
#include "XML.h" #include "XML.h"
#include "rbuild.h"
using std::string; using std::string;
using std::vector; using std::vector;
@ -397,8 +398,8 @@ XMLElement::GetAttribute ( const string& attribute,
} }
if ( required ) if ( required )
{ {
printf ( "syntax error: attribute '%s' required for <%s>\n", throw RequiredAttributeNotFoundException ( attribute,
attribute.c_str(), name.c_str() ); name );
} }
return NULL; return NULL;
} }
@ -416,8 +417,8 @@ XMLElement::GetAttribute ( const string& attribute,
} }
if ( required ) if ( required )
{ {
printf ( "syntax error: attribute '%s' required for <%s>\n", throw RequiredAttributeNotFoundException ( attribute,
attribute.c_str(), name.c_str() ); name );
} }
return NULL; return NULL;
} }
@ -462,7 +463,7 @@ XMLParse(XMLFile& f,
e->attributes.push_back ( new XMLAttribute ( "top_href", top_file ) ); e->attributes.push_back ( new XMLAttribute ( "top_href", top_file ) );
XMLFile fInc; XMLFile fInc;
if ( !fInc.open ( file ) ) if ( !fInc.open ( file ) )
printf ( "xi:include error, couldn't find file '%s'\n", file.c_str() ); throw FileNotFoundException ( file );
else else
{ {
Path path2 ( path, att->value ); Path path2 ( path, att->value );

View file

@ -6,6 +6,36 @@
using std::string; using std::string;
using std::vector; using std::vector;
#ifdef WIN32
#define EXEPOSTFIX ".exe"
#define SEP "\\"
string FixSep ( const string& s )
{
string s2(s);
char* p = strchr ( &s2[0], '/' );
while ( p )
{
*p++ = '\\';
p = strchr ( p, '/' );
}
return s2;
}
#else
#define EXEPOSTFIX
#define SEP "/"
string FixSep ( const string& s )
{
string s2(s);
char* p = strchr ( &s2[0], '\\' );
while ( p )
{
*p++ = '/';
p = strchr ( p, '\\' );
}
return s2;
}
#endif
MingwBackend::MingwBackend ( Project& project ) MingwBackend::MingwBackend ( Project& project )
: Backend ( project ) : Backend ( project )
{ {
@ -13,18 +43,54 @@ MingwBackend::MingwBackend ( Project& project )
void MingwBackend::Process () void MingwBackend::Process ()
{ {
CreateMakefile ();
GenerateHeader ();
GenerateAllTarget ();
for ( size_t i = 0; i < ProjectNode.modules.size (); i++ ) for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
{ {
Module& module = *ProjectNode.modules[i]; Module& module = *ProjectNode.modules[i];
ProcessModule ( module ); ProcessModule ( module );
} }
CloseMakefile ();
}
void MingwBackend::CreateMakefile ()
{
fMakefile = fopen ( ProjectNode.makefile.c_str (), "w" );
if ( !fMakefile )
throw AccessDeniedException ( ProjectNode.makefile );
}
void MingwBackend::CloseMakefile ()
{
if (fMakefile)
fclose ( fMakefile );
}
void MingwBackend::GenerateHeader ()
{
fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
}
void MingwBackend::GenerateAllTarget ()
{
fprintf ( fMakefile, "all: " );
for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
{
Module& module = *ProjectNode.modules[i];
fprintf ( fMakefile,
" %s" SEP "%s" EXEPOSTFIX,
FixSep(module.path).c_str (),
module.name.c_str () );
}
fprintf ( fMakefile, "\n\n" );
} }
void MingwBackend::ProcessModule ( Module& module ) void MingwBackend::ProcessModule ( Module& module )
{ {
MingwModuleHandlerList moduleHandlers; MingwModuleHandlerList moduleHandlers;
GetModuleHandlers ( moduleHandlers ); GetModuleHandlers ( moduleHandlers );
for (size_t i = 0; i < moduleHandlers.size(); i++) for (size_t i = 0; i < moduleHandlers.size (); i++)
{ {
MingwModuleHandler& moduleHandler = *moduleHandlers[i]; MingwModuleHandler& moduleHandler = *moduleHandlers[i];
if (moduleHandler.CanHandleModule ( module ) ) if (moduleHandler.CanHandleModule ( module ) )

View file

@ -25,6 +25,11 @@ public:
private: private:
void ProcessModule ( Module& module ); void ProcessModule ( Module& module );
void GetModuleHandlers ( MingwModuleHandlerList& moduleHandlers ); void GetModuleHandlers ( MingwModuleHandlerList& moduleHandlers );
void CreateMakefile ();
void CloseMakefile ();
void GenerateHeader ();
void GenerateAllTarget ();
FILE* fMakefile;
}; };
#endif /* MINGW_H */ #endif /* MINGW_H */

View file

@ -40,6 +40,13 @@ FileNotFoundException::FileNotFoundException(const string& filename)
} }
AccessDeniedException::AccessDeniedException(const string& filename)
: Exception ( "Access denied to file '%s'.", filename.c_str() )
{
Filename = filename;
}
InvalidBuildFileException::InvalidBuildFileException(const char* message, InvalidBuildFileException::InvalidBuildFileException(const char* message,
...) ...)
{ {
@ -48,3 +55,13 @@ InvalidBuildFileException::InvalidBuildFileException(const char* message,
SetMessage(message, args); SetMessage(message, args);
va_end(args); va_end(args);
} }
RequiredAttributeNotFoundException::RequiredAttributeNotFoundException(const std::string& attributeName,
const std::string& elementName)
: InvalidBuildFileException ( "Required attribute '%s' not found on '%s'.",
attributeName.c_str (),
elementName.c_str ())
{
}

View file

@ -25,6 +25,14 @@ public:
}; };
class AccessDeniedException : public Exception
{
public:
AccessDeniedException(const std::string& filename);
std::string Filename;
};
class InvalidBuildFileException : public Exception class InvalidBuildFileException : public Exception
{ {
public: public:
@ -32,4 +40,12 @@ public:
...); ...);
}; };
class RequiredAttributeNotFoundException : public InvalidBuildFileException
{
public:
RequiredAttributeNotFoundException(const std::string& attributeName,
const std::string& elementName);
};
#endif /* __EXCEPTION_H */ #endif /* __EXCEPTION_H */

View file

@ -6,36 +6,6 @@
using std::string; using std::string;
using std::vector; using std::vector;
#ifdef WIN32
#define EXEPOSTFIX ".exe"
#define SEP "\\"
string FixSep ( const string& s )
{
string s2(s);
char* p = strchr ( &s2[0], '/' );
while ( p )
{
*p++ = '\\';
p = strchr ( p, '/' );
}
return s2;
}
#else
#define EXEPOSTFIX
#define SEP "/"
string FixSep ( const string& s )
{
string s2(s);
char* p = strchr ( &s2[0], '\\' );
while ( p )
{
*p++ = '/';
p = strchr ( p, '\\' );
}
return s2;
}
#endif
Project::Project() Project::Project()
{ {
} }
@ -83,6 +53,9 @@ Project::ProcessXML ( const XMLElement& e, const string& path )
name = "Unnamed"; name = "Unnamed";
else else
name = att->value; name = att->value;
att = e.GetAttribute ( "makefile", true );
makefile = att->value;
} }
else if ( e.name == "module" ) else if ( e.name == "module" )
{ {
@ -105,32 +78,3 @@ Project::ProcessXML ( const XMLElement& e, const string& path )
for ( size_t i = 0; i < e.subElements.size (); i++ ) for ( size_t i = 0; i < e.subElements.size (); i++ )
ProcessXML ( *e.subElements[i], subpath ); ProcessXML ( *e.subElements[i], subpath );
} }
bool
Project::GenerateOutput()
{
const XMLAttribute* att;
size_t i;
att = head->GetAttribute ( "makefile", true );
if ( !att )
return false;
FILE* f = fopen ( att->value.c_str(), "w" );
if ( !f )
{
throw Exception ( "Unable to open '%s' for output", att->value.c_str() );
return false;
}
fprintf ( f, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
// generate module list:
fprintf ( f, "all: " );
for ( i = 0; i < modules.size(); i++ )
{
Module& m = *modules[i];
fprintf ( f, " %s" SEP "%s" EXEPOSTFIX, FixSep(m.path).c_str(), m.name.c_str() );
}
fprintf ( f, "\n\n" );
return true;
}

View file

@ -20,9 +20,10 @@ main ( int argc, char** argv )
try try
{ {
string projectFilename ( "ReactOS.xml" ); string projectFilename ( "ReactOS.xml" );
Project project = Project ( projectFilename ); Project project ( projectFilename );
Backend* backend = new MingwBackend ( project ); Backend* backend = new MingwBackend ( project );
backend->Process (); backend->Process ();
delete backend;
// REM TODO FIXME actually do something with Project object... // REM TODO FIXME actually do something with Project object...
#if 0 #if 0

View file

@ -15,6 +15,7 @@ class Project
{ {
public: public:
std::string name; std::string name;
std::string makefile;
std::vector<Module*> modules; std::vector<Module*> modules;
Project (); Project ();
@ -22,13 +23,13 @@ public:
~Project (); ~Project ();
void ProcessXML ( const XMLElement& e, void ProcessXML ( const XMLElement& e,
const std::string& path ); const std::string& path );
bool GenerateOutput();
private: private:
void ReadXml (); void ReadXml ();
XMLFile xmlfile; XMLFile xmlfile;
XMLElement* head; XMLElement* head;
}; };
class Module class Module
{ {
public: public:
@ -46,6 +47,7 @@ public:
void ProcessXML ( const XMLElement& e, const std::string& path ); void ProcessXML ( const XMLElement& e, const std::string& path );
}; };
class File class File
{ {
public: public:

View file

@ -1,4 +1,4 @@
<project name="Project"> <project name="Project" makefile="Makefile">
<directory name="dir1"> <directory name="dir1">
<module name="module1" type="buildtool"> <module name="module1" type="buildtool">
<file>file1.c</file> <file>file1.c</file>

View file

@ -1,4 +1,4 @@
<project name="Project"> <project name="Project" makefile="Makefile">
<directory name="dir1"> <directory name="dir1">
<module name="module1" type="buildtool"> <module name="module1" type="buildtool">
</module> </module>

View file

@ -5,15 +5,15 @@ using std::string;
void ModuleTest::Run() void ModuleTest::Run()
{ {
string projectFilename ( "tests/data/module.xml" ); string projectFilename ( "tests/data/module.xml" );
Project* project = new Project( projectFilename ); Project project ( projectFilename );
ARE_EQUAL(2, project->modules.size()); ARE_EQUAL(2, project.modules.size());
Module& module1 = *project->modules[0]; Module& module1 = *project.modules[0];
ARE_EQUAL(2, module1.files.size()); ARE_EQUAL(2, module1.files.size());
ARE_EQUAL("./dir1/file1.c", module1.files[0]->name); ARE_EQUAL("./dir1/file1.c", module1.files[0]->name);
ARE_EQUAL("./dir1/file2.c", module1.files[1]->name); ARE_EQUAL("./dir1/file2.c", module1.files[1]->name);
Module& module2 = *project->modules[1]; Module& module2 = *project.modules[1];
ARE_EQUAL(2, module2.files.size()); ARE_EQUAL(2, module2.files.size());
ARE_EQUAL("./dir2/file3.c", module2.files[0]->name); ARE_EQUAL("./dir2/file3.c", module2.files[0]->name);
ARE_EQUAL("./dir2/file4.c", module2.files[1]->name); ARE_EQUAL("./dir2/file4.c", module2.files[1]->name);

View file

@ -5,6 +5,6 @@ using std::string;
void ProjectTest::Run() void ProjectTest::Run()
{ {
string projectFilename ( "tests/data/project.xml" ); string projectFilename ( "tests/data/project.xml" );
Project* project = new Project( projectFilename ); Project project( projectFilename );
ARE_EQUAL(2, project->modules.size()); ARE_EQUAL(2, project.modules.size());
} }