Started on automatic dependencies support Modified: branches/xmlbuildsystem/reactos/tools/rbuild/XML.h Added: branches/xmlbuildsystem/reactos/tools/rbuild/automaticdependency.cpp Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.cpp Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.h Modified: branches/xmlbuildsystem/reactos/tools/rbuild/makefile Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h Modified: branches/xmlbuildsystem/reactos/tools/rbuild/test.h Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/automaticdepende ncy.xml Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1/ Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1/sour cefile1_header3.h Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1.c Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er1.h Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er2.h Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/sourcefiletest.cpp _____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/XML.h --- branches/xmlbuildsystem/reactos/tools/rbuild/XML.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/XML.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -8,6 +8,13 @@
void InitWorkingDirectory();
+#ifdef _MSC_VER +unsigned __int64 +#else +unsigned long long +#endif +filelen ( FILE* f ); + class Path { std::vectorstd::string path; _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/automaticdependency.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/automaticdependency.cpp 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/automaticdependency.cpp 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1,240 @@
+#include "pch.h" + +#ifdef WIN32 +#include <direct.h> +#include <io.h> +#else +#include <sys/stat.h> +#define _MAX_PATH 255 +#endif +#include <assert.h> + +#include "rbuild.h" + +/* Read at most this amount of bytes from each file and assume that all #includes are located within this block */ +#define MAX_BYTES_TO_READ 4096 + +using std::string; +using std::vector; +using std::map; + +SourceFile::SourceFile ( AutomaticDependency* automaticDependency, + Module& module, + const string& filename ) + : automaticDependency ( automaticDependency ), + module ( module ), + filename ( filename ) +{ +} + +void +SourceFile::Close () +{ + buf.resize ( 0 ); + p = end = NULL; +} + +void +SourceFile::Open () +{ + Close (); + FILE* f = fopen ( filename.c_str (), "rb" ); + if ( !f ) + throw FileNotFoundException ( filename ); + unsigned long len = (unsigned long) filelen ( f ); + if ( len > MAX_BYTES_TO_READ) + len = MAX_BYTES_TO_READ; + buf.resize ( len ); + fread ( &buf[0], 1, len, f ); + fclose ( f ); + p = buf.c_str (); + end = p + len; +} + +void +SourceFile::SkipWhitespace () +{ + while ( p < end && isspace ( *p )) + p++; +} + +bool +SourceFile::ReadInclude ( string& filename ) +{ + while ( p < end ) + { + if ( ( *p == '#') && ( end - p > 8 ) ) + { + if ( strncmp ( p, "#include", 8 ) == 0 ) + { + p += 8; + SkipWhitespace (); + if ( p < end && *p == '<' || *p == '"' ) + { + p++; + filename.resize ( MAX_PATH ); + int i = 0; + while ( p < end && *p != '>' && *p != '"' && *p != '\n' ) + filename[i++] = *p++; + filename.resize ( i ); + return true; + } + } + } + p++; + } + filename = ""; + return false; +} + +SourceFile* +SourceFile::ParseFile ( const string& normalizedFilename ) +{ + string extension = GetExtension ( normalizedFilename ); + if ( extension == ".c" || extension == ".C" || extension == ".h" || extension == ".H") + { + SourceFile* sourceFile = automaticDependency->RetrieveFromCacheOrParse ( module, + normalizedFilename ); + return sourceFile; + } + return NULL; +} + +void +SourceFile::Parse () +{ + Open (); + while ( p < end ) + { + string includedFilename ( "" ); + //printf ( "Parsing '%s'\n", filename.c_str () ); + + while ( ReadInclude ( includedFilename )) + { + string resolvedFilename ( "" ); + bool locatedFile = automaticDependency->LocateIncludedFile ( module, + includedFilename, + resolvedFilename ); + if ( locatedFile ) + { + SourceFile* sourceFile = ParseFile ( resolvedFilename ); + files.push_back ( sourceFile ); + } + } + p++; + } + Close (); +} + +string +SourceFile::Location () const +{ + int line = 1; + const char* end_of_line = strchr ( buf.c_str (), '\n' ); + while ( end_of_line && end_of_line < p ) + { + ++line; + end_of_line = strchr ( end_of_line + 1, '\n' ); + } + return ssprintf ( "%s(%i)", + filename.c_str (), + line ); +} + + +AutomaticDependency::AutomaticDependency ( const Project& project ) + : project ( project ) +{ +} + +AutomaticDependency::~AutomaticDependency () +{ + std::map<std::string, SourceFile*>::iterator theIterator; + for ( theIterator = sourcefile_map.begin (); theIterator != sourcefile_map.end (); theIterator++ ) + delete theIterator->second; +} + +void +AutomaticDependency::Process () +{ + for ( size_t i = 0; i < project.modules.size (); i++ ) + ProcessModule ( *project.modules[i] ); +} + +void +AutomaticDependency::ProcessModule ( Module& module ) +{ + for ( size_t i = 0; i < module.files.size (); i++ ) + ProcessFile ( module, *module.files[i] ); +} + +void +AutomaticDependency::ProcessFile ( Module& module, + const File& file ) +{ + string normalizedFilename = NormalizeFilename ( file.name ); + SourceFile sourceFile = SourceFile ( this, + module, + normalizedFilename ); + sourceFile.Parse (); +} + +bool +AutomaticDependency::LocateIncludedFile ( const string& directory, + const string& includedFilename, + string& resolvedFilename ) +{ + string normalizedFilename = NormalizeFilename ( directory + SSEP + includedFilename ); + FILE* f = fopen ( normalizedFilename.c_str (), "rb" ); + if ( f != NULL ) + { + fclose ( f ); + resolvedFilename = normalizedFilename; + return true; + } + resolvedFilename = ""; + return false; +} + +bool +AutomaticDependency::LocateIncludedFile ( Module& module, + const string& includedFilename, + string& resolvedFilename ) +{ + for ( size_t i = 0; i < module.includes.size (); i++ ) + { + Include* include = module.includes[0]; + if ( LocateIncludedFile ( include->directory, + includedFilename, + resolvedFilename ) ) + return true; + } + + /* FIXME: Ifs */ + + resolvedFilename = ""; + return false; +} + +SourceFile* +AutomaticDependency::RetrieveFromCacheOrParse ( Module& module, + const string& filename ) +{ + SourceFile* sourceFile = sourcefile_map[filename]; + if ( sourceFile == NULL ) + { + sourceFile = new SourceFile ( this, + module, + filename ); + sourceFile->Parse (); + sourcefile_map[filename] = sourceFile; + } + return sourceFile; +} + +SourceFile* +AutomaticDependency::RetrieveFromCache ( Module& module, + const string& filename ) +{ + return sourcefile_map[filename]; +} _____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.cpp 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.cpp 2005-01-28 19:11:22 UTC (rev 13353) @@ -35,6 +35,7 @@
Module& module = *ProjectNode.modules[i]; ProcessModule ( module ); } + //GenerateAutomaticDependencies (); CloseMakefile (); }
@@ -240,6 +241,52 @@ }
void +MingwBackend::GenerateAutomaticDependencies () const +{ + AutomaticDependency automaticDependency ( ProjectNode ); + automaticDependency.Process (); + + for ( size_t mi = 0; mi < ProjectNode.modules.size (); mi++ ) + { + Module& module = *ProjectNode.modules[mi]; + for ( size_t fi = 0; fi < module.files.size (); fi++ ) + { + File& file = *module.files[fi]; + string normalizedFilename = NormalizeFilename ( file.name ); + SourceFile* sourceFile = automaticDependency.RetrieveFromCache ( module, + normalizedFilename ); + if ( sourceFile != NULL ) + { + string dependencies ( "" ); + GenerateAutomaticDependenciesForFile ( sourceFile, + dependencies ); + fprintf ( fMakefile, + "%s:: %s", + normalizedFilename.c_str (), + dependencies.c_str () ); + } + } + } +} + +void +MingwBackend::GenerateAutomaticDependenciesForFile ( SourceFile* sourceFile, + string& dependencies ) const +{ + if ( dependencies.size () > 0 ) + dependencies += " "; + dependencies += sourceFile->filename; + + for ( size_t i = 0; i < sourceFile->files.size (); i++) + { + SourceFile* childSourceFile = sourceFile->files[0]; + + GenerateAutomaticDependenciesForFile ( childSourceFile, + dependencies ); + } +} + +void MingwBackend::ProcessModule ( Module& module ) const { MingwModuleHandler* h = MingwModuleHandler::LookupHandler ( _____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.h --- branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/mingw.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -27,6 +27,9 @@
void GenerateGlobalVariables () const; bool IncludeInAllTarget ( const Module& module ) const; void GenerateAllTarget () const; + void GenerateAutomaticDependencies () const; + void GenerateAutomaticDependenciesForFile ( SourceFile* sourceFile, + std::string& dependencies ) const; FILE* fMakefile; };
_____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/makefile --- branches/xmlbuildsystem/reactos/tools/rbuild/makefile 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/makefile 2005-01-28 19:11:22 UTC (rev 13353) @@ -17,6 +17,7 @@
BASE_OBJECTS = \ $(BACKEND_BASE_OBJECTS) \ + automaticdependency.o \ compilerflag.o \ define.o \ exception.o \ @@ -37,7 +38,8 @@ tests/invoketest.o \ tests/linkerflagtest.o \ tests/moduletest.o \ - tests/projecttest.o + tests/projecttest.o \ + tests/sourcefiletest.o
TEST_OBJECTS = $(BASE_OBJECTS) $(TESTS) tests/alltests.o
_____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp 2005-01-28 19:11:22 UTC (rev 13353) @@ -30,7 +30,8 @@
{ string projectFilename ( "ReactOS.xml" ); Project project ( projectFilename ); - Backend* backend = Backend::Factory::Create ( buildtarget, project ); + Backend* backend = Backend::Factory::Create ( buildtarget, + project ); backend->Process (); delete backend;
_____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h --- branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -35,7 +35,10 @@
class CompilerFlag; class LinkerFlag; class Property; +class AutomaticDependency;
+class SourceFileTest; + class Project { std::string xmlfile; @@ -343,6 +346,58 @@ void ProcessXML(); };
+ +class SourceFile +{ +public: + SourceFile ( AutomaticDependency* automaticDependency, + Module& module, + const std::string& filename ); + SourceFile* ParseFile ( const std::string& normalizedFilename ); + void Parse (); + std::string Location () const; + std::vector<SourceFile*> files; + AutomaticDependency* automaticDependency; + Module& module; + std::string filename; +private: + void Close (); + void Open (); + void SkipWhitespace (); + bool ReadInclude ( std::string& filename ); + std::string buf; + const char *p; + const char *end; +}; + + +class AutomaticDependency +{ + friend class SourceFileTest; +public: + const Project& project; + + AutomaticDependency ( const Project& project ); + ~AutomaticDependency (); + void Process (); + bool LocateIncludedFile ( const std::string& directory, + const std::string& includedFilename, + std::string& resolvedFilename ); + bool LocateIncludedFile ( Module& module, + const std::string& includedFilename, + std::string& resolvedFilename ); + SourceFile* RetrieveFromCacheOrParse ( Module& module, + const std::string& filename ); + SourceFile* RetrieveFromCache ( Module& module, + const std::string& filename ); +private: + void ProcessModule ( Module& module ); + void ProcessFile ( Module& module, + const File& file ); + std::map<std::string, SourceFile*> sourcefile_map; +}; + + extern std::string FixSeparator ( const std::string& s );
_____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/test.h --- branches/xmlbuildsystem/reactos/tools/rbuild/test.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/test.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -96,10 +96,18 @@
void Run(); };
+ class FunctionTest : public BaseTest { public: void Run(); };
+ +class SourceFileTest : public BaseTest +{ +public: + void Run(); +}; + #endif /* __TEST_H */ _____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp 2005-01-28 19:11:22 UTC (rev 13353) @@ -177,6 +177,7 @@
tests.push_back(new LinkerFlagTest()); tests.push_back(new IfTest()); tests.push_back(new FunctionTest()); + tests.push_back(new SourceFileTest()); } };
_____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/automaticdepende ncy.xml --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/automaticdepende ncy.xml 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/automaticdepende ncy.xml 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1,11 @@
+<?xml version="1.0" ?> +<project name="Project" makefile="Makefile"> + <directory name="tests"> + <directory name="data"> + <module name="module1" type="buildtool"> + <include base="module1">.</include> + <file>sourcefile1.c</file> + </module> + </directory> + </directory> +</project> _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1/sour cefile1_header3.h --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1/sour cefile1_header3.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1/sour cefile1_header3.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1 @@
+/* empty */ _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1.c --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1.c 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1.c 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1,13 @@
+/* + * ReactOS kernel + */ +/* $Id: main.c 12694 2005-01-01 11:47:33Z hbirr $ + * FILE: ntoskrnl/ke/main.c + */ + +/* INCLUDES *****************************************************************/ + +#include <sourcefile1_header1.h> +#include <sourcefile1_header2.h> + +/* GLOBALS *******************************************************************/ _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er1.h --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er1.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er1.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1 @@
+#include <sourcefile1_header2.h> _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er2.h --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er2.h 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/sourcefile1_head er2.h 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1,2 @@
+#include <sourcefile1/sourcefile1_header3.h> +#include <sourcefile2/sourcefile1_dontexist.h> _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/sourcefiletest.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/tests/sourcefiletest.cpp 2005-01-28 18:35:21 UTC (rev 13352) +++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/sourcefiletest.cpp 2005-01-28 19:11:22 UTC (rev 13353) @@ -0,0 +1,11 @@
+#include "test.h" + +using std::string; + +void SourceFileTest::Run() +{ + const Project project ( "tests/data/automaticdependency.xml" ); + AutomaticDependency automaticDependency ( project ); + automaticDependency.Process (); + ARE_EQUAL(3, automaticDependency.sourcefile_map.size()); +}