summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMinze Zwerver <ysblokje@gmail.com>2016-09-23 06:42:20 (GMT)
committerBrad King <brad.king@kitware.com>2016-09-26 17:40:38 (GMT)
commitcbe488792746377396a9f38aeb2999750ade518a (patch)
tree0a55ad14b161d0e8dccfd0a725e31231d1b7a4d5
parentd0a27ae998e5ff313937f346b53d672c6353bd74 (diff)
downloadCMake-cbe488792746377396a9f38aeb2999750ade518a.zip
CMake-cbe488792746377396a9f38aeb2999750ade518a.tar.gz
CMake-cbe488792746377396a9f38aeb2999750ade518a.tar.bz2
CodeLite: Optionally use targets to create (sub)project files
The basic codelite generator creates .project files based on the `project()` stanza. Add a `CMAKE_CODELITE_USE_TARGETS` option to use the targets instead.
-rw-r--r--Help/generator/CodeLite.rst6
-rw-r--r--Help/manual/cmake-variables.7.rst1
-rw-r--r--Help/release/dev/codelite-organize-by-target.rst6
-rw-r--r--Help/variable/CMAKE_CODELITE_USE_TARGETS.rst7
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx334
-rw-r--r--Source/cmExtraCodeLiteGenerator.h21
6 files changed, 280 insertions, 95 deletions
diff --git a/Help/generator/CodeLite.rst b/Help/generator/CodeLite.rst
index dbc46d7..3e60aa6 100644
--- a/Help/generator/CodeLite.rst
+++ b/Help/generator/CodeLite.rst
@@ -5,7 +5,11 @@ Generates CodeLite project files.
Project files for CodeLite will be created in the top directory and
in every subdirectory which features a CMakeLists.txt file containing
-a PROJECT() call. The appropriate make program can build the
+a :command:`project` call.
+The :variable:`CMAKE_CODELITE_USE_TARGETS` variable may be set to ``ON``
+to change the default behaviour from projects to targets as the basis
+for project files.
+The appropriate make program can build the
project through the default make target. A "make install" target is
also provided.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 9e0efe9..2d2a0b6 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -112,6 +112,7 @@ Variables that Change Behavior
/variable/CMAKE_AUTOMOC_RELAXED_MODE
/variable/CMAKE_BACKWARDS_COMPATIBILITY
/variable/CMAKE_BUILD_TYPE
+ /variable/CMAKE_CODELITE_USE_TARGETS
/variable/CMAKE_COLOR_MAKEFILE
/variable/CMAKE_CONFIGURATION_TYPES
/variable/CMAKE_DEBUG_TARGET_PROPERTIES
diff --git a/Help/release/dev/codelite-organize-by-target.rst b/Help/release/dev/codelite-organize-by-target.rst
new file mode 100644
index 0000000..0979228
--- /dev/null
+++ b/Help/release/dev/codelite-organize-by-target.rst
@@ -0,0 +1,6 @@
+codelite-organize-by-target
+---------------------------
+
+* The :generator:`CodeLite` generator gained a new
+ :variable:`CMAKE_CODELITE_USE_TARGETS` option
+ to change project creation from projects to targets.
diff --git a/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst b/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst
new file mode 100644
index 0000000..4aede03
--- /dev/null
+++ b/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst
@@ -0,0 +1,7 @@
+CMAKE_CODELITE_USE_TARGETS
+--------------------------
+
+Change the way the CodeLite generator creates projectfiles.
+
+If this variable is set to ``ON`` the generator creates projectfiles
+based on targets rather than projects.
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index a039f49..aaaa07a 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -70,6 +70,8 @@ void cmExtraCodeLiteGenerator::Generate()
// loop projects and locate the root project.
// and extract the information for creating the worspace
+ // root makefile
+ const cmMakefile* rmf = CM_NULLPTR;
for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
it = projectMap.begin();
it != projectMap.end(); ++it) {
@@ -84,6 +86,7 @@ void cmExtraCodeLiteGenerator::Generate()
workspaceFileName = workspaceOutputDir + "/";
workspaceFileName += workspaceProjectName + ".workspace";
this->WorkspacePath = it->second[0]->GetCurrentBinaryDirectory();
+ rmf = it->second[0]->GetMakefile();
;
break;
}
@@ -96,26 +99,14 @@ void cmExtraCodeLiteGenerator::Generate()
xml.StartElement("CodeLite_Workspace");
xml.Attribute("Name", workspaceProjectName);
- // for each sub project in the workspace create a codelite project
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = projectMap.begin();
- it != projectMap.end(); ++it) {
- // retrive project information
- std::string outputDir = it->second[0]->GetCurrentBinaryDirectory();
- std::string projectName = it->second[0]->GetProjectName();
- std::string filename = outputDir + "/" + projectName + ".project";
-
- // Make the project file relative to the workspace
- filename = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
- filename.c_str());
+ bool const targetsAreProjects =
+ rmf && rmf->IsOn("CMAKE_CODELITE_USE_TARGETS");
- // 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();
+ std::vector<std::string> ProjectNames;
+ if (targetsAreProjects) {
+ ProjectNames = CreateProjectsByTarget(&xml);
+ } else {
+ ProjectNames = CreateProjectsByProjectMaps(&xml);
}
xml.StartElement("BuildMatrix");
@@ -123,14 +114,10 @@ void cmExtraCodeLiteGenerator::Generate()
xml.Attribute("Name", this->ConfigName);
xml.Attribute("Selected", "yes");
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = projectMap.begin();
- it != projectMap.end(); ++it) {
- // retrive project information
- std::string projectName = it->second[0]->GetProjectName();
-
+ for (std::vector<std::string>::iterator it(ProjectNames.begin());
+ it != ProjectNames.end(); it++) {
xml.StartElement("Project");
- xml.Attribute("Name", projectName);
+ xml.Attribute("Name", *it);
xml.Attribute("ConfigName", this->ConfigName);
xml.EndElement();
}
@@ -140,6 +127,79 @@ void cmExtraCodeLiteGenerator::Generate()
xml.EndElement(); // CodeLite_Workspace
}
+// 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;
+}
+
/* create the project file */
void cmExtraCodeLiteGenerator::CreateProjectFile(
const std::vector<cmLocalGenerator*>& lgs)
@@ -152,6 +212,70 @@ void cmExtraCodeLiteGenerator::CreateProjectFile(
this->CreateNewProjectFile(lgs, filename);
}
+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;
+}
+
void cmExtraCodeLiteGenerator::CreateNewProjectFile(
const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
@@ -168,81 +292,41 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
xml.Attribute("Name", lgs[0]->GetProjectName());
xml.Attribute("InternalType", "");
+ std::string projectType;
+
// 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> srcExts =
- this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
- std::vector<std::string> headerExts =
- this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
-
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();
std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
ti != targets.end(); ti++) {
+ projectType = CollectSourceFiles(makefile, *ti, cFiles, otherFiles);
+ }
+ }
- switch ((*ti)->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;
- }
+ // Get the project path ( we need it later to convert files to
+ // their relative path)
+ std::string projectPath = cmSystemTools::GetFilenamePath(filename);
- switch ((*ti)->GetType()) {
- case cmState::EXECUTABLE:
- case cmState::STATIC_LIBRARY:
- case cmState::SHARED_LIBRARY:
- case cmState::MODULE_LIBRARY: {
- 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++) {
- // 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;
- }
- }
- }
+ CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
+ projectType);
- // 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;
- }
- }
- }
+ 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();
// The following loop tries to add header files matching to implementation
// files to the project. It does that by iterating over all source files,
@@ -275,11 +359,17 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
}
}
}
+}
- // Get the project path ( we need it later to convert files to
- // their relative path)
- std::string projectPath = cmSystemTools::GetFilenamePath(filename);
+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)
+{
+ cmXMLWriter& xml(*_xml);
+ FindMatchingHeaderfiles(cFiles, otherFiles);
// Create 2 virtual folders: src and include
// and place all the implementation files into the src
// folder, the rest goes to the include folder
@@ -292,8 +382,10 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
cFiles.begin();
sit != cFiles.end(); ++sit) {
xml.StartElement("File");
- xml.Attribute("Name", cmSystemTools::RelativePath(projectPath.c_str(),
- sit->first.c_str()));
+ std::string fpath(sit->first);
+ std::string frelapath =
+ cmSystemTools::RelativePath(projectPath.c_str(), sit->first.c_str());
+ xml.Attribute("Name", frelapath);
xml.EndElement();
}
xml.EndElement(); // VirtualDirectory
@@ -350,11 +442,18 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
xml.EndElement(); // ResourceCompiler
xml.StartElement("General");
- xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
+ std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ if (!outputPath.empty())
+ xml.Attribute("OutputFile", outputPath + "/$(ProjectName)");
+ else
+ xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
xml.Attribute("IntermediateDirectory", "./");
xml.Attribute("Command", "./$(ProjectName)");
xml.Attribute("CommandArguments", "");
- xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)");
+ if (!outputPath.empty())
+ xml.Attribute("WorkingDirectory", outputPath);
+ else
+ xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)");
xml.Attribute("PauseExecWhenProcTerminates", "yes");
xml.EndElement(); // General
@@ -408,6 +507,53 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
xml.EndElement(); // GlobalSettings
xml.EndElement(); // Settings
+}
+
+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);
+
xml.EndElement(); // CodeLite_Project
}
diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h
index f5765d8..9c571a5 100644
--- a/Source/cmExtraCodeLiteGenerator.h
+++ b/Source/cmExtraCodeLiteGenerator.h
@@ -18,11 +18,16 @@
#include "cmExternalMakefileProjectGenerator.h"
+#include <map>
+#include <set>
#include <string>
#include <vector>
class cmLocalGenerator;
class cmMakefile;
+class cmGeneratorTarget;
+class cmXMLWriter;
+class cmSourceFile;
class cmExtraCodeLiteGenerator : public cmExternalMakefileProjectGenerator
{
@@ -38,6 +43,20 @@ protected:
std::string GetCleanCommand(const cmMakefile* mf) const;
std::string GetRebuildCommand(const cmMakefile* mf) const;
std::string GetSingleFileBuildCommand(const cmMakefile* mf) const;
+ std::vector<std::string> CreateProjectsByTarget(cmXMLWriter* xml);
+ std::vector<std::string> CreateProjectsByProjectMaps(cmXMLWriter* xml);
+ std::string CollectSourceFiles(const cmMakefile* makefile,
+ const cmGeneratorTarget* gt,
+ std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles);
+ void FindMatchingHeaderfiles(std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles);
+ void 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);
public:
cmExtraCodeLiteGenerator();
@@ -49,6 +68,8 @@ public:
void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
const std::string& filename);
+ void CreateNewProjectFile(const cmGeneratorTarget* lg,
+ const std::string& filename);
};
#endif