summaryrefslogtreecommitdiff
path: root/Source/cmExtraCodeBlocksGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmExtraCodeBlocksGenerator.cxx')
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx1028
1 files changed, 490 insertions, 538 deletions
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index dfbb1c0ad..5b7b82762 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -1,27 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraCodeBlocksGenerator.h"
-#include "cmGlobalUnixMakefileGenerator3.h"
-#include "cmLocalUnixMakefileGenerator3.h"
+
+#include <map>
+#include <ostream>
+#include <string.h>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmake.h"
#include "cmSourceFile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmTarget.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
-
-#include <cmsys/SystemTools.hxx>
+#include "cmXMLWriter.h"
+#include "cmake.h"
/* Some useful URLs:
Homepage:
@@ -36,66 +32,59 @@ Discussion:
http://forums.codeblocks.org/index.php/topic,6789.0.html
*/
-//----------------------------------------------------------------------------
-void cmExtraCodeBlocksGenerator
-::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
+ : cmExternalMakefileProjectGenerator()
{
- entry.Name = this->GetName();
- entry.Brief = "Generates CodeBlocks project files.";
- entry.Full =
- "Project files for CodeBlocks will be created in the top directory "
- "and in every subdirectory which features a CMakeLists.txt file "
- "containing a PROJECT() call. "
- "Additionally a hierarchy of makefiles is generated into the "
- "build tree. The appropriate make program can build the project through "
- "the default make target. A \"make install\" target is also provided.";
}
-cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
-:cmExternalMakefileProjectGenerator()
+cmExternalMakefileProjectGeneratorFactory*
+cmExtraCodeBlocksGenerator::GetFactory()
{
+ static cmExternalMakefileProjectGeneratorSimpleFactory<
+ cmExtraCodeBlocksGenerator>
+ factory("CodeBlocks", "Generates CodeBlocks project files.");
+
+ if (factory.GetSupportedGlobalGenerators().empty()) {
#if defined(_WIN32)
- this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
- this->SupportedGlobalGenerators.push_back("NMake Makefiles");
+ factory.AddSupportedGlobalGenerator("MinGW Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles JOM");
// disable until somebody actually tests it:
-// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
+// this->AddSupportedGlobalGenerator("MSYS Makefiles");
#endif
- this->SupportedGlobalGenerators.push_back("Ninja");
- this->SupportedGlobalGenerators.push_back("Unix Makefiles");
-}
+ factory.AddSupportedGlobalGenerator("Ninja");
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
+ }
+ return &factory;
+}
void cmExtraCodeBlocksGenerator::Generate()
{
// for each sub project in the project create a codeblocks project
- for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it!= this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
+ for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
// create a project file
this->CreateProjectFile(it->second);
- }
+ }
}
-
/* create the project file */
void cmExtraCodeBlocksGenerator::CreateProjectFile(
- const std::vector<cmLocalGenerator*>& lgs)
+ const std::vector<cmLocalGenerator*>& lgs)
{
- const cmMakefile* mf=lgs[0]->GetMakefile();
- std::string outputDir=mf->GetStartOutputDirectory();
- std::string projectName=mf->GetProjectName();
+ std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
+ std::string projectName = lgs[0]->GetProjectName();
- std::string filename=outputDir+"/";
- filename+=projectName+".cbp";
- std::string sessionFilename=outputDir+"/";
- sessionFilename+=projectName+".layout";
+ std::string filename = outputDir + "/";
+ filename += projectName + ".cbp";
+ std::string sessionFilename = outputDir + "/";
+ sessionFilename += projectName + ".layout";
this->CreateNewProjectFile(lgs, filename);
}
-
/* Tree is used to create a "Virtual Folder" in CodeBlocks, in which all
CMake files this project depends on will be put. This means additionally
to the "Sources" and "Headers" virtual folders of CodeBlocks, there will
@@ -104,720 +93,683 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile(
files in QtCreator).*/
struct Tree
{
- std::string path; //only one component of the path
+ std::string path; // only one component of the path
std::vector<Tree> folders;
std::vector<std::string> files;
void InsertPath(const std::vector<std::string>& splitted,
std::vector<std::string>::size_type start,
const std::string& fileName);
- void BuildVirtualFolder(std::string& virtualFolders) const;
+ void BuildVirtualFolder(cmXMLWriter& xml) const;
void BuildVirtualFolderImpl(std::string& virtualFolders,
const std::string& prefix) const;
- void BuildUnit(std::string& unitString, const std::string& fsPath) const;
- void BuildUnitImpl(std::string& unitString,
- const std::string& virtualFolderPath,
+ void BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const;
+ void BuildUnitImpl(cmXMLWriter& xml, const std::string& virtualFolderPath,
const std::string& fsPath) const;
};
-
void Tree::InsertPath(const std::vector<std::string>& splitted,
std::vector<std::string>::size_type start,
const std::string& fileName)
{
- if (start == splitted.size())
- {
+ if (start == splitted.size()) {
files.push_back(fileName);
return;
- }
- for (std::vector<Tree>::iterator
- it = folders.begin();
- it != folders.end();
- ++it)
- {
- if ((*it).path == splitted[start])
- {
- if (start + 1 < splitted.size())
- {
+ }
+ for (std::vector<Tree>::iterator it = folders.begin(); it != folders.end();
+ ++it) {
+ if ((*it).path == splitted[start]) {
+ if (start + 1 < splitted.size()) {
it->InsertPath(splitted, start + 1, fileName);
return;
- }
- else
- {
- // last part of splitted
- it->files.push_back(fileName);
- return;
- }
}
+ // last part of splitted
+ it->files.push_back(fileName);
+ return;
}
+ }
// Not found in folders, thus insert
Tree newFolder;
newFolder.path = splitted[start];
- if (start + 1 < splitted.size())
- {
+ if (start + 1 < splitted.size()) {
newFolder.InsertPath(splitted, start + 1, fileName);
folders.push_back(newFolder);
return;
- }
- else
- {
- // last part of splitted
- newFolder.files.push_back(fileName);
- folders.push_back(newFolder);
- return;
- }
+ }
+ // last part of splitted
+ newFolder.files.push_back(fileName);
+ folders.push_back(newFolder);
}
-
-void Tree::BuildVirtualFolder(std::string& virtualFolders) const
+void Tree::BuildVirtualFolder(cmXMLWriter& xml) const
{
- virtualFolders += "<Option virtualFolders=\"CMake Files\\;";
+ xml.StartElement("Option");
+ std::string virtualFolders = "CMake Files\\;";
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
+ it != folders.end(); ++it) {
it->BuildVirtualFolderImpl(virtualFolders, "");
- }
- virtualFolders += "\" />";
+ }
+ xml.Attribute("virtualFolders", virtualFolders);
+ xml.EndElement();
}
-
void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
const std::string& prefix) const
{
- virtualFolders += "CMake Files\\" + prefix + path + "\\;";
+ virtualFolders += "CMake Files\\" + prefix + path + "\\;";
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
+ it != folders.end(); ++it) {
it->BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
- }
+ }
}
-
-void Tree::BuildUnit(std::string& unitString, const std::string& fsPath) const
+void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
{
for (std::vector<std::string>::const_iterator it = files.begin();
- it != files.end();
- ++it)
- {
- unitString += " <Unit filename=\"" + fsPath + *it + "\">\n";
- unitString += " <Option virtualFolder=\"CMake Files\\\" />\n";
- unitString += " </Unit>\n";
- }
+ it != files.end(); ++it) {
+ xml.StartElement("Unit");
+ xml.Attribute("filename", fsPath + *it);
+
+ xml.StartElement("Option");
+ xml.Attribute("virtualFolder", "CMake Files\\");
+ xml.EndElement();
+
+ xml.EndElement();
+ }
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
- it->BuildUnitImpl(unitString, "", fsPath);
- }
+ it != folders.end(); ++it) {
+ it->BuildUnitImpl(xml, "", fsPath);
+ }
}
-
-void Tree::BuildUnitImpl(std::string& unitString,
+void Tree::BuildUnitImpl(cmXMLWriter& xml,
const std::string& virtualFolderPath,
const std::string& fsPath) const
{
for (std::vector<std::string>::const_iterator it = files.begin();
- it != files.end();
- ++it)
- {
- unitString += " <Unit filename=\"" +fsPath+path+ "/" + *it + "\">\n";
- unitString += " <Option virtualFolder=\"CMake Files\\"
- + virtualFolderPath + path + "\\\" />\n";
- unitString += " </Unit>\n";
- }
+ it != files.end(); ++it) {
+ xml.StartElement("Unit");
+ xml.Attribute("filename", fsPath + path + "/" + *it);
+
+ xml.StartElement("Option");
+ xml.Attribute("virtualFolder",
+ "CMake Files\\" + virtualFolderPath + path + "\\");
+ xml.EndElement();
+
+ xml.EndElement();
+ }
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
- it->BuildUnitImpl(unitString,
- virtualFolderPath + path + "\\", fsPath + path + "/");
- }
+ it != folders.end(); ++it) {
+ it->BuildUnitImpl(xml, virtualFolderPath + path + "\\",
+ fsPath + path + "/");
+ }
}
-
-void cmExtraCodeBlocksGenerator
- ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
- const std::string& filename)
+void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
- const cmMakefile* mf=lgs[0]->GetMakefile();
+ const cmMakefile* mf = lgs[0]->GetMakefile();
cmGeneratedFileStream fout(filename.c_str());
- if(!fout)
- {
+ if (!fout) {
return;
- }
+ }
Tree tree;
// build tree of virtual folders
- for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
+ for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
// Collect all files
std::vector<std::string> listFiles;
- for (std::vector<cmLocalGenerator *>::const_iterator
- jt = it->second.begin();
- jt != it->second.end();
- ++jt)
- {
- const std::vector<std::string> & files =
- (*jt)->GetMakefile()->GetListFiles();
+ for (std::vector<cmLocalGenerator*>::const_iterator jt =
+ it->second.begin();
+ jt != it->second.end(); ++jt) {
+ const std::vector<std::string>& files =
+ (*jt)->GetMakefile()->GetListFiles();
listFiles.insert(listFiles.end(), files.begin(), files.end());
- }
+ }
// Convert
- const char* cmakeRoot = mf->GetDefinition("CMAKE_ROOT");
for (std::vector<std::string>::const_iterator jt = listFiles.begin();
- jt != listFiles.end();
- ++jt)
- {
+ jt != listFiles.end(); ++jt) {
// don't put cmake's own files into the project (#12110):
- if (jt->find(cmakeRoot) == 0)
- {
+ if (jt->find(cmSystemTools::GetCMakeRoot()) == 0) {
continue;
- }
+ }
- const std::string &relative = cmSystemTools::RelativePath(
- it->second[0]->GetMakefile()->GetHomeDirectory(),
- jt->c_str());
+ const std::string& relative = cmSystemTools::RelativePath(
+ it->second[0]->GetSourceDirectory(), jt->c_str());
std::vector<std::string> splitted;
- cmSystemTools::SplitPath(relative.c_str(), splitted, false);
+ cmSystemTools::SplitPath(relative, splitted, false);
// Split filename from path
- std::string fileName = *(splitted.end()-1);
+ std::string fileName = *(splitted.end() - 1);
splitted.erase(splitted.end() - 1, splitted.end());
// We don't want paths with CMakeFiles in them
// or do we?
// In speedcrunch those where purely internal
- if (splitted.size() >= 1
- && relative.find("CMakeFiles") == std::string::npos)
- {
+ if (!splitted.empty() &&
+ relative.find("CMakeFiles") == std::string::npos) {
tree.InsertPath(splitted, 1, fileName);
- }
}
}
-
- // Now build a virtual tree string
- std::string virtualFolders;
- tree.BuildVirtualFolder(virtualFolders);
- // And one for <Unit>
- std::string unitFiles;
- tree.BuildUnit(unitFiles, std::string(mf->GetHomeDirectory()) + "/");
+ }
// figure out the compiler
std::string compiler = this->GetCBCompilerId(mf);
std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string makeArgs =
+ mf->GetSafeDefinition("CMAKE_CODEBLOCKS_MAKE_ARGUMENTS");
+
+ cmXMLWriter xml(fout);
+ xml.StartDocument();
+ xml.StartElement("CodeBlocks_project_file");
+
+ xml.StartElement("FileVersion");
+ xml.Attribute("major", 1);
+ xml.Attribute("minor", 6);
+ xml.EndElement();
+
+ xml.StartElement("Project");
+
+ xml.StartElement("Option");
+ xml.Attribute("title", lgs[0]->GetProjectName());
+ xml.EndElement();
- fout<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
- "<CodeBlocks_project_file>\n"
- " <FileVersion major=\"1\" minor=\"6\" />\n"
- " <Project>\n"
- " <Option title=\"" << mf->GetProjectName()<<"\" />\n"
- " <Option makefile_is_custom=\"1\" />\n"
- " <Option compiler=\"" << compiler << "\" />\n"
- " "<<virtualFolders<<"\n"
- " <Build>\n";
+ xml.StartElement("Option");
+ xml.Attribute("makefile_is_custom", 1);
+ xml.EndElement();
- this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str());
+ xml.StartElement("Option");
+ xml.Attribute("compiler", compiler);
+ xml.EndElement();
+
+ // Now build a virtual tree
+ tree.BuildVirtualFolder(xml);
+
+ xml.StartElement("Build");
+
+ this->AppendTarget(xml, "all", CM_NULLPTR, make.c_str(), lgs[0],
+ compiler.c_str(), makeArgs);
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
- lg!=lgs.end(); lg++)
- {
- cmMakefile* makefile=(*lg)->GetMakefile();
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- switch(ti->second.GetType())
- {
- case cmTarget::GLOBAL_TARGET:
- {
- bool insertTarget = false;
+ for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
+ lg != lgs.end(); lg++) {
+ std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
+ ti != targets.end(); ti++) {
+ std::string targetName = (*ti)->GetName();
+ switch ((*ti)->GetType()) {
+ case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp(makefile->GetStartOutputDirectory(),
- makefile->GetHomeOutputDirectory())==0)
- {
- insertTarget = true;
- // only add the "edit_cache" target if it's not ccmake, because
- // this will not work within the IDE
- if (ti->first == "edit_cache")
- {
- const char* editCommand = makefile->GetDefinition
- ("CMAKE_EDIT_COMMAND");
- if (editCommand == 0)
- {
- insertTarget = false;
- }
- else if (strstr(editCommand, "ccmake")!=NULL)
- {
- insertTarget = false;
- }
- }
- }
- if (insertTarget)
- {
- this->AppendTarget(fout, ti->first.c_str(), 0,
- make.c_str(), makefile, compiler.c_str());
- }
+ if (strcmp((*lg)->GetCurrentBinaryDirectory(),
+ (*lg)->GetBinaryDirectory()) == 0) {
+ this->AppendTarget(xml, targetName, CM_NULLPTR, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
}
- break;
- case cmTarget::UTILITY:
+ } break;
+ case cmStateEnums::UTILITY:
// Add all utility targets, except the Nightly/Continuous/
// Experimental-"sub"targets as e.g. NightlyStart
- if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly"))
- || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
- || ((ti->first.find("Experimental")==0)
- && (ti->first!="Experimental")))
- {
+ if (((targetName.find("Nightly") == 0) &&
+ (targetName != "Nightly")) ||
+ ((targetName.find("Continuous") == 0) &&
+ (targetName != "Continuous")) ||
+ ((targetName.find("Experimental") == 0) &&
+ (targetName != "Experimental"))) {
break;
- }
+ }
- this->AppendTarget(fout, ti->first.c_str(), 0,
- make.c_str(), makefile, compiler.c_str());
+ this->AppendTarget(xml, targetName, CM_NULLPTR, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
break;
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- {
- this->AppendTarget(fout, ti->first.c_str(), &ti->second,
- make.c_str(), makefile, compiler.c_str());
- std::string fastTarget = ti->first;
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY: {
+ cmGeneratorTarget* gt = *ti;
+ this->AppendTarget(xml, targetName, gt, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
+ std::string fastTarget = targetName;
fastTarget += "/fast";
- this->AppendTarget(fout, fastTarget.c_str(), &ti->second,
- make.c_str(), makefile, compiler.c_str());
- }
- break;
+ this->AppendTarget(xml, fastTarget, gt, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
+ } break;
default:
break;
- }
}
}
-
- fout<<" </Build>\n";
-
-
- // Collect all used source files in the project
- // Sort them into two containers, one for C/C++ implementation files
- // which may have an acompanying header, one for all other files
- std::map<std::string, cmSourceFile*> cFiles;
- std::set<std::string> otherFiles;
- for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
- lg!=lgs.end(); lg++)
- {
- cmMakefile* makefile=(*lg)->GetMakefile();
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- switch(ti->second.GetType())
+ }
+
+ xml.EndElement(); // Build
+
+ // Collect all used source files in the project.
+ // Keep a list of C/C++ source files which might have an acompanying header
+ // that should be looked for.
+ typedef std::map<std::string, CbpUnit> all_files_map_t;
+ all_files_map_t allFiles;
+ std::vector<std::string> cFiles;
+
+ std::vector<std::string> const& srcExts =
+ this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
+
+ for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
+ lg != lgs.end(); lg++) {
+ cmMakefile* makefile = (*lg)->GetMakefile();
+ std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
+ ti != targets.end(); ti++) {
+ switch ((*ti)->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::UTILITY: // can have sources since 2.6.3
{
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::UTILITY: // can have sources since 2.6.3
- {
- const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
- for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();
- si!=sources.end(); si++)
- {
- // don't add source files which have the GENERATED property set:
- if ((*si)->GetPropertyAsBool("GENERATED"))
- {
+ std::vector<cmSourceFile*> sources;
+ cmGeneratorTarget* gt = *ti;
+ gt->GetSourceFiles(sources,
+ makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
+ for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
+ si != sources.end(); si++) {
+ // don't add source files from UTILITY target which have the
+ // GENERATED property set:
+ if (gt->GetType() == cmStateEnums::UTILITY &&
+ (*si)->GetPropertyAsBool("GENERATED")) {
continue;
- }
+ }
// check whether it is a C/C++ implementation file
bool isCFile = false;
- if ((*si)->GetLanguage() && (*(*si)->GetLanguage() == 'C'))
- {
- for(std::vector<std::string>::const_iterator
- ext = mf->GetSourceExtensions().begin();
- ext != mf->GetSourceExtensions().end();
- ++ext)
- {
- if ((*si)->GetExtension() == *ext)
- {
+ std::string lang = (*si)->GetLanguage();
+ if (lang == "C" || lang == "CXX") {
+ std::string const& srcext = (*si)->GetExtension();
+ for (std::vector<std::string>::const_iterator ext =
+ srcExts.begin();
+ ext != srcExts.end(); ++ext) {
+ if (srcext == *ext) {
isCFile = true;
break;
- }
}
}
+ }
- // then put it accordingly into one of the two containers
- if (isCFile)
- {
- cFiles[(*si)->GetFullPath()] = *si ;
- }
- else
- {
- otherFiles.insert((*si)->GetFullPath());
- }
+ std::string const& fullPath = (*si)->GetFullPath();
+
+ if (isCFile) {
+ cFiles.push_back(fullPath);
}
+
+ CbpUnit& cbpUnit = allFiles[fullPath];
+ cbpUnit.Targets.push_back(*ti);
}
- default: // intended fallthrough
- break;
}
+ default: // intended fallthrough
+ break;
}
}
+ }
+
+ std::vector<std::string> const& headerExts =
+ this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
// The following loop tries to add header files matching to implementation
- // files to the project. It does that by iterating over all source files,
+ // files to the project. It does that by iterating over all
+ // C/C++ source files,
// replacing the file name extension with ".h" and checks whether such a
// file exists. If it does, it is inserted into the map of files.
// A very similar version of that code exists also in the kdevelop
// project generator.
- for (std::map<std::string, cmSourceFile*>::const_iterator
- sit=cFiles.begin();
- sit!=cFiles.end();
- ++sit)
- {
- std::string headerBasename=cmSystemTools::GetFilenamePath(sit->first);
- headerBasename+="/";
- headerBasename+=cmSystemTools::GetFilenameWithoutExtension(sit->first);
+ for (std::vector<std::string>::const_iterator sit = cFiles.begin();
+ sit != cFiles.end(); ++sit) {
+ std::string const& fileName = *sit;
+ std::string headerBasename = cmSystemTools::GetFilenamePath(fileName);
+ headerBasename += "/";
+ headerBasename += cmSystemTools::GetFilenameWithoutExtension(fileName);
// check if there's a matching header around
- for(std::vector<std::string>::const_iterator
- ext = mf->GetHeaderExtensions().begin();
- ext != mf->GetHeaderExtensions().end();
- ++ext)
- {
- std::string hname=headerBasename;
+ for (std::vector<std::string>::const_iterator ext = headerExts.begin();
+ ext != headerExts.end(); ++ext) {
+ std::string hname = headerBasename;
hname += ".";
hname += *ext;
// if it's already in the set, don't check if it exists on disk
- std::set<std::string>::const_iterator headerIt=otherFiles.find(hname);
- if (headerIt != otherFiles.end())
- {
+ if (allFiles.find(hname) != allFiles.end()) {
break;
- }
+ }
- if(cmSystemTools::FileExists(hname.c_str()))
- {
- otherFiles.insert(hname);
+ if (cmSystemTools::FileExists(hname.c_str())) {
+ allFiles[hname].Targets = allFiles[fileName].Targets;
break;
- }
}
}
+ }
// insert all source files in the CodeBlocks project
- // first the C/C++ implementation files, then all others
- for (std::map<std::string, cmSourceFile*>::const_iterator
- sit=cFiles.begin();
- sit!=cFiles.end();
- ++sit)
- {
- fout<<" <Unit filename=\""<< sit->first <<"\">\n"
- " </Unit>\n";
- }
- for (std::set<std::string>::const_iterator
- sit=otherFiles.begin();
- sit!=otherFiles.end();
- ++sit)
- {
- fout<<" <Unit filename=\""<< sit->c_str() <<"\">\n"
- " </Unit>\n";
+ for (all_files_map_t::const_iterator sit = allFiles.begin();
+ sit != allFiles.end(); ++sit) {
+ std::string const& unitFilename = sit->first;
+ CbpUnit const& unit = sit->second;
+
+ xml.StartElement("Unit");
+ xml.Attribute("filename", unitFilename);
+
+ for (std::vector<const cmGeneratorTarget*>::const_iterator ti =
+ unit.Targets.begin();
+ ti != unit.Targets.end(); ++ti) {
+ xml.StartElement("Option");
+ xml.Attribute("target", (*ti)->GetName());
+ xml.EndElement();
}
+ xml.EndElement();
+ }
+
// Add CMakeLists.txt
- fout<<unitFiles;
+ tree.BuildUnit(xml, std::string(mf->GetHomeDirectory()) + "/");
- fout<<" </Project>\n"
- "</CodeBlocks_project_file>\n";
+ xml.EndElement(); // Project
+ xml.EndElement(); // CodeBlocks_project_file
+ xml.EndDocument();
}
-
// Write a dummy file for OBJECT libraries, so C::B can reference some file
std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
- cmMakefile* mf, cmTarget* target) const
+ cmLocalGenerator* lg, cmGeneratorTarget* target) const
{
// this file doesn't seem to be used by C::B in custom makefile mode,
// but we generate a unique file for each OBJECT library so in case
// C::B uses it in some way, the targets don't interfere with each other.
- std::string filename = mf->GetCurrentOutputDirectory();
+ std::string filename = lg->GetCurrentBinaryDirectory();
filename += "/";
- filename += mf->GetLocalGenerator()->GetTargetDirectory(*target);
+ filename += lg->GetTargetDirectory(target);
filename += "/";
filename += target->GetName();
filename += ".objlib";
cmGeneratedFileStream fout(filename.c_str());
- if(fout)
- {
+ if (fout) {
+ /* clang-format off */
fout << "# This is a dummy file for the OBJECT library "
<< target->GetName()
<< " for the CMake CodeBlocks project generator.\n"
<< "# Don't edit, this file will be overwritten.\n";
- }
+ /* clang-format on */
+ }
return filename;
}
-
// Generate the xml code for one target.
-void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
- const char* targetName,
- cmTarget* target,
- const char* make,
- const cmMakefile* makefile,
- const char* compiler)
+void cmExtraCodeBlocksGenerator::AppendTarget(
+ cmXMLWriter& xml, const std::string& targetName, cmGeneratorTarget* target,
+ const char* make, const cmLocalGenerator* lg, const char* compiler,
+ const std::string& makeFlags)
{
- std::string makefileName = makefile->GetStartOutputDirectory();
+ cmMakefile const* makefile = lg->GetMakefile();
+ std::string makefileName = lg->GetCurrentBinaryDirectory();
makefileName += "/Makefile";
- fout<<" <Target title=\"" << targetName << "\">\n";
- if (target!=0)
- {
+ xml.StartElement("Target");
+ xml.Attribute("title", targetName);
+
+ if (target != CM_NULLPTR) {
int cbTargetType = this->GetCBTargetType(target);
- std::string workingDir = makefile->GetStartOutputDirectory();
- if ( target->GetType()==cmTarget::EXECUTABLE)
- {
+ std::string workingDir = lg->GetCurrentBinaryDirectory();
+ if (target->GetType() == cmStateEnums::EXECUTABLE) {
// Determine the directory where the executable target is created, and
// set the working directory to this dir.
- const char* runtimeOutputDir = makefile->GetDefinition(
- "CMAKE_RUNTIME_OUTPUT_DIRECTORY");
- if (runtimeOutputDir != 0)
- {
+ const char* runtimeOutputDir =
+ makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
+ if (runtimeOutputDir != CM_NULLPTR) {
workingDir = runtimeOutputDir;
- }
- else
- {
- const char* executableOutputDir = makefile->GetDefinition(
- "EXECUTABLE_OUTPUT_PATH");
- if (executableOutputDir != 0)
- {
+ } else {
+ const char* executableOutputDir =
+ makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
+ if (executableOutputDir != CM_NULLPTR) {
workingDir = executableOutputDir;
- }
}
}
+ }
- const char* buildType = makefile->GetDefinition("CMAKE_BUILD_TYPE");
+ std::string buildType = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
std::string location;
- if ( target->GetType()==cmTarget::OBJECT_LIBRARY)
- {
- location = this->CreateDummyTargetFile(const_cast<cmMakefile*>(makefile),
- target);
- }
- else
- {
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ location =
+ this->CreateDummyTargetFile(const_cast<cmLocalGenerator*>(lg), target);
+ } else {
location = target->GetLocation(buildType);
- }
+ }
+
+ xml.StartElement("Option");
+ xml.Attribute("output", location);
+ xml.Attribute("prefix_auto", 0);
+ xml.Attribute("extension_auto", 0);
+ xml.EndElement();
+
+ xml.StartElement("Option");
+ xml.Attribute("working_dir", workingDir);
+ xml.EndElement();
- fout<<" <Option output=\"" << location
- << "\" prefix_auto=\"0\" extension_auto=\"0\" />\n"
- " <Option working_dir=\"" << workingDir << "\" />\n"
- " <Option object_output=\"./\" />\n"
- " <Option type=\"" << cbTargetType << "\" />\n"
- " <Option compiler=\"" << compiler << "\" />\n"
- " <Compiler>\n";
+ xml.StartElement("Option");
+ xml.Attribute("object_output", "./");
+ xml.EndElement();
- cmGeneratorTarget *gtgt = this->GlobalGenerator
- ->GetGeneratorTarget(target);
+ xml.StartElement("Option");
+ xml.Attribute("type", cbTargetType);
+ xml.EndElement();
+
+ xml.StartElement("Option");
+ xml.Attribute("compiler", compiler);
+ xml.EndElement();
+
+ xml.StartElement("Compiler");
// the compilerdefines for this target
std::vector<std::string> cdefs;
- target->GetCompileDefinitions(cdefs, buildType);
+ target->GetCompileDefinitions(cdefs, buildType, "C");
// Expand the list.
- for(std::vector<std::string>::const_iterator di = cdefs.begin();
- di != cdefs.end(); ++di)
- {
- cmXMLSafe safedef(di->c_str());
- fout <<" <Add option=\"-D" << safedef.str() << "\" />\n";
- }
+ for (std::vector<std::string>::const_iterator di = cdefs.begin();
+ di != cdefs.end(); ++di) {
+ xml.StartElement("Add");
+ xml.Attribute("option", "-D" + *di);
+ xml.EndElement();
+ }
// the include directories for this target
- std::set<std::string> uniqIncludeDirs;
+ std::vector<std::string> allIncludeDirs;
std::vector<std::string> includes;
- target->GetMakefile()->GetLocalGenerator()->
- GetIncludeDirectories(includes, gtgt, "C", buildType);
- for(std::vector<std::string>::const_iterator dirIt=includes.begin();
- dirIt != includes.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
+ lg->GetIncludeDirectories(includes, target, "C", buildType);
+
+ allIncludeDirs.insert(allIncludeDirs.end(), includes.begin(),
+ includes.end());
std::string systemIncludeDirs = makefile->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
- if (!systemIncludeDirs.empty())
- {
+ "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
+ if (!systemIncludeDirs.empty()) {
std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
- for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
- }
+ cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+ }
systemIncludeDirs = makefile->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
- if (!systemIncludeDirs.empty())
- {
+ "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
+ if (!systemIncludeDirs.empty()) {
std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
- for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
- }
+ cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+ }
- for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin();
- dirIt != uniqIncludeDirs.end();
- ++dirIt)
- {
- fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n";
- }
+ std::vector<std::string>::const_iterator end =
+ cmRemoveDuplicates(allIncludeDirs);
- fout<<" </Compiler>\n";
- }
- else // e.g. all and the GLOBAL and UTILITY targets
- {
- fout<<" <Option working_dir=\""
- << makefile->GetStartOutputDirectory() << "\" />\n"
- <<" <Option type=\"" << 4 << "\" />\n";
+ for (std::vector<std::string>::const_iterator i = allIncludeDirs.begin();
+ i != end; ++i) {
+ xml.StartElement("Add");
+ xml.Attribute("directory", *i);
+ xml.EndElement();
}
- fout<<" <MakeCommands>\n"
- " <Build command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(), targetName)
- << "\" />\n"
- " <CompileFile command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(),"&quot;$file&quot;")
- << "\" />\n"
- " <Clean command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
- << "\" />\n"
- " <DistClean command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
- << "\" />\n"
- " </MakeCommands>\n"
- " </Target>\n";
+ xml.EndElement(); // Compiler
+ } else // e.g. all and the GLOBAL and UTILITY targets
+ {
+ xml.StartElement("Option");
+ xml.Attribute("working_dir", lg->GetCurrentBinaryDirectory());
+ xml.EndElement();
-}
+ xml.StartElement("Option");
+ xml.Attribute("type", 4);
+ xml.EndElement();
+ }
+
+ xml.StartElement("MakeCommands");
+ xml.StartElement("Build");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ targetName, makeFlags));
+ xml.EndElement();
+
+ xml.StartElement("CompileFile");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ "\"$file\"", makeFlags));
+ xml.EndElement();
+
+ xml.StartElement("Clean");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ "clean", makeFlags));
+ xml.EndElement();
+
+ xml.StartElement("DistClean");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ "clean", makeFlags));
+ xml.EndElement();
+
+ xml.EndElement(); // MakeCommands
+ xml.EndElement(); // Target
+}
// Translate the cmake compiler id into the CodeBlocks compiler id
std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
{
// figure out which language to use
- // for now care only for C and C++
- std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
- if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false)
- {
+ // for now care only for C, C++, and Fortran
+
+ // projects with C/C++ and Fortran are handled as C/C++ projects
+ bool pureFortran = false;
+ std::string compilerIdVar;
+ if (this->GlobalGenerator->GetLanguageEnabled("CXX")) {
+ compilerIdVar = "CMAKE_CXX_COMPILER_ID";
+ } else if (this->GlobalGenerator->GetLanguageEnabled("C")) {
compilerIdVar = "CMAKE_C_COMPILER_ID";
- }
-
- std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
- std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- std::string compilerId = mf->GetSafeDefinition(compilerIdVar.c_str());
- std::string compiler = "gcc"; // default to gcc
- if (compilerId == "MSVC")
- {
- compiler = "msvc8";
- }
- else if (compilerId == "Borland")
- {
+ } else if (this->GlobalGenerator->GetLanguageEnabled("Fortran")) {
+ compilerIdVar = "CMAKE_Fortran_COMPILER_ID";
+ pureFortran = true;
+ }
+
+ std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string compiler = "gcc"; // default to gcc
+ if (compilerId == "MSVC") {
+ if (mf->IsDefinitionSet("MSVC10")) {
+ compiler = "msvc10";
+ } else {
+ compiler = "msvc8";
+ }
+ } else if (compilerId == "Borland") {
compiler = "bcc";
- }
- else if (compilerId == "SDCC")
- {
+ } else if (compilerId == "SDCC") {
compiler = "sdcc";
+ } else if (compilerId == "Intel") {
+ if (pureFortran && mf->IsDefinitionSet("WIN32")) {
+ compiler = "ifcwin"; // Intel Fortran for Windows (known by cbFortran)
+ } else {
+ compiler = "icc";
}
- else if (compilerId == "Intel")
- {
- compiler = "icc";
- }
- else if (compilerId == "Watcom")
- {
+ } else if (compilerId == "Watcom" || compilerId == "OpenWatcom") {
compiler = "ow";
- }
- else if (compilerId == "GNU")
- {
- compiler = "gcc";
- }
+ } else if (compilerId == "Clang") {
+ compiler = "clang";
+ } else if (compilerId == "PGI") {
+ if (pureFortran) {
+ compiler = "pgifortran";
+ } else {
+ compiler = "pgi"; // does not exist as default in CodeBlocks 16.01
+ }
+ } else if (compilerId == "GNU") {
+ if (pureFortran) {
+ compiler = "gfortran";
+ } else {
+ compiler = "gcc";
+ }
+ }
return compiler;
}
-
// Translate the cmake target type into the CodeBlocks target type id
-int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
+int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target)
{
- if ( target->GetType()==cmTarget::EXECUTABLE)
- {
- if ((target->GetPropertyAsBool("WIN32_EXECUTABLE"))
- || (target->GetPropertyAsBool("MACOSX_BUNDLE")))
- {
- return 0;
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ if ((target->GetPropertyAsBool("WIN32_EXECUTABLE")) ||
+ (target->GetPropertyAsBool("MACOSX_BUNDLE"))) {
+ return 0;
}
- else
- {
return 1;
- }
- }
- else if (( target->GetType()==cmTarget::STATIC_LIBRARY)
- || (target->GetType()==cmTarget::OBJECT_LIBRARY))
- {
- return 2;
- }
- else if ((target->GetType()==cmTarget::SHARED_LIBRARY)
- || (target->GetType()==cmTarget::MODULE_LIBRARY))
- {
- return 3;
- }
- return 4;
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ return 2;
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ return 3;
+ default:
+ return 4;
+ }
}
// Create the command line for building the given target using the selected
// make
std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
- const std::string& make, const char* makefile, const char* target)
+ const std::string& make, const char* makefile, const std::string& target,
+ const std::string& makeFlags)
{
std::string command = make;
- if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
- {
+ if (!makeFlags.empty()) {
+ command += " ";
+ command += makeFlags;
+ }
+
+ std::string generator = this->GlobalGenerator->GetName();
+ if (generator == "NMake Makefiles" || generator == "NMake Makefiles JOM") {
+ // For Windows ConvertToOutputPath already adds quotes when required.
+ // These need to be escaped, see
+ // https://gitlab.kitware.com/cmake/cmake/issues/13952
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += " /NOLOGO /f &quot;";
+ command += " /NOLOGO /f ";
command += makefileName;
- command += "&quot; ";
command += " VERBOSE=1 ";
command += target;
- }
- else if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
- {
+ } else if (generator == "MinGW Makefiles") {
// no escaping of spaces in this case, see
- // http://public.kitware.com/Bug/view.php?id=10014
+ // https://gitlab.kitware.com/cmake/cmake/issues/10014
std::string makefileName = makefile;
- command += " -f &quot;";
+ command += " -f \"";
command += makefileName;
- command += "&quot; ";
+ command += "\" ";
command += " VERBOSE=1 ";
command += target;
- }
- else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
- {
+ } else if (generator == "Ninja") {
command += " -v ";
command += target;
- }
- else
- {
+ } else {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += " -f &quot;";
+ command += " -f \"";
command += makefileName;
- command += "&quot; ";
+ command += "\" ";
command += " VERBOSE=1 ";
command += target;
- }
+ }
return command;
}