⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmake.cpp

📁 利用XML来作为Makefile的make工具源代码.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// XMLMake.cpp : Defines the entry point for the console application.
//

#include "StdAfx.h"
#include "xmake.h"
#include "XMLParser.h"
#include "CmdLine.h"
#include <exception>
#include <stdexcept>

#ifdef WIN32
static FILETIME currentMakeTime;
#endif

#ifdef GCC
  #include <dirent.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <sys/stat.h>
#endif

const char* XMLMake::nextNonWhiteSpace( const char *s )
{
	const char* result = NULL;
	
	// Check the string.
	while( *s ) {
		
		// If this is a whitespace character than continue the loop.
		if ( (*s == ' ') || (*s == 9) || (*s == '\n') || (*s == '\r') ) {
			s++;
			continue;
		} // if
		
		// Found a none whitespace character.
		result = s;
		break;
		
	} // while
	
	return result;
}


const char* XMLMake::nextWhiteSpace( const char *s )
{
	const char* result =  NULL;
	// Check the string.
	while( *s ) {
		
		// Found a whitespace character.
		if ( (*s == ' ') || (*s == 9) || (*s == '\n') || (*s == '\r') ) {
			result = s;
			break;
		}
		
		// Else continue the loop.
		s++;
	} // while
	
	return result;
}


void XMLMake::searchIncludeFile( const String& name, long& dependencyCount, StringList& dependsList )
{
#ifdef WIN32
	int      i, j;
	char     tmp[MAXPATH];
	struct   _finddata_t  find;
	
	// Try to find in all include directory.
	for(i=0; i<includeCount; i++) {
		
		// Make the full name.
		strcpy(tmp, includeDirectories[i].c_str());
		strcat(tmp, name.c_str());
		
		// Try to locate the include file.
		long hFile = _findfirst(tmp, &find);
		if ( hFile != -1 ) {
			
			// Check if it appears in the dependecy list.
			for(j=0; j<dependencyCount; j++)
				if ( !strcmp(dependsList[j].c_str(), tmp) )
					return;
				
				// It is a new dependent file.
				if ( dependencyCount == MAX_INCLUDE_DEPTH ) {
					//puts();
					throw std::logic_error( "Too many dependent file." );
					//exit(DOS_ERROR);
					
				} // if
				
				//strcpy(dependList[dependencyCount++], tmp);
				dependsList[dependencyCount++] = tmp;
				_findclose( hFile );
				return;
		} // if
		
	} // for
#endif

#ifdef GCC

	int      i, j;
	char     tmp[MAXPATH];
	
	// Try to find in all include directory.
	for(i=0; i<includeCount; i++) {
		
		// Make the full name.
		strcpy(tmp, includeDirectories[i].c_str());
		strcat(tmp, name.c_str());

		//* // gets the file list in the include dir
		//* StringList files = findFilesInDir(includeDirectories[i]);
		//* // looks for the file
		//* for (int c=0;c<files.size();c++)
		//* {
		//*	if (files[c] == name)
		//*		fileExists = true;
		//* }

		bool fileExists;
		FILE* fileExistsHandle = fopen(name.c_str(),"r");
		if (fileExistsHandle != NULL)
		{
			fileExists = true;
			fclose(fileExistsHandle);
		}
		else
		{
			fileExists = false;
		}
		
		if (fileExists)
		{	
			// Check if it appears in the dependecy list.
			for(j=0; j<dependencyCount; j++)
				if ( !strcmp(dependsList[j].c_str(), tmp) )
					return;
				
				// It is a new dependent file.
				if ( dependencyCount == MAX_INCLUDE_DEPTH ) {
					//puts();
					throw std::logic_error( "Too many dependent file." );
					//exit(DOS_ERROR);
					
				} // if
				
				//strcpy(dependList[dependencyCount++], tmp);
				dependsList[dependencyCount++] = tmp;
				return;
		} // if
		
	} // for
#endif

}

