From 6be86147f292b3178413bc644853ad80b620042e Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 19 Nov 2010 12:14:18 +0000 Subject: Reintegrate tools from trunk --- tools/mhmake/src/build.cpp | 1703 -------------------------------------------- 1 file changed, 1703 deletions(-) delete mode 100644 tools/mhmake/src/build.cpp (limited to 'tools/mhmake/src/build.cpp') diff --git a/tools/mhmake/src/build.cpp b/tools/mhmake/src/build.cpp deleted file mode 100644 index 865ac8e2c..000000000 --- a/tools/mhmake/src/build.cpp +++ /dev/null @@ -1,1703 +0,0 @@ -/* This file is part of mhmake. - * - * Copyright (C) 2001-2009 Marc Haesen - * - * Mhmake is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Mhmake is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mhmake. If not, see . -*/ - -/* $Rev$ */ - -#include "stdafx.h" - -#include "mhmakefileparser.h" -#include "mhmakeparser.h" -#include "rule.h" -#include "util.h" - -/* Calling py2exe is only implemented on windows for now. */ -#ifdef WIN32 -static const string &GetPythonExe(); - -/* Python exe create script in parts: -import zipfile,tempfile,shutil,os - -def UpdateZipFile(SrcZip,DestZip): - NewZip=tempfile.mktemp('.zip') - - Src=zipfile.ZipFile(SrcZip) - - New=zipfile.ZipFile(NewZip,'w') - - InFile={} - for name in Src.namelist(): - InFile[name]=1 - New.writestr(name,Src.read(name)) - Src.close() - - try: - Dest=zipfile.ZipFile(DestZip) - - for name in Dest.namelist(): - if not InFile.has_key(name): - New.writestr(name,Dest.read(name)) - Dest.close() - except IOError: - pass - New.close() - - shutil.move(NewZip,DestZip) - -OutFileName=tempfile.mktemp('.py') -pOut=open(OutFileName,'w') - -Script=r'' -DirScript=os.path.split(Script)[0] -pOut.write(r''' - -from distutils.core import setup -import py2exe -import sys -sys.path.append(r'%s') -setup(zipfile=None, console=[r'%s']) -'''%(DirScript,Script)) - -pOut.close() - -import os - -stdin,stdout=os.popen4(r'"" %s py2exe'%OutFileName); -stdout.read() -stdout.close() -stdin.close() - -OutDir=os.path.split(Script)[0] - -import shutil -def CopyFiles(Src,Dest): - for File in os.listdir(Src): - SrcDir=os.path.join(Src,File) - if File=='library.zip': - UpdateZipFile(os.path.join(Src,File),os.path.join(Dest,File)) - elif os.path.isdir(SrcDir): - DestDir=os.path.join(Dest,File) - os.mkdir(DestDir) - CopyFiles(SrcDir,DestDir) - else: - shutil.copy(os.path.join(Src,File),os.path.join(Dest,File)) - -if os.path.isdir('dist'): - CopyFiles('dist',OutDir) - - try: - shutil.rmtree('dist') - except: - pass - try: - shutil.rmtree('build') - except: - pass -os.remove(OutFileName) -*/ - -static const string PythonScriptPart1= -"import zipfile,tempfile,shutil,os\n" -"\n" -"def UpdateZipFile(SrcZip,DestZip):\n" -" NewZip=tempfile.mktemp('.zip')\n" -"\n" -" Src=zipfile.ZipFile(SrcZip)\n" -"\n" -" New=zipfile.ZipFile(NewZip,'w')\n" -"\n" -" InFile={}\n" -" for name in Src.namelist():\n" -" InFile[name]=1\n" -" New.writestr(name,Src.read(name))\n" -" Src.close()\n" -"\n" -" try:\n" -" Dest=zipfile.ZipFile(DestZip)\n" -"\n" -" for name in Dest.namelist():\n" -" if not InFile.has_key(name):\n" -" New.writestr(name,Dest.read(name))\n" -" Dest.close()\n" -" except IOError:\n" -" pass\n" -" New.close()\n" -"\n" -" shutil.move(NewZip,DestZip)\n" -"\n" -"OutFileName=tempfile.mktemp('.py')\n" -"pOut=open(OutFileName,'w')\n" -"\n" -"Script=r'" -; - -static const string PythonScriptPart2= -"'\n" -"DirScript=os.path.split(Script)[0]\n" -"\n" -"pOut.write(r'''\n" -"\n" -"from distutils.core import setup\n" -"import py2exe\n" -"import sys\n" -"sys.path.append(r'%s')\n" -"setup(console=[r'%s'])\n" -"'''%(DirScript,Script))\n" -"\n" -"pOut.close()\n" -"\n" -"import os\n" -"\n" -"stdin,stdout=os.popen4(r'" -; - -static const string PythonScriptPart3= -"%s py2exe'%OutFileName);\n" -"stdout.read()\n" -"stdout.close()\n" -"stdin.close()\n" -"\n" -"OutDir=os.path.split(Script)[0]\n" -"\n" -"import shutil\n" -"def CopyFiles(Src,Dest):\n" -" for File in os.listdir(Src):\n" -" SrcDir=os.path.join(Src,File)\n" -" if File=='library.zip':\n" -" UpdateZipFile(os.path.join(Src,File),os.path.join(Dest,File))\n" -" elif os.path.isdir(SrcDir):\n" -" DestDir=os.path.join(Dest,File)\n" -" os.mkdir(DestDir)\n" -" CopyFiles(SrcDir,DestDir)\n" -" else:\n" -" shutil.copy(os.path.join(Src,File),os.path.join(Dest,File))\n" -"\n" -"if os.path.isdir('dist'):\n" -" CopyFiles('dist',OutDir)\n" -"\n" -" try:\n" -" shutil.rmtree('dist')\n" -" except:\n" -" pass\n" -" try:\n" -" shutil.rmtree('build')\n" -" except:\n" -" pass\n" -"os.remove(OutFileName)\n" -; -/*****************************************************************************/ -/* Converts a python script to an executable if py2exe is installed */ - -void mhmakefileparser::CreatePythonExe(const string &FullCommand) -{ - /* First create a python script to run */ - cout << "Converting "< >::iterator It; - vector< refptr >::iterator ItEnd; - - refptr CommandFile=GetFileInfo(Command); - if (CommandFile->Exists()) - { - goto found; - } - static vector< refptr > vSearchPath; - if (!vSearchPath.size()) - { - char Path[1024]; - char *pPath=getenv(PATH); - if (!pPath) - return 0; - strcpy(Path,pPath); // To be able to use strtok - char *pTok=strtok(Path,OSPATHENVSEPSTR); - while (pTok) - { - vSearchPath.push_back(GetFileInfo(pTok)); - pTok=strtok(NULL,OSPATHENVSEPSTR); - } - } - It=vSearchPath.begin(); - ItEnd=vSearchPath.end(); - while (It!=ItEnd) - { - CommandFile=GetFileInfo(Command,*It); - if (CommandFile->Exists()) - goto found; - It++; - } - - return 0; - -found: - string FullCommand=CommandFile->GetFullFileName(); - int CommandLen=FullCommand.size(); - if (CommandLen>Len-1) - { - cerr << "Fatal error: Command to long: "< > Files; - - // First check if the first parameter is -e meaning don't give an error when file does not exist - if (Params[1]=='-') - { - if (Params[2]=='e') - { - IgnoreError=true; - SplitToItems(Params.substr(4),Files); - } - else - { - cerr << "Invalid option "< >::const_iterator It=Files.begin(); - while (It!=Files.end()) - { - refptr pFile=*It++; - string DirSearch="*"; - bool bRemoveDir=true; - - /* Now check if there is a wildcard */ - if (pFile->GetFullFileName().find('*')!=string::npos) - { - DirSearch=pFile->GetName(); - pFile=pFile->GetDir(); - bRemoveDir=false; - } - - pFile->InvalidateDate(); - if (IgnoreError && !pFile->Exists() && !pFile->IsDir()) - { - continue; - } - - const string &FileName=pFile->GetFullFileName(); - if (pFile->IsDir()) - { - if (DeleteDir(FileName,DirSearch,bRemoveDir) && !IgnoreError) - { - cerr << "Error deleting "< pSrc, refptr pDest) -{ - if (pDest->IsDir()) - { - pDest=GetFileInfo(pSrc->GetName(),pDest); - } - string SrcFileName=pSrc->GetFullFileName(); - string DestFileName=pDest->GetFullFileName(); - - /* Now copy the file */ - FILE *pSrcFile=fopen(SrcFileName.c_str(),"rb"); - if (!pSrcFile) - { - cerr << "copy: error opening file "< 0) - { - fwrite(Buf,1,Ret,pDestFile); - } - fclose(pSrcFile); - fclose(pDestFile); - pDest->InvalidateDate(); - return true; -} - -/*****************************************************************************/ -/* Copies a complete directory to a destination (currenlty not recursive */ -static bool CopyDir(refptr pDir,refptr pDest,const string WildSearch="*") -{ - bool Error=true; - string Dir=pDir->GetFullFileName()+OSPATHSEP; - string Pattern=Dir+WildSearch; -#ifdef WIN32 - WIN32_FIND_DATA FindData; - HANDLE hFind=FindFirstFile(Pattern.c_str(),&FindData); - if (hFind==INVALID_HANDLE_VALUE) - { - return Error; - } - - do - { - /* Only handle items which are not . and .. */ - if (FindData.cFileName[0]!='.' || (FindData.cFileName[1] && (FindData.cFileName[1]!='.' || FindData.cFileName[2])) ) - { - string FileName=Dir+FindData.cFileName; - refptr pSrc=GetFileInfo(FileName); - - if (pSrc->IsDir()) - { - /* Currently we do not do a recursion */ - } - else - { - Error = CopyFile(pSrc,pDest); - } - } - } while (FindNextFile(hFind,&FindData)); - - FindClose(hFind); -#else - glob_t Res; - if (glob (Pattern.c_str(), GLOB_ERR|GLOB_NOSORT|GLOB_MARK, NULL, &Res)) - return Error; - - for (int i=0; i character - int Pos=Params.find_first_of('>'); - if (Pos==string::npos) - { - // Just echo it - cout << Params << endl; - } - else - { - FILE *pfFile; - /* Extra the filename */ - string Filename; - if (Params[Pos+1]=='>') - { - NextItem(Params.substr(Pos+2).c_str(),Filename); - refptr pFile=GetFileInfo(Filename); - // Open file in append - pfFile=fopen(pFile->GetFullFileName().c_str(),"a"); - } - else - { - NextItem(Params.substr(Pos+1).c_str(),Filename); - refptr pFile=GetFileInfo(Filename); - pfFile=fopen(pFile->GetFullFileName().c_str(),"w"); - } - if (!pfFile) - { - cerr << "Error opening file "< > Files; - - SplitToItems(Params,Files); - - int NrSrcs=Files.size()-1; - - if (NrSrcs<1) - { - cerr << "Wrong number of arguments in copy: "< pDest=Files[NrSrcs]; - if (NrSrcs>1 && !pDest->IsDir()) - { - cerr << "copy: Destination must be a directory when more then one source : "< pSrc=Files[i]; - - string SrcFileName=pSrc->GetFullFileName(); - - if (pSrc->IsDir()) - { - SrcFileName+=OSPATHSEPSTR"*"; - pSrc=GetFileInfo(SrcFileName); - } - - //cerr << "copy "<GetFullFileName()<<" "<GetFullFileName()<GetDir(), pDest, pSrc->GetName()); - } - else - { - if (!CopyFile(pSrc,pDest)) - { - cerr << "copy: Error copying file: " << Params << endl; - return false; - } - } - } - - return true; - -} - -/*****************************************************************************/ -static bool TouchFiles(const string &Params) -{ - vector< refptr > Files; - - SplitToItems(Params,Files); - - vector< refptr >::const_iterator It=Files.begin(); - while (It!=Files.end()) - { - refptr pFile=*It++; - const string &FileName=pFile->GetFullFileName(); - - /* Since this can be part of a list of commands for a certain rule, and it is possible that the file - * was generated by one on the previous commands, we first need the invalidate the date so that the - * existance checking is done again */ - pFile->InvalidateDate(); - - if (pFile->IsDir()) - { - cerr << "touch: Cannot touch a directory: " << FileName << endl; - return false; - } - if (pFile->Exists()) - { - int fd; - char c; - int status = 0; - struct stat st; - int Ret; - int saved_errno = 0; - - fd = open (FileName.c_str(), O_RDWR); - if (fd<0) - { - st.st_size=0; - } - else - { - if (fstat (fd, &st) < 0) - { - cerr << "touch: Cannot stat file " << FileName << endl; - return false; - } - } - - if (st.st_size == 0) - { - FILE *pFile; - if (fd>=0 && close(fd) < 0) - { - cerr << "touch: Error closing file " << FileName << endl; - return false; - } - /*Re-Create an empty file */ - pFile=fopen(FileName.c_str(),"wb"); - if (!pFile) - { - cerr << "touch: Cannot create file: " << FileName << endl; - return false; - } - fclose(pFile); - } - else - { - Ret=read (fd, &c, sizeof(c)); - if (Ret!=sizeof(c) && Ret!=EOF) - { - cerr << "touch: Cannot read file " << FileName << ": "<InvalidateDate(); - } - return true; -} - -/*****************************************************************************/ -static const string &GetPythonExe() -{ - static string PythonExe; - if (PythonExe.empty()) - { - string FullCommand=SearchCommand(PYTHONEXE); - if (!FullCommand.empty()) - { - PythonExe="\""+FullCommand+"\" "; - } - else - { - cerr<<"python executable not found in path and registry.\n"; - exit(1); - } - } - return PythonExe; -} - -/*****************************************************************************/ -static const string &GetComspec() -{ - static string Comspec; - if (Comspec.empty()) - { - const char *pComspec=getenv(COMSPEC); - if (pComspec) - { - Comspec=getenv(COMSPEC); - #ifdef WIN32 - Comspec+=" /c "; - #else - Comspec+=" -c \""; - #endif - } - else - { - #ifdef WIN32 - Comspec="cmd.exe /c "; - #else - Comspec="sh -c \""; - #endif - } - } - return Comspec; -} - -/*****************************************************************************/ -string mhmakefileparser::GetFullCommand(string Command) -{ - map::iterator pFound=m_CommandCache.find(Command); - string OriCommand=Command; - if (pFound==m_CommandCache.end()) - { - bool Found=false; - // Not found in the stack, search in the environment path - // Check if an extension is specified - const char *pBeg=Command.c_str(); - const char *pEnd=pBeg+Command.length()-1; - bool HasExt=false; - while (pEnd>pBeg && *pEnd!=OSPATHSEP) - { - if (*pEnd=='.') - { - HasExt=true; - break; - } - pEnd--; - } - if (HasExt) - { - string FullCommand=SearchCommand(Command); - if (!FullCommand.empty()) - { - Found=true; - Command=FullCommand; - } - } - else - { - static bool s_Py2ExeInstalled=true; - /* First check for special internal commands */ - if (OriCommand=="del") - { - m_CommandCache[OriCommand]="del"; - return Command; - } - // Try with different extensions - string FullCommand=SearchCommand(Command,EXEEXT); - if (!FullCommand.empty()) - { - Found=true; - #ifdef WIN32 - /* Check if a python script also exists, is so try generating the executable again. */ - string PythonFullCommand=SearchCommand(Command,".py"); - Command=FullCommand; - if (!PythonFullCommand.empty()&&s_Py2ExeInstalled) - { - refptr pExeFile=GetFileInfo(FullCommand); - refptr pPyFile=GetFileInfo(PythonFullCommand); - bool bBuild=false; - if (pExeFile->GetDate().IsOlder(pPyFile->GetDate())) - { - bBuild=true; - } - if (!bBuild) - { - set< refptr > Autodeps; - GetAutoDeps(pPyFile, Autodeps); - set< refptr >::iterator It=Autodeps.begin(); - while (It!=Autodeps.end()) - { - if (pExeFile->GetDate().IsOlder((*It)->GetDate())) - { - bBuild=true; - break; - } - It++; - } - } - if (bBuild) - { - if (pExeFile->Exists()) - remove(pExeFile->GetFullFileName().c_str()); - CreatePythonExe(PythonFullCommand); - // Invalidate the exe date since it could have been recreated by the CreatePythonExe - pExeFile->InvalidateDate(); - } - - } - #else - Command=FullCommand; - #endif - } - else - { - FullCommand=SearchCommand(Command,".py"); - if (!FullCommand.empty()) - { - Found=true; - #ifdef WIN32 - /* Now first try to create an executable for it */ - if (s_Py2ExeInstalled) - { - refptr pExeFile; - CreatePythonExe(FullCommand); - string ExeFullCommand=SearchCommand(Command,EXEEXT); - if (!ExeFullCommand.empty()) - { - pExeFile=GetFileInfo(ExeFullCommand); - pExeFile->InvalidateDate(); // The file was just generated, make sure the correct date is taken. - } - if (ExeFullCommand.empty() || !pExeFile->Exists()) - { - s_Py2ExeInstalled=false; - cout << "\nWarning: cannot convert "<second; -} - -static bool OsExeCommand(const string &Command,const string &Params,bool IgnoreError,string *pOutput) -{ -#ifdef WIN32 - STARTUPINFO StartupInfo; - memset(&StartupInfo,0,sizeof(StartupInfo)); - StartupInfo.cb=sizeof(STARTUPINFO); - PROCESS_INFORMATION ProcessInfo; - string FullCommandLine; - string ComSpec=GetComspec(); - - if (Command.substr(0,ComSpec.size())==ComSpec) - { - string tmpCommand=Command.substr(ComSpec.size(),Command.size()); - FullCommandLine=ComSpec; - if (tmpCommand.find(' ')!=string::npos) - FullCommandLine+="\""+tmpCommand+"\""+Params; - else - FullCommandLine+=tmpCommand+Params; - } - else - { - const string PythonExe=GetPythonExe(); - if (Command.find(' ')!=string::npos && - !(Command.substr(0,PythonExe.size())==PythonExe)) - FullCommandLine="\""+Command+"\""+Params; - else - FullCommandLine=Command+Params; - } - char *pFullCommand=new char[FullCommandLine.length()+1]; - strcpy(pFullCommand,FullCommandLine.c_str()); - - if (pOutput || g_Quiet) - { - HANDLE hChildStdinRd; - HANDLE hChildStdinWr; - HANDLE hChildStdoutRd; - HANDLE hChildStdoutWr; - HANDLE hChildStdinWrDup; - HANDLE hChildStdoutRdDup; - SECURITY_ATTRIBUTES saAttr; - BOOL fSuccess; - - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) - return false; - - /* Create new output read handle and the input write handle. Set - * the inheritance properties to FALSE. Otherwise, the child inherits - * the these handles; resulting in non-closeable handles to the pipes - * being created. */ - fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, - GetCurrentProcess(), &hChildStdinWrDup, 0, - FALSE, DUPLICATE_SAME_ACCESS); - if (!fSuccess) return false; - /* Close the inheritable version of ChildStdin that we're using. */ - CloseHandle(hChildStdinWr); - - if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) - return false; - - fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, - GetCurrentProcess(), &hChildStdoutRdDup, 0, - FALSE, DUPLICATE_SAME_ACCESS); - if (!fSuccess) return false; - CloseHandle(hChildStdoutRd); - - int hStdIn = _open_osfhandle((long)hChildStdinWrDup, _O_WRONLY|_O_TEXT); - FILE *pStdIn = _fdopen(hStdIn, "w"); - int hStdOut = _open_osfhandle((long)hChildStdoutRdDup, _O_RDONLY|_O_TEXT); - FILE *pStdOut = _fdopen(hStdOut, "r"); - - StartupInfo.dwFlags = STARTF_USESTDHANDLES; - StartupInfo.hStdInput = hChildStdinRd; - StartupInfo.hStdOutput = hChildStdoutWr; - StartupInfo.hStdError = hChildStdoutWr; - - if (!CreateProcess(NULL,pFullCommand,NULL,NULL,TRUE,CREATE_NO_WINDOW,NULL,curdir::GetCurDir()->GetFullFileName().c_str(),&StartupInfo,&ProcessInfo)) - { - delete[] pFullCommand; - cerr << "Error starting command: "< 0) - { - if (pOutput) - { - Buf[Nbr]=0; - *pOutput+=Buf; - } - } - WaitForSingleObject(ProcessInfo.hProcess,INFINITE); - fclose(pStdIn); - fclose(pStdOut); - } - else - { - if (!CreateProcess(NULL,pFullCommand,NULL,NULL,TRUE,0,NULL,curdir::GetCurDir()->GetFullFileName().c_str(),&StartupInfo,&ProcessInfo)) - { - delete[] pFullCommand; - cerr << "Error starting command: "< 0) - { - if (pOutput) - { - Buf[Nbr]=0; - *pOutput+=Buf; - } - } - close( pipefrom[0]); - _exit (EXIT_FAILURE); - } - else - { - /* close unused pipe end */ - close( pipefrom[0] ); - close( pipeto[1] ); - - int Status; - waitpid(ID2,&Status,0); // Wait until the reading of the output is finished - } - } - int Status; - int Ret=waitpid(ID,&Status,0); - if (Ret!=ID || Status) - { - if (IgnoreError) - { - cerr << "Error running command: "<|&",Params[i])) - { - break; - } - } - if (i==Params.size()) - { - if (Command!="del" && Command!="touch" && Command!="copy" && Command!="echo") - Command=GetFullCommand(Command);// + Params; -#ifndef WIN32 - if (Command.substr(0,GetComspec().size())==GetComspec()) - { - Params=EscapeQuotes(Params); - Params+="\""; - } -#endif - } - else - { - if (Command!="echo") - { - string FullCommand=GetFullCommand(Command); - string ComSpec=GetComspec(); - if (FullCommand.substr(0,ComSpec.size())!=ComSpec) - Command=FullCommand; // Only use FullCommand when it was found and not prepending by the comspec. - Command=ComSpec+Command; -#ifndef WIN32 - Params=EscapeQuotes(Params); - Params+="\""; -#endif - } - } - if (Echo - #ifdef _DEBUG - || g_DoNotExecute - #endif - ) - { - #ifdef _DEBUG - if (g_PrintAdditionalInfo) - cout << Command << Params << endl; - else - cout << InCommand << endl; - #endif - } - - /* first we check special internal commands */ - #ifdef _DEBUG - if (pOutput || !g_DoNotExecute) - { - #endif - if (Command=="del") - { - return DeleteFiles(Params); - } - else if (Command=="touch") - { - return TouchFiles(Params); - } - else if (Command=="copy") - { - return CopyFiles(Params); - } - else if (Command=="echo") - { - return EchoCommand(Params); - } - - return OsExeCommand(Command,Params,IgnoreError,pOutput); - #ifdef _DEBUG - } - #endif - return true; /* No Error */ -} - -/////////////////////////////////////////////////////////////////////////////// -void mhmakefileparser::BuildDependencies(const refptr &pRule, const refptr &Target, mh_time_t TargetDate, mh_time_t &YoungestDate, bool &MakeTarget) -{ - - vector< refptr > &Deps=Target->GetDeps(); - vector< refptr >::iterator pDepIt=Deps.begin(); - while (pDepIt!=Deps.end()) - { - mh_time_t DepDate=BuildTarget(*pDepIt); - if (DepDate.IsNewer(YoungestDate)) - YoungestDate=DepDate; - if (DepDate.IsNewer(TargetDate)) - { - #ifdef _DEBUG - if (pRule&&g_pPrintDependencyCheck && DepDate.IsExistingFile() && TargetDate.IsExistingFile()) - cout<<"Going to build "<GetFullFileName()<<" because "<<(*pDepIt)->GetFullFileName()<<" is more recent\n"; - #endif - MakeTarget=true; - } - pDepIt++; - } -} - -/////////////////////////////////////////////////////////////////////////////// -mh_time_t mhmakefileparser::BuildTarget(const refptr &Target,bool bCheckTargetDir) -{ - #ifdef _DEBUG - if (g_CheckCircularDeps) - { - deque< refptr >::const_iterator pFind=find(m_TargetStack.begin(),m_TargetStack.end(),Target); - if (pFind!=m_TargetStack.end()) - { - cout << "Circular dependency detected.\n"<GetFullFileName()<<" depending on itself.\n"; - cout << "Dependency stack:\n"; - deque< refptr >::const_iterator pIt=m_TargetStack.begin(); - while (pIt!=m_TargetStack.end()) - { - cout << " " << (*pIt)->GetFullFileName() << endl; - pIt++; - } - } - if (!Target->IsBuild()) m_TargetStack.push_back(Target); - } - #endif - - #ifdef _DEBUG - static int Indent; - #endif - - if (Target->IsBuild()) - { - #ifdef _DEBUG - if (g_pPrintDependencyCheck) - { - for (int i=0; iGetFullFileName()<<" : "<GetDate()<GetDate(); - } - - #ifdef _DEBUG - if (g_GenProjectTree) - cout << Target->GetFullFileName() << endl; - - Indent++; - if (g_pPrintDependencyCheck) - { - for (int i=0; iGetFullFileName()<SetBuild(); - - /* Optimisation: do not build target when target dir does not exist, - but first build the target dir, in case there exists a rule for it*/ - refptr pRule=Target->GetRule(); - - if (!pRule && bCheckTargetDir) - { - refptr TargetDir=Target->GetDir(); - mh_time_t TargetDirDate=BuildTarget(TargetDir,false); - - if (!TargetDir->Exists()) - { - #ifdef _DEBUG - Indent--; - if (g_CheckCircularDeps) - { - m_TargetStack.pop_back(); - } - #endif - return TargetDirDate; - } - } - - mh_time_t TargetDate=Target->GetDate(); - bool MakeTarget=false; - mh_time_t YoungestDate=TargetDate; - - if (!pRule || !pRule->GetCommands().size()) - { - vector< pair,refptr > > Result; - - - IMPLICITRULE::SearchImplicitRule(Target,Result); - - vector< pair,refptr > >::iterator ResultIt=Result.begin(); - while (ResultIt!=Result.end()) - { - if (ResultIt->first==NullFileInfo) - { - pRule=ResultIt->second; - Target->SetRule(pRule); - #ifdef _DEBUG - if (g_PrintAdditionalInfo) - { - cout<<"Found implicit rule for "<GetFullFileName()<PrintCommands(Target); - } - #endif - break; - } - else - { - #ifdef _DEBUG - m_ImplicitSearch++; - #endif - mh_time_t DepDate=BuildTarget(ResultIt->first); - #ifdef _DEBUG - m_ImplicitSearch--; - #endif - if (DepDate.DoesExist()) { - if (DepDate.IsNewer(YoungestDate)) - YoungestDate=DepDate; - pRule=ResultIt->second; - Target->AddMainDep(ResultIt->first); - Target->SetRule(pRule); /* This is an implicit rule so do not add the target */ - #ifdef _DEBUG - if (g_PrintAdditionalInfo) - { - cout<<"Found implicit rule for "<GetFullFileName()<<". Dependent "<first->GetFullFileName()<PrintCommands(Target); - } - #endif - if (DepDate.IsNewer(TargetDate)) - { - #ifdef _DEBUG - if (pRule,g_pPrintDependencyCheck && DepDate.IsExistingFile() && TargetDate.IsExistingFile()) - cout<<"Going to build "<GetFullFileName()<<" because "<first->GetFullFileName()<<" is more recent\n"; - #endif - MakeTarget=true; - } - break; - } - } - ResultIt++; - } - } - - mhmakeparser *pMakefile=NULL; - if (pRule) - { - pMakefile=pRule->GetMakefile(); - if (pMakefile->ForceAutoDepRescan()||MakeTarget==true) - pMakefile->UpdateAutomaticDependencies(Target); - } - - BuildDependencies(pRule,Target,TargetDate,YoungestDate,MakeTarget); - - if (pRule) - { - #ifdef _DEBUG - if (g_pPrintDependencyCheck) - { - for (int i=0; iGetFullFileName()<m_RebuildAll) && TargetDate.IsOlder(m_sBuildTime))) - { - #ifdef _DEBUG - if (g_pPrintDependencyCheck) - { - if (!TargetDate.DoesExist()) - { - if (!m_ImplicitSearch && !Target->IsPhony()) - cout<<"Building "<GetFullFileName()<<" because it does not exist yet\n"; - } - else if (TargetDate.IsOlder(m_sBuildTime)) - { - cout<<"Building "<GetFullFileName()<<" because need to rebuild all (-a)\n"; - } - } - #endif - MakeTarget=true; - } - } - - // Now execute the commands - vector &Commands=pRule->GetCommands(); - - while (1) - { - vector::iterator CommandIt=Commands.begin(); - if (MakeTarget) - { - pMakefile->UpdateAutomaticDependencies(Target); - BuildDependencies(pRule,Target,TargetDate,YoungestDate,MakeTarget); /* Since it could be that there are dependencies added, make sure that they are all build before building this target */ - - pMakefile->InitEnv(); // Make sure that the exports are set in the evironment -#ifdef _DEBUG - if (!g_GenProjectTree) -#endif - cout << "Building " << Target->GetFullFileName()<GetMakeDir()); - - md5_context ctx; - md5_starts( &ctx ); - while (CommandIt!=Commands.end()) - { - pMakefile->SetRuleThatIsBuild(Target); // Make sure that the command expension is correct - string Command=pMakefile->ExpandExpression(*CommandIt); - pMakefile->ClearRuleThatIsBuild(); /* Make sure that further expansion is not taking this rule into account.*/ - md5_update( &ctx, (uint8 *)Command.c_str(), (unsigned long)Command.size()); - if (MakeTarget) - { - #ifdef _DEBUG - if (g_pPrintDependencyCheck) - { - for (int i=0; i "<ExecuteCommand(Command)) - { - cerr << "Error running command: "<GetFullFileName()<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); - } - } - CommandIt++; - } - - uint32 Md5_32=md5_finish32( &ctx); - if (MakeTarget) - { - #ifdef _DEBUG - if (g_DoNotExecute||g_GenProjectTree) - Target->SetDateToNow(); - else - #endif - Target->InvalidateDate(); - mh_time_t NewDate=Target->GetDate(); - if (NewDate.IsNewer(YoungestDate)) - YoungestDate=NewDate; - - Target->SetCommandsMd5_32(Md5_32); /* If the rule of the target was added with an implicit rule the targets in the rule is empty */ - pMakefile->AddTarget(Target); - pRule->SetTargetsIsBuild(Md5_32); - break; - } - else if (!Target->CompareMd5_32(Md5_32)) - { - if (TargetDate.IsNewerOrSame(m_sBuildTime) || TargetDate.IsDir()) - { - // Only rebuild if it is not yet rebuild in this current run. This may happen for implicit rules that have multiple targets (implicit rules that build more then one target at the same time - Target->SetCommandsMd5_32(Md5_32); - pMakefile->AddTarget(Target); - m_AutoDepsDirty=true; /* We need to update the autodeps file if the md5 has been changed */ - break; - } - else - { - #ifdef _DEBUG - if (!g_GenProjectTree) - cout << "Md5 is different for " << Target->GetFullFileName() << " Old:"<GetCommandsMd5_32()<<", New: "<GetFullFileName()<<" finished : "<< YoungestDate << endl; - } - Indent--; - if (g_CheckCircularDeps) - { - m_TargetStack.pop_back(); - } - - if (!m_ImplicitSearch && !Target->Exists() && !Target->IsPhony() && !g_DoNotExecute && !g_GenProjectTree) - { - // This is only a warning for phony messages - cout<<"Warning: don't know how to make "<GetFullFileName()<<"\nMake the rule a phony rule to avoid this warning (but only do it when it is really phony).\n";; - } - #endif - Target->SetDate(YoungestDate); /* This is especially needed for phony targets in between real targets */ - return YoungestDate; -} - -/////////////////////////////////////////////////////////////////////////////// -void mhmakefileparser::BuildIncludedMakefiles() -{ - vector< refptr >::iterator MakefileIt=m_IncludedMakefiles.begin(); - while (MakefileIt!=m_IncludedMakefiles.end()) - { - #ifdef _DEBUG - if (g_PrintAdditionalInfo) - cout<<"Building include file "<<(*MakefileIt)->GetFullFileName()<