aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/api
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2013-06-06 10:06:30 +0200
committerJoerg Bornemann <joerg.bornemann@digia.com>2013-06-17 14:23:19 +0200
commitab60f6e4c489ace089785c002d75018ac6a31e30 (patch)
tree91053ec752d9aa56df8061ba5e62c13431804a6b /src/lib/api
parentd3877c67d060d454ac66fde7b6ad41a2bb50d808 (diff)
Allow projects to be nested.
This is nice to have for grouping products and a requirement for aggregating existing projects into a bigger one. Change-Id: I3394642e95ea57dbc6bf1603cfed6902a5906e4c Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/lib/api')
-rw-r--r--src/lib/api/internaljobs.cpp23
-rw-r--r--src/lib/api/internaljobs.h20
-rw-r--r--src/lib/api/jobs.cpp9
-rw-r--r--src/lib/api/jobs.h8
-rw-r--r--src/lib/api/project.cpp63
-rw-r--r--src/lib/api/project.h2
-rw-r--r--src/lib/api/projectdata.cpp51
-rw-r--r--src/lib/api/projectdata.h5
-rw-r--r--src/lib/api/projectdata_p.h3
9 files changed, 132 insertions, 52 deletions
diff --git a/src/lib/api/internaljobs.cpp b/src/lib/api/internaljobs.cpp
index 946a87fa6..2f67243d3 100644
--- a/src/lib/api/internaljobs.cpp
+++ b/src/lib/api/internaljobs.cpp
@@ -119,7 +119,7 @@ void InternalJob::cancel()
m_observer->cancel();
}
-void InternalJob::storeBuildGraph(const ResolvedProjectConstPtr &project)
+void InternalJob::storeBuildGraph(const TopLevelProjectConstPtr &project)
{
try {
project->store(logger());
@@ -154,7 +154,7 @@ void InternalSetupProjectJob::reportError(const Error &error)
Q_ARG(Internal::InternalJob *, this));
}
-ResolvedProjectPtr InternalSetupProjectJob::project() const
+TopLevelProjectPtr InternalSetupProjectJob::project() const
{
return m_project;
}
@@ -201,10 +201,6 @@ void InternalSetupProjectJob::execute()
loader.setProgressObserver(observer());
m_project = loader.loadProject(m_parameters);
}
- if (m_project->products.isEmpty()) {
- throw Error(Tr::tr("Project '%1' does not contain products.")
- .arg(m_parameters.projectFilePath()));
- }
}
// copy the environment from the platform config into the project's config
@@ -216,7 +212,7 @@ void InternalSetupProjectJob::execute()
foreach (const ResolvedProductConstPtr &p, m_project->products) {
logger().qbsDebug() << QString::fromLocal8Bit(" - [%1] %2 as %3")
.arg(p->fileTags.toStringList().join(QLatin1String(", ")))
- .arg(p->name).arg(p->project->id());
+ .arg(p->name).arg(p->topLevelProject()->id());
}
logger().qbsDebug() << '\n';
@@ -244,7 +240,7 @@ BuildGraphTouchingJob::~BuildGraphTouchingJob()
{
}
-void BuildGraphTouchingJob::setup(const ResolvedProjectPtr &project,
+void BuildGraphTouchingJob::setup(const TopLevelProjectPtr &project,
const QList<ResolvedProductPtr> &products, bool dryRun)
{
m_project = project;
@@ -263,7 +259,7 @@ InternalBuildJob::InternalBuildJob(const Logger &logger, QObject *parent)
{
}
-void InternalBuildJob::build(const ResolvedProjectPtr &project,
+void InternalBuildJob::build(const TopLevelProjectPtr &project,
const QList<ResolvedProductPtr> &products, const BuildOptions &buildOptions)
{
setup(project, products, buildOptions.dryRun());
@@ -308,7 +304,7 @@ InternalCleanJob::InternalCleanJob(const Logger &logger, QObject *parent)
{
}
-void InternalCleanJob::clean(const ResolvedProjectPtr &project,
+void InternalCleanJob::clean(const TopLevelProjectPtr &project,
const QList<ResolvedProductPtr> &products, const CleanOptions &options)
{
setup(project, products, options.dryRun());
@@ -350,9 +346,10 @@ InternalInstallJob::~InternalInstallJob()
{
}
-void InternalInstallJob::install(const QList<ResolvedProductPtr> &products,
- const InstallOptions &options)
+void InternalInstallJob::install(const TopLevelProjectPtr &project,
+ const QList<ResolvedProductPtr> &products, const InstallOptions &options)
{
+ m_project = project;
m_products = products;
m_options = options;
setTimed(options.logElapsedTime());
@@ -374,7 +371,7 @@ void InternalInstallJob::start()
void InternalInstallJob::doInstall()
{
try {
- ProductInstaller(m_products, m_options, observer(), logger()).install();
+ ProductInstaller(m_project, m_products, m_options, observer(), logger()).install();
} catch (const Error &error) {
setError(error);
}
diff --git a/src/lib/api/internaljobs.h b/src/lib/api/internaljobs.h
index b94403fcb..37b2f607d 100644
--- a/src/lib/api/internaljobs.h
+++ b/src/lib/api/internaljobs.h
@@ -68,7 +68,7 @@ protected:
JobObserver *observer() const { return m_observer; }
void setError(const Error &error) { m_error = error; }
void setTimed(bool timed) { m_timed = timed; }
- void storeBuildGraph(const ResolvedProjectConstPtr &project);
+ void storeBuildGraph(const TopLevelProjectConstPtr &project);
signals:
void finished(Internal::InternalJob *job);
@@ -94,7 +94,7 @@ public:
void resolve(const SetupProjectParameters &parameters);
void reportError(const Error &error);
- ResolvedProjectPtr project() const;
+ TopLevelProjectPtr project() const;
private slots:
void start();
@@ -108,7 +108,7 @@ private:
QMutex m_runMutex;
QWaitCondition m_runWaitCondition;
- ResolvedProjectPtr m_project;
+ TopLevelProjectPtr m_project;
SetupProjectParameters m_parameters;
};
@@ -118,7 +118,7 @@ class BuildGraphTouchingJob : public InternalJob
Q_OBJECT
public:
const QList<ResolvedProductPtr> &products() const { return m_products; }
- const ResolvedProjectPtr &project() const { return m_project; }
+ const TopLevelProjectPtr &project() const { return m_project; }
signals:
void reportCommandDescription(const QString &highlight, const QString &message);
@@ -128,12 +128,12 @@ protected:
BuildGraphTouchingJob(const Logger &logger, QObject *parent = 0);
~BuildGraphTouchingJob();
- void setup(const ResolvedProjectPtr &project, const QList<ResolvedProductPtr> &products,
+ void setup(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
bool dryRun);
void storeBuildGraph();
private:
- ResolvedProjectPtr m_project;
+ TopLevelProjectPtr m_project;
QList<ResolvedProductPtr> m_products;
bool m_dryRun;
};
@@ -145,7 +145,7 @@ class InternalBuildJob : public BuildGraphTouchingJob
public:
InternalBuildJob(const Logger &logger, QObject *parent = 0);
- void build(const ResolvedProjectPtr &project, const QList<ResolvedProductPtr> &products,
+ void build(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
const BuildOptions &buildOptions);
private slots:
@@ -163,7 +163,7 @@ class InternalCleanJob : public BuildGraphTouchingJob
public:
InternalCleanJob(const Logger &logger, QObject *parent = 0);
- void clean(const ResolvedProjectPtr &project, const QList<ResolvedProductPtr> &products,
+ void clean(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
const CleanOptions &options);
private slots:
@@ -185,7 +185,8 @@ public:
InternalInstallJob(const Logger &logger, QObject *parent = 0);
~InternalInstallJob();
- void install(const QList<ResolvedProductPtr> &products, const InstallOptions &options);
+ void install(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
+ const InstallOptions &options);
private slots:
void handleFinished();
@@ -195,6 +196,7 @@ private:
void doInstall();
private:
+ TopLevelProjectPtr m_project;
QList<ResolvedProductPtr> m_products;
InstallOptions m_options;
};
diff --git a/src/lib/api/jobs.cpp b/src/lib/api/jobs.cpp
index a344cc5c0..47bda7191 100644
--- a/src/lib/api/jobs.cpp
+++ b/src/lib/api/jobs.cpp
@@ -242,7 +242,7 @@ BuildJob::BuildJob(const Logger &logger, QObject *parent)
this, SIGNAL(reportProcessResult(qbs::ProcessResult)));
}
-void BuildJob::build(const ResolvedProjectPtr &project, const QList<ResolvedProductPtr> &products,
+void BuildJob::build(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
const BuildOptions &options)
{
qobject_cast<InternalBuildJob *>(internalJob())->build(project, products, options);
@@ -259,7 +259,7 @@ CleanJob::CleanJob(const Logger &logger, QObject *parent)
{
}
-void CleanJob::clean(const ResolvedProjectPtr &project, const QList<ResolvedProductPtr> &products,
+void CleanJob::clean(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
const qbs::CleanOptions &options)
{
qobject_cast<InternalCleanJob *>(internalJob())->clean(project, products, options);
@@ -275,9 +275,10 @@ InstallJob::InstallJob(const Logger &logger, QObject *parent)
{
}
-void InstallJob::install(const QList<ResolvedProductPtr> &products, const InstallOptions &options)
+void InstallJob::install(const TopLevelProjectPtr &project,
+ const QList<ResolvedProductPtr> &products, const InstallOptions &options)
{
- qobject_cast<InternalInstallJob *>(internalJob())->install(products, options);
+ qobject_cast<InternalInstallJob *>(internalJob())->install(project, products, options);
}
} // namespace qbs
diff --git a/src/lib/api/jobs.h b/src/lib/api/jobs.h
index 19d4f8dcb..791ad2af7 100644
--- a/src/lib/api/jobs.h
+++ b/src/lib/api/jobs.h
@@ -113,7 +113,7 @@ signals:
private:
BuildJob(const Internal::Logger &logger, QObject *parent);
- void build(const Internal::ResolvedProjectPtr &project,
+ void build(const Internal::TopLevelProjectPtr &project,
const QList<qbs::Internal::ResolvedProductPtr> &products,
const BuildOptions &options);
};
@@ -127,7 +127,7 @@ class QBS_EXPORT CleanJob : public AbstractJob
private:
CleanJob(const Internal::Logger &logger, QObject *parent);
- void clean(const Internal::ResolvedProjectPtr &project,
+ void clean(const Internal::TopLevelProjectPtr &project,
const QList<Internal::ResolvedProductPtr> &products, const CleanOptions &options);
};
@@ -138,8 +138,8 @@ class QBS_EXPORT InstallJob : public AbstractJob
private:
InstallJob(const Internal::Logger &logger, QObject *parent);
- void install(const QList<Internal::ResolvedProductPtr> &products,
- const InstallOptions &options);
+ void install(const Internal::TopLevelProjectPtr &project,
+ const QList<Internal::ResolvedProductPtr> &products, const InstallOptions &options);
};
} // namespace qbs
diff --git a/src/lib/api/project.cpp b/src/lib/api/project.cpp
index f9744d648..dca2104d8 100644
--- a/src/lib/api/project.cpp
+++ b/src/lib/api/project.cpp
@@ -91,7 +91,7 @@ static void loadPlugins(const QStringList &_pluginPaths, const Logger &logger)
class ProjectPrivate : public QSharedData
{
public:
- ProjectPrivate(const ResolvedProjectPtr &internalProject, const Logger &logger)
+ ProjectPrivate(const TopLevelProjectPtr &internalProject, const Logger &logger)
: internalProject(internalProject), logger(logger), m_projectDataRetrieved(false)
{
}
@@ -109,11 +109,12 @@ public:
QList<ResolvedProductPtr> allEnabledInternalProducts() const;
ResolvedProductPtr internalProduct(const ProductData &product) const;
- const ResolvedProjectPtr internalProject;
+ const TopLevelProjectPtr internalProject;
Logger logger;
private:
- void retrieveProjectData();
+ void retrieveProjectData(ProjectData &projectData,
+ const ResolvedProjectConstPtr &internalProject);
ProjectData m_projectData;
bool m_projectDataRetrieved;
@@ -121,8 +122,11 @@ private:
ProjectData ProjectPrivate::projectData()
{
- if (!m_projectDataRetrieved)
- retrieveProjectData();
+ if (!m_projectDataRetrieved) {
+ retrieveProjectData(m_projectData, internalProject);
+ m_projectData.d->buildDir = internalProject->buildDirectory;
+ m_projectDataRetrieved = true;
+ }
return m_projectData;
}
@@ -165,7 +169,7 @@ InstallJob *ProjectPrivate::installProducts(const QList<ResolvedProductPtr> &pro
if (needsDepencencyResolving)
addDependencies(productsToInstall);
InstallJob * const job = new InstallJob(logger, jobOwner);
- job->install(productsToInstall, options);
+ job->install(internalProject, productsToInstall, options);
return job;
}
@@ -179,30 +183,49 @@ QList<ResolvedProductPtr> ProjectPrivate::internalProducts(const QList<ProductDa
return internalProducts;
}
-QList<ResolvedProductPtr> ProjectPrivate::allEnabledInternalProducts() const
+static QList<ResolvedProductPtr> enabledInternalProducts(const ResolvedProjectConstPtr &project)
{
QList<ResolvedProductPtr> products;
- foreach (const ResolvedProductPtr &p, internalProject->products) {
+ foreach (const ResolvedProductPtr &p, project->products) {
if (p->enabled)
products << p;
}
+ foreach (const ResolvedProjectConstPtr &subProject, project->subProjects)
+ products << enabledInternalProducts(subProject);
return products;
}
-ResolvedProductPtr ProjectPrivate::internalProduct(const ProductData &product) const
+QList<ResolvedProductPtr> ProjectPrivate::allEnabledInternalProducts() const
+{
+ return enabledInternalProducts(internalProject);
+}
+
+static ResolvedProductPtr internalProductForProject(const ResolvedProjectConstPtr &project,
+ const ProductData &product)
{
- foreach (const ResolvedProductPtr &resolvedProduct, internalProject->products) {
+ foreach (const ResolvedProductPtr &resolvedProduct, project->products) {
if (product.name() == resolvedProduct->name)
return resolvedProduct;
}
- qFatal("No build product '%s'", qPrintable(product.name()));
+ foreach (const ResolvedProjectConstPtr &subProject, project->subProjects) {
+ const ResolvedProductPtr &p = internalProductForProject(subProject, product);
+ if (p)
+ return p;
+ }
return ResolvedProductPtr();
}
-void ProjectPrivate::retrieveProjectData()
+ResolvedProductPtr ProjectPrivate::internalProduct(const ProductData &product) const
+{
+ return internalProductForProject(internalProject, product);
+}
+
+void ProjectPrivate::retrieveProjectData(ProjectData &projectData,
+ const ResolvedProjectConstPtr &internalProject)
{
- m_projectData.d->location = internalProject->location;
- m_projectData.d->buildDir = internalProject->buildDirectory;
+ projectData.d->name = internalProject->name;
+ projectData.d->location = internalProject->location;
+ projectData.d->enabled = internalProject->enabled;
foreach (const ResolvedProductConstPtr &resolvedProduct, internalProject->products) {
ProductData product;
product.d->name = resolvedProduct->name;
@@ -227,9 +250,15 @@ void ProjectPrivate::retrieveProjectData()
product.d->groups << group;
}
qSort(product.d->groups);
- m_projectData.d->products << product;
+ projectData.d->products << product;
+ }
+ foreach (const ResolvedProjectConstPtr &internalSubProject, internalProject->subProjects) {
+ ProjectData subProject;
+ retrieveProjectData(subProject, internalSubProject);
+ projectData.d->subProjects << subProject;
}
- qSort(m_projectData.d->products);
+ qSort(projectData.d->products);
+ qSort(projectData.d->subProjects);
m_projectDataRetrieved = true;
}
@@ -242,7 +271,7 @@ using namespace Internal;
* \brief The \c Project class provides services related to a qbs project.
*/
-Project::Project(const ResolvedProjectPtr &internalProject, const Logger &logger)
+Project::Project(const TopLevelProjectPtr &internalProject, const Logger &logger)
: d(new ProjectPrivate(internalProject, logger))
{
}
diff --git a/src/lib/api/project.h b/src/lib/api/project.h
index 099b82d9a..48c3fd71b 100644
--- a/src/lib/api/project.h
+++ b/src/lib/api/project.h
@@ -107,7 +107,7 @@ public:
private:
Project();
- Project(const Internal::ResolvedProjectPtr &internalProject, const Internal::Logger &logger);
+ Project(const Internal::TopLevelProjectPtr &internalProject, const Internal::Logger &logger);
QExplicitlySharedDataPointer<Internal::ProjectPrivate> d;
};
diff --git a/src/lib/api/projectdata.cpp b/src/lib/api/projectdata.cpp
index 7b46f1829..9d48f5f2f 100644
--- a/src/lib/api/projectdata.cpp
+++ b/src/lib/api/projectdata.cpp
@@ -130,6 +130,11 @@ QStringList GroupData::allFilePaths() const
return d->filePaths + d->expandedWildcards;
}
+bool operator!=(const GroupData &lhs, const GroupData &rhs)
+{
+ return !(lhs == rhs);
+}
+
bool operator==(const GroupData &lhs, const GroupData &rhs)
{
return lhs.name() == rhs.name()
@@ -140,9 +145,9 @@ bool operator==(const GroupData &lhs, const GroupData &rhs)
&& lhs.isEnabled() == rhs.isEnabled();
}
-bool operator!=(const GroupData &lhs, const GroupData &rhs)
+bool operator<(const GroupData &lhs, const GroupData &rhs)
{
- return !(lhs == rhs);
+ return lhs.name() < rhs.name();
}
/*!
@@ -237,7 +242,7 @@ bool operator!=(const ProductData &lhs, const ProductData &rhs)
return !(lhs == rhs);
}
-bool operator<(const GroupData &lhs, const GroupData &rhs)
+bool operator<(const ProductData &lhs, const ProductData &rhs)
{
return lhs.name() < rhs.name();
}
@@ -271,6 +276,14 @@ ProjectData::~ProjectData()
}
/*!
+ * \brief The name of this project.
+ */
+QString ProjectData::name() const
+{
+ return d->name;
+}
+
+/*!
* \brief The location at which the project is defined in a qbs source file.
*/
CodeLocation ProjectData::location() const
@@ -279,7 +292,17 @@ CodeLocation ProjectData::location() const
}
/*!
+ * \brief Whether the project is enabled.
+ * \note Disabled projects never have any products or sub-projects.
+ */
+bool ProjectData::isEnabled() const
+{
+ return d->enabled;
+}
+
+/*!
* \brief The base directory under which the build artifacts of this project will be created.
+ * This is only valid for the top-level project.
*/
QString ProjectData::buildDirectory() const
{
@@ -295,9 +318,29 @@ QList<ProductData> ProjectData::products() const
return d->products;
}
+/*!
+ * The sub-projects of this project.
+ */
+QList<ProjectData> ProjectData::subProjects() const
+{
+ return d->subProjects;
+}
+
+/*!
+ * All products in this projects and its direct and indirect sub-projects.
+ */
+QList<ProductData> ProjectData::allProducts() const
+{
+ QList<ProductData> productList = products();
+ foreach (const ProjectData &pd, subProjects())
+ productList << pd.allProducts();
+ return productList;
+}
+
bool operator==(const ProjectData &lhs, const ProjectData &rhs)
{
return lhs.location() == rhs.location()
+ && lhs.subProjects() == rhs.subProjects()
&& lhs.products() == rhs.products();
}
@@ -306,7 +349,7 @@ bool operator!=(const ProjectData &lhs, const ProjectData &rhs)
return !(lhs == rhs);
}
-bool operator<(const ProductData &lhs, const ProductData &rhs)
+bool operator<(const ProjectData &lhs, const ProjectData &rhs)
{
return lhs.name() < rhs.name();
}
diff --git a/src/lib/api/projectdata.h b/src/lib/api/projectdata.h
index 1097c5e24..d7ae66b8f 100644
--- a/src/lib/api/projectdata.h
+++ b/src/lib/api/projectdata.h
@@ -139,9 +139,13 @@ public:
ProjectData &operator=(const ProjectData &other);
~ProjectData();
+ QString name() const;
CodeLocation location() const;
+ bool isEnabled() const;
QString buildDirectory() const;
QList<ProductData> products() const;
+ QList<ProjectData> subProjects() const;
+ QList<ProductData> allProducts() const;
private:
QExplicitlySharedDataPointer<Internal::ProjectDataPrivate> d;
@@ -149,6 +153,7 @@ private:
QBS_EXPORT bool operator==(const ProjectData &lhs, const ProjectData &rhs);
QBS_EXPORT bool operator!=(const ProjectData &lhs, const ProjectData &rhs);
+QBS_EXPORT bool operator<(const ProjectData &lhs, const ProjectData &rhs);
} // namespace qbs
diff --git a/src/lib/api/projectdata_p.h b/src/lib/api/projectdata_p.h
index c544dd9d9..14ed79efd 100644
--- a/src/lib/api/projectdata_p.h
+++ b/src/lib/api/projectdata_p.h
@@ -61,8 +61,11 @@ public:
class ProjectDataPrivate : public QSharedData
{
public:
+ QString name;
CodeLocation location;
+ bool enabled;
QList<ProductData> products;
+ QList<ProjectData> subProjects;
QString buildDir;
};