2014-01-10 11:20:11 +04:00
|
|
|
/*============================================================================
|
|
|
|
CMake - Cross Platform Makefile Generator
|
|
|
|
Copyright 2004-2009 Kitware, Inc.
|
|
|
|
Copyright 2004 Alexander Neundorf (neundorf@kde.org)
|
|
|
|
Copyright 2013 Eran Ifrah (eran.ifrah@gmail.com)
|
|
|
|
|
|
|
|
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.
|
|
|
|
============================================================================*/
|
|
|
|
#include "cmExtraCodeLiteGenerator.h"
|
2016-04-29 16:40:20 +03:00
|
|
|
|
2016-04-29 17:53:13 +03:00
|
|
|
#include "cmGeneratedFileStream.h"
|
2016-09-01 21:59:28 +03:00
|
|
|
#include "cmGeneratorTarget.h"
|
|
|
|
#include "cmGlobalGenerator.h"
|
|
|
|
#include "cmLocalGenerator.h"
|
2014-01-10 11:20:11 +04:00
|
|
|
#include "cmMakefile.h"
|
|
|
|
#include "cmSourceFile.h"
|
2016-09-01 21:59:28 +03:00
|
|
|
#include "cmState.h"
|
2014-01-10 11:20:11 +04:00
|
|
|
#include "cmSystemTools.h"
|
2016-09-01 21:59:28 +03:00
|
|
|
#include "cmXMLWriter.h"
|
2016-04-29 17:53:13 +03:00
|
|
|
#include "cmake.h"
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-04-29 17:53:13 +03:00
|
|
|
#include <cmsys/SystemInformation.hxx>
|
2016-09-01 21:59:28 +03:00
|
|
|
#include <map>
|
|
|
|
#include <set>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string.h>
|
|
|
|
#include <utility>
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
cmExtraCodeLiteGenerator::cmExtraCodeLiteGenerator()
|
|
|
|
: cmExternalMakefileProjectGenerator()
|
|
|
|
, ConfigName("NoConfig")
|
|
|
|
, CpuCount(2)
|
|
|
|
{
|
2016-07-20 19:28:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
cmExternalMakefileProjectGeneratorFactory*
|
|
|
|
cmExtraCodeLiteGenerator::GetFactory()
|
|
|
|
{
|
|
|
|
static cmExternalMakefileProjectGeneratorSimpleFactory<
|
|
|
|
cmExtraCodeLiteGenerator>
|
|
|
|
factory("CodeLite", "Generates CodeLite project files.");
|
|
|
|
|
|
|
|
if (factory.GetSupportedGlobalGenerators().empty()) {
|
2014-01-10 11:20:11 +04:00
|
|
|
#if defined(_WIN32)
|
2016-07-20 19:28:39 +03:00
|
|
|
factory.AddSupportedGlobalGenerator("MinGW Makefiles");
|
|
|
|
factory.AddSupportedGlobalGenerator("NMake Makefiles");
|
2014-01-10 11:20:11 +04:00
|
|
|
#endif
|
2016-07-20 19:28:39 +03:00
|
|
|
factory.AddSupportedGlobalGenerator("Ninja");
|
|
|
|
factory.AddSupportedGlobalGenerator("Unix Makefiles");
|
|
|
|
}
|
|
|
|
|
|
|
|
return &factory;
|
2014-01-10 11:20:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void cmExtraCodeLiteGenerator::Generate()
|
|
|
|
{
|
|
|
|
// Hold root tree information for creating the workspace
|
|
|
|
std::string workspaceProjectName;
|
|
|
|
std::string workspaceOutputDir;
|
|
|
|
std::string workspaceFileName;
|
|
|
|
std::string workspaceSourcePath;
|
|
|
|
|
2015-07-16 22:53:17 +03:00
|
|
|
const std::map<std::string, std::vector<cmLocalGenerator*> >& projectMap =
|
2016-05-16 17:34:04 +03:00
|
|
|
this->GlobalGenerator->GetProjectMap();
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
// loop projects and locate the root project.
|
|
|
|
// and extract the information for creating the worspace
|
2016-09-23 09:42:20 +03:00
|
|
|
// root makefile
|
|
|
|
const cmMakefile* rmf = CM_NULLPTR;
|
2014-02-10 09:21:34 +04:00
|
|
|
for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
|
2016-05-16 17:34:04 +03:00
|
|
|
it = projectMap.begin();
|
|
|
|
it != projectMap.end(); ++it) {
|
|
|
|
const cmMakefile* mf = it->second[0]->GetMakefile();
|
|
|
|
this->ConfigName = GetConfigurationName(mf);
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2015-09-25 01:13:20 +03:00
|
|
|
if (strcmp(it->second[0]->GetCurrentBinaryDirectory(),
|
2016-05-16 17:34:04 +03:00
|
|
|
it->second[0]->GetBinaryDirectory()) == 0) {
|
|
|
|
workspaceOutputDir = it->second[0]->GetCurrentBinaryDirectory();
|
2015-10-07 01:29:25 +03:00
|
|
|
workspaceProjectName = it->second[0]->GetProjectName();
|
2016-05-16 17:34:04 +03:00
|
|
|
workspaceSourcePath = it->second[0]->GetSourceDirectory();
|
|
|
|
workspaceFileName = workspaceOutputDir + "/";
|
|
|
|
workspaceFileName += workspaceProjectName + ".workspace";
|
|
|
|
this->WorkspacePath = it->second[0]->GetCurrentBinaryDirectory();
|
2016-09-23 09:42:20 +03:00
|
|
|
rmf = it->second[0]->GetMakefile();
|
2016-05-16 17:34:04 +03:00
|
|
|
;
|
2015-07-16 22:53:17 +03:00
|
|
|
break;
|
2014-01-10 11:20:11 +04:00
|
|
|
}
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2015-07-16 22:53:17 +03:00
|
|
|
cmGeneratedFileStream fout(workspaceFileName.c_str());
|
|
|
|
cmXMLWriter xml(fout);
|
|
|
|
|
|
|
|
xml.StartDocument("utf-8");
|
|
|
|
xml.StartElement("CodeLite_Workspace");
|
|
|
|
xml.Attribute("Name", workspaceProjectName);
|
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
bool const targetsAreProjects =
|
|
|
|
rmf && rmf->IsOn("CMAKE_CODELITE_USE_TARGETS");
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
std::vector<std::string> ProjectNames;
|
|
|
|
if (targetsAreProjects) {
|
|
|
|
ProjectNames = CreateProjectsByTarget(&xml);
|
|
|
|
} else {
|
|
|
|
ProjectNames = CreateProjectsByProjectMaps(&xml);
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2015-07-16 22:53:17 +03:00
|
|
|
|
|
|
|
xml.StartElement("BuildMatrix");
|
|
|
|
xml.StartElement("WorkspaceConfiguration");
|
|
|
|
xml.Attribute("Name", this->ConfigName);
|
|
|
|
xml.Attribute("Selected", "yes");
|
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
for (std::vector<std::string>::iterator it(ProjectNames.begin());
|
|
|
|
it != ProjectNames.end(); it++) {
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.StartElement("Project");
|
2016-09-23 09:42:20 +03:00
|
|
|
xml.Attribute("Name", *it);
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.Attribute("ConfigName", this->ConfigName);
|
|
|
|
xml.EndElement();
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.EndElement(); // WorkspaceConfiguration
|
|
|
|
xml.EndElement(); // BuildMatrix
|
|
|
|
xml.EndElement(); // CodeLite_Workspace
|
2014-01-10 11:20:11 +04:00
|
|
|
}
|
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
// Create projects where targets are the projects
|
|
|
|
std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
|
|
|
|
cmXMLWriter* xml)
|
|
|
|
{
|
|
|
|
std::vector<std::string> retval;
|
|
|
|
// for each target in the workspace create a codelite project
|
|
|
|
const std::vector<cmLocalGenerator*>& lgs =
|
|
|
|
this->GlobalGenerator->GetLocalGenerators();
|
|
|
|
for (std::vector<cmLocalGenerator*>::const_iterator lg(lgs.begin());
|
|
|
|
lg != lgs.end(); lg++) {
|
|
|
|
for (std::vector<cmGeneratorTarget*>::const_iterator lt =
|
|
|
|
(*lg)->GetGeneratorTargets().begin();
|
|
|
|
lt != (*lg)->GetGeneratorTargets().end(); lt++) {
|
|
|
|
cmState::TargetType type = (*lt)->GetType();
|
|
|
|
std::string outputDir = (*lg)->GetCurrentBinaryDirectory();
|
|
|
|
std::string filename = outputDir + "/" + (*lt)->GetName() + ".project";
|
|
|
|
retval.push_back((*lt)->GetName());
|
|
|
|
// Make the project file relative to the workspace
|
|
|
|
std::string relafilename = cmSystemTools::RelativePath(
|
|
|
|
this->WorkspacePath.c_str(), filename.c_str());
|
|
|
|
std::string visualname = (*lt)->GetName();
|
|
|
|
switch (type) {
|
|
|
|
case cmState::SHARED_LIBRARY:
|
|
|
|
case cmState::STATIC_LIBRARY:
|
|
|
|
case cmState::MODULE_LIBRARY:
|
|
|
|
visualname = "lib" + visualname;
|
|
|
|
case cmState::EXECUTABLE:
|
|
|
|
xml->StartElement("Project");
|
|
|
|
xml->Attribute("Name", visualname);
|
|
|
|
xml->Attribute("Path", relafilename);
|
|
|
|
xml->Attribute("Active", "No");
|
|
|
|
xml->EndElement();
|
|
|
|
|
|
|
|
CreateNewProjectFile(*lt, filename);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The "older way of doing it.
|
|
|
|
std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
|
|
|
|
cmXMLWriter* xml)
|
|
|
|
{
|
|
|
|
std::vector<std::string> retval;
|
|
|
|
// for each sub project in the workspace create a codelite project
|
|
|
|
for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
|
|
|
|
it = this->GlobalGenerator->GetProjectMap().begin();
|
|
|
|
it != this->GlobalGenerator->GetProjectMap().end(); it++) {
|
|
|
|
|
|
|
|
std::string outputDir = it->second[0]->GetCurrentBinaryDirectory();
|
|
|
|
std::string projectName = it->second[0]->GetProjectName();
|
|
|
|
retval.push_back(projectName);
|
|
|
|
std::string filename = outputDir + "/" + projectName + ".project";
|
|
|
|
|
|
|
|
// Make the project file relative to the workspace
|
|
|
|
filename = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
|
|
|
|
filename.c_str());
|
|
|
|
|
|
|
|
// create a project file
|
|
|
|
this->CreateProjectFile(it->second);
|
|
|
|
xml->StartElement("Project");
|
|
|
|
xml->Attribute("Name", projectName);
|
|
|
|
xml->Attribute("Path", filename);
|
|
|
|
xml->Attribute("Active", "No");
|
|
|
|
xml->EndElement();
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2014-01-10 11:20:11 +04:00
|
|
|
/* create the project file */
|
|
|
|
void cmExtraCodeLiteGenerator::CreateProjectFile(
|
|
|
|
const std::vector<cmLocalGenerator*>& lgs)
|
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
|
2015-10-07 01:29:25 +03:00
|
|
|
std::string projectName = lgs[0]->GetProjectName();
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string filename = outputDir + "/";
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
filename += projectName + ".project";
|
|
|
|
this->CreateNewProjectFile(lgs, filename);
|
|
|
|
}
|
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
|
|
|
|
const cmMakefile* makefile, const cmGeneratorTarget* gt,
|
|
|
|
std::map<std::string, cmSourceFile*>& cFiles,
|
|
|
|
std::set<std::string>& otherFiles)
|
|
|
|
{
|
|
|
|
const std::vector<std::string>& srcExts =
|
|
|
|
this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
|
|
|
|
|
|
|
|
std::string projectType;
|
|
|
|
switch (gt->GetType()) {
|
|
|
|
case cmState::EXECUTABLE: {
|
|
|
|
projectType = "Executable";
|
|
|
|
} break;
|
|
|
|
case cmState::STATIC_LIBRARY: {
|
|
|
|
projectType = "Static Library";
|
|
|
|
} break;
|
|
|
|
case cmState::SHARED_LIBRARY: {
|
|
|
|
projectType = "Dynamic Library";
|
|
|
|
} break;
|
|
|
|
case cmState::MODULE_LIBRARY: {
|
|
|
|
projectType = "Dynamic Library";
|
|
|
|
} break;
|
|
|
|
default: // intended fallthrough
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (gt->GetType()) {
|
|
|
|
case cmState::EXECUTABLE:
|
|
|
|
case cmState::STATIC_LIBRARY:
|
|
|
|
case cmState::SHARED_LIBRARY:
|
|
|
|
case cmState::MODULE_LIBRARY: {
|
|
|
|
std::vector<cmSourceFile*> sources;
|
|
|
|
gt->GetSourceFiles(sources,
|
|
|
|
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
|
|
|
|
for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
|
|
|
|
si != sources.end(); si++) {
|
|
|
|
// check whether it is a C/C++ implementation file
|
|
|
|
bool isCFile = false;
|
|
|
|
std::string lang = (*si)->GetLanguage();
|
|
|
|
if (lang == "C" || lang == "CXX") {
|
|
|
|
std::string 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default: // intended fallthrough
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return projectType;
|
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
void cmExtraCodeLiteGenerator::CreateNewProjectFile(
|
|
|
|
const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
const cmMakefile* mf = lgs[0]->GetMakefile();
|
2014-01-10 11:20:11 +04:00
|
|
|
cmGeneratedFileStream fout(filename.c_str());
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!fout) {
|
2014-01-10 11:20:11 +04:00
|
|
|
return;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2015-07-16 22:53:17 +03:00
|
|
|
cmXMLWriter xml(fout);
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
////////////////////////////////////
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.StartDocument("utf-8");
|
|
|
|
xml.StartElement("CodeLite_Project");
|
|
|
|
xml.Attribute("Name", lgs[0]->GetProjectName());
|
|
|
|
xml.Attribute("InternalType", "");
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
std::string projectType;
|
|
|
|
|
2014-01-10 11:20:11 +04:00
|
|
|
// 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;
|
2016-09-23 09:42:20 +03:00
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
|
|
|
|
lg != lgs.end(); lg++) {
|
|
|
|
cmMakefile* makefile = (*lg)->GetMakefile();
|
|
|
|
std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
|
2015-10-18 18:06:14 +03:00
|
|
|
for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
|
2016-05-16 17:34:04 +03:00
|
|
|
ti != targets.end(); ti++) {
|
2016-09-23 09:42:20 +03:00
|
|
|
projectType = CollectSourceFiles(makefile, *ti, cFiles, otherFiles);
|
|
|
|
}
|
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
// Get the project path ( we need it later to convert files to
|
|
|
|
// their relative path)
|
|
|
|
std::string projectPath = cmSystemTools::GetFilenamePath(filename);
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
|
|
|
|
projectType);
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
xml.EndElement(); // CodeLite_Project
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
|
|
|
|
std::map<std::string, cmSourceFile*>& cFiles,
|
|
|
|
std::set<std::string>& otherFiles)
|
|
|
|
{
|
|
|
|
|
|
|
|
const std::vector<std::string>& headerExts =
|
|
|
|
this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
// The following loop tries to add header files matching to implementation
|
|
|
|
// files to the project. It does that by iterating over all 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.
|
2016-05-16 17:34:04 +03:00
|
|
|
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);
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
// check if there's a matching header around
|
2016-05-16 17:34:04 +03:00
|
|
|
for (std::vector<std::string>::const_iterator ext = headerExts.begin();
|
|
|
|
ext != headerExts.end(); ++ext) {
|
|
|
|
std::string hname = headerBasename;
|
2014-01-10 11:20:11 +04:00
|
|
|
hname += ".";
|
|
|
|
hname += *ext;
|
|
|
|
// if it's already in the set, don't check if it exists on disk
|
2016-05-16 17:34:04 +03:00
|
|
|
std::set<std::string>::const_iterator headerIt = otherFiles.find(hname);
|
|
|
|
if (headerIt != otherFiles.end()) {
|
2014-01-10 11:20:11 +04:00
|
|
|
break;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
if (cmSystemTools::FileExists(hname.c_str())) {
|
2014-01-10 11:20:11 +04:00
|
|
|
otherFiles.insert(hname);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2016-09-23 09:42:20 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
|
|
|
|
std::map<std::string, cmSourceFile*>& cFiles,
|
|
|
|
std::set<std::string>& otherFiles, cmXMLWriter* _xml,
|
|
|
|
const std::string& projectPath, const cmMakefile* mf,
|
|
|
|
const std::string& projectType)
|
|
|
|
{
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2016-09-23 09:42:20 +03:00
|
|
|
cmXMLWriter& xml(*_xml);
|
|
|
|
FindMatchingHeaderfiles(cFiles, otherFiles);
|
2014-01-10 11:20:11 +04:00
|
|
|
// Create 2 virtual folders: src and include
|
|
|
|
// and place all the implementation files into the src
|
|
|
|
// folder, the rest goes to the include folder
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.StartElement("VirtualDirectory");
|
|
|
|
xml.Attribute("Name", "src");
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
// insert all source files in the codelite project
|
|
|
|
// first the C/C++ implementation files, then all others
|
2016-05-16 17:34:04 +03:00
|
|
|
for (std::map<std::string, cmSourceFile*>::const_iterator sit =
|
|
|
|
cFiles.begin();
|
|
|
|
sit != cFiles.end(); ++sit) {
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.StartElement("File");
|
2016-09-23 09:42:20 +03:00
|
|
|
std::string fpath(sit->first);
|
|
|
|
std::string frelapath =
|
|
|
|
cmSystemTools::RelativePath(projectPath.c_str(), sit->first.c_str());
|
|
|
|
xml.Attribute("Name", frelapath);
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.EndElement();
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.EndElement(); // VirtualDirectory
|
|
|
|
xml.StartElement("VirtualDirectory");
|
|
|
|
xml.Attribute("Name", "include");
|
2016-05-16 17:34:04 +03:00
|
|
|
for (std::set<std::string>::const_iterator sit = otherFiles.begin();
|
|
|
|
sit != otherFiles.end(); ++sit) {
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.StartElement("File");
|
2016-05-16 17:34:04 +03:00
|
|
|
xml.Attribute(
|
|
|
|
"Name", cmSystemTools::RelativePath(projectPath.c_str(), sit->c_str()));
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.EndElement();
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.EndElement(); // VirtualDirectory
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
// Get the number of CPUs. We use this information for the make -jN
|
|
|
|
// command
|
|
|
|
cmsys::SystemInformation info;
|
|
|
|
info.RunCPUCheck();
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
this->CpuCount =
|
|
|
|
info.GetNumberOfLogicalCPU() * info.GetNumberOfPhysicalCPU();
|
2014-01-10 11:20:11 +04:00
|
|
|
|
|
|
|
std::string codeliteCompilerName = this->GetCodeLiteCompilerName(mf);
|
|
|
|
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.StartElement("Settings");
|
|
|
|
xml.Attribute("Type", projectType);
|
|
|
|
|
|
|
|
xml.StartElement("Configuration");
|
|
|
|
xml.Attribute("Name", this->ConfigName);
|
|
|
|
xml.Attribute("CompilerType", this->GetCodeLiteCompilerName(mf));
|
|
|
|
xml.Attribute("DebuggerType", "GNU gdb debugger");
|
|
|
|
xml.Attribute("Type", projectType);
|
|
|
|
xml.Attribute("BuildCmpWithGlobalSettings", "append");
|
|
|
|
xml.Attribute("BuildLnkWithGlobalSettings", "append");
|
|
|
|
xml.Attribute("BuildResWithGlobalSettings", "append");
|
|
|
|
|
|
|
|
xml.StartElement("Compiler");
|
|
|
|
xml.Attribute("Options", "-g");
|
|
|
|
xml.Attribute("Required", "yes");
|
|
|
|
xml.Attribute("PreCompiledHeader", "");
|
|
|
|
xml.StartElement("IncludePath");
|
|
|
|
xml.Attribute("Value", ".");
|
|
|
|
xml.EndElement(); // IncludePath
|
|
|
|
xml.EndElement(); // Compiler
|
|
|
|
|
|
|
|
xml.StartElement("Linker");
|
|
|
|
xml.Attribute("Options", "");
|
|
|
|
xml.Attribute("Required", "yes");
|
|
|
|
xml.EndElement(); // Linker
|
|
|
|
|
|
|
|
xml.StartElement("ResourceCompiler");
|
|
|
|
xml.Attribute("Options", "");
|
|
|
|
xml.Attribute("Required", "no");
|
|
|
|
xml.EndElement(); // ResourceCompiler
|
|
|
|
|
|
|
|
xml.StartElement("General");
|
2016-09-23 09:42:20 +03:00
|
|
|
std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
|
|
|
|
if (!outputPath.empty())
|
|
|
|
xml.Attribute("OutputFile", outputPath + "/$(ProjectName)");
|
|
|
|
else
|
|
|
|
xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.Attribute("IntermediateDirectory", "./");
|
|
|
|
xml.Attribute("Command", "./$(ProjectName)");
|
|
|
|
xml.Attribute("CommandArguments", "");
|
2016-09-23 09:42:20 +03:00
|
|
|
if (!outputPath.empty())
|
|
|
|
xml.Attribute("WorkingDirectory", outputPath);
|
|
|
|
else
|
|
|
|
xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)");
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.Attribute("PauseExecWhenProcTerminates", "yes");
|
|
|
|
xml.EndElement(); // General
|
|
|
|
|
|
|
|
xml.StartElement("Debugger");
|
|
|
|
xml.Attribute("IsRemote", "no");
|
|
|
|
xml.Attribute("RemoteHostName", "");
|
|
|
|
xml.Attribute("RemoteHostPort", "");
|
|
|
|
xml.Attribute("DebuggerPath", "");
|
|
|
|
xml.Element("PostConnectCommands");
|
|
|
|
xml.Element("StartupCommands");
|
|
|
|
xml.EndElement(); // Debugger
|
|
|
|
|
|
|
|
xml.Element("PreBuild");
|
|
|
|
xml.Element("PostBuild");
|
|
|
|
|
|
|
|
xml.StartElement("CustomBuild");
|
|
|
|
xml.Attribute("Enabled", "yes");
|
|
|
|
xml.Element("RebuildCommand", GetRebuildCommand(mf));
|
|
|
|
xml.Element("CleanCommand", GetCleanCommand(mf));
|
|
|
|
xml.Element("BuildCommand", GetBuildCommand(mf));
|
|
|
|
xml.Element("SingleFileCommand", GetSingleFileBuildCommand(mf));
|
|
|
|
xml.Element("PreprocessFileCommand");
|
|
|
|
xml.Element("WorkingDirectory", "$(WorkspacePath)");
|
|
|
|
xml.EndElement(); // CustomBuild
|
|
|
|
|
|
|
|
xml.StartElement("AdditionalRules");
|
|
|
|
xml.Element("CustomPostBuild");
|
|
|
|
xml.Element("CustomPreBuild");
|
|
|
|
xml.EndElement(); // AdditionalRules
|
|
|
|
|
|
|
|
xml.EndElement(); // Configuration
|
|
|
|
xml.StartElement("GlobalSettings");
|
|
|
|
|
|
|
|
xml.StartElement("Compiler");
|
|
|
|
xml.Attribute("Options", "");
|
|
|
|
xml.StartElement("IncludePath");
|
|
|
|
xml.Attribute("Value", ".");
|
|
|
|
xml.EndElement(); // IncludePath
|
|
|
|
xml.EndElement(); // Compiler
|
|
|
|
|
|
|
|
xml.StartElement("Linker");
|
|
|
|
xml.Attribute("Options", "");
|
|
|
|
xml.StartElement("LibraryPath");
|
|
|
|
xml.Attribute("Value", ".");
|
|
|
|
xml.EndElement(); // LibraryPath
|
|
|
|
xml.EndElement(); // Linker
|
|
|
|
|
|
|
|
xml.StartElement("ResourceCompiler");
|
|
|
|
xml.Attribute("Options", "");
|
|
|
|
xml.EndElement(); // ResourceCompiler
|
|
|
|
|
|
|
|
xml.EndElement(); // GlobalSettings
|
|
|
|
xml.EndElement(); // Settings
|
2016-09-23 09:42:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void cmExtraCodeLiteGenerator::CreateNewProjectFile(
|
|
|
|
const cmGeneratorTarget* gt, const std::string& filename)
|
|
|
|
{
|
|
|
|
const cmMakefile* mf = gt->Makefile;
|
|
|
|
cmGeneratedFileStream fout(filename.c_str());
|
|
|
|
if (!fout) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cmXMLWriter xml(fout);
|
|
|
|
|
|
|
|
////////////////////////////////////
|
|
|
|
xml.StartDocument("utf-8");
|
|
|
|
xml.StartElement("CodeLite_Project");
|
|
|
|
std::string visualname = gt->GetName();
|
|
|
|
switch (gt->GetType()) {
|
|
|
|
case cmState::STATIC_LIBRARY:
|
|
|
|
case cmState::SHARED_LIBRARY:
|
|
|
|
case cmState::MODULE_LIBRARY:
|
|
|
|
visualname = "lib" + visualname;
|
|
|
|
default: // intended fallthrough
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
xml.Attribute("Name", visualname);
|
|
|
|
xml.Attribute("InternalType", "");
|
|
|
|
|
|
|
|
// 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::string projectType;
|
|
|
|
|
|
|
|
std::vector<std::string> headerExts =
|
|
|
|
this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
|
|
|
|
|
|
|
|
std::map<std::string, cmSourceFile*> cFiles;
|
|
|
|
std::set<std::string> otherFiles;
|
|
|
|
|
|
|
|
projectType = CollectSourceFiles(mf, gt, cFiles, otherFiles);
|
|
|
|
|
|
|
|
// Get the project path ( we need it later to convert files to
|
|
|
|
// their relative path)
|
|
|
|
std::string projectPath = cmSystemTools::GetFilenamePath(filename);
|
|
|
|
|
|
|
|
CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
|
|
|
|
projectType);
|
|
|
|
|
2015-07-16 22:53:17 +03:00
|
|
|
xml.EndElement(); // CodeLite_Project
|
2014-01-10 11:20:11 +04:00
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName(
|
|
|
|
const cmMakefile* mf) const
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
|
|
|
// figure out which language to use
|
|
|
|
// for now care only for C and C++
|
|
|
|
std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
|
2016-06-02 00:29:53 +03:00
|
|
|
if (!this->GlobalGenerator->GetLanguageEnabled("CXX")) {
|
2014-01-10 11:20:11 +04:00
|
|
|
compilerIdVar = "CMAKE_C_COMPILER_ID";
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
|
2014-03-11 03:04:11 +04:00
|
|
|
std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
|
2014-01-10 11:20:11 +04:00
|
|
|
std::string compiler = "gnu g++"; // default to g++
|
|
|
|
|
|
|
|
// Since we need the compiler for parsing purposes only
|
|
|
|
// it does not matter if we use clang or clang++, same as
|
|
|
|
// "gnu gcc" vs "gnu g++"
|
2016-05-16 17:34:04 +03:00
|
|
|
if (compilerId == "MSVC") {
|
2014-01-10 11:20:11 +04:00
|
|
|
compiler = "VC++";
|
2016-05-16 17:34:04 +03:00
|
|
|
} else if (compilerId == "Clang") {
|
2014-01-10 11:20:11 +04:00
|
|
|
compiler = "clang++";
|
2016-05-16 17:34:04 +03:00
|
|
|
} else if (compilerId == "GNU") {
|
2014-01-10 11:20:11 +04:00
|
|
|
compiler = "gnu g++";
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
return compiler;
|
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::GetConfigurationName(
|
|
|
|
const cmMakefile* mf) const
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
|
|
|
std::string confName = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
|
|
|
|
// Trim the configuration name from whitespaces (left and right)
|
|
|
|
confName.erase(0, confName.find_first_not_of(" \t\r\v\n"));
|
2016-05-16 17:34:04 +03:00
|
|
|
confName.erase(confName.find_last_not_of(" \t\r\v\n") + 1);
|
|
|
|
if (confName.empty()) {
|
2014-01-10 11:20:11 +04:00
|
|
|
confName = "NoConfig";
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
return confName;
|
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::GetBuildCommand(
|
|
|
|
const cmMakefile* mf) const
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
|
|
|
std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
|
|
|
|
std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
|
|
|
|
std::string buildCommand = make; // Default
|
2016-05-16 17:34:04 +03:00
|
|
|
if (generator == "NMake Makefiles" || generator == "Ninja") {
|
2014-01-10 11:20:11 +04:00
|
|
|
buildCommand = make;
|
2016-05-16 17:34:04 +03:00
|
|
|
} else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
|
2015-01-05 22:31:31 +03:00
|
|
|
std::ostringstream ss;
|
2014-01-30 22:16:48 +04:00
|
|
|
ss << make << " -j " << this->CpuCount;
|
|
|
|
buildCommand = ss.str();
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-04-15 22:13:42 +04:00
|
|
|
return buildCommand;
|
2014-01-10 11:20:11 +04:00
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::GetCleanCommand(
|
|
|
|
const cmMakefile* mf) const
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
|
|
|
return GetBuildCommand(mf) + " clean";
|
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::GetRebuildCommand(
|
|
|
|
const cmMakefile* mf) const
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
2015-07-16 22:53:17 +03:00
|
|
|
return GetCleanCommand(mf) + " && " + GetBuildCommand(mf);
|
2014-01-10 11:20:11 +04:00
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
|
|
|
|
const cmMakefile* mf) const
|
2014-01-10 11:20:11 +04:00
|
|
|
{
|
|
|
|
std::string buildCommand;
|
|
|
|
std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
|
|
|
|
std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
|
2016-05-16 17:34:04 +03:00
|
|
|
if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
|
2015-01-05 22:31:31 +03:00
|
|
|
std::ostringstream ss;
|
2014-01-10 11:20:11 +04:00
|
|
|
ss << make << " -f$(ProjectPath)/Makefile $(CurrentFileName).cpp.o";
|
|
|
|
buildCommand = ss.str();
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-01-10 11:20:11 +04:00
|
|
|
return buildCommand;
|
|
|
|
}
|