summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/generator/Qbs.rst25
-rw-r--r--Help/manual/cmake-generators.7.rst1
-rw-r--r--Help/release/dev/add-extra-qbs-generator.rst6
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmExtraQbsGenerator.cxx260
-rw-r--r--Source/cmExtraQbsGenerator.h48
-rw-r--r--Source/cmake.cxx4
-rw-r--r--Tests/CMakeLists.txt16
8 files changed, 361 insertions, 1 deletions
diff --git a/Help/generator/Qbs.rst b/Help/generator/Qbs.rst
new file mode 100644
index 0000000..e569b77
--- /dev/null
+++ b/Help/generator/Qbs.rst
@@ -0,0 +1,25 @@
+Qbs
+---
+
+Generates Qbs project files.
+
+Project files for Qbs 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.
+
+This "extra" generator may be specified as:
+
+``Qbs - MinGW Makefiles``
+ Generate with :generator:`MinGW Makefiles`.
+
+``Qbs - NMake Makefiles``
+ Generate with :generator:`NMake Makefiles`.
+
+``Qbs - Ninja``
+ Generate with :generator:`Ninja`.
+
+``Qbs - Unix Makefiles``
+ Generate with :generator:`Unix Makefiles`.
diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst
index bda7eef..804229b 100644
--- a/Help/manual/cmake-generators.7.rst
+++ b/Help/manual/cmake-generators.7.rst
@@ -85,3 +85,4 @@ The following extra generators are known to CMake.
/generator/KDevelop3
/generator/Kate
/generator/Sublime Text 2
+ /generator/Qbs
diff --git a/Help/release/dev/add-extra-qbs-generator.rst b/Help/release/dev/add-extra-qbs-generator.rst
new file mode 100644
index 0000000..edb441f
--- /dev/null
+++ b/Help/release/dev/add-extra-qbs-generator.rst
@@ -0,0 +1,6 @@
+add-extra-qbs-geneator
+----------------------
+
+* It is now possible to generate :generator:`Qbs` project files
+ for use with QtCreator IDE, matching make tool must be used
+ to build the project through the generated makefiles.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 482bd39..04f6a81 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -229,6 +229,8 @@ set(SRCS
cmExtraKateGenerator.h
cmExtraSublimeTextGenerator.cxx
cmExtraSublimeTextGenerator.h
+ cmExtraQbsGenerator.cxx
+ cmExtraQbsGenerator.h
cmFileLock.cxx
cmFileLock.h
cmFileLockPool.cxx
diff --git a/Source/cmExtraQbsGenerator.cxx b/Source/cmExtraQbsGenerator.cxx
new file mode 100644
index 0000000..5a1f9ef
--- /dev/null
+++ b/Source/cmExtraQbsGenerator.cxx
@@ -0,0 +1,260 @@
+#include "cmExtraQbsGenerator.h"
+
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSourceFile.h"
+
+cmExtraQbsGenerator::cmExtraQbsGenerator()
+{
+#if defined(_WIN32)
+ this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
+ this->SupportedGlobalGenerators.push_back("NMake Makefiles");
+#endif
+ this->SupportedGlobalGenerators.push_back("Ninja");
+ this->SupportedGlobalGenerators.push_back("Unix Makefiles");
+}
+
+cmExtraQbsGenerator::~cmExtraQbsGenerator() {}
+
+void cmExtraQbsGenerator::GetDocumentation(cmDocumentationEntry &entry,
+ const std::string &) const
+{
+ entry.Name = this->GetName();
+ entry.Brief = "Generates Qbs project files.";
+}
+
+void cmExtraQbsGenerator::Generate()
+{
+ 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->first, it->second);
+ }
+}
+
+void cmExtraQbsGenerator::CreateProjectFile(
+ const std::string &name,
+ const std::vector<cmLocalGenerator *> &lgs)
+{
+ const cmMakefile *mf = lgs[0]->GetMakefile();
+ std::string outputDir = mf->GetStartOutputDirectory();
+
+ const std::string filename = outputDir + "/" + name + ".qbs";
+
+ this->CreateNewProjectFile(name, lgs, filename);
+}
+
+void cmExtraQbsGenerator::CreateNewProjectFile(
+ const std::string &projectName, const std::vector<cmLocalGenerator *> &lgs,
+ const std::string &filename)
+{
+ cmGeneratedFileStream fout(filename.c_str());
+ if (!fout)
+ {
+ return;
+ }
+
+ fout << "import qbs\n"
+ << "import qbs.File\n\n"
+ << "Project {\n"
+ << "\tname:\"" << projectName << "\"\n";
+ std::vector<cmLocalGenerator *>::const_iterator itr = lgs.begin();
+ for (; itr != lgs.end(); ++itr)
+ {
+ cmLocalGenerator *lg = (*itr);
+ this->AppendSubProject(fout, lg);
+ }
+ fout << "}\n";
+}
+
+void cmExtraQbsGenerator::AppendSubProject(cmGeneratedFileStream &fout,
+ cmLocalGenerator *lg)
+{
+ const cmMakefile *mk = lg->GetMakefile();
+ if (!mk || mk->GetTargets().size() == 0)
+ {
+ return;
+ }
+
+ const std::string &relativePath = cmSystemTools::RelativePath(
+ mk->GetHomeDirectory(), mk->GetCurrentDirectory());
+ fout << "\tProject {\n"
+ << "\t\tname:\"" << relativePath << "\"\n";
+ this->AppendProduct(fout, lg);
+ fout << "\t}\n";
+}
+
+void cmExtraQbsGenerator::AppendProduct(cmGeneratedFileStream &fout,
+ cmLocalGenerator *lg)
+{
+ const cmMakefile *mk = lg->GetMakefile();
+ const cmTargets &ts = mk->GetTargets();
+ std::string cfg = mk->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmTargets::const_iterator itr = ts.begin();
+ for (; itr != ts.end(); ++itr)
+ {
+ const cmTarget &t = itr->second;
+ this->AppendTarget(fout, lg, t, cfg);
+ }
+}
+
+void cmExtraQbsGenerator::AppendTarget(cmGeneratedFileStream &fout,
+ cmLocalGenerator *lg, const cmTarget &t,
+ const std::string &cfg)
+{
+ std::string type;
+ bool isBuildable = true;
+ switch (t.GetType())
+ {
+ case cmTarget::EXECUTABLE:
+ type = "application";
+ break;
+ case cmTarget::SHARED_LIBRARY:
+ type = "dynamiclibrary";
+ break;
+ case cmTarget::STATIC_LIBRARY:
+ type = "staticlibrary";
+ break;
+ default:
+ isBuildable = false;
+ break;
+ }
+
+ if (type.empty())
+ {
+ fout << "\t\tProject {\n";
+ }
+ else
+ {
+ fout << "\t\tProduct {\n";
+ fout << "\t\t\tdestinationDirectory: \"" << t.GetDirectory(cfg) << "\"\n";
+ }
+ fout << "\t\t\tname:\"" << t.GetName() << "\"\n";
+
+ if (!type.empty())
+ {
+ fout << "\t\t\ttype: \"" << type << "\"\n";
+ fout << "\t\t\ttargetName: \"" << t.GetName() << "\"\n";
+ }
+
+ if (isBuildable)
+ {
+ fout << "\t\t\tDepends { name: \"cpp\" }\n";
+ cmGeneratorTarget *gt = this->GlobalGenerator->GetGeneratorTarget(&t);
+ this->AppendSources(fout, gt, t, cfg);
+
+ std::set<std::string> langs, incPaths, defs;
+ t.GetLanguages(langs, cfg);
+ for (std::set<std::string>::const_iterator lang = langs.begin();
+ lang != langs.end();
+ ++ lang)
+ {
+ const std::vector<std::string> &paths =
+ gt->GetIncludeDirectories(cfg, *lang);
+ std::copy(paths.begin(), paths.end(),
+ std::inserter(incPaths, incPaths.end()));
+
+ lg->AddCompileDefinitions(defs, &t, cfg, *lang);
+ }
+ this->AppendIncludePaths(fout, incPaths);
+ this->AppendCompileDefinitions(fout, defs);
+ }
+
+ fout << "\t\t}\n";
+}
+
+void cmExtraQbsGenerator::AppendSources(cmGeneratedFileStream &fout,
+ cmGeneratorTarget *gt,
+ const cmTarget &t,
+ const std::string &cfg)
+{
+ std::vector<cmSourceFile *> sources;
+ gt->GetSourceFiles(sources, cfg);
+ if (sources.empty())
+ {
+ return;
+ }
+
+ std::vector<cmSourceFile *> genSources;
+ std::vector<cmSourceFile *>::const_iterator itr = sources.begin();
+ fout << "\t\t\tfiles: [\n"
+ << "\t\t\t\t\"" << t.GetMakefile()->GetCurrentListFile() << "\",\n";
+ for (; itr != sources.end(); ++itr)
+ {
+ if (!(*itr)->GetPropertyAsBool("GENERATED"))
+ {
+ fout << "\t\t\t\t\"" << (*itr)->GetFullPath() << "\",\n";
+ }
+ else
+ {
+ genSources.push_back(*itr);
+ }
+ }
+ fout << "\t\t\t]\n";
+
+ if (!genSources.empty())
+ {
+ fout << "\t\t\tGroup {\n"
+ << "\t\t\t\tname:\"Generated\"\n"
+ << "\t\t\t\tfiles: [\n";
+ itr = genSources.begin();
+ std::string groupCondition;
+ bool initialCondition = true;
+ for (; itr != genSources.end(); ++itr)
+ {
+ const std::string &path = (*itr)->GetFullPath();
+ fout << "\t\t\t\t\t\"" << path << "\",\n";
+ if (initialCondition)
+ {
+ initialCondition = false;
+ }
+ else
+ {
+ groupCondition += "\t\t\t\t\t && ";
+ }
+ groupCondition += "File.exists(\"" + path + "\")\n";
+ }
+ fout << "\t\t\t\t]\n"
+ << "\t\t\t\tcondition: " << groupCondition << "\t\t\t}\n";
+ }
+}
+
+void cmExtraQbsGenerator::AppendIncludePaths(
+ cmGeneratedFileStream &fout,
+ const std::set<std::string> &paths)
+{
+ if (paths.empty())
+ {
+ return;
+ }
+
+ std::set<std::string>::const_iterator itr = paths.begin();
+ fout << "\t\t\tcpp.includePaths: [\n";
+ for (; itr != paths.end(); ++ itr)
+ {
+ fout << "\t\t\t\t\"" << (*itr) << "\",\n";
+ }
+ fout << "\t\t\t]\n";
+}
+
+void cmExtraQbsGenerator::AppendCompileDefinitions(
+ cmGeneratedFileStream &fout,
+ const std::set<std::string> &defs)
+{
+ if (defs.empty())
+ {
+ return;
+ }
+
+ std::set<std::string>::const_iterator itr = defs.begin();
+ fout << "\t\t\tcpp.defines: [\n";
+ for (; itr != defs.end(); ++ itr)
+ {
+ fout << "\t\t\t\t'" << (*itr) << "',\n";
+ }
+ fout << "\t\t\t]\n";
+}
diff --git a/Source/cmExtraQbsGenerator.h b/Source/cmExtraQbsGenerator.h
new file mode 100644
index 0000000..531ccc9
--- /dev/null
+++ b/Source/cmExtraQbsGenerator.h
@@ -0,0 +1,48 @@
+#ifndef CMEXTRAQBSGENERATOR_H
+#define CMEXTRAQBSGENERATOR_H
+
+#include "cmExternalMakefileProjectGenerator.h"
+
+class cmGeneratorTarget;
+
+class cmExtraQbsGenerator : public cmExternalMakefileProjectGenerator
+{
+public:
+ cmExtraQbsGenerator();
+ ~cmExtraQbsGenerator();
+
+ virtual std::string GetName() const
+ { return cmExtraQbsGenerator::GetActualName(); }
+ static std::string GetActualName() { return "Qbs"; }
+ static cmExternalMakefileProjectGenerator *New()
+ { return new cmExtraQbsGenerator; }
+
+ /** Get the documentation entry for this generator. */
+ virtual void GetDocumentation(cmDocumentationEntry &entry,
+ const std::string &fullName) const;
+
+ virtual void Generate();
+
+private:
+ void CreateProjectFile(const std::string &name,
+ const std::vector<cmLocalGenerator *> &lgs);
+ void CreateNewProjectFile(const std::string &projectName,
+ const std::vector<cmLocalGenerator *> &lgs,
+ const std::string &filename);
+ void AppendSubProject(cmGeneratedFileStream &fout, cmLocalGenerator *lg);
+ void AppendProduct(cmGeneratedFileStream &fout, cmLocalGenerator *lg);
+ void AppendTarget(cmGeneratedFileStream &fout,
+ cmLocalGenerator *lg,
+ const cmTarget &t,
+ const std::string &cfg);
+ void AppendSources(cmGeneratedFileStream &fout,
+ cmGeneratorTarget *gt,
+ const cmTarget &t,
+ const std::string &cfg);
+ void AppendIncludePaths(cmGeneratedFileStream &fout,
+ const std::set<std::string> &paths);
+ void AppendCompileDefinitions(cmGeneratedFileStream &fout,
+ const std::set<std::string> &defs);
+};
+
+#endif // CMEXTRAQBSGENERATOR_H
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 11196e4..51df7f2 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -86,6 +86,8 @@
# include "cmGlobalKdevelopGenerator.h"
#endif
+#include "cmExtraQbsGenerator.h"
+
#ifdef CMAKE_USE_ECLIPSE
# include "cmExtraEclipseCDT4Generator.h"
#endif
@@ -1029,6 +1031,8 @@ void cmake::AddDefaultExtraGenerators()
&cmExtraSublimeTextGenerator::New);
this->AddExtraGenerator(cmExtraKateGenerator::GetActualName(),
&cmExtraKateGenerator::New);
+ this->AddExtraGenerator(cmExtraQbsGenerator::GetActualName(),
+ &cmExtraQbsGenerator::New);
#ifdef CMAKE_USE_ECLIPSE
this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 40bea51..5fa7044 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -560,7 +560,21 @@ if(BUILD_TESTING)
--test-command Simple)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Simple_KDevelop3Generator")
endif ()
-
+ # check for the Qbs generator
+ if ("${cmakeOutput}" MATCHES Qbs)
+ add_test(Simple_QbsGenerator ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Simple"
+ "${CMake_BINARY_DIR}/Tests/Simple_QbsGenerator"
+ --build-two-config
+ --build-generator "Qbs - Unix Makefiles"
+ --build-generator-platform "${CMAKE_GENERATOR_PLATFORM}"
+ --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}"
+ --build-project Simple
+ --build-options ${build_options}
+ --test-command Simple)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Simple_QbsGenerator")
+ endif ()
endif()
# test for correct sub-project generation