summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmDocumentVariables.cxx9
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx471
-rw-r--r--Source/cmExtraSublimeTextGenerator.h77
-rw-r--r--Source/cmake.cxx3
5 files changed, 562 insertions, 0 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8bf6c40..8e842a9 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -184,6 +184,8 @@ set(SRCS
cmExtraCodeBlocksGenerator.h
cmExtraEclipseCDT4Generator.cxx
cmExtraEclipseCDT4Generator.h
+ cmExtraSublimeTextGenerator.cxx
+ cmExtraSublimeTextGenerator.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmGeneratedFileStream.cxx
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 8db0e8f..6232162 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -896,6 +896,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" script, it may get fatal error messages from the script.",false,
"Variables That Change Behavior");
+ cm->DefineProperty
+ ("CMAKE_SUBLIMECLANG_DISABLED", cmProperty::VARIABLE,
+ "Used by the Sublime Text 2 generator to disable SublimeClang in "
+ "generated project files.",
+ "For very large projects SublimeClang might run slowly. Set this variable"
+ " to TRUE to instruct the Sublime Text 2 generator to disable "
+ " SublimeClang in the generated project files.", false,
+ "Variables That Change Behavior");
+
// Variables defined by CMake that describe the system
cm->DefineProperty
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
new file mode 100644
index 0000000..d1ea484
--- /dev/null
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -0,0 +1,471 @@
+/*============================================================================
+ 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.
+============================================================================*/
+#include "cmExtraSublimeTextGenerator.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmMakefile.h"
+#include "cmake.h"
+#include "cmSourceFile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmTarget.h"
+#include "cmSystemTools.h"
+#include "cmXMLSafe.h"
+
+#include <cmsys/SystemTools.hxx>
+
+/*
+Sublime Text 2 Generator
+Author: Morné Chamberlain
+This generator was initially based off of the CodeBlocks generator.
+
+Some useful URLs:
+Homepage:
+http://www.sublimetext.com/
+
+File format docs:
+http://www.sublimetext.com/docs/2/projects.html
+http://sublimetext.info/docs/en/reference/build_systems.html
+*/
+
+//----------------------------------------------------------------------------
+void cmExtraSublimeTextGenerator
+::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+{
+ entry.Name = this->GetName();
+ entry.Brief = "Generates Sublime Text 2 project files.";
+ entry.Full =
+ "Project files for Sublime Text 2 will be created in the top directory "
+ "and in every subdirectory which features a CMakeLists.txt file "
+ "containing a PROJECT() call. "
+ "Additionally Makefiles (or build.ninja files) are 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.";
+}
+
+cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator()
+:cmExternalMakefileProjectGenerator()
+{
+#if defined(_WIN32)
+ this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
+ this->SupportedGlobalGenerators.push_back("NMake Makefiles");
+// disable until somebody actually tests it:
+// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
+#endif
+ this->SupportedGlobalGenerators.push_back("Ninja");
+ this->SupportedGlobalGenerators.push_back("Unix Makefiles");
+}
+
+
+void cmExtraSublimeTextGenerator::Generate()
+{
+ // for each sub project in the project create a sublime text 2 project
+ for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it!= this->GlobalGenerator->GetProjectMap().end();
+ ++it)
+ {
+ // create a project file
+ this->CreateProjectFile(it->second);
+ }
+}
+
+
+void cmExtraSublimeTextGenerator::CreateProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs)
+{
+ const cmMakefile* mf=lgs[0]->GetMakefile();
+ std::string outputDir=mf->GetStartOutputDirectory();
+ std::string projectName=mf->GetProjectName();
+
+ std::string filename=outputDir+"/";
+ filename+=projectName+".sublime-project";
+
+ this->CreateNewProjectFile(lgs, filename);
+}
+
+void cmExtraSublimeTextGenerator
+ ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
+ const std::string& filename)
+{
+ const cmMakefile* mf=lgs[0]->GetMakefile();
+ cmGeneratedFileStream fout(filename.c_str());
+ if(!fout)
+ {
+ return;
+ }
+
+ const std::string &sourceRootRelativeToOutput = cmSystemTools::RelativePath(
+ lgs[0]->GetMakefile()->GetHomeOutputDirectory(),
+ lgs[0]->GetMakefile()->GetHomeDirectory());
+ // Write the folder entries to the project file
+ fout << "{\n";
+ fout << "\t\"folders\":\n\t[\n\t";
+ if (!sourceRootRelativeToOutput.empty())
+ {
+ fout << "\t{\n\t\t\t\"path\": \"" << sourceRootRelativeToOutput << "\"";
+ const std::string &outputRelativeToSourceRoot =
+ cmSystemTools::RelativePath(lgs[0]->GetMakefile()->GetHomeDirectory(),
+ lgs[0]->GetMakefile()->
+ GetHomeOutputDirectory());
+ if ((!outputRelativeToSourceRoot.empty()) &&
+ ((outputRelativeToSourceRoot.length() < 3) ||
+ (outputRelativeToSourceRoot.substr(0, 3) != "../")))
+ {
+ fout << ",\n\t\t\t\"folder_exclude_patterns\": [\"" <<
+ outputRelativeToSourceRoot << "\"]";
+ }
+ }
+ else
+ {
+ fout << "\t{\n\t\t\t\"path\": \"./\"";
+ }
+ fout << "\n\t\t}";
+ // In order for SublimeClang's path resolution to work, the directory that
+ // contains the sublime-project file must be included here. We just ensure
+ // that no files or subfolders are included.
+ // In the case of an in-source build, however, this must not be used, since
+ // it'll end up excluding the source directory.
+ if (!sourceRootRelativeToOutput.empty())
+ {
+ fout << ",\n\t\t{\n\t\t\t\"path\": \"./\",\n";
+ fout << "\t\t\t\"folder_exclude_patterns\": [\"*\"],\n";
+ fout << "\t\t\t\"file_exclude_patterns\": [\"*\"]\n";
+ fout << "\t\t}";
+ }
+ // End of the folders section
+ fout << "\n\t]";
+
+ // Write the beginning of the build systems section to the project file
+ fout << ",\n\t\"build_systems\":\n\t[\n\t";
+
+ // Set of include directories over all targets (sublime text/sublimeclang
+ // doesn't currently support these settings per build system, only project
+ // wide
+ std::set<std::string> includeDirs;
+ std::set<std::string> defines;
+ AppendAllTargets(lgs, mf, fout, includeDirs, defines);
+ // End of build_systems
+ fout << "\n\t]";
+
+ // Write the settings section with sublimeclang options
+ fout << ",\n\t\"settings\":\n\t{\n\t";
+ // Check if the CMAKE_SUBLIMECLANG_DISABLED flag has been set. If it has
+ // disable sublimeclang for this project.
+ const char* sublimeclangDisabledValue =
+ lgs[0]->GetMakefile()->GetSafeDefinition("CMAKE_SUBLIMECLANG_DISABLED");
+ bool sublimeclangEnabled = cmSystemTools::IsOff(sublimeclangDisabledValue);
+ // Per project sublimeclang settings override default and user settings,
+ // so we only write the sublimeclang_enabled setting to the project file
+ // if it is set to be disabled.
+ if (!sublimeclangEnabled)
+ {
+ fout << "\t\"sublimeclang_enabled\": false,\n\t";
+ }
+ fout << "\t\"sublimeclang_options\":\n\t\t[\n\t\t";
+ std::set<std::string>::const_iterator stringSetIter = includeDirs.begin();
+ while (stringSetIter != includeDirs.end())
+ {
+ const std::string &includeDir = *stringSetIter;
+ const std::string &relative = cmSystemTools::RelativePath(
+ lgs[0]->GetMakefile()->GetHomeOutputDirectory(),
+ includeDir.c_str());
+ // It appears that a relative path to the sublime-project file doesn't
+ // always work. So we use ${folder:${project_path:<project_filename>}}
+ // that SublimeClang will expand to the correct path
+ fout << "\t\"-I${folder:${project_path:" << mf->GetProjectName() <<
+ ".sublime-project}}/" << relative << "\"";
+ stringSetIter++;
+ if ((stringSetIter != includeDirs.end()) || (!defines.empty()))
+ {
+ fout << ",";
+ }
+ fout << "\n\t\t";
+ }
+ stringSetIter = defines.begin();
+ while (stringSetIter != defines.end())
+ {
+ fout << "\t\"-D" << *stringSetIter << "\"";
+ stringSetIter++;
+ if (stringSetIter != defines.end())
+ {
+ fout << ",";
+ }
+ fout << "\n\t\t";
+ }
+ // End of the sublimeclang_options section
+ fout << "]\n\t";
+ // End of the settings section
+ fout << "}\n";
+
+ // End of file
+ fout << "}";
+}
+
+void cmExtraSublimeTextGenerator::
+ AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
+ const cmMakefile* mf,
+ cmGeneratedFileStream& fout,
+ std::set<std::string>& includeDirs,
+ std::set<std::string>& defines)
+{
+ std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ std::string compiler = "";
+ this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str(),
+ includeDirs, defines, true);
+ this->AppendTarget(fout, "clean", 0, make.c_str(), mf, compiler.c_str(),
+ includeDirs, defines, false);
+
+ // 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;
+ // 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(),
+ includeDirs, defines, false);
+ }
+ }
+ break;
+ case cmTarget::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")))
+ {
+ break;
+ }
+
+ this->AppendTarget(fout, ti->first.c_str(), 0,
+ make.c_str(), makefile, compiler.c_str(),
+ includeDirs, defines, false);
+ 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(),
+ includeDirs, defines, false);
+ std::string fastTarget = ti->first;
+ fastTarget += "/fast";
+ this->AppendTarget(fout, fastTarget.c_str(), &ti->second,
+ make.c_str(), makefile, compiler.c_str(),
+ includeDirs, defines, false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void cmExtraSublimeTextGenerator::
+ ExtractDefines(const char* value, bool check,
+ std::set<std::string> &defines)
+{
+ std::vector<std::string> defs;
+ cmSystemTools::ExpandListArgument(value, defs);
+ for(std::vector<std::string>::const_iterator di = defs.begin();
+ di != defs.end(); ++di)
+ {
+ cmXMLSafe safedef(di->c_str());
+ if (check)
+ {
+ std::string safedefString = safedef.str();
+ if ((safedefString.length() >= 2) &&
+ (safedefString.substr(0, 2) == "-D"))
+ {
+ defines.insert(safedefString.substr(2));
+ }
+ }
+ else
+ {
+ defines.insert(safedef.str());
+ }
+ }
+}
+
+void cmExtraSublimeTextGenerator::AppendTarget(cmGeneratedFileStream& fout,
+ const char* targetName,
+ cmTarget* target,
+ const char* make,
+ const cmMakefile* makefile,
+ const char* compiler,
+ std::set<std::string>&
+ includeDirs,
+ std::set<std::string>& defines,
+ bool firstTarget)
+{
+ if (target != 0)
+ {
+ // the compilerdefines for this target
+ cmGeneratorTarget *gtgt = this->GlobalGenerator
+ ->GetGeneratorTarget(target);
+ std::string cdefs = gtgt->GetCompileDefinitions();
+ ExtractDefines(cdefs.c_str(), false, defines);
+ // Get compiler definitions from CMAKE_CXX_FLAGS and CMAKE_C_FLAGS as
+ // well, in case the user set those flags directly
+ std::string cflags = makefile->GetSafeDefinition("CMAKE_CXX_FLAGS");
+ ExtractDefines(cflags.c_str(), true, defines);
+ cflags = makefile->GetSafeDefinition("CMAKE_C_FLAGS");
+ ExtractDefines(cflags.c_str(), true, defines);
+ // the include directories for this target
+ std::vector<std::string> includes;
+ target->GetMakefile()->GetLocalGenerator()->
+ GetIncludeDirectories(includes, gtgt);
+ for(std::vector<std::string>::const_iterator dirIt=includes.begin();
+ dirIt != includes.end();
+ ++dirIt)
+ {
+ includeDirs.insert(*dirIt);
+ }
+
+ std::string systemIncludeDirs = makefile->GetSafeDefinition(
+ "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)
+ {
+ includeDirs.insert(*dirIt);
+ }
+ }
+
+ systemIncludeDirs = makefile->GetSafeDefinition(
+ "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)
+ {
+ includeDirs.insert(*dirIt);
+ }
+ }
+ }
+
+ // Ninja uses ninja.build files (look for a way to get the output file name
+ // from cmMakefile or something)
+ std::string makefileName;
+ if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
+ {
+ makefileName = "build.ninja";
+ }
+ else
+ {
+ makefileName = "Makefile";
+ }
+ if (!firstTarget)
+ {
+ fout << ",\n\t";
+ }
+ fout << "\t{\n\t\t\t\"name\": \"" << makefile->GetProjectName() << " - " <<
+ targetName << "\",\n";
+ fout << "\t\t\t\"cmd\": [" <<
+ this->BuildMakeCommand(make, makefileName.c_str(), targetName) <<
+ "],\n";
+ fout << "\t\t\t\"working_dir\": \"${project_path}\",\n";
+ fout << "\t\t\t\"file_regex\": \"^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$\"\n";
+ fout << "\t\t}";
+}
+
+// Create the command line for building the given target using the selected
+// make
+std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
+ const std::string& make, const char* makefile, const char* target)
+{
+ std::string command = "\"";
+ command += make + "\"";
+ if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
+ {
+ std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ command += ", \"/NOLOGO\", \"/f\", \"";
+ command += makefileName + "\"";
+ command += ", \"VERBOSE=1\", \"";
+ command += target;
+ command += "\"";
+ }
+ else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
+ {
+ std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ command += ", \"-f\", \"";
+ command += makefileName + "\"";
+ command += ", \"-v\", \"";
+ command += target;
+ command += "\"";
+ }
+ else
+ {
+ std::string makefileName;
+ if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
+ {
+ // no escaping of spaces in this case, see
+ // http://public.kitware.com/Bug/view.php?id=10014
+ makefileName = makefile;
+ }
+ else
+ {
+ makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ }
+ command += ", \"-f\", \"";
+ command += makefileName + "\"";
+ command += ", \"VERBOSE=1\", \"";
+ command += target;
+ command += "\"";
+ }
+ return command;
+}
diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h
new file mode 100644
index 0000000..1735b75
--- /dev/null
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -0,0 +1,77 @@
+/*============================================================================
+ 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.
+============================================================================*/
+#ifndef cmExtraSublimeTextGenerator_h
+#define cmExtraSublimeTextGenerator_h
+
+#include "cmExternalMakefileProjectGenerator.h"
+
+class cmLocalGenerator;
+class cmMakefile;
+class cmTarget;
+class cmGeneratedFileStream;
+
+/** \class cmExtraSublimeTextGenerator
+ * \brief Write Sublime Text 2 project files for Makefile based projects
+ */
+class cmExtraSublimeTextGenerator : public cmExternalMakefileProjectGenerator
+{
+public:
+ cmExtraSublimeTextGenerator();
+
+ virtual const char* GetName() const
+ { return cmExtraSublimeTextGenerator::GetActualName();}
+ static const char* GetActualName()
+ { return "Sublime Text 2";}
+ static cmExternalMakefileProjectGenerator* New()
+ { return new cmExtraSublimeTextGenerator; }
+ /** Get the documentation entry for this generator. */
+ virtual void GetDocumentation(cmDocumentationEntry& entry,
+ const char* fullName) const;
+
+ virtual void Generate();
+private:
+
+ void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
+
+ void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
+ const std::string& filename);
+ /** Appends all targets as build systems to the project file and get all
+ * include directories and compiler definitions used.
+ */
+ void AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
+ const cmMakefile* mf,
+ cmGeneratedFileStream& fout,
+ std::set<std::string>& includeDirs,
+ std::set<std::string>& defines);
+ /** Returns the build command that needs to be executed to build the
+ * specified target.
+ */
+ std::string BuildMakeCommand(const std::string& make, const char* makefile,
+ const char* target);
+ /** Appends the specified target to the generated project file as a Sublime
+ * Text build system.
+ */
+ void AppendTarget(cmGeneratedFileStream& fout,
+ const char* targetName,
+ cmTarget* target,
+ const char* make,
+ const cmMakefile* makefile,
+ const char* compiler,
+ std::set<std::string>& includeDirs,
+ std::set<std::string>& defines, bool firstTarget);
+ /** Extracts -D compile flags from a variable */
+ void ExtractDefines(const char* value, bool check,
+ std::set<std::string> &defines);
+};
+
+#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 0123427..3a25605 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -94,6 +94,7 @@
#if !defined(CMAKE_BOOT_MINGW)
# include "cmExtraCodeBlocksGenerator.h"
#endif
+#include "cmExtraSublimeTextGenerator.h"
#ifdef CMAKE_USE_KDEVELOP
# include "cmGlobalKdevelopGenerator.h"
@@ -1847,6 +1848,8 @@ void cmake::AddDefaultExtraGenerators()
this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
&cmExtraCodeBlocksGenerator::New);
+ this->AddExtraGenerator(cmExtraSublimeTextGenerator::GetActualName(),
+ &cmExtraSublimeTextGenerator::New);
#ifdef CMAKE_USE_ECLIPSE
this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),