Qbs: Add new 'extra' generator for qbs project files

This commit is contained in:
Stanislav Ionascu 2015-02-08 13:50:16 +01:00 committed by Brad King
parent 380db3de00
commit f85db2f323
8 changed files with 361 additions and 1 deletions

25
Help/generator/Qbs.rst Normal file
View File

@ -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`.

View File

@ -85,3 +85,4 @@ The following extra generators are known to CMake.
/generator/KDevelop3
/generator/Kate
/generator/Sublime Text 2
/generator/Qbs

View File

@ -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.

View File

@ -229,6 +229,8 @@ set(SRCS
cmExtraKateGenerator.h
cmExtraSublimeTextGenerator.cxx
cmExtraSublimeTextGenerator.h
cmExtraQbsGenerator.cxx
cmExtraQbsGenerator.h
cmFileLock.cxx
cmFileLock.h
cmFileLockPool.cxx

View File

@ -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";
}

View File

@ -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

View File

@ -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(),

View File

@ -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