From 516cdec4894096305f5002b922ba02d49cb3e816 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 2 Oct 2009 09:28:00 +0000 Subject: Optimised auto dependency generation Added control c handler in windows Now throw string exceptions instead of integer exceptions. --- tools/mhmake/src/build.cpp | 34 ++++++++++------ tools/mhmake/src/curdir.cpp | 3 +- tools/mhmake/src/fileinfo.cpp | 18 +++++---- tools/mhmake/src/fileinfo.h | 16 ++++++-- tools/mhmake/src/functions.cpp | 27 +++++-------- tools/mhmake/src/mhmake.cpp | 16 +++++++- tools/mhmake/src/mhmakefileparser.cpp | 74 ++++++++++++++++++++--------------- tools/mhmake/src/mhmakefileparser.h | 9 ++++- tools/mhmake/src/mhmakelexer.l | 30 +++++--------- tools/mhmake/src/mhmakeparser.y | 3 +- tools/mhmake/src/rule.cpp | 32 ++++++++------- tools/mhmake/src/stdafx.h | 1 + tools/mhmake/src/util.cpp | 16 +++----- tools/mhmake/src/util.h | 2 +- 14 files changed, 152 insertions(+), 129 deletions(-) (limited to 'tools/mhmake/src') diff --git a/tools/mhmake/src/build.cpp b/tools/mhmake/src/build.cpp index 97366d88a..3d31b4605 100644 --- a/tools/mhmake/src/build.cpp +++ b/tools/mhmake/src/build.cpp @@ -287,8 +287,7 @@ found: int CommandLen=FullCommand.size(); if (CommandLen>Len-1) { - cerr << "Fatal error: Command to long: "< > Autodeps; + deps_t Autodeps; GetAutoDeps(pPyFile, Autodeps); - set< refptr >::iterator It=Autodeps.begin(); + deps_t::iterator It=Autodeps.begin(); while (It!=Autodeps.end()) { if (pExeFile->GetDate().IsOlder((*It)->GetDate())) @@ -1063,9 +1062,11 @@ bool OsExeCommand(const string &Command,const string &Params,bool IgnoreError,st if (!CreateProcess(NULL,pFullCommand,NULL,NULL,TRUE,CREATE_NO_WINDOW,NULL,curdir::GetCurDir()->GetFullFileName().c_str(),&StartupInfo,&ProcessInfo)) { delete[] pFullCommand; - cerr << "Error starting command: "<GetFullFileName().c_str(),&StartupInfo,&ProcessInfo)) { delete[] pFullCommand; - cerr << "Error starting command: "< &Target,bool bChe static int Indent; #endif + if (g_StopCompiling) + { + throw string("Compilation Interrupted by user."); + } + if (Target->IsBuild()) { #ifdef _DEBUG @@ -1646,11 +1654,11 @@ mh_time_t mhmakefileparser::BuildTarget(const refptr &Target,bool bChe #endif if (!pMakefile->ExecuteCommand(Command)) { - cerr << "Error running command: "<GetQuotedFullFileName()<GetQuotedFullFileName(); Target->SetCommandsMd5_32(0); /* Clear the md5 to make sure that the target is rebuild the next time mhmake is ran */ m_AutoDepsDirty=true; /* We need to update the autodeps file if the md5 has been changed */ - throw(1); + throw ErrorMessage; } } CommandIt++; diff --git a/tools/mhmake/src/curdir.cpp b/tools/mhmake/src/curdir.cpp index 68cf505e7..64389c993 100644 --- a/tools/mhmake/src/curdir.cpp +++ b/tools/mhmake/src/curdir.cpp @@ -52,8 +52,7 @@ void curdir::ChangeCurDir(const refptr&NewDir) #endif if (-1==chdir(NewDir->GetFullFileName().c_str())) { - cerr<<"Error changing to directory "<GetQuotedFullFileName()<GetQuotedFullFileName(); } m_pCurrentDir=NewDir; } diff --git a/tools/mhmake/src/fileinfo.cpp b/tools/mhmake/src/fileinfo.cpp index b79d51678..6ea9c158e 100644 --- a/tools/mhmake/src/fileinfo.cpp +++ b/tools/mhmake/src/fileinfo.cpp @@ -174,12 +174,12 @@ string fileinfo::GetPrerequisits() const // Build a string with all prerequisits, but make sure that every dependency // is only in there once (we do this be building a set in parallel vector< refptr >::const_iterator DepIt=m_Deps.begin(); - set< refptr > Deps; + deps_t Deps; bool first=true; string Ret=g_EmptyString; while (DepIt!=m_Deps.end()) { - set< refptr >::iterator pFound=Deps.find(*DepIt); + deps_t::iterator pFound=Deps.find(*DepIt); if (pFound==Deps.end()) { if (first) @@ -228,24 +228,26 @@ bool fileinfo::IsAutoDepExtention(void) const #ifdef _DEBUG /////////////////////////////////////////////////////////////////////////////// -void fileinfo::DumpErrorMessageDuplicateRule(const refptr&pRule) +string fileinfo::GetErrorMessageDuplicateRule(const refptr&pRule) { - cerr << GetQuotedFullFileName() << ": rule is defined multiple times\n"; - cerr << "First ("<GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<<") :\n"; + string Ret; + Ret = GetQuotedFullFileName() + ": rule is defined multiple times\n"; + Ret += "First (" + m_pRule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName() + ") :\n"; vector::const_iterator It=m_pRule->GetCommands().begin(); while (It!=m_pRule->GetCommands().end()) { - cerr << " " << m_pRule->GetMakefile()->ExpandExpression(*It) << endl; + Ret+= " " + m_pRule->GetMakefile()->ExpandExpression(*It) + "\n"; It++; } - cerr << "Second ("<GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<<") :\n"; + Ret += "Second (" + pRule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName() + ") :\n"; It=pRule->GetCommands().begin(); while (It!=pRule->GetCommands().end()) { - cerr << " " << pRule->GetMakefile()->ExpandExpression(*It) << endl; + Ret += " " + pRule->GetMakefile()->ExpandExpression(*It) +"\n"; It++; } + return Ret; } #endif diff --git a/tools/mhmake/src/fileinfo.h b/tools/mhmake/src/fileinfo.h index 227ba5e1f..a6606b294 100644 --- a/tools/mhmake/src/fileinfo.h +++ b/tools/mhmake/src/fileinfo.h @@ -49,6 +49,7 @@ extern bool g_CheckCircularDeps; extern bool g_ForceAutoDepRescan; extern bool g_PrintLexYacc; extern bool g_Clean; +extern bool g_StopCompiling; extern bool g_PrintMultipleDefinedRules; extern const string g_EmptyString; @@ -58,6 +59,14 @@ extern const string g_QuoteString; string QuoteFileName(const string &Filename); string UnquoteFileName(const string &Filename); +template +inline string stringify(const T& x) +{ + ostringstream o; + o << x; + return o.str(); +} + #define TIMESAFETY 3 class mh_time { @@ -196,7 +205,7 @@ public: string GetName() const; bool IsDir() const; - void DumpErrorMessageDuplicateRule(const refptr &pRule); + string GetErrorMessageDuplicateRule(const refptr &pRule); void SetRule(refptr &pRule) { @@ -222,12 +231,11 @@ public: { if (*m_pRule!=*pRule) { - DumpErrorMessageDuplicateRule(pRule); - throw(1); + throw(GetErrorMessageDuplicateRule(pRule)); } else if (g_PrintMultipleDefinedRules) { - DumpErrorMessageDuplicateRule(pRule); + cerr<second; @@ -205,8 +202,7 @@ string mhmakefileparser::f_subst(const string & Arg) const pTmp=NextCharItem(pTmp,FromString,','); #ifdef _DEBUG if (!*pTmp) { - cerr << "Wrong number of arguments in function subst" << endl; - throw(1); + throw string("Wrong number of arguments in function subst"); } #endif @@ -242,8 +238,7 @@ string mhmakefileparser::f_patsubst(const string & Arg) const pTmp=NextCharItem(pTmp,FromString,','); #ifdef _DEBUG if (!*pTmp) { - cerr << "Wrong number of arguments in function subst" << endl; - throw(1); + throw string("Wrong number of arguments in function subst"); } #endif @@ -408,8 +403,7 @@ string mhmakefileparser::f_filesindirs(const string & Arg) const pTmp=NextCharItem(pTmp,strFiles,','); #ifdef _DEBUG if (!*pTmp) { - cerr << "Wrong number of arguments in function filesindirs" << endl; - throw(1); + throw string("Wrong number of arguments in function filesindirs"); } #endif string strDirs; @@ -541,8 +535,7 @@ string mhmakefileparser::f_addprefix(const string & Arg) const pTmp=NextCharItem(pTmp,PreFix,','); #ifdef _DEBUG if (!*pTmp) { - cerr << "Wrong number of arguments in function addprefix" << endl; - throw(1); + throw ("Wrong number of arguments in function addprefix"); } #endif string FileNames; @@ -564,8 +557,7 @@ string mhmakefileparser::f_addsuffix(const string & Arg) const pTmp=NextCharItem(pTmp,SufFix,','); #ifdef _DEBUG if (!*pTmp) { - cerr << "Wrong number of arguments in function addsuffix" << endl; - throw(1); + throw string("Wrong number of arguments in function addsuffix"); } #endif string FileNames; @@ -588,8 +580,7 @@ string mhmakefileparser::f_word(const string & Arg) const if (!WordNbr) { if (!WordNbr) { - cerr << "Expecting a number bigger then 0 for the word function"<*pFunc)(Arg); @@ -278,8 +277,7 @@ string mhmakefileparser::ExpandMacro(const string &Expr) const else { #ifdef _DEBUG - cerr << "Fatal error in ExpandMacro (bug in mhmake ? ? ?)"; - throw 1; + throw string("Fatal error in ExpandMacro (bug in mhmake ? ? ?)"); #else return g_EmptyString; #endif @@ -382,8 +380,7 @@ void mhmakefileparser::ParseBuildedIncludeFiles() int result=ParseFile(GetFileInfo(*It)); if (result) { - fprintf(stderr,"Error parsing %s\n",It->c_str()); - throw(1); + throw string("Error parsing ")+*It; } It++; } @@ -461,7 +458,7 @@ void mhmakefileparser::AddRule() } /////////////////////////////////////////////////////////////////////////////// -void mhmakefileparser::GetAutoDeps(const refptr &FirstDep,set< refptr > &Autodeps) +void mhmakefileparser::GetAutoDeps(const refptr &FirstDep, deps_t &Autodeps) { /* Here we have to scan only c/c++ headers so skip certain extensions */ const char *pFullName=FirstDep->GetFullFileName().c_str(); @@ -553,11 +550,11 @@ void mhmakefileparser::GetAutoDeps(const refptr &FirstDep,set< refptr< /* Add the dependency when the file alrady exist or there is a rule available to be build */ if (BuildTarget(pInclude).DoesExist()) // Try to build the target, and add it if it exists after building { - set< refptr >::iterator pFind=Autodeps.find(pInclude); + deps_t::const_iterator pFind=Autodeps.find(pInclude); if (pFind==Autodeps.end()) { Autodeps.insert(pInclude); - GetAutoDeps(pInclude,Autodeps); + GetAutoDepsIfNeeded(pInclude,pInclude); } } } @@ -568,11 +565,11 @@ void mhmakefileparser::GetAutoDeps(const refptr &FirstDep,set< refptr< refptr pInclude=GetFileInfo(IncludeFile,*It); if (BuildTarget(pInclude).DoesExist()) // Try to build the target, and add it if it exists after building { - set< refptr >::iterator pFind=Autodeps.find(pInclude); + deps_t::const_iterator pFind=Autodeps.find(pInclude); if (pFind==Autodeps.end()) { Autodeps.insert(pInclude); - GetAutoDeps(pInclude,Autodeps); + GetAutoDepsIfNeeded(pInclude,pInclude); } break; } @@ -591,6 +588,28 @@ void mhmakefileparser::GetAutoDeps(const refptr &FirstDep,set< refptr< } /////////////////////////////////////////////////////////////////////////////// + +void mhmakefileparser::GetAutoDepsIfNeeded(const refptr &Target, const refptr&FirstDep) +{ + autodeps_entry_t &Autodeps=m_AutoDeps[Target]; + if (!Autodeps.first) + { + Autodeps.first=true; + /* We are going to rescan, so throw away the old. */ + Autodeps.second.clear(); + GetAutoDeps(FirstDep,Autodeps.second); + // Now add these dependencies also to the rules + deps_t::iterator It=Autodeps.second.begin(); + while (It!=Autodeps.second.end()) + { + Target->AddDep(*It); + It++; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + void mhmakefileparser::UpdateAutomaticDependencies(const refptr &Target) { m_AutoDepsDirty=true; /* Always assume dirty since in the autodeps file, the md5 strings are also saved. */ @@ -601,17 +620,7 @@ void mhmakefileparser::UpdateAutomaticDependencies(const refptr &Targe if (!Deps.size()) return; // There is no first dep refptr FirstDep=Deps[0]; - - set< refptr > &Autodeps=m_AutoDeps[Target]; - Autodeps.clear(); // We are going to scan again, so clear the list - GetAutoDeps(FirstDep,Autodeps); - // Now add these dependencies also to the rules - set< refptr >::iterator It=Autodeps.begin(); - while (It!=Autodeps.end()) - { - Target->AddDep(*It); - It++; - } + GetAutoDepsIfNeeded(Target,FirstDep); } } @@ -688,14 +697,14 @@ void mhmakefileparser::LoadAutoDepsFile(refptr &DepFile) while (FileName[0]) { refptr Target=GetFileInfo(FileName); - set< refptr > &Autodeps=m_AutoDeps[Target]; + autodeps_entry_t &Autodeps=m_AutoDeps[Target]; ReadStr(pIn,FileName); while (FileName[0]) { if (!g_ForceAutoDepRescan) /* If we are forcing the autodepscan we do not have to load the dependencies. */ { refptr Dep=GetFileInfo(FileName); - Autodeps.insert(Dep); + Autodeps.second.insert(Dep); Target->AddDep(Dep); } ReadStr(pIn,FileName); @@ -783,17 +792,20 @@ void mhmakefileparser::SaveAutoDepsFile() fwrite(&Md5_32,sizeof(Md5_32),1,pOut); fprintf(pOut,"%s\n",m_Variables[USED_ENVVARS].c_str()); - map< refptr, set< refptr > >::const_iterator It=m_AutoDeps.begin(); + autodeps_t::const_iterator It=m_AutoDeps.begin(); while (It!=m_AutoDeps.end()) { - fprintf(pOut,"%s\n",It->first->GetFullFileName().c_str()); - set< refptr >::const_iterator DepIt=It->second.begin(); - while (DepIt!=It->second.end()) + if (!It->second.second.empty()) { - fprintf(pOut,"%s\n",(*DepIt)->GetFullFileName().c_str()); - DepIt++; + fprintf(pOut,"%s\n",It->first->GetFullFileName().c_str()); + deps_t::const_iterator DepIt=It->second.second.begin(); + while (DepIt!=It->second.second.end()) + { + fprintf(pOut,"%s\n",(*DepIt)->GetFullFileName().c_str()); + DepIt++; + } + fprintf(pOut,"\n"); } - fprintf(pOut,"\n"); It++; } /* Now save the Md5 strings */ diff --git a/tools/mhmake/src/mhmakefileparser.h b/tools/mhmake/src/mhmakefileparser.h index 84d69a878..e5c435cec 100644 --- a/tools/mhmake/src/mhmakefileparser.h +++ b/tools/mhmake/src/mhmakefileparser.h @@ -47,6 +47,10 @@ class fileinfoarray : public refbase,public vector > { }; +typedef set< refptr > deps_t; +typedef pair< bool, deps_t > autodeps_entry_t; +typedef map< refptr, autodeps_entry_t > autodeps_t; + class mhmakefileparser : public refbase { @@ -77,7 +81,7 @@ protected: fileinfoarray m_IncludedMakefiles; refptr< fileinfoarray > m_pIncludeDirs; string m_IncludeDirs; - map< refptr, set< refptr > > m_AutoDeps; + autodeps_t m_AutoDeps; set< const fileinfo* , less_fileinfo > m_Targets; // List of targets that are build by this makefile bool m_DoubleColonRule; bool m_AutoDepsDirty; @@ -153,9 +157,10 @@ public: { m_RuleThatIsBuild=NULL; } + void GetAutoDepsIfNeeded(const refptr &Target, const refptr&FirstDep); void UpdateAutomaticDependencies(const refptr &Target); const refptr GetIncludeDirs() const; - void GetAutoDeps(const refptr &FirstDep,set< refptr > &Autodeps); + void GetAutoDeps(const refptr &FirstDep, deps_t &Autodeps); void SaveAutoDepsFile(); void LoadAutoDepsFile(refptr &DepFile); bool SkipHeaderFile(const string &FileName); diff --git a/tools/mhmake/src/mhmakelexer.l b/tools/mhmake/src/mhmakelexer.l index b9484159a..0b25d4c74 100644 --- a/tools/mhmake/src/mhmakelexer.l +++ b/tools/mhmake/src/mhmakelexer.l @@ -47,8 +47,7 @@ static void SaveMakMd5(refptr &Target) FILE *pFile=fopen(FileName.c_str(),"wb"); if (!pFile) { - cout << "Error creating file "<WriteMd5_32(pFile); fclose(pFile); @@ -189,8 +188,7 @@ load_makefile { pTmp=NextCharItem(pTmp,Item,';'); if (Item.empty()) { - cerr << m_InputFileName << "("<AddMakefileToMakefilesToLoad(Item); } @@ -319,8 +317,7 @@ load_makefile { } else { - cerr << "Unexpected endif at line "<ExpandExpression((const char*)yytext)<ExpandExpression((const char*)yytext); } else { yymore(); } @@ -876,22 +869,19 @@ export { } <> { - cerr << "Missing endif or else statement. #else or #endif used?\n"; - throw(1); + throw string("Missing endif or else statement. #else or #endif used?"); } <> { if (m_BraceIndent) { - cerr << "Missing closing ) of macro usage in "< > >&Im bool bCommandsDifferent=OldCommands.size()!=NewCommands.size(); if (g_PrintMultipleDefinedRules || bCommandsDifferent) { + string ErrorMessage; if (bCommandsDifferent) - cerr << "Implicit Rule '"<< DepName << "' defined twice with different commands\n"; + ErrorMessage += "Implicit Rule '"+ DepName + "' defined twice with different commands\n"; else - cerr << "Implicit Rule '"<< DepName << "' defined twice with same commands\n"; - cerr << "Command 1: makedir = " << SecIt->second->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<< endl; + ErrorMessage += "Implicit Rule '"+ DepName + "' defined twice with same commands\n"; + ErrorMessage += "Command 1: makedir = " + SecIt->second->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()+ "\n"; vector::const_iterator It; if (bCommandsDifferent) @@ -61,19 +62,21 @@ static bool FindDep(const string &DepName,vector > >&Im It=OldCommands.begin(); while (It!=OldCommands.end()) { - cerr << " " << *It << endl; + ErrorMessage += " " + *It + "\n"; } } - cerr << "Command 2: makedir = "<< Rule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<< endl; + cerr << "Command 2: makedir = "+ Rule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()+ "\n"; if (bCommandsDifferent) { It=NewCommands.begin(); while (It!=NewCommands.end()) { - cerr << " " << *It << endl; + ErrorMessage += " " + *It + "\n"; } - throw(1); + throw ErrorMessage; } + else + cerr << ErrorMessage << endl; } mhmakeparser *pOldMakefile=SecIt->second->GetMakefile(); mhmakeparser *pNewMakefile=Rule->GetMakefile(); @@ -83,12 +86,12 @@ static bool FindDep(const string &DepName,vector > >&Im { if (pOldMakefile->ExpandExpression(*OldIt)!=pNewMakefile->ExpandExpression(*NewIt)) { - cerr << "Implicit Rule '"<< DepName << "' defined twice with different commands\n"; - cerr << "Command 1: makedir = " << pOldMakefile->GetMakeDir()->GetQuotedFullFileName()<< endl; - cerr << " " << pOldMakefile->ExpandExpression(*OldIt) << endl; - cerr << "Command 2: makedir = "<< pNewMakefile->GetMakeDir()->GetQuotedFullFileName()<< endl; - cerr << " " << pNewMakefile->ExpandExpression(*NewIt) << endl; - throw(1); + string ErrorMessage = string("Implicit Rule '") + DepName + "' defined twice with different commands\n"; + ErrorMessage += "Command 1: makedir = " + pOldMakefile->GetMakeDir()->GetQuotedFullFileName()+ "\n"; + ErrorMessage += " " + pOldMakefile->ExpandExpression(*OldIt) + "\n"; + ErrorMessage += "Command 2: makedir = " + pNewMakefile->GetMakeDir()->GetQuotedFullFileName()+ "\n"; + ErrorMessage += " " + pNewMakefile->ExpandExpression(*NewIt); + throw ErrorMessage; } OldIt++; NewIt++; @@ -141,8 +144,7 @@ void IMPLICITRULE::SearchImplicitRule(const refptr &Target,vector< pai #ifdef _DEBUG if (!ResIt->second) { - cerr << "No rhs for implicit rule : "<< ImpRegExIt->first << endl; - throw(1); + throw string("No rhs for implicit rule : ") + ImpRegExIt->first; } #endif ResIt->second->SetStem(Res.m_Stem); diff --git a/tools/mhmake/src/stdafx.h b/tools/mhmake/src/stdafx.h index d7e7bf4b7..bc686e03e 100644 --- a/tools/mhmake/src/stdafx.h +++ b/tools/mhmake/src/stdafx.h @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef _MSC_VER #include diff --git a/tools/mhmake/src/util.cpp b/tools/mhmake/src/util.cpp index 608311e94..f89009206 100644 --- a/tools/mhmake/src/util.cpp +++ b/tools/mhmake/src/util.cpp @@ -406,9 +406,7 @@ loadedmakefile::loadedmakefile(vector &Args,const string&Makefile) break; #endif default: - cerr << "\nUnknown option: "<<*ArgIt<ParseFile(BeforeMakefile,true); if (result) { - printf("Error parsing %s\n",BeforeMakefile->GetQuotedFullFileName().c_str()); - throw(1); + throw string("Error parsing ")+BeforeMakefile->GetQuotedFullFileName(); } m_pParser->UpdateDate(BeforeMakefile->GetDate()); @@ -511,8 +508,7 @@ void loadedmakefile::LoadMakefile() string ObjDirName=m_pParser->ExpandExpression("$(OBJDIR)"); if (!ObjDirName.size()) { - printf("When making use of MHMAKECONF, you have to define OBJDIR in makefile.before"); - throw(1); + throw string("When making use of MHMAKECONF, you have to define OBJDIR in makefile.before"); } DepFile=GetFileInfo(ObjDirName+OSPATHSEPSTR MAKEDEPFILE); m_pParser->SetVariable(AUTODEPFILE,DepFile->GetQuotedFullFileName()); @@ -547,8 +543,7 @@ void loadedmakefile::LoadMakefile() int result=m_pParser->ParseFile(m_Makefile,true); if (result) { - printf("Error parsing %s\n",m_Makefile->GetQuotedFullFileName().c_str()); - throw(1); + throw string("Error parsing ")+m_Makefile->GetQuotedFullFileName(); } #ifdef _DEBUG /* Check if the makefile has changed the AUTODEPFILE variable, if so generate a warning that a @@ -574,8 +569,7 @@ void loadedmakefile::LoadMakefile() refptr AfterMakefile=GetFileInfo(BaseAutoMak+".after",sm_Statics.m_MhMakeConf); int result=m_pParser->ParseFile(AfterMakefile); if (result) { - printf("Error parsing %s\n",AfterMakefile->GetQuotedFullFileName().c_str()); - throw(1); + throw string("Error parsing ")+AfterMakefile->GetQuotedFullFileName(); } m_pParser->UpdateDate(AfterMakefile->GetDate()); } diff --git a/tools/mhmake/src/util.h b/tools/mhmake/src/util.h index 5cd242d51..607c1cb37 100644 --- a/tools/mhmake/src/util.h +++ b/tools/mhmake/src/util.h @@ -50,7 +50,7 @@ #define PLATFORM "linux" #endif -#define MHMAKEVER "1.4.0" +#define MHMAKEVER "1.4.1" #define MAKEDEPFILE ".makefile.dep" -- cgit v1.2.3