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

📄 xmake.cpp

📁 利用XML来作为Makefile的make工具源代码.
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	FILE* f = fopen( XMLMake::makefile.c_str(), "rt" );
	if ( NULL == f ) {

		XMLMake::error( "couldn't open a makefile in this directory" );		

		return;	
	}

	XMLMake::defaultOutputDir = XMLMake::getCurrentDirectory();

#ifdef WIN32
	if ( XMLMake::defaultOutputDir[XMLMake::defaultOutputDir.size()-1] != '\\' ) {
		XMLMake::defaultOutputDir += "\\";
	}
#else
	if ( XMLMake::defaultOutputDir[XMLMake::defaultOutputDir.size()-1] != '/' ) {
		XMLMake::defaultOutputDir += "/";
	}	
#endif

	fseek( f, 0, SEEK_END );
	int size = ftell( f );
	
	fseek( f, 0, SEEK_SET );
	
	char* buf = new char[size+1];
	
	fread( buf, 1, size, f );
	
	fclose( f );
	
	
	buf[size] = 0;
	
	String xml(buf);
	
	XMLParser parser;
	parser.parse( xml );
	
	Enumerator<XMLNode*>* nodes = parser.getParsedNodes();
	
	XMLMake::replaceEnvironmentStrings( nodes );
	
	nodes->reset();
	
	XMLMake::buildDependencyList( nodes );
	
	String compilerFlags;
	String compiler;
	
	String linkerFlags;
	String linker;
	/*
	HANDLE hPipeWrite = NULL;		
	HANDLE hPipeRead = NULL;
	*/
	/*
	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa); 
	sa.lpSecurityDescriptor = NULL; 
	sa.bInheritHandle = TRUE;
	if( ! ::CreatePipe(
	&hPipeRead,					// address of variable for read handle 
	&hPipeWrite,					// address of variable for write handle  
	&sa,							// pointer to security attributes 
	0								// number of bytes reserved for pipe 
	) )
	{
	printf ( "error creating pipe !" );
	return 1;
	}
	*/
	
	
	String currentDir = XMLMake::getCurrentDirectory();
	
	std::map<String,String> toolMap;

	while ( nodes->hasMoreElements() ) {
		XMLNode* node = nodes->nextElement();
		if ( node->getName() == "config" ) {
			
			XMLAttr* attr = node->getAttrByName( "name" );
			if ( attr->getValue() == configToBuild ) {

				XMLNode* toolsNode = node->getNodeByName( "tools" );
				if ( NULL != toolsNode ) {
					Enumerator<XMLNode*>* tools = toolsNode->getChildNodes();
					if ( tools->hasMoreElements() ) {
						toolMap.clear();
					}

					while ( tools->hasMoreElements() ) {
						XMLNode* tool = tools->nextElement();
						XMLNode* flagsNode = tool->getNodeByName( "flags" );
						String toolCmdLine;
						toolCmdLine = tool->getAttrByName( "name" )->getValue() + " ";
						if ( flagsNode ) {
							Enumerator<XMLNode*>* flags = flagsNode->getChildNodes();
							while ( flags->hasMoreElements() ) {
								XMLNode* flag = flags->nextElement();
								toolCmdLine += flag->getAttrByName( "value" )->getValue() + " ";
							}
						}

						toolMap[tool->getAttrByName( "id" )->getValue()] = toolCmdLine;
					}
				}

				XMLNode* compilerNode = node->getNodeByName( "compiler" );
				XMLAttr* attr = compilerNode->getAttrByName( "name" );
				compiler = attr->getValue();
				
				int pos = compiler.find( "'" );
				while ( pos >= 0 ) {
					compiler[pos] = '"';
					pos = compiler.find( "'" );
				}
				
				XMLNode* flags = compilerNode->getNodeByName( "flags" );
				Enumerator<XMLNode*>* children = flags->getChildNodes();
				while ( children->hasMoreElements() ) {
					XMLNode* flag = children->nextElement();
					XMLAttr* attr = flag->getAttrByName( "value" );
					String val = attr->getValue();
					int pos = val.find( "'" );
					while ( pos >= 0 ) {
						val[pos] = '"';
						pos = val.find( "'" );
					}
					
					compilerFlags += val + " ";
				}
				
				
				XMLNode* linkerNode = node->getNodeByName( "linker" );
				if ( NULL != linkerNode ) {
					attr = linkerNode->getAttrByName( "name" );
					linker = attr->getValue();
					flags = linkerNode->getNodeByName( "flags" );
					Enumerator<XMLNode*>* children = flags->getChildNodes();
					while ( children->hasMoreElements() ) {
						XMLNode* flag = children->nextElement();
						XMLAttr* attr = flag->getAttrByName( "value" );
						String val = attr->getValue();
						int pos = val.find( "'" );
						while ( pos >= 0 ) {
							val[pos] = '"';
							pos = val.find( "'" );
						}
						
						linkerFlags += val + " ";
					}						
				}
				
			}
		}
		else if ( node->getName() == "sources" ) {
			Enumerator<XMLNode*>* sources = node->getChildNodes();
			bool linkNeeded = false;
			String linkCmdLine;
			
			linkCmdLine = linker + " " + linkerFlags;
			
			printf( "Preparing to compile source files...\n" );
			while ( sources->hasMoreElements() ) {
				XMLNode* source = sources->nextElement();
				XMLAttr* attr = source->getAttrByName( "name" );
				XMLAttr* build = source->getAttrByName( "build" );
				XMLAttr* config = source->getAttrByName( "partOfConfig" );
				
				XMLAttr* tool = source->getAttrByName( "tool" );

				XMLAttr* outputAs = source->getAttrByName( "outputAs" );
				
				bool filePartOfConfig = false;
				bool buildFile = false;
				String name = attr->getValue();
				String outputName;
				if ( outputAs ) {
					outputName = outputAs->getValue();
				}
				
				outputName = XMLMake::getOutputFileName( name, outputName );								
				
				//lets check to see if this file is actually part of the config to build
				if ( NULL != config ) {						
					String srcConfig = config->getValue();
					int pos = srcConfig.find( "|" );					
					while ( pos >= 0 ) {
						String s = srcConfig.substr( 0, pos );
						srcConfig.erase( 0, pos+1 );
						if ( s == configToBuild ) {
							filePartOfConfig = true;
							break;
						}
						pos = srcConfig.find( "|" );
					}
					if ( !filePartOfConfig ) {
						if ( srcConfig == configToBuild ) {
							filePartOfConfig = true;
						}
					}										
				}
				else {
					XMLMake::error( "Hmmm...you do not appear to have specified what configuration " + 
									name + " is partf of - please fix this and then rebuild." );

				}

				if ( filePartOfConfig && ((NULL == build) || (build->getValue() == "yes")) ) {
					buildFile = true;
				}

				if ( filePartOfConfig ) {
					//this will check the file dependencies for C or C++ files 	

					if ( (name.find(".cpp") != String::npos) || (name.find(".c") != String::npos) || 
						(name.find(".cxx") != String::npos) || (name.find(".cc") != String::npos) ) {
						StringListIterator found = 
							std::find( XMLMake::buildList.begin(), XMLMake::buildList.end(), name );
						
						buildFile = (found != XMLMake::buildList.end());
					}
				}
				
				
				if ( buildFile ) {					

					if ( NULL != tool ) {
						linkNeeded = true;
						std::map<String,String>::iterator found = toolMap.find( tool->getValue() );
						if ( found != toolMap.end() ) {
							String file = attr->getValue();
							String cmdLine = found->second;
							cmdLine += file;
							if ( XMLMake::verbose ) {
								printf( "%s\n", cmdLine.c_str() );
							}
							XMLMake::exec( cmdLine, String(currentDir) );
						}
					}
					else {											
						
						String file = attr->getValue();
						
						String cmdLine = compilerFlags + file;
						
						cmdLine = compiler + " " + cmdLine;
						//check the exit code here 
						if ( XMLMake::verbose ) {
							printf( "%s\n", cmdLine.c_str() );
						}

						linkNeeded = true;
						XMLMake::exec( cmdLine, String(currentDir) );

						XMLMake::verifyOutputFileForSrc( file, outputName );
					}

					linkCmdLine += outputName + " ";
				}
				else if ( filePartOfConfig ){
					linkCmdLine += outputName + " ";
				}
			}
			
			
			
			if ( linkNeeded ) {				
				printf( "Preparing to link object files...\n" );
				if ( XMLMake::verbose ) {
					printf( "%s\n", linkCmdLine.c_str() );
				}
				printf( "%s\n", linkCmdLine.c_str() );
				XMLMake::exec( linkCmdLine, String(currentDir) );
				
			}
			
			break;
		}
	
	}		
		
	delete buf;
}