void XMLMake::makeDependFiles( String name, StringList& dependsList, long& dependencyCount )
{
	FILE  *sf;
	char  line[LINE_SIZE];
	const char  *s; 
	char* e;
	int   i, first, last;	
	
	

	// Register the first dependent file.
	first = dependencyCount;
	
	// Open source file.
	if ( (sf = fopen(name.c_str(), "rt")) == NULL ) {
		printf("Unable to open %s file.\n", name.c_str());
		//exit(DOS_ERROR);
	} // if
	
	// Scan source file for include statments.
	while( fgets(line, LINE_SIZE, sf) ) {
		
		// Go to first nonwhitespace character in line.
		if ( (s = nextNonWhiteSpace(line)) == NULL )
			continue;
		
		// This is an #include statment ?
		if ( !strncmp(s, "#include", 8) ) {
			s += 8;
			
			// Search begin of include file name.
			if ( (s = nextNonWhiteSpace(s)) == NULL )
				continue;
			s++;
			
			// Search end of include file name.
			if ( (e = strchr(s, '>')) == NULL )
				if ( (e = strchr(s, '"')) == NULL )
					continue;
				*e = '\0';
				
				// Search full path of include file.
				searchIncludeFile( s, dependencyCount, dependsList );
		} // if
		
		
		
	} // while
	
	// Register the last dependent file.
	last = dependencyCount;
	
	// Close the source file.
	fclose(sf);
	
	// Check include files in this source file.
	if ( first < last ) {
		for(i=first; i<last; i++) {
			makeDependFiles( dependsList[i], dependsList, dependencyCount );
		}
	}
}

void XMLMake::replaceEnvironmentStrings( Enumerator<XMLNode*>* nodes )
{

	std::map<String,String> subList;
	
	XMLNode* lastVarNode = NULL;
	while ( nodes->hasMoreElements() ) {
		XMLNode* node = nodes->nextElement();
		if ( node->getName() == "substitutions" ) {
			Enumerator<XMLNode*>* variables = node->getChildNodes();
			while ( variables->hasMoreElements() ) {
				XMLNode* var = variables->nextElement();
				
				if ( var->getName() == "variable" ) {
					subList[var->getAttrByName("name")->getValue()] =
						var->getAttrByName("value")->getValue();
					if ( XMLMake::verbose ) {
						printf( "variable %s: %s\n", 
								var->getAttrByName("name")->getValue().c_str(),
								var->getAttrByName("value")->getValue().c_str() );

								
					}
				}	
				lastVarNode = var;
			}
			while ( (nodes->hasMoreElements()) && (node !=lastVarNode) ) {
				node = nodes->nextElement();
			}
			break;
		}
	}

	//nodes->reset();

	while ( nodes->hasMoreElements() ) {
		XMLNode* node = nodes->nextElement();
		Enumerator<XMLAttr>* attrs = node->getAttrs();
		while ( attrs->hasMoreElements() ) {
			XMLAttr attr = attrs->nextElement();
			String name = attr.getName();
			String val = attr.getValue();
			
			const VCFChar* P = val.c_str();
			const VCFChar* start = P;
			String variableString;			
			String rawVariableString;
			while ( (P-start) < val.size() ) {
				if ( *P == '%' ) {
					const VCFChar* tmp = P;
					P++;
					const VCFChar* variable = P;
					while ( ((P-start) < val.size()) && (*P !='%') ) {
						P++;	
					}
					if ( *P != '%' ) {
						//throw exception malformed variable
					}

					variableString = val.substr( variable-start, P-variable);

					P++;
					rawVariableString.append( tmp, P-tmp );

					break;
				}
				else if ( (*P == '$') ) {
					const VCFChar* tmp = P;
					while ( ((P-start) < val.size()) && (*P != '(') ) {
						P++;
					}
					
					if ( *P == '(' ) {
						P++;						
						const VCFChar* variable = P;
						while ( ((P-start) < val.size()) && (*P !=')') ) {
							P++;	
						}
						if ( *P != ')' ) {
							//throw exception malformed variable
						}						
						
						variableString = val.substr( variable-start, P-variable);
						P++;
						rawVariableString.append( tmp, P-tmp );

						break;
					}					
				}	
				P++;
			}

			if ( !variableString.empty() ) {
				//look in the subsitution variable list
				std::map<String,String>::iterator found = subList.find( variableString );
				if ( found != subList.end() ) {
					int pos = val.find( rawVariableString );
					while ( pos >= 0 ) {
						val.erase( pos, rawVariableString.size() );
						val.insert( pos, found->second );
						node->getAttrByName( name )->setValue( val );
						pos = val.find( rawVariableString );
					}					
				}
				else {
					//try environment variables					
					String envValue = getEnvironmentVariableValue( variableString );
					if ( !envValue.empty() ) {
						
						int pos = val.find( rawVariableString );
						while ( pos >= 0 ) {
							val.erase( pos, rawVariableString.size() );
							val.insert( pos, envValue );
							node->getAttrByName( name )->setValue( val );
							pos = val.find( rawVariableString );
						}
					}
				}
			}
		}
	}
}


