Code::Blocks project importer / CodeLite .project format
Posted: Fri Oct 08, 2010 8:15 pm
Hi Eran,
I'm working on a Code::Blocks project importer, which will convert Code::Blocks' .cbp to CodeLite's .project files. So far I've got the parsing of the cbp done into my own structure (with not all but the features I use most), now i've just to implement the converting and writing to .project structure.
Do you have a specification for the ".project" format, in your computer (or elsewhere), similiar to CodeBlocks' http://wiki.codeblocks.org/index.php?title=Project_file, listing the structure of the Project file formats? That'd be most helpful!
Thanks
EDIT: update with preliminary code for the converter. It's incomplete at the moment, I'll add to it as I progress.
It uses the TinyXML library.
XMLUtils.h:
I'm working on a Code::Blocks project importer, which will convert Code::Blocks' .cbp to CodeLite's .project files. So far I've got the parsing of the cbp done into my own structure (with not all but the features I use most), now i've just to implement the converting and writing to .project structure.
Do you have a specification for the ".project" format, in your computer (or elsewhere), similiar to CodeBlocks' http://wiki.codeblocks.org/index.php?title=Project_file, listing the structure of the Project file formats? That'd be most helpful!
Thanks
EDIT: update with preliminary code for the converter. It's incomplete at the moment, I'll add to it as I progress.
It uses the TinyXML library.
Code: Select all
#include "XMLUtils.h"
#include <iostream>
#include <vector>
#define TIXML_USE_STL
#include <tinyxml.h>
int main(void)
{
// input and output files
// VERY IMPORTANT: OUTPUT PROJECT FILE NAME MUST BE = PROJECT NAME!!!
std::string pathToCodeBlocksProject = "Codeblocks Input Files/Utils.cbp";
std::string filepathCodeLiteProject = "Output/Utils.project";
// load codeblocks xml file
TiXmlDocument* xmlElmCB_Root = new TiXmlDocument();
xmlElmCB_Root->LoadFile(pathToCodeBlocksProject);
//XMLUtils::dump_to_stdout(xmlElmCB_Root); // debug
// write CodeLite output
// create CodeLite xml file
TiXmlDocument* xmlElmCL_Root = new TiXmlDocument();
// add declaration
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "utf-8", "" );
xmlElmCL_Root->LinkEndChild(decl);
// add "CodeLite_Project" tag
std::string elementName = "CodeLite_Project";
TiXmlElement* xmlElmCL_CodeLite_Project = new TiXmlElement(elementName);
// add "Name" attribute
// get CodeBlocks project name
std::string projectName = "";
// search for "CodeBlocks_project_file"
TiXmlElement* xmlElmCB_CodeBlocks_project_file = xmlElmCB_Root->FirstChildElement("CodeBlocks_project_file");
if(xmlElmCB_CodeBlocks_project_file == 0)
{
std::cout << "could not find \"CodeBlocks_project_file\" below root!\n";
return 0;
}
// find "Project" below
TiXmlElement* xmlElmCB_Project = xmlElmCB_CodeBlocks_project_file->FirstChildElement("Project");
if(xmlElmCB_Project == 0)
{
std::cout << "could not find \"Project\" below!\n";
return 0;
}
// find an "Option" with an attribute named "title", and get that attribute value as the Project title
for( TiXmlElement* child = xmlElmCB_Project->FirstChildElement(); child; child = child->NextSiblingElement())
{
if(child->ValueStr() == "Option")
if(child->Attribute("title") != 0)
{
projectName = std::string(child->Attribute("title"));
break;
}
}
xmlElmCL_CodeLite_Project->SetAttribute("Name", projectName);
// set CodeLite "InternalType" attribute
// InternalType: Console, GUI, Library, Others, UnitTest++, User Templates
// odd since a project can have both executable + library + others targets, which don't fall on just "Console" or "Library" categories
// just set it to "Console" for now
//xmlElmCL_CodeLite_Project->SetAttribute("InternalType", "Console");
xmlElmCL_CodeLite_Project->SetAttribute("InternalType", "Library");
// now that all attribute for CodeLite_Project have been added, add it to CodeLite xml file
xmlElmCL_Root->LinkEndChild(xmlElmCL_CodeLite_Project);
// add Plugins
TiXmlElement* xmlElmPlugins = new TiXmlElement("Plugins");
xmlElmCL_CodeLite_Project->LinkEndChild(xmlElmPlugins);
// add Description
TiXmlElement* xmlElmDescription = new TiXmlElement("Description");
xmlElmCL_CodeLite_Project->LinkEndChild(xmlElmDescription);
// add Dependencies
TiXmlElement* xmlElmDependencies = new TiXmlElement("Dependencies");
xmlElmCL_CodeLite_Project->LinkEndChild(xmlElmDependencies);
// add files list (VirtualDirectory)
// add list of "File" for each file in CodeBlocks project
// get CodeBlocks files list: CodeBlocks_project_file -> Project -> Unit filename=""
std::vector<std::string> filesList;
for( TiXmlElement* xmlElmCB_Unit = xmlElmCB_Project->FirstChildElement("Unit");
xmlElmCB_Unit;
xmlElmCB_Unit = xmlElmCB_Unit->NextSiblingElement("Unit"))
{
if(xmlElmCB_Unit->Attribute("filename") != 0)
{
std::string fileName(xmlElmCB_Unit->Attribute("filename"));
// in filename, replace "\" with "/"
for(unsigned int idxChar = 0; idxChar < fileName.size(); ++idxChar)
if(fileName[idxChar] == '\\') fileName[idxChar] = '/';
filesList.push_back(fileName);
}
else
{
std::cout << "Error: expected <Unit filename="">, did not find it\n";
}
}
// for every file, parse directory structure and add
for(unsigned int idxFile = 0; idxFile < filesList.size(); ++idxFile)
{
std::string fileName = filesList[idxFile];
// parse fileName, get directory structure, and create virtual directories if necessary
// TODO create full directory tree (right now, only creating top dir)
std::string::size_type dirSeparator = fileName.find('/');
std::string::size_type currentSeparatorPos = 0;
//while(dirSeparator != fileName.npos)
if(dirSeparator != fileName.npos)
{
std::string dirName = fileName.substr(currentSeparatorPos, dirSeparator);
// check if we've added this VirtualDirectory already;
TiXmlElement* xmlElmCL_VirtualDir_ToAddTo = 0;
for( TiXmlElement* xmlElmCL_VirtualDir = xmlElmCL_CodeLite_Project->FirstChildElement("VirtualDirectory");
xmlElmCL_VirtualDir;
xmlElmCL_VirtualDir = xmlElmCL_VirtualDir->NextSiblingElement("VirtualDirectory"))
{
if(xmlElmCL_VirtualDir->Attribute("Name") != 0)
{
if(std::string(xmlElmCL_VirtualDir->Attribute("Name")) == dirName) // found, add to this one
{
xmlElmCL_VirtualDir_ToAddTo = xmlElmCL_VirtualDir;
break;
}
}
}
// if yes, add file to it;
// if not, create and add file to it
if(xmlElmCL_VirtualDir_ToAddTo == 0)
{
xmlElmCL_VirtualDir_ToAddTo = new TiXmlElement("VirtualDirectory");
xmlElmCL_CodeLite_Project->LinkEndChild(xmlElmCL_VirtualDir_ToAddTo);
xmlElmCL_VirtualDir_ToAddTo->SetAttribute("Name", dirName);
}
// add File
TiXmlElement* xmlElmCL_File = new TiXmlElement("File");
xmlElmCL_File->SetAttribute("Name", fileName);
xmlElmCL_VirtualDir_ToAddTo->LinkEndChild(xmlElmCL_File);
//fileName = fileName.substr(dirSeparator+1);
}
}
// add Settings
TiXmlElement* xmlElmCL_Settings = new TiXmlElement("Settings");
// set Settings Type: Static Library, Dynamic Library and Executable
// might be irrelevant, since Settings can have several Configurations, and each can be a Static,Dynamic library or Executable,
// independant from the Settings "Type", which makes it irrelevant
// so setting it to Executable by default
//xmlElmCL_Settings->SetAttribute("Type", "Executable");
xmlElmCL_Settings->SetAttribute("Type", "Dynamic Library");
xmlElmCL_CodeLite_Project->LinkEndChild(xmlElmCL_Settings);
// add "Configuration" list
// get them from CodeBlocks "Target"
std::vector<std::string> configurationNamesList;
TiXmlElement* xmlElmCB_Build = xmlElmCB_Project->FirstChildElement("Build");
if(xmlElmCB_Build == 0)
{
std::cout << "Error: expected Project->Build in CodeBlocks file, did not find Build. exiting\n";
return 0;
}
for( TiXmlElement* xmlElmCB_Target = xmlElmCB_Build->FirstChildElement("Target");
xmlElmCB_Target;
xmlElmCB_Target = xmlElmCB_Target->NextSiblingElement("Target"))
{
TiXmlElement* xmlElmCL_Configuration = new TiXmlElement("Configuration");
xmlElmCL_Settings->LinkEndChild(xmlElmCL_Configuration);
// get Configuration "Name" (Target "title")
if(xmlElmCB_Target->Attribute("title") == 0)
{
std::cout << "Error: expected Project->Build->Target \"title\" in CodeBlocks file, did not find \"title\". exiting\n";
return 0;
}
std::string configurationName(xmlElmCB_Target->Attribute("title"));
xmlElmCL_Configuration->SetAttribute("Name", configurationName);
configurationNamesList.push_back(configurationName);
// get configuration CompilerType
// defaulting to CompilerType="G++ Mingw4.4.3"
// TODO get this from elsewhere
xmlElmCL_Configuration->SetAttribute("CompilerType", "G++ Mingw4.4.3");
// get configuration DebuggerType
// defaulting to DebuggerType="GNU gdb debugger"
// TODO get this from elsewhere
xmlElmCL_Configuration->SetAttribute("DebuggerType", "GNU gdb debugger");
// get configuration Type ("Static Library", "Dynamic Library" or "Executable")
// CodeBlocks: Build -> Option type=""
// available types: 0 - GUI application (no console); 1 - Console application; 2 - Static library;
// 3 - Dynamic library (dll/so), 4 - Commands only (doesn't generate any output, just executes pre/post build steps),
// 5 - Native executable (valid only under windows where it produces a .sys file)
// search for Build -> Option type=""
std::string configurationType = "";
int outputFileType;
for( TiXmlElement* xmlElmCB_Option = xmlElmCB_Target->FirstChildElement("Option");
xmlElmCB_Option;
xmlElmCB_Option = xmlElmCB_Option->NextSiblingElement("Option"))
{
if(xmlElmCB_Option->Attribute("type") != 0)
{
int result = xmlElmCB_Option->QueryIntAttribute("type", &outputFileType);
if(result == TIXML_SUCCESS)
{
switch(outputFileType)
{
case 0: // Gui application
configurationType = "Executable";
break;
case 1: // console application
configurationType = "Executable";
break;
case 2: // static library
configurationType = "Static Library";
break;
case 3: // dynamic library
configurationType = "Dynamic Library";
break;
default:
configurationType = "Executable";
}
break;
}
}
}
xmlElmCL_Configuration->SetAttribute("Type", configurationType);
// how to deal with Global Settings, default to append
xmlElmCL_Configuration->SetAttribute("BuildCmpWithGlobalSettings", "append");
xmlElmCL_Configuration->SetAttribute("BuildLnkWithGlobalSettings", "append");
xmlElmCL_Configuration->SetAttribute("BuildResWithGlobalSettings", "append");
// add Compiler
TiXmlElement* xmlElmCL_Compiler = new TiXmlElement("Compiler");
// set Compiler attribute Options
// get from CodeBlocks Build -> Target -> Compiler
TiXmlElement* xmlElmCB_Compiler = xmlElmCB_Target->FirstChildElement("Compiler");
// get all compiler options
std::vector<std::string> compilerOptions;
std::vector<std::string> compilerIncludeDirectories;
for( TiXmlElement* xmlElmCB_CompilerOption = xmlElmCB_Compiler->FirstChildElement("Add");
xmlElmCB_CompilerOption;
xmlElmCB_CompilerOption = xmlElmCB_CompilerOption->NextSiblingElement("Add"))
{
if(xmlElmCB_CompilerOption->Attribute("option") != 0)
{
std::string compilerOption(xmlElmCB_CompilerOption->Attribute("option"));
compilerOptions.push_back(compilerOption);
}
if(xmlElmCB_CompilerOption->Attribute("directory") != 0)
{
std::string compilerIncludeDirectory(xmlElmCB_CompilerOption->Attribute("directory"));
compilerIncludeDirectories.push_back(compilerIncludeDirectory);
}
}
// add all compiler options to the CodeLite compiler options, separaated by space
std::string compilerOptionsCLString = "";
for(unsigned int idxOption = 0; idxOption < compilerOptions.size(); ++idxOption)
{
compilerOptionsCLString += compilerOptions[idxOption];
if(idxOption < compilerOptions.size() - 1)
compilerOptionsCLString += " ";
}
xmlElmCL_Compiler->SetAttribute("Options", compilerOptionsCLString);
// compiler settings:
// Required="yes"
// PreCompiledHeader=""
xmlElmCL_Compiler->SetAttribute("Required", "yes");
xmlElmCL_Compiler->SetAttribute("PreCompiledHeader", "");
// add Compiler -> IncludePath
std::string compilerIncludeDirectoryCLString = "";
for(unsigned int idxDir = 0; idxDir < compilerIncludeDirectories.size(); ++idxDir)
{
compilerIncludeDirectoryCLString += compilerIncludeDirectories[idxDir];
if(idxDir < compilerIncludeDirectories.size() - 1)
compilerIncludeDirectoryCLString += " ";
}
TiXmlElement* xmlElmCL_IncludePath = new TiXmlElement("IncludePath");
xmlElmCL_IncludePath->SetAttribute("Value", compilerIncludeDirectoryCLString);
xmlElmCL_Compiler->LinkEndChild(xmlElmCL_IncludePath);
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_Compiler);
// add Linker options
TiXmlElement* xmlElmCL_Linker = new TiXmlElement("Linker");
// get CB Linker options
TiXmlElement* xmlElmCB_Linker = xmlElmCB_Target->FirstChildElement("Linker");
std::vector<std::string> linkerOptions;
std::vector<std::string> linkerDirectories;
std::vector<std::string> linkerLibraries;
if(xmlElmCB_Linker != 0)
{
for( TiXmlElement* xmlElmCB_LinkerOption = xmlElmCB_Linker->FirstChildElement("Add");
xmlElmCB_LinkerOption;
xmlElmCB_LinkerOption = xmlElmCB_LinkerOption->NextSiblingElement("Add"))
{
if(xmlElmCB_LinkerOption->Attribute("option") != 0)
{
std::string linkerOption(xmlElmCB_LinkerOption->Attribute("option"));
linkerOptions.push_back(linkerOption);
}
if(xmlElmCB_LinkerOption->Attribute("directory") != 0)
{
std::string linkerIncludeDirectory(xmlElmCB_LinkerOption->Attribute("directory"));
linkerDirectories.push_back(linkerIncludeDirectory);
}
if(xmlElmCB_LinkerOption->Attribute("library") != 0)
{
std::string linkerLibrary(xmlElmCB_LinkerOption->Attribute("library"));
linkerLibraries.push_back(linkerLibrary);
}
}
} // if(xmlElmCB_Linker != 0)
/*
CB
<Add option="">
Adds a linker option (e.g. "-Wl,--export-all-symbols").
<Add directory="">
Adds a linker search directory.
<Add library="">
*/
// create CodeLite linker strings
std::string linkerOptionsCL;
for(unsigned int idxOption = 0; idxOption < linkerOptions.size(); ++idxOption)
{
linkerOptionsCL += linkerOptions[idxOption];
if(idxOption < linkerOptions.size() - 1)
linkerOptionsCL += " ";
}
std::string linkerDirectoriesCL;
for(unsigned int idxDir = 0; idxDir < linkerDirectories.size(); ++idxDir)
{
linkerDirectoriesCL += linkerDirectories[idxDir];
if(idxDir < linkerDirectories.size() - 1)
linkerDirectoriesCL += ";";
}
std::string linkerLibrariesCL;
for(unsigned int idxLib = 0; idxLib < linkerLibraries.size(); ++idxLib)
{
linkerLibrariesCL += "-l" + linkerLibraries[idxLib];
if(idxLib < linkerLibraries.size() - 1)
linkerLibrariesCL += " ";
}
// add to CodeLite Linker
/*
CL
<Linker Options="-l" Required="yes">
<LibraryPath Value="c:\"/>
<Library Value="-lalleg"/>
</Linker>
*/
xmlElmCL_Linker->SetAttribute("Options", linkerOptionsCL);
if(linkerDirectoriesCL != "")
{
TiXmlElement* xmlElmCL_LibraryPath = new TiXmlElement("LibraryPath");
xmlElmCL_LibraryPath->SetAttribute("Value", linkerDirectoriesCL);
xmlElmCL_Linker->LinkEndChild(xmlElmCL_LibraryPath);
}
if(linkerLibrariesCL != "")
{
TiXmlElement* xmlElmCL_Library = new TiXmlElement("Library");
xmlElmCL_Library->SetAttribute("Value", linkerLibrariesCL);
xmlElmCL_Linker->LinkEndChild(xmlElmCL_Library);
}
// add Required attribute
// using default Required="yes"
xmlElmCL_Linker->SetAttribute("Required", "yes");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_Linker);
// add ResourceCompiler
TiXmlElement* xmlElmCL_ResourceCompiler = new TiXmlElement("ResourceCompiler");
xmlElmCL_ResourceCompiler->SetAttribute("Options", "");
xmlElmCL_ResourceCompiler->SetAttribute("Required", "no");
// set General options
//<General OutputFile="./CodeLite/UtilsD.dll" IntermediateDirectory="./CodeLite/obj/Debug" Command="" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
TiXmlElement* xmlElmCL_General = new TiXmlElement("General");
// set OutputFile attribute
// get output info from CodeBlocks (dependant on the following)
// Target -> Option output="<filename path>" prefix_auto="<1 or not present>" extension_auto="<1 or not present>"
// Target -> Option type="<filename path>"
// Target -> Option createStaticLib="1"
std::string outputFilePath;
std::string outputFilePrefixAuto;
std::string outputFileExtensionAuto;
//std::string outputFileType; // already gotten previously in "int outputFileType"
std::string outputFileCreateStaticLib;
for( TiXmlElement* xmlElmCB_Option = xmlElmCB_Target->FirstChildElement("Option");
xmlElmCB_Option;
xmlElmCB_Option = xmlElmCB_Option->NextSiblingElement("Option"))
{
if(xmlElmCB_Option->Attribute("output") != 0)
{
outputFilePath = std::string(xmlElmCB_Option->Attribute("output"));
}
if(xmlElmCB_Option->Attribute("prefix_auto") != 0)
{
outputFilePrefixAuto = std::string(xmlElmCB_Option->Attribute("prefix_auto"));
}
if(xmlElmCB_Option->Attribute("extension_auto") != 0)
{
outputFileExtensionAuto = std::string(xmlElmCB_Option->Attribute("extension_auto"));
}
if(xmlElmCB_Option->Attribute("createStaticLib") != 0)
{
outputFileCreateStaticLib = std::string(xmlElmCB_Option->Attribute("createStaticLib"));
}
}
// generate OutputFile attribute based on CodeBlocks properties
std::string outputFileCL;
// separate directories from output file path
std::string outputFileCLDirectories;
std::string outputFileCLFilename;
// parse
unsigned int lastSlashPos = outputFilePath.find_last_of("\\");
if(lastSlashPos != outputFilePath.npos)
{
outputFileCLDirectories = outputFilePath.substr(0, lastSlashPos);
outputFileCLFilename = outputFilePath.substr(lastSlashPos);
}
else
outputFileCLFilename = outputFilePath;
if(outputFilePrefixAuto == "1")
{
switch(outputFileType)
{
case 2:
outputFileCLFilename = "lib" + outputFileCLFilename;
break;
}
}
if(outputFileExtensionAuto == "1")
{
switch(outputFileType)
{
// Exe's
case 0: // gui (no console)
case 1: // console
outputFileCLFilename += ".exe";
break;
// libs
case 2: // static lib
outputFileCLFilename += ".a";
break;
case 3: // dynamic lib
outputFileCLFilename += ".dll";
break;
default:
break;
}
}
outputFileCL += outputFileCLDirectories + outputFileCLFilename;
// in filename, replace "\" with "/"
for(unsigned int idxChar = 0; idxChar < outputFileCL.size(); ++idxChar)
if(outputFileCL[idxChar] == '\\') outputFileCL[idxChar] = '/';
// set OutputFile attribute
xmlElmCL_General->SetAttribute("OutputFile", outputFileCL);
// set IntermediateDirectory attribute
// based on CodeBlocks Target -> Option attribute "object_output"
std::string CBtargetObjectOutputDir;
for( TiXmlElement* xmlElmCB_Option = xmlElmCB_Target->FirstChildElement("Option");
xmlElmCB_Option;
xmlElmCB_Option = xmlElmCB_Option->NextSiblingElement("Option"))
{
if(xmlElmCB_Option->Attribute("object_output") != 0)
{
CBtargetObjectOutputDir = std::string(xmlElmCB_Option->Attribute("object_output"));
}
}
// in filename, replace "\" with "/"
for(unsigned int idxChar = 0; idxChar < CBtargetObjectOutputDir.size(); ++idxChar)
if(CBtargetObjectOutputDir[idxChar] == '\\') CBtargetObjectOutputDir[idxChar] = '/';
xmlElmCL_General->SetAttribute("IntermediateDirectory", CBtargetObjectOutputDir);
// setting default parameters
// Command="" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"
xmlElmCL_General->SetAttribute("Command", "");
xmlElmCL_General->SetAttribute("CommandArguments", "");
xmlElmCL_General->SetAttribute("WorkingDirectory", "$(IntermediateDirectory)");
xmlElmCL_General->SetAttribute("PauseExecWhenProcTerminates", "yes");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_General);
//<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
// <PostConnectCommands/>
// <StartupCommands/>
//</Debugger>
TiXmlElement* xmlElmCL_Debugger = new TiXmlElement("Debugger");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_Debugger);
xmlElmCL_Debugger->SetAttribute("IsRemote", "no");
xmlElmCL_Debugger->SetAttribute("RemoteHostName", "");
xmlElmCL_Debugger->SetAttribute("RemoteHostPort", "");
xmlElmCL_Debugger->SetAttribute("DebuggerPath", "");
TiXmlElement* xmlElmCL_PostConnectCommands = new TiXmlElement("PostConnectCommands");
xmlElmCL_Debugger->LinkEndChild(xmlElmCL_PostConnectCommands);
TiXmlElement* xmlElmCL_StartupCommands = new TiXmlElement("StartupCommands");
xmlElmCL_Debugger->LinkEndChild(xmlElmCL_StartupCommands);
//<PreBuild/>
TiXmlElement* xmlElmCL_PreBuild = new TiXmlElement("PreBuild");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_PreBuild);
//<PostBuild/>
TiXmlElement* xmlElmCL_PostBuild = new TiXmlElement("PostBuild");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_PostBuild);
// <CustomBuild Enabled="no">
// <RebuildCommand/>
// <CleanCommand/>
// <BuildCommand/>
// <PreprocessFileCommand/>
// <SingleFileCommand/>
// <MakefileGenerationCommand/>
// <ThirdPartyToolName>None</ThirdPartyToolName>
// <WorkingDirectory/>
// </CustomBuild>
TiXmlElement* xmlElmCL_CustomBuild = new TiXmlElement("CustomBuild");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_CustomBuild);
xmlElmCL_CustomBuild->SetAttribute("Enabled", "no");
TiXmlElement* xmlElmCL_RebuildCommand = new TiXmlElement("RebuildCommand");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_RebuildCommand);
TiXmlElement* xmlElmCL_CleanCommand = new TiXmlElement("CleanCommand");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_CleanCommand);
TiXmlElement* xmlElmCL_BuildCommand = new TiXmlElement("BuildCommand");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_BuildCommand);
TiXmlElement* xmlElmCL_PreprocessFileCommand = new TiXmlElement("PreprocessFileCommand");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_PreprocessFileCommand);
TiXmlElement* xmlElmCL_SingleFileCommand = new TiXmlElement("SingleFileCommand");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_SingleFileCommand);
TiXmlElement* xmlElmCL_MakefileGenerationCommand = new TiXmlElement("MakefileGenerationCommand");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_MakefileGenerationCommand);
TiXmlElement* xmlElmCL_ThirdPartyToolName = new TiXmlElement("ThirdPartyToolName");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_ThirdPartyToolName);
TiXmlText* xmlElmCL_ThirdPartyToolNameText = new TiXmlText("None");
xmlElmCL_ThirdPartyToolName->LinkEndChild(xmlElmCL_ThirdPartyToolNameText);
TiXmlElement* xmlElmCL_WorkingDirectory = new TiXmlElement("WorkingDirectory");
xmlElmCL_CustomBuild->LinkEndChild(xmlElmCL_WorkingDirectory);
// <AdditionalRules>
// <CustomPostBuild/>
// <CustomPreBuild/>
// </AdditionalRules>
TiXmlElement* xmlElmCL_AdditionalRules = new TiXmlElement("AdditionalRules");
xmlElmCL_Configuration->LinkEndChild(xmlElmCL_AdditionalRules);
TiXmlElement* xmlElmCL_CustomPostBuild = new TiXmlElement("CustomPostBuild");
xmlElmCL_AdditionalRules->LinkEndChild(xmlElmCL_CustomPostBuild);
TiXmlElement* xmlElmCL_CustomPreBuild = new TiXmlElement("CustomPreBuild");
xmlElmCL_AdditionalRules->LinkEndChild(xmlElmCL_CustomPreBuild);
}
// add GlobalSettings
TiXmlElement* xmlElmCL_GlobalSettings = new TiXmlElement("GlobalSettings");
xmlElmCL_Settings->LinkEndChild(xmlElmCL_GlobalSettings);
// GlobalSettings -> Compiler
// get settings from CodeBlocks global Compiler settings (Project -> Compiler)
TiXmlElement* xmlElmCB_Compiler = xmlElmCB_Project->FirstChildElement("Compiler");
if(xmlElmCB_Compiler != 0)
{
std::vector<std::string> globalSettingsCompilerOptions;
std::vector<std::string> globalSettingsCompilerDirectories;
for( TiXmlElement* xmlElmCB_Option = xmlElmCB_Compiler->FirstChildElement("Add");
xmlElmCB_Option;
xmlElmCB_Option = xmlElmCB_Option->NextSiblingElement("Add"))
{
if(xmlElmCB_Option->Attribute("option") != 0)
{
globalSettingsCompilerOptions.push_back(std::string(xmlElmCB_Option->Attribute("option")));
}
if(xmlElmCB_Option->Attribute("directory") != 0)
{
globalSettingsCompilerDirectories.push_back(std::string(xmlElmCB_Option->Attribute("directory")));
}
}
// add CB compiler options
// Compiler Options="<add concatenated compiler options string here>"
TiXmlElement* xmlElmCL_CompilerGlobal = new TiXmlElement("Compiler");
xmlElmCL_GlobalSettings->LinkEndChild(xmlElmCL_CompilerGlobal);
std::string compilerOptionsCL;
for(unsigned int idxOpt = 0; idxOpt < globalSettingsCompilerOptions.size(); ++idxOpt)
{
compilerOptionsCL += globalSettingsCompilerOptions[idxOpt];
if(idxOpt < globalSettingsCompilerOptions.size() - 1)
compilerOptionsCL += " ";
}
xmlElmCL_CompilerGlobal->SetAttribute("Options", compilerOptionsCL);
// add CB include path
// one Compiler -> IncludePath tag for each entry
for(unsigned int idxIncPath = 0; idxIncPath < globalSettingsCompilerDirectories.size(); ++idxIncPath)
{
TiXmlElement* xmlElmCL_IncludePath = new TiXmlElement("IncludePath");
xmlElmCL_CompilerGlobal->LinkEndChild(xmlElmCL_IncludePath);
// in filename, replace "\" with "/"
for(unsigned int idxChar = 0; idxChar < globalSettingsCompilerDirectories[idxIncPath].size(); ++idxChar)
if(globalSettingsCompilerDirectories[idxIncPath][idxChar] == '\\') globalSettingsCompilerDirectories[idxIncPath][idxChar] = '/';
xmlElmCL_IncludePath->SetAttribute("Value", globalSettingsCompilerDirectories[idxIncPath]);
}
} // if(xmlElmCB_Compiler != 0)
else
{
// add default compiler stuff
/*
<Compiler Options="">
<IncludePath Value="."/>
</Compiler>
*/
TiXmlElement* xmlElmCL_CompilerGlobal = new TiXmlElement("Compiler");
xmlElmCL_GlobalSettings->LinkEndChild(xmlElmCL_CompilerGlobal);
xmlElmCL_CompilerGlobal->SetAttribute("Options","");
TiXmlElement* xmlElmCL_IncludePath = new TiXmlElement("IncludePath");
xmlElmCL_CompilerGlobal->LinkEndChild(xmlElmCL_IncludePath);
xmlElmCL_IncludePath->SetAttribute("Value",".");
}
// GlobalSettings -> Linker
// get settings from CodeBlocks global Linker settings (Project -> Linker)
TiXmlElement* xmlElmCB_Linker = xmlElmCB_Project->FirstChildElement("Linker");
if(xmlElmCB_Linker != 0)
{
std::vector<std::string> globalSettingsLinkerOptions;
std::vector<std::string> globalSettingsLinkerDirectories;
std::vector<std::string> globalSettingsLinkerLibraries;
for( TiXmlElement* xmlElmCB_Option = xmlElmCB_Linker->FirstChildElement("Add");
xmlElmCB_Option;
xmlElmCB_Option = xmlElmCB_Option->NextSiblingElement("Add"))
{
if(xmlElmCB_Option->Attribute("option") != 0)
{
globalSettingsLinkerOptions.push_back(std::string(xmlElmCB_Option->Attribute("option")));
}
if(xmlElmCB_Option->Attribute("directory") != 0)
{
globalSettingsLinkerDirectories.push_back(std::string(xmlElmCB_Option->Attribute("directory")));
}
if(xmlElmCB_Option->Attribute("library") != 0)
{
globalSettingsLinkerLibraries.push_back(std::string(xmlElmCB_Option->Attribute("library")));
}
}
// add CB linker options
TiXmlElement* xmlElmCL_LinkerGlobal = new TiXmlElement("Linker");
xmlElmCL_GlobalSettings->LinkEndChild(xmlElmCL_LinkerGlobal);
std::string linkerOptionsCL;
for(unsigned int idxOpt = 0; idxOpt < globalSettingsLinkerOptions.size(); ++idxOpt)
{
linkerOptionsCL += globalSettingsLinkerOptions[idxOpt];
if(idxOpt < globalSettingsLinkerOptions.size() - 1)
linkerOptionsCL += " ";
}
xmlElmCL_LinkerGlobal->SetAttribute("Options", linkerOptionsCL);
// add CB linker library path
// one Linker -> LibraryPath tag for each entry
for(unsigned int idxLibPath = 0; idxLibPath < globalSettingsLinkerDirectories.size(); ++idxLibPath)
{
TiXmlElement* xmlElmCL_LibraryPath = new TiXmlElement("LibraryPath");
xmlElmCL_LinkerGlobal->LinkEndChild(xmlElmCL_LibraryPath);
xmlElmCL_LibraryPath->SetAttribute("Value", globalSettingsLinkerDirectories[idxLibPath]);
}
// add CB linker libraries
// one Linker -> Library tag for each entry
for(unsigned int idxLib = 0; idxLib < globalSettingsLinkerLibraries.size(); ++idxLib)
{
TiXmlElement* xmlElmCL_Library = new TiXmlElement("Library");
xmlElmCL_LinkerGlobal->LinkEndChild(xmlElmCL_Library);
xmlElmCL_Library->SetAttribute("Value", globalSettingsLinkerLibraries[idxLib]);
}
} // if(xmlElmCB_Linker != 0)
else
{
/*
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
*/
TiXmlElement* xmlElmCL_LinkerGlobal = new TiXmlElement("Linker");
xmlElmCL_GlobalSettings->LinkEndChild(xmlElmCL_LinkerGlobal);
xmlElmCL_LinkerGlobal->SetAttribute("Options","");
TiXmlElement* xmlElmCL_LibraryPath = new TiXmlElement("LibraryPath");
xmlElmCL_LinkerGlobal->LinkEndChild(xmlElmCL_LibraryPath);
xmlElmCL_LibraryPath->SetAttribute("Value", ".");
}
// GlobalSettings -> ResourceCompiler
// get settings from CodeBlocks global ResourceCompiler settings (Project -> ResourceCompiler)
TiXmlElement* xmlElmCB_ResourceCompiler = xmlElmCB_Project->FirstChildElement("ResourceCompiler");
if(xmlElmCB_ResourceCompiler != 0)
{
// TODO really get it, using default
// <ResourceCompiler Options=""/>
TiXmlElement* xmlElmCL_ResourceCompiler = new TiXmlElement("ResourceCompiler");
xmlElmCL_GlobalSettings->LinkEndChild(xmlElmCL_ResourceCompiler);
xmlElmCL_ResourceCompiler->SetAttribute("Options", "");
}
else
{
// <ResourceCompiler Options=""/>
TiXmlElement* xmlElmCL_ResourceCompiler = new TiXmlElement("ResourceCompiler");
xmlElmCL_GlobalSettings->LinkEndChild(xmlElmCL_ResourceCompiler);
xmlElmCL_ResourceCompiler->SetAttribute("Options", "");
}
// add CodeLite Dependencies, one for each Configuration
// use configurationNamesList
for(unsigned int idxConfigName = 0; idxConfigName < configurationNamesList.size(); ++idxConfigName)
{
TiXmlElement* xmlElmCL_Dependencies = new TiXmlElement("Dependencies");
xmlElmCL_CodeLite_Project->LinkEndChild(xmlElmCL_Dependencies);
xmlElmCL_Dependencies->SetAttribute("Name", configurationNamesList[idxConfigName]);
}
XMLUtils::dump_to_stdout(xmlElmCL_Root); // debug
// save CodeLite project
xmlElmCL_Root->SaveFile(filepathCodeLiteProject);
return 0;
}
Code: Select all
#ifndef XMLUTILS_H
#define XMLUTILS_H
#define TIXML_USE_STL
#include <tinyxml.h>
class XMLUtils {
public:
// tutorial demo program
//#include "stdafx.h"
//#include "tinyxml.h"
static const int NUM_INDENTS_PER_SPACE = 2;
// ----------------------------------------------------------------------
// STDOUT dump and indenting utility functions
// ----------------------------------------------------------------------
static const char * getIndent( unsigned int numIndents )
{
static const char * pINDENT=" + ";
static const unsigned int LENGTH=strlen( pINDENT );
unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
if ( n > LENGTH ) n = LENGTH;
return &pINDENT[ LENGTH-n ];
}
// same as getIndent but no "+" at the end
static const char * getIndentAlt( unsigned int numIndents )
{
static const char * pINDENT=" ";
static const unsigned int LENGTH=strlen( pINDENT );
unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
if ( n > LENGTH ) n = LENGTH;
return &pINDENT[ LENGTH-n ];
}
static int dump_attribs_to_stdout(TiXmlElement* pElement, unsigned int indent)
{
if ( !pElement ) return 0;
TiXmlAttribute* pAttrib=pElement->FirstAttribute();
int i=0;
int ival;
double dval;
const char* pIndent=getIndent(indent);
printf("\n");
while (pAttrib)
{
printf( "%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value());
if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( " int=%d", ival);
if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
printf( "\n" );
i++;
pAttrib=pAttrib->Next();
}
return i;
}
static void dump_to_stdout( TiXmlNode* pParent, unsigned int indent = 0 )
{
if ( !pParent ) return;
TiXmlNode* pChild;
TiXmlText* pText;
int t = pParent->Type();
printf( "%s", getIndent(indent));
int num;
switch ( t )
{
case TiXmlNode::DOCUMENT:
printf( "Document" );
break;
case TiXmlNode::ELEMENT:
printf( "Element [%s]", pParent->Value() );
num=dump_attribs_to_stdout(pParent->ToElement(), indent+1);
switch(num)
{
case 0: printf( " (No attributes)"); break;
case 1: printf( "%s1 attribute", getIndentAlt(indent)); break;
default: printf( "%s%d attributes", getIndentAlt(indent), num); break;
}
break;
case TiXmlNode::COMMENT:
printf( "Comment: [%s]", pParent->Value());
break;
case TiXmlNode::UNKNOWN:
printf( "Unknown" );
break;
case TiXmlNode::TEXT:
pText = pParent->ToText();
printf( "Text: [%s]", pText->Value() );
break;
case TiXmlNode::DECLARATION:
printf( "Declaration" );
break;
default:
break;
}
printf( "\n" );
for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
{
dump_to_stdout( pChild, indent+1 );
}
}
// load the named file and dump its structure to STDOUT
static void dump_to_stdout(const char* pFilename)
{
TiXmlDocument doc(pFilename);
bool loadOkay = doc.LoadFile();
if (loadOkay)
{
printf("\n%s:\n", pFilename);
dump_to_stdout( &doc ); // defined later in the tutorial
}
else
{
printf("Failed to load file \"%s\"\n", pFilename);
}
}
};
#endif // XMLUTILS_H