void XMLMake::doPreBuild( XMLNode* preBuildnode )
{

}

void XMLMake::doPostBuild( XMLNode* postBuildnode )
{

}

bool XMLMake::isSourceNodeInConfig( const String& configName, XMLNode* node )
{
	bool result = false;
	
	XMLAttr* attr = node->getAttrByName("partOfConfig");

	if ( NULL != attr ) {
		
		String srcConfig = attr->getValue();
		int pos = srcConfig.find( "|" );
		bool found = false;
		while ( pos >= 0 ) {
			String s = srcConfig.substr( 0, pos );
			srcConfig.erase( 0, pos+1 );
			if ( s == configName ) {
				found = true;
				break;
			}
			pos = srcConfig.find( "|" );
		}
		if ( !found ) {
			if ( srcConfig == configName ) {
				found = true;
			}
		}
		
		result = found;
	}
	
	return result;
}


void XMLMake::buildDependencyList( Enumerator<XMLNode*>* nodes )
{
	nodes->reset();
	String currentDir = XMLMake::getCurrentDirectory();

	if ( XMLMake::verbose ) {
		printf( "building dependencies...\n" );
	}
	
	while ( nodes->hasMoreElements() ) {
		XMLNode* node = nodes->nextElement();

		/**
		check the dependencies of the source files.
		Each file is checked against the headers it includes. If those have changed
		(or any of hte headers that those headers include...) then file 
		needs to be rebuilt.
		*/
		if ( node->getName() == "sources" ) {
			Enumerator<XMLNode*>* sources = node->getChildNodes();			
			
			while ( sources->hasMoreElements() ) {
				XMLNode* src = sources->nextElement();
				
				if ( XMLMake::isSourceNodeInConfig( XMLMake::configToBuild, src ) ) {
					String name = src->getAttrByName("name")->getValue();
					
					if ( (name.find(".cpp") != String::npos) || (name.find(".c") != String::npos) || 
						(name.find(".cxx") != String::npos) || (name.find(".cc") != String::npos) ) {
						
						StringList depends;
						depends.resize( MAX_INCLUDE_DEPTH, "" );
						depends[0] = name;
						
						XMLAttr* attr = src->getAttrByName("outputAs");
						
						String outputBin;
						if ( attr ) {
							outputBin = attr->getValue();
						}
						//this will get the output file name for the binary obj
						outputBin = XMLMake::getOutputFileName( name, outputBin );
						
						long dependCount = 1;
						
						XMLMake::makeDependFiles( name, depends, dependCount );
						
						if ( XMLMake::verbose ) {
							printf( "%s depends on:\n", name.c_str() );
						}
						bool added = false;
						for ( int i=0;i<dependCount;i++ ) {
							String& s = depends[i];
							if ( XMLMake::verbose ) {
								printf( "\t%s\n", s.c_str() );
							}
							
							if ( !added ) {
								if ( (XMLMake::fileNewerThan( s, name )) && (XMLMake::fileNewerThan(s,outputBin) ) ) {
									XMLMake::buildList.push_back( name );
									added = true;
									if ( ! XMLMake::verbose ) {
										break;
									}
								}
							}
						}
						if ( !added ) {							

							//check agains the binary obj file
							XMLMake::verifyFileName( outputBin );
							if ( XMLMake::fileNewerThan( name, outputBin ) ) {
								XMLMake::buildList.push_back( name );
							}
						}
					}
				}
			}
		}
		else if ( node->getName() == "config" ) {
			
			XMLAttr* attr = node->getAttrByName( "name" );		

			if ( attr->getValue() == XMLMake::configToBuild ) {

				attr = node->getAttrByName( "srcBinaryExt" );		
				if ( attr ) {
					XMLMake::srcBinExt = attr->getValue();
				}
				else {
					XMLMake::srcBinExt = ".obj";
				}

				Enumerator<XMLNode*>* configNodes = node->getChildNodes();
				while ( configNodes->hasMoreElements() ) {
					XMLNode* cfgNode = configNodes->nextElement();
					if ( cfgNode->getName() == "includes" ) {
						Enumerator<XMLNode*>* includes = cfgNode->getChildNodes();
						while ( includes->hasMoreElements() ) {
							XMLNode* include = includes->nextElement();
							attr = include->getAttrByName( "path" );
							if ( attr ) {
								String path = attr->getValue();
								int pos = path.find( "." );
								if ( pos > -1 ) {
									if ( path.size() > 1 ) {
										//more complicated
									}
									else {
										path = currentDir;							
									}
								}
								if ( path[path.size()-1] != '\\' ) {
									path += "\\";
								}
								XMLMake::includeDirectories.push_back( path );								
							}
						}

						XMLMake::includeCount = XMLMake::includeDirectories.size();
					}
				}
			}
		}
	}
	nodes->reset();

	if ( XMLMake::verbose ) {
		printf( "finished building dependencies.\n" );
	}
}