String XMLMake::getEnvironmentVariableValue( const String& variableName )
{
	String result;

#ifdef WIN32
	VCFChar envValue[1024];
	memset( envValue, 0, 1024 );
	GetEnvironmentVariable( variableName.c_str(), envValue, 1023 );

	result = envValue;
#endif

#ifdef GCC
           result = getenv(variableName.c_str()); 
#endif 


	return result;
}

bool XMLMake::parseCommandLine( int argc, char** argv )
{
	bool result = false;
	CCmdLine cmdLine;
	try {
		int argsFound = cmdLine.SplitLine( argc, argv );
		
		if ( cmdLine.HasSwitch( "-config" )  ){
			XMLMake::configToBuild = cmdLine.GetArgument( "-config", 0 );
			//check for quotes and strip them off
			int pos = XMLMake::configToBuild.find( "\"" );
			while ( pos >= 0 ) {
				XMLMake::configToBuild.erase( pos, 1 );

				pos = XMLMake::configToBuild.find( "\"" );
			}

			if ( cmdLine.HasSwitch( "-f" ) ) {
				XMLMake::makefile = cmdLine.GetArgument( "-f", 0 );
			}

			if ( cmdLine.HasSwitch( "-clean" ) ) {
				XMLMake::runClean = true;
			}
			else if ( cmdLine.HasSwitch( "-install" ) ) {
				XMLMake::runInstall = true;
			}

			if ( cmdLine.HasSwitch( "-v" ) ) {
				XMLMake::verbose = true;
			}

			result = argsFound > 0;
		}
		else {
			XMLMake::error( "incorrect usage - you probably didn't specify\n a configuration to build "\
							"by using the -config switch\n\n" );

		}
		
	}
	catch (...) {
		result = false;
	}
	return result;
}

int XMLMake::exec( const String& commandLine, const String& currentDirectory )
{
	int result = 0;
#ifdef WIN32
	HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
	HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE hStdError = GetStdHandle(STD_ERROR_HANDLE);

	
	STARTUPINFO si = {0};
	si.cb = sizeof( STARTUPINFO );
	
	si.hStdInput = hStdIn;		// stdin of parent
	//si.hStdOutput = hPipeWrite;	// write side of child-to-parent
	si.hStdError = hStdError;		// stderr of parent
	
	PROCESS_INFORMATION pi = {0};				
	
	
	
	char tmp[1024];
	commandLine.copy( tmp, commandLine.size() ); 
	tmp[commandLine.size()] = 0;
	
	if ( CreateProcess( NULL, tmp, 
						NULL, 
						NULL, 
						TRUE, 
						NORMAL_PRIORITY_CLASS, 
						NULL, 
						currentDirectory.c_str(), 
						&si, 
						&pi ) ) {
		
		
		WaitForSingleObject ( pi.hProcess, INFINITE );
		
		DWORD exitCode;
		GetExitCodeProcess(pi.hProcess,&exitCode);
		
		result = (int) exitCode;

		CloseHandle( pi.hProcess );
	}
	else {
		
		printf( "GetLastError(): %d for cmd line %s\n", GetLastError(), commandLine.c_str() );
	}
#endif

// ------------------------------ GCC --------------------------
   #ifdef GCC 
       // save a copy of the current dir 
           char currentDir[1000]; 
           getcwd(currentDir,1000); 
    
           // changes to the dir specified as parameter 
           chdir(commandLine.c_str()); 
    
           // runs the command line 
           result = system(commandLine.c_str()); 
    
           // switch back to the original dir 
           chdir(currentDir); 
 #endif

	return result;
}

void XMLMake::error( const String& errMessage )
{
	String msg = "xmake failed: " + errMessage + "\n";
	printf( msg.c_str() );
	if ( XMLMake::verbose ) {
#ifdef WIN32
		printf( "GetLastError() returned %d\n", GetLastError() );
#endif
	}
}



String XMLMake::getCurrentDirectory()
{
	String result;
#ifdef WIN32
	char currentDir[1024];
	GetCurrentDirectory( 1023, currentDir );
	result = currentDir;
#endif

#ifdef GCC
	char currentDir[1024];
	getcwd(currentDir, 1023);
	result = currentDir;
#endif

	return result;
}

void XMLMake::doBuild()
{	
	XMLMake::dependencyList.clear();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -