📄 xmake.cpp
字号:
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 + -