void XMLMake::doInstall()
{

}

void XMLMake::doClean()
{
	FILE* f = fopen( XMLMake::makefile.c_str(), "rt" );
	if ( NULL == f ) {

		XMLMake::error( "couldn't open a makefile in this directory" );		

		return;	
	}

	fseek( f, 0, SEEK_END );
	int size = ftell( f );
	
	fseek( f, 0, SEEK_SET );
	
	char* buf = new char[size+1];
	
	fread( buf, 1, size, f );
	
	fclose( f );
	
	
	buf[size] = 0;
	
	String xml(buf);
	
	XMLParser parser;
	parser.parse( xml );
	
	Enumerator<XMLNode*>* nodes = parser.getParsedNodes();
	
	XMLMake::replaceEnvironmentStrings( nodes );
	
	nodes->reset();	


	while ( nodes->hasMoreElements() ) {
		XMLNode* node = nodes->nextElement();
		if ( node->getName() == "project" ) {
			//delete the project output
			XMLAttr* attr = node->getAttrByName( "outputAs" );
			if ( NULL != attr ) {
				String filename = attr->getValue();
				if ( XMLMake::deleteFile( filename ) ) {
					printf( "deleted %s\n", filename.c_str() );
				}
				else {
					printf( "error deleting %s\n", filename.c_str() );
				}
			}
		}
		else if ( node->getName() == "sources" ) {

⌨️ 快捷键说明

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