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