mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:12:59 +00:00
Generate MinGW makefile in the backend.
svn path=/branches/xmlbuildsystem/; revision=12837
This commit is contained in:
parent
222bde955c
commit
1568981925
12 changed files with 127 additions and 75 deletions
|
@ -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 );
|
||||||
|
|
|
@ -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 ) )
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 ())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue