summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app/qbs/commandlinefrontend.cpp30
-rw-r--r--src/app/qbs/parser/commandlineparser.cpp43
-rw-r--r--src/app/qbs/status.cpp8
-rw-r--r--src/lib/api/api.pri3
-rw-r--r--src/lib/api/internaljobs.cpp20
-rw-r--r--src/lib/api/project.cpp45
-rw-r--r--src/lib/api/projectdata.cpp344
-rw-r--r--src/lib/api/projectdata.h74
-rw-r--r--src/lib/api/projectdata_p.h72
-rw-r--r--src/lib/buildgraph/artifactcleaner.cpp12
-rw-r--r--src/lib/buildgraph/buildgraph.cpp28
-rw-r--r--src/lib/buildgraph/executor.cpp22
-rw-r--r--src/lib/buildgraph/jscommandexecutor.cpp6
-rw-r--r--src/lib/buildgraph/processcommandexecutor.cpp21
-rw-r--r--src/lib/buildgraph/productinstaller.cpp34
-rw-r--r--src/lib/buildgraph/projectbuilddata.cpp4
-rw-r--r--src/lib/buildgraph/rulesapplicator.cpp12
-rw-r--r--src/lib/buildgraph/transformer.cpp4
-rw-r--r--src/lib/language/language.cpp15
-rw-r--r--src/lib/language/loader.cpp13
-rw-r--r--src/lib/language/tst_language.cpp47
-rw-r--r--src/lib/lib.qbs3
-rw-r--r--src/lib/logging/ilogsink.cpp29
-rw-r--r--src/lib/logging/ilogsink.h12
-rw-r--r--src/lib/tools/buildoptions.cpp158
-rw-r--r--src/lib/tools/buildoptions.h26
-rw-r--r--src/lib/tools/cleanoptions.cpp120
-rw-r--r--src/lib/tools/cleanoptions.h22
-rw-r--r--src/lib/tools/codelocation.cpp86
-rw-r--r--src/lib/tools/codelocation.h17
-rw-r--r--src/lib/tools/error.cpp79
-rw-r--r--src/lib/tools/error.h29
-rw-r--r--src/lib/tools/installoptions.cpp147
-rw-r--r--src/lib/tools/installoptions.h27
-rw-r--r--src/lib/tools/processresult.cpp121
-rw-r--r--src/lib/tools/processresult.h31
-rw-r--r--src/lib/tools/processresult_p.h56
-rw-r--r--src/lib/tools/qbsassert.cpp2
-rw-r--r--src/lib/tools/setupprojectparameters.cpp173
-rw-r--r--src/lib/tools/setupprojectparameters.h40
-rw-r--r--src/lib/tools/tools.pri2
-rw-r--r--tests/auto/cmdlineparser/tst_cmdlineparser.cpp4
42 files changed, 1514 insertions, 527 deletions
diff --git a/src/app/qbs/commandlinefrontend.cpp b/src/app/qbs/commandlinefrontend.cpp
index 8ac89d0b2..d734b9120 100644
--- a/src/app/qbs/commandlinefrontend.cpp
+++ b/src/app/qbs/commandlinefrontend.cpp
@@ -99,15 +99,15 @@ void CommandLineFrontend::start()
const QString qbsRootPath = QDir::cleanPath(QCoreApplication::applicationDirPath()
+ QLatin1String("/../"));
SetupProjectParameters params;
- params.projectFilePath = m_parser.projectFilePath();
- params.buildRoot = QDir::currentPath();
- params.searchPaths = Preferences(m_settings).searchPaths(qbsRootPath);
- params.pluginPaths = Preferences(m_settings).pluginPaths(qbsRootPath);
- params.ignoreDifferentProjectFilePath = m_parser.force();
- params.dryRun = m_parser.dryRun();
- params.logElapsedTime = m_parser.logTime();
+ params.setProjectFilePath(m_parser.projectFilePath());
+ params.setBuildRoot(QDir::currentPath());
+ params.setSearchPaths(Preferences(m_settings).searchPaths(qbsRootPath));
+ params.setPluginPaths(Preferences(m_settings).pluginPaths(qbsRootPath));
+ params.setIgnoreDifferentProjectFilePath(m_parser.force());
+ params.setDryRun(m_parser.dryRun());
+ params.setLogElapsedTime(m_parser.logTime());
foreach (const QVariantMap &buildConfig, m_parser.buildConfigurations()) {
- params.buildConfiguration = buildConfig;
+ params.setBuildConfiguration(buildConfig);
SetupProjectJob * const job = Project::setupProject(params, m_settings,
ConsoleLogger::instance().logSink(), this);
connectJob(job);
@@ -236,15 +236,15 @@ void CommandLineFrontend::handleWarningReport(const qbs::Error &warning)
void CommandLineFrontend::handleProcessResultReport(const qbs::ProcessResult &result)
{
- bool hasOutput = !result.stdOut.isEmpty() || !result.stdErr.isEmpty();
- if (!hasOutput && result.success)
+ bool hasOutput = !result.stdOut().isEmpty() || !result.stdErr().isEmpty();
+ if (!hasOutput && result.success())
return;
- (result.success ? qbsInfo() : qbsError())
- << result.binary << " " << result.arguments.join(QLatin1String(" "))
+ (result.success() ? qbsInfo() : qbsError())
+ << result.executableFilePath() << " " << result.arguments().join(QLatin1String(" "))
<< (hasOutput ? QString::fromLatin1("\n") : QString())
- << (result.stdOut.isEmpty() ? QString() : result.stdOut.join(QLatin1String("\n")))
- << (result.stdErr.isEmpty() ? QString() : result.stdErr.join(QLatin1String("\n")));
+ << (result.stdOut().isEmpty() ? QString() : result.stdOut().join(QLatin1String("\n")))
+ << (result.stdErr().isEmpty() ? QString() : result.stdErr().join(QLatin1String("\n")));
}
bool CommandLineFrontend::resolvingMultipleProjects() const
@@ -395,7 +395,7 @@ int CommandLineFrontend::runTarget()
Q_ASSERT(products.count() == 1);
const ProductData productToRun = products.first();
const QString executableFilePath = project.targetExecutable(productToRun,
- m_parser.installOptions().installRoot);
+ m_parser.installOptions().installRoot());
if (executableFilePath.isEmpty()) {
throw Error(Tr::tr("Cannot run: Product '%1' is not an application.")
.arg(productToRun.name()));
diff --git a/src/app/qbs/parser/commandlineparser.cpp b/src/app/qbs/parser/commandlineparser.cpp
index 1b8a657c6..cea0c8587 100644
--- a/src/app/qbs/parser/commandlineparser.cpp
+++ b/src/app/qbs/parser/commandlineparser.cpp
@@ -138,11 +138,11 @@ CleanOptions CommandLineParser::cleanOptions() const
{
Q_ASSERT(command() == CleanCommandType);
CleanOptions options;
- options.cleanType = d->optionPool.allArtifactsOption()->enabled()
- ? CleanOptions::CleanupAll : CleanOptions::CleanupTemporaries;
- options.dryRun = buildOptions().dryRun;
- options.keepGoing = buildOptions().keepGoing;
- options.logElapsedTime = logTime();
+ options.setCleanType(d->optionPool.allArtifactsOption()->enabled()
+ ? CleanOptions::CleanupAll : CleanOptions::CleanupTemporaries);
+ options.setDryRun(buildOptions().dryRun());
+ options.setKeepGoing(buildOptions().keepGoing());
+ options.setLogElapsedTime(logTime());
return options;
}
@@ -150,16 +150,16 @@ InstallOptions CommandLineParser::installOptions() const
{
Q_ASSERT(command() == InstallCommandType || command() == RunCommandType);
InstallOptions options;
- options.removeFirst = d->optionPool.removeFirstoption()->enabled();
- options.installRoot = d->optionPool.installRootOption()->installRoot();
- if (!options.installRoot.isEmpty()) {
- QFileInfo fi(options.installRoot);
+ options.setRemoveExistingInstallation(d->optionPool.removeFirstoption()->enabled());
+ options.setInstallRoot(d->optionPool.installRootOption()->installRoot());
+ if (!options.installRoot().isEmpty()) {
+ QFileInfo fi(options.installRoot());
if (!fi.isAbsolute())
- options.installRoot = fi.absoluteFilePath();
+ options.setInstallRoot(fi.absoluteFilePath());
}
- options.dryRun = buildOptions().dryRun;
- options.keepGoing = buildOptions().keepGoing;
- options.logElapsedTime = logTime();
+ options.setDryRun(buildOptions().dryRun());
+ options.setKeepGoing(buildOptions().keepGoing());
+ options.setLogElapsedTime(logTime());
return options;
}
@@ -462,18 +462,19 @@ void CommandLineParser::CommandLineParserPrivate::setupProjectFile()
void CommandLineParser::CommandLineParserPrivate::setupBuildOptions()
{
- buildOptions.dryRun = dryRun();
- buildOptions.changedFiles = optionPool.changedFilesOption()->arguments();
+ buildOptions.setDryRun(dryRun());
+ QStringList changedFiles = optionPool.changedFilesOption()->arguments();
QDir currentDir;
- for (int i = 0; i < buildOptions.changedFiles.count(); ++i) {
- QString &file = buildOptions.changedFiles[i];
+ for (int i = 0; i < changedFiles.count(); ++i) {
+ QString &file = changedFiles[i];
file = QDir::fromNativeSeparators(currentDir.absoluteFilePath(file));
}
- buildOptions.keepGoing = optionPool.keepGoingOption()->enabled();
+ buildOptions.setChangedFiles(changedFiles);
+ buildOptions.setKeepGoing(optionPool.keepGoingOption()->enabled());
const JobsOption * jobsOption = optionPool.jobsOption();
- buildOptions.maxJobCount = jobsOption->jobCount() > 0
- ? jobsOption->jobCount() : Preferences(settings).jobs();
- buildOptions.logElapsedTime = logTime;
+ buildOptions.setMaxJobCount(jobsOption->jobCount() > 0
+ ? jobsOption->jobCount() : Preferences(settings).jobs());
+ buildOptions.setLogElapsedTime(logTime);
}
void CommandLineParser::CommandLineParserPrivate::setupProgress()
diff --git a/src/app/qbs/status.cpp b/src/app/qbs/status.cpp
index 2683d468a..c09190f5e 100644
--- a/src/app/qbs/status.cpp
+++ b/src/app/qbs/status.cpp
@@ -112,7 +112,7 @@ QStringList allFiles(const ProductData &product)
int printStatus(const ProjectData &project)
{
- const QString projectFilePath = project.location().fileName;
+ const QString projectFilePath = project.location().fileName();
QString projectDirectory = QFileInfo(projectFilePath).dir().path();
int projectDirectoryPathLength = projectDirectory.length();
@@ -120,10 +120,12 @@ int printStatus(const ProjectData &project)
QStringList missingFiles;
foreach (const ProductData &product, project.products()) {
qbsInfo() << "\nProduct: " << product.name()
- << " (" << product.location().fileName << ":" << product.location().line << ")";
+ << " (" << product.location().fileName() << ":"
+ << product.location().line() << ")";
foreach (const GroupData &group, product.groups()) {
qbsInfo() << " Group: " << group.name()
- << " (" << group.location().fileName << ":" << group.location().line << ")";
+ << " (" << group.location().fileName() << ":"
+ << group.location().line() << ")";
QStringList sourceFiles = group.allFilePaths();
qSort(sourceFiles);
foreach (const QString &sourceFile, sourceFiles) {
diff --git a/src/lib/api/api.pri b/src/lib/api/api.pri
index e82cf8382..61632356b 100644
--- a/src/lib/api/api.pri
+++ b/src/lib/api/api.pri
@@ -4,7 +4,8 @@ HEADERS += \
$$PWD/runenvironment.h \
$$PWD/jobs.h \
$$PWD/project.h \
- $$PWD/propertymap_p.h
+ $$PWD/propertymap_p.h \
+ $$PWD/projectdata_p.h
SOURCES += \
$$PWD/internaljobs.cpp \
diff --git a/src/lib/api/internaljobs.cpp b/src/lib/api/internaljobs.cpp
index 5a721ba34..d6de8ce81 100644
--- a/src/lib/api/internaljobs.cpp
+++ b/src/lib/api/internaljobs.cpp
@@ -143,7 +143,7 @@ InternalSetupProjectJob::~InternalSetupProjectJob()
void InternalSetupProjectJob::resolve(const SetupProjectParameters &parameters)
{
m_parameters = parameters;
- setTimed(parameters.logElapsedTime);
+ setTimed(parameters.logElapsedTime());
QTimer::singleShot(0, this, SLOT(start()));
}
@@ -197,19 +197,19 @@ void InternalSetupProjectJob::execute()
m_project = loadResult.newlyResolvedProject;
} else {
Loader loader(evalContext->engine(), logger());
- loader.setSearchPaths(m_parameters.searchPaths);
+ loader.setSearchPaths(m_parameters.searchPaths());
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));
+ .arg(m_parameters.projectFilePath()));
}
}
// copy the environment from the platform config into the project's config
const QVariantMap platformEnvironment
- = m_parameters.buildConfiguration.value(QLatin1String("environment")).toMap();
+ = m_parameters.buildConfiguration().value(QLatin1String("environment")).toMap();
m_project->platformEnvironment = platformEnvironment;
logger().qbsDebug() << QString::fromLocal8Bit("for %1:").arg(m_project->id());
@@ -227,7 +227,7 @@ void InternalSetupProjectJob::execute()
BuildDataResolver::rescueBuildData(loadResult.loadedProject, m_project, logger());
}
- if (!m_parameters.dryRun)
+ if (!m_parameters.dryRun())
storeBuildGraph(m_project);
// The evalutation context cannot be re-used for building, which runs in a different thread.
@@ -267,8 +267,8 @@ void InternalBuildJob::build(const ResolvedProjectPtr &project,
const QList<ResolvedProductPtr> &products, const BuildOptions &buildOptions,
const QProcessEnvironment &env)
{
- setup(project, products, buildOptions.dryRun);
- setTimed(buildOptions.logElapsedTime);
+ setup(project, products, buildOptions.dryRun());
+ setTimed(buildOptions.logElapsedTime());
m_executor = new Executor(logger());
m_executor->setProject(project);
@@ -314,8 +314,8 @@ InternalCleanJob::InternalCleanJob(const Logger &logger, QObject *parent)
void InternalCleanJob::clean(const ResolvedProjectPtr &project,
const QList<ResolvedProductPtr> &products, const CleanOptions &options)
{
- setup(project, products, options.dryRun);
- setTimed(options.logElapsedTime);
+ setup(project, products, options.dryRun());
+ setTimed(options.logElapsedTime());
m_options = options;
QTimer::singleShot(0, this, SLOT(start()));
}
@@ -358,7 +358,7 @@ void InternalInstallJob::install(const QList<ResolvedProductPtr> &products,
{
m_products = products;
m_options = options;
- setTimed(options.logElapsedTime);
+ setTimed(options.logElapsedTime());
QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
}
diff --git a/src/lib/api/project.cpp b/src/lib/api/project.cpp
index dc5eebe25..b9820242f 100644
--- a/src/lib/api/project.cpp
+++ b/src/lib/api/project.cpp
@@ -31,6 +31,7 @@
#include "internaljobs.h"
#include "jobs.h"
#include "projectdata.h"
+#include "projectdata_p.h"
#include "propertymap_p.h"
#include "runenvironment.h"
#include <buildgraph/artifact.h>
@@ -200,35 +201,35 @@ ResolvedProductPtr ProjectPrivate::internalProduct(const ProductData &product) c
void ProjectPrivate::retrieveProjectData()
{
- m_projectData.m_location = internalProject->location;
- m_projectData.m_buildDir = internalProject->buildDirectory;
+ m_projectData.d->location = internalProject->location;
+ m_projectData.d->buildDir = internalProject->buildDirectory;
foreach (const ResolvedProductConstPtr &resolvedProduct, internalProject->products) {
ProductData product;
- product.m_name = resolvedProduct->name;
- product.m_location = resolvedProduct->location;
- product.m_fileTags = resolvedProduct->fileTags.toStringList();
- product.m_properties.d->m_map = resolvedProduct->properties;
- product.m_isEnabled = resolvedProduct->enabled;
+ product.d->name = resolvedProduct->name;
+ product.d->location = resolvedProduct->location;
+ product.d->fileTags = resolvedProduct->fileTags.toStringList();
+ product.d->properties.d->m_map = resolvedProduct->properties;
+ product.d->isEnabled = resolvedProduct->enabled;
foreach (const GroupPtr &resolvedGroup, resolvedProduct->groups) {
GroupData group;
- group.m_name = resolvedGroup->name;
- group.m_location = resolvedGroup->location;
+ group.d->name = resolvedGroup->name;
+ group.d->location = resolvedGroup->location;
foreach (const SourceArtifactConstPtr &sa, resolvedGroup->files)
- group.m_filePaths << sa->absoluteFilePath;
+ group.d->filePaths << sa->absoluteFilePath;
if (resolvedGroup->wildcards) {
foreach (const SourceArtifactConstPtr &sa, resolvedGroup->wildcards->files)
- group.m_expandedWildcards << sa->absoluteFilePath;
+ group.d->expandedWildcards << sa->absoluteFilePath;
}
- qSort(group.m_filePaths);
- qSort(group.m_expandedWildcards);
- group.m_properties.d->m_map = resolvedGroup->properties;
- group.m_isEnabled = resolvedGroup->enabled;
- product.m_groups << group;
+ qSort(group.d->filePaths);
+ qSort(group.d->expandedWildcards);
+ group.d->properties.d->m_map = resolvedGroup->properties;
+ group.d->isEnabled = resolvedGroup->enabled;
+ product.d->groups << group;
}
- qSort(product.m_groups);
- m_projectData.m_products << product;
+ qSort(product.d->groups);
+ m_projectData.d->products << product;
}
- qSort(m_projectData.m_products);
+ qSort(m_projectData.d->products);
m_projectDataRetrieved = true;
}
@@ -325,10 +326,10 @@ SetupProjectJob *Project::setupProject(const SetupProjectParameters &_parameters
Logger logger(logSink);
SetupProjectJob * const job = new SetupProjectJob(logger, jobOwner);
try {
- loadPlugins(_parameters.pluginPaths, logger);
+ loadPlugins(_parameters.pluginPaths(), logger);
SetupProjectParameters parameters = _parameters;
- parameters.buildConfiguration
- = expandBuildConfiguration(parameters.buildConfiguration, settings);
+ parameters.setBuildConfiguration(expandBuildConfiguration(
+ parameters.buildConfiguration(), settings));
job->resolve(parameters);
} catch (const Error &error) {
// Throwing from here would complicate the API, so let's report the error the same way
diff --git a/src/lib/api/projectdata.cpp b/src/lib/api/projectdata.cpp
index f228f997b..7b46f1829 100644
--- a/src/lib/api/projectdata.cpp
+++ b/src/lib/api/projectdata.cpp
@@ -28,6 +28,7 @@
****************************************************************************/
#include "projectdata.h"
+#include "projectdata_p.h"
#include "propertymap_p.h"
#include <language/propertymapinternal.h>
#include <tools/propertyfinder.h>
@@ -36,7 +37,98 @@
namespace qbs {
-GroupData::GroupData() { }
+/*!
+ * \class GroupData
+ * \brief The \c GroupData class corresponds to the Group item in a qbs source file.
+ */
+
+GroupData::GroupData() : d(new Internal::GroupDataPrivate)
+{
+}
+
+GroupData::GroupData(const GroupData &other) : d(other.d)
+{
+}
+
+GroupData &GroupData::operator=(const GroupData &other)
+{
+ d = other.d;
+ return *this;
+}
+
+GroupData::~GroupData()
+{
+}
+
+/*!
+ * \brief The location at which the group is defined in the respective source file.
+ */
+CodeLocation GroupData::location() const
+{
+ return d->location;
+}
+
+/*!
+ * \brief The name of the group.
+ */
+QString GroupData::name() const
+{
+ return d->name;
+}
+
+/*!
+ * \brief The files listed in the group item's "files" binding.
+ * \note These do not include expanded wildcards.
+ * \sa GroupData::expandedWildcards
+ */
+QStringList GroupData::filePaths() const
+{
+ return d->filePaths;
+}
+
+/*!
+ * \brief The list of files resulting from expanding all wildcard patterns in the group.
+ */
+QStringList GroupData::expandedWildcards() const
+{
+ return d->expandedWildcards;
+}
+
+/*!
+ * \brief The set of properties valid in this group.
+ * Typically, most of them are inherited from the respective \c Product.
+ */
+PropertyMap GroupData::properties() const
+{
+ return d->properties;
+}
+
+/*!
+ * \brief Returns true if this group is enabled in Qbs
+ * This method returns the "condition" property of the \c Group definition. If the group is enabled
+ * then the files in this group will be processed, provided the product it belongs to is also
+ * enabled.
+ *
+ * Note that a group can be enabled, even if the product it belongs to is not. In this case
+ * the files in the group will not be processed.
+ * \sa ProductData::isEnabled()
+ */
+bool GroupData::isEnabled() const
+{
+ return d->isEnabled;
+}
+
+/*!
+ * \fn QStringList GroupData::allFilePaths() const
+ * \brief All files in this group, regardless of how whether they were given explicitly
+ * or via wildcards.
+ * \sa GroupData::filePaths
+ * \sa GroupData::expandedWildcards
+ */
+QStringList GroupData::allFilePaths() const
+{
+ return d->filePaths + d->expandedWildcards;
+}
bool operator==(const GroupData &lhs, const GroupData &rhs)
{
@@ -53,7 +145,82 @@ bool operator!=(const GroupData &lhs, const GroupData &rhs)
return !(lhs == rhs);
}
-ProductData::ProductData() { }
+/*!
+ * \class ProductData
+ * \brief The \c ProductData class corresponds to the Product item in a qbs source file.
+ */
+
+ProductData::ProductData() : d(new Internal::ProductDataPrivate)
+{
+}
+
+ProductData::ProductData(const ProductData &other) : d(other.d)
+{
+}
+
+ProductData &ProductData::operator=(const ProductData &other)
+{
+ d = other.d;
+ return *this;
+}
+
+ProductData::~ProductData()
+{
+}
+
+/*!
+ * \brief The name of the product as given in the qbs source file.
+ */
+QString ProductData::name() const
+{
+ return d->name;
+}
+
+/*!
+ * \brief The location at which the product is defined in the source file.
+ */
+CodeLocation ProductData::location() const
+{
+ return d->location;
+}
+
+/*!
+ * \brief The file tags of this product. Corresponds to a Product's "type" property in
+ * a qbs source file.
+ */
+QStringList ProductData::fileTags() const
+{
+ return d->fileTags;
+}
+
+/*!
+ * \brief The set of properties valid in this product.
+ * \note product properties can be overwritten in a group.
+ * \sa GroupData::properties()
+ */
+PropertyMap ProductData::properties() const
+{
+ return d->properties;
+}
+
+/*!
+ * \brief The list of \c GroupData in this product.
+ */
+QList<GroupData> ProductData::groups() const
+{
+ return d->groups;
+}
+
+/*!
+ * \brief Returns true if this Product is enabled in Qbs.
+ * This method returns the \c condition property of the \c Product definition. If a product is
+ * enabled, then it will be built in the current configuration.
+ * \sa GroupData::isEnabled()
+ */
+bool ProductData::isEnabled() const
+{
+ return d->isEnabled;
+}
bool operator==(const ProductData &lhs, const ProductData &rhs)
{
@@ -75,7 +242,58 @@ bool operator<(const GroupData &lhs, const GroupData &rhs)
return lhs.name() < rhs.name();
}
-ProjectData::ProjectData() { }
+/*!
+ * \class ProjectData
+ * \brief The \c ProjectData class corresponds to the \c Project item in a qbs source file.
+ */
+
+/*!
+ * \fn QList<ProductData> ProjectData::products() const
+ * \brief The products in this project.
+ */
+
+ProjectData::ProjectData() : d(new Internal::ProjectDataPrivate)
+{
+}
+
+ProjectData::ProjectData(const ProjectData &other) : d(other.d)
+{
+}
+
+ProjectData &ProjectData::operator =(const ProjectData &other)
+{
+ d = other.d;
+ return *this;
+}
+
+ProjectData::~ProjectData()
+{
+}
+
+/*!
+ * \brief The location at which the project is defined in a qbs source file.
+ */
+CodeLocation ProjectData::location() const
+{
+ return d->location;
+}
+
+/*!
+ * \brief The base directory under which the build artifacts of this project will be created.
+ */
+QString ProjectData::buildDirectory() const
+{
+ return d->buildDir;
+}
+
+/*!
+ * The products in this project.
+ * \note This also includes disabled products.
+ */
+QList<ProductData> ProjectData::products() const
+{
+ return d->products;
+}
bool operator==(const ProjectData &lhs, const ProjectData &rhs)
{
@@ -215,124 +433,4 @@ bool operator!=(const PropertyMap &pm1, const PropertyMap &pm2)
return !(pm1.d->m_map->value() == pm2.d->m_map->value());
}
-/*!
- * \class GroupData
- * \brief The \c GroupData class corresponds to the Group item in a qbs source file.
- */
-
- /*!
- * \fn QString GroupData::name() const
- * \brief The name of the group.
- */
-
-/*!
- * \fn int GroupData::qbsLine() const
- * \brief The line at which the group is defined in the respective source file.
- */
-
- /*!
- * \fn QStringList GroupData::filePaths() const
- * \brief The files listed in the group item's "files" binding.
- * Note that these do not include expanded wildcards.
- * \sa GroupData::expandedWildcards
- */
-
-/*!
- * \fn QStringList GroupData::expandedWildcards() const
- * \brief The list of files resulting from expanding all wildcard patterns in the group.
- */
-
-/*!
- * \fn QVariantMap GroupData::properties() const
- * \brief The set of properties valid in this group.
- * Typically, most of them are inherited from the respective Product.
- */
-
- /*!
- * \fn QStringList GroupData::allFilePaths() const
- * \brief All files in this group, regardless of how whether they were given explicitly
- * or via wildcards.
- * \sa GroupData::filePaths
- * \sa GroupData::expandedWildcards
- */
-
-/*!
- * \fn bool GroupData::isEnabled() const
- * \brief Returns true if this Group is enabled in Qbs
- * This method returns the "condition" property of the Group definition. If the group is enabled
- * then the files in this Group will be processed, provided the Product it belongs to is also
- * enabled.
- *
- * Note that a Group can be enabled, even if the Product it belongs to is not. In this case
- * the files in the Group will not be processed.
- * \sa ProductData::isEnabled()
- */
-
-/*!
- * \class ProductData
- * \brief The \c ProductData class corresponds to the Product item in a qbs source file.
- */
-
-/*!
- * \fn QString ProductData::name() const
- * \brief The name of the product as given in the qbs source file.
- */
-
-/*!
- * \fn QString ProductData::qbsFilePath() const
- * \brief The qbs source file in which the product is defined.
- */
-
-/*!
- * \fn int ProductData::qbsLine() const
- * \brief The line in at which the product is defined in the source file.
- */
-
-/*!
- * \fn QString ProductData::fileTags() const
- * \brief The file tags of this product. Corresponds to a Product's "type" property in
- * a qbs source file.
- */
-
-/*!
- * \fn QVariantMap ProductData::properties() const
- * \brief The set of properties valid in this product.
- * Note that product properties can be overwritten in a Group.
- * \sa GroupData::properties()
- */
-
-/*!
- * \fn QList<GroupData> groups() const
- * \brief The list of \c GroupData in this product.
- */
-
-
-/*!
- * \class ProjectData
- * \brief The \c ProjectData class corresponds to the Project item in a qbs source file.
- */
-
-/*!
- * \fn CodeLocation ProjectData::location() const
- * \brief The qbs source file in which the project is defined.
- */
-
-/*!
- * \fn QString ProjectData::buildDirectory() const
- * \brief The base directory under which the build artifacts of this project will be created.
- */
-
-/*!
- * \fn QList<ProductData> ProjectData::products() const
- * \brief The products in this project.
- */
-
-/*!
- * \fn bool ProductData::isEnabled() const
- * \brief Returns true if this Product is enabled in Qbs.
- * This method returns the "condition" property of the Product definition. If a product is
- * enabled, then it will be built in the current configuration.
- * \sa GroupData::isEnabled()
- */
-
} // namespace qbs
diff --git a/src/lib/api/projectdata.h b/src/lib/api/projectdata.h
index e16678a21..1097c5e24 100644
--- a/src/lib/api/projectdata.h
+++ b/src/lib/api/projectdata.h
@@ -32,6 +32,7 @@
#include "../tools/codelocation.h"
#include "../tools/qbs_export.h"
+#include <QExplicitlySharedDataPointer>
#include <QList>
#include <QPair>
#include <QString>
@@ -39,11 +40,13 @@
#include <QVariantMap>
namespace qbs {
-namespace Internal
-{
+namespace Internal {
+class GroupDataPrivate;
+class ProductDataPrivate;
class ProjectPrivate;
+class ProjectDataPrivate;
class PropertyMapPrivate;
-}
+} // namespace Internal
class PropertyMap;
@@ -78,31 +81,25 @@ private:
Internal::PropertyMapPrivate *d;
};
-// TODO: explicitly shared?
-
class QBS_EXPORT GroupData
{
friend class Internal::ProjectPrivate;
public:
GroupData();
-
- CodeLocation location() const { return m_location; }
- QString name() const { return m_name; }
- QStringList filePaths() const { return m_filePaths; }
- QStringList expandedWildcards() const { return m_expandedWildcards; }
- PropertyMap properties() const { return m_properties; }
- bool isEnabled() const { return m_isEnabled; }
-
- // TODO: Filter out double entries here or somewhere else?
- QStringList allFilePaths() const { return filePaths() + expandedWildcards(); }
+ GroupData(const GroupData &other);
+ GroupData &operator=(const GroupData &other);
+ ~GroupData();
+
+ CodeLocation location() const;
+ QString name() const;
+ QStringList filePaths() const;
+ QStringList expandedWildcards() const;
+ PropertyMap properties() const;
+ bool isEnabled() const;
+ QStringList allFilePaths() const;
private:
- QString m_name;
- CodeLocation m_location;
- QStringList m_filePaths;
- QStringList m_expandedWildcards;
- PropertyMap m_properties;
- bool m_isEnabled;
+ QExplicitlySharedDataPointer<Internal::GroupDataPrivate> d;
};
QBS_EXPORT bool operator==(const GroupData &lhs, const GroupData &rhs);
@@ -114,21 +111,19 @@ class QBS_EXPORT ProductData
friend class Internal::ProjectPrivate;
public:
ProductData();
+ ProductData(const ProductData &other);
+ ProductData &operator=(const ProductData &other);
+ ~ProductData();
- QString name() const { return m_name; }
- CodeLocation location() const { return m_location; }
- QStringList fileTags() const { return m_fileTags; }
- PropertyMap properties() const { return m_properties; }
- QList<GroupData> groups() const { return m_groups; }
- bool isEnabled() const { return m_isEnabled; }
+ QString name() const;
+ CodeLocation location() const;
+ QStringList fileTags() const;
+ PropertyMap properties() const;
+ QList<GroupData> groups() const;
+ bool isEnabled() const;
private:
- QString m_name;
- CodeLocation m_location;
- QStringList m_fileTags;
- PropertyMap m_properties;
- QList<GroupData> m_groups;
- bool m_isEnabled;
+ QExplicitlySharedDataPointer<Internal::ProductDataPrivate> d;
};
QBS_EXPORT bool operator==(const ProductData &lhs, const ProductData &rhs);
@@ -140,15 +135,16 @@ class QBS_EXPORT ProjectData
friend class Internal::ProjectPrivate;
public:
ProjectData();
+ ProjectData(const ProjectData &other);
+ ProjectData &operator=(const ProjectData &other);
+ ~ProjectData();
- CodeLocation location() const { return m_location; }
- QString buildDirectory() const { return m_buildDir; }
- QList<ProductData> products() const { return m_products; }
+ CodeLocation location() const;
+ QString buildDirectory() const;
+ QList<ProductData> products() const;
private:
- CodeLocation m_location;
- QList<ProductData> m_products;
- QString m_buildDir;
+ QExplicitlySharedDataPointer<Internal::ProjectDataPrivate> d;
};
QBS_EXPORT bool operator==(const ProjectData &lhs, const ProjectData &rhs);
diff --git a/src/lib/api/projectdata_p.h b/src/lib/api/projectdata_p.h
new file mode 100644
index 000000000..c544dd9d9
--- /dev/null
+++ b/src/lib/api/projectdata_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef QBS_PROJECTDATA_P_H
+#define QBS_PROJECTDATA_P_H
+
+#include "projectdata.h"
+
+#include <QSharedData>
+
+namespace qbs {
+namespace Internal {
+
+class GroupDataPrivate : public QSharedData
+{
+public:
+ QString name;
+ CodeLocation location;
+ QStringList filePaths;
+ QStringList expandedWildcards;
+ PropertyMap properties;
+ bool isEnabled;
+};
+
+class ProductDataPrivate : public QSharedData
+{
+public:
+ QString name;
+ CodeLocation location;
+ QStringList fileTags;
+ PropertyMap properties;
+ QList<GroupData> groups;
+ bool isEnabled;
+};
+
+class ProjectDataPrivate : public QSharedData
+{
+public:
+ CodeLocation location;
+ QList<ProductData> products;
+ QString buildDir;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // Include guard.
diff --git a/src/lib/buildgraph/artifactcleaner.cpp b/src/lib/buildgraph/artifactcleaner.cpp
index 538685b69..33cef580a 100644
--- a/src/lib/buildgraph/artifactcleaner.cpp
+++ b/src/lib/buildgraph/artifactcleaner.cpp
@@ -107,12 +107,14 @@ private:
{
if (artifact->product != m_product)
return;
- if (artifact->parents.isEmpty() && m_options.cleanType == CleanOptions::CleanupTemporaries)
+ if (artifact->parents.isEmpty()
+ && m_options.cleanType() == CleanOptions::CleanupTemporaries) {
return;
+ }
try {
- removeArtifactFromDisk(artifact, m_options.dryRun, m_logger);
+ removeArtifactFromDisk(artifact, m_options.dryRun(), m_logger);
} catch (const Error &error) {
- if (!m_options.keepGoing)
+ if (!m_options.keepGoing())
throw;
m_logger.qbsWarning() << error.toString();
m_hasError = true;
@@ -176,10 +178,10 @@ void ArtifactCleaner::removeEmptyDirectories(const QString &rootDir, const Clean
subTreeIsEmpty = false;
}
if (subTreeIsEmpty) {
- printRemovalMessage(rootDir, options.dryRun, m_logger);
+ printRemovalMessage(rootDir, options.dryRun(), m_logger);
if (!QDir::root().rmdir(rootDir)) {
Error error(Tr::tr("Failure to remove empty directory '%1'.").arg(rootDir));
- if (!options.keepGoing)
+ if (!options.keepGoing())
throw error;
m_logger.qbsWarning() << error.toString();
m_hasError = true;
diff --git a/src/lib/buildgraph/buildgraph.cpp b/src/lib/buildgraph/buildgraph.cpp
index a9ddbf7d8..6e311bad3 100644
--- a/src/lib/buildgraph/buildgraph.cpp
+++ b/src/lib/buildgraph/buildgraph.cpp
@@ -191,8 +191,9 @@ void setupScriptEngineForProduct(ScriptEngine *engine, const ResolvedProductCons
QVariant(reinterpret_cast<qulonglong>(product->project.data())));
QScriptValue projectScriptValue;
projectScriptValue = engine->newObject();
- projectScriptValue.setProperty("filePath", product->project->location.fileName);
- projectScriptValue.setProperty("path", FileInfo::path(product->project->location.fileName));
+ projectScriptValue.setProperty("filePath", product->project->location.fileName());
+ projectScriptValue.setProperty("path",
+ FileInfo::path(product->project->location.fileName()));
const QVariantMap &projectProperties = product->project->projectProperties();
for (QVariantMap::const_iterator it = projectProperties.begin();
it != projectProperties.end(); ++it)
@@ -463,8 +464,9 @@ BuildGraphLoader::LoadResult BuildGraphLoader::load(const SetupProjectParameters
m_result = LoadResult();
m_evalContext = evalContext;
- const QString projectId = ResolvedProject::deriveId(parameters.buildConfiguration);
- const QString buildDir = ResolvedProject::deriveBuildDirectory(parameters.buildRoot, projectId);
+ const QString projectId = ResolvedProject::deriveId(parameters.buildConfiguration());
+ const QString buildDir
+ = ResolvedProject::deriveBuildDirectory(parameters.buildRoot(), projectId);
const QString buildGraphFilePath
= ProjectBuildData::deriveBuildGraphFilePath(buildDir, projectId);
@@ -472,7 +474,7 @@ BuildGraphLoader::LoadResult BuildGraphLoader::load(const SetupProjectParameters
m_logger.qbsDebug() << "[BG] trying to load: " << buildGraphFilePath;
if (!pool.load(buildGraphFilePath))
return m_result;
- if (!isConfigCompatible(parameters.buildConfiguration, pool.headData().projectConfig)) {
+ if (!isConfigCompatible(parameters.buildConfiguration(), pool.headData().projectConfig)) {
m_logger.qbsDebug() << "[BG] Cannot use stored build graph: "
"Incompatible project configuration.";
return m_result;
@@ -496,12 +498,12 @@ BuildGraphLoader::LoadResult BuildGraphLoader::load(const SetupProjectParameters
}
}
- if (QFileInfo(project->location.fileName) != QFileInfo(parameters.projectFilePath)) {
+ if (QFileInfo(project->location.fileName()) != QFileInfo(parameters.projectFilePath())) {
QString errorMessage = Tr::tr("Stored build graph is for project file '%1', but "
"input file is '%2'. ")
- .arg(QDir::toNativeSeparators(project->location.fileName),
- QDir::toNativeSeparators(parameters.projectFilePath));
- if (!parameters.ignoreDifferentProjectFilePath) {
+ .arg(QDir::toNativeSeparators(project->location.fileName()),
+ QDir::toNativeSeparators(parameters.projectFilePath()));
+ if (!parameters.ignoreDifferentProjectFilePath()) {
errorMessage += Tr::tr("Aborting.");
throw Error(errorMessage);
}
@@ -512,7 +514,7 @@ BuildGraphLoader::LoadResult BuildGraphLoader::load(const SetupProjectParameters
}
foreach (const ResolvedProductPtr &p, project->products)
p->project = project;
- project->location = CodeLocation(parameters.projectFilePath, 1, 1);
+ project->location = CodeLocation(parameters.projectFilePath(), 1, 1);
project->setBuildConfiguration(pool.headData().projectConfig);
project->buildDirectory = buildDir;
m_result.loadedProject = project;
@@ -526,7 +528,7 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters &paramet
{
const FileInfo bgfi(buildGraphFilePath);
const bool projectFileChanged
- = bgfi.lastModified() < FileInfo(parameters.projectFilePath).lastModified();
+ = bgfi.lastModified() < FileInfo(parameters.projectFilePath()).lastModified();
if (projectFileChanged)
m_logger.qbsTrace() << "Project file changed, must re-resolve project.";
@@ -541,7 +543,7 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters &paramet
bool referencedProductRemoved = false;
QList<ResolvedProductPtr> changedProducts;
foreach (const ResolvedProductPtr &product, restoredProject->products) {
- const FileInfo pfi(product->location.fileName);
+ const FileInfo pfi(product->location.fileName());
if (!pfi.exists()) {
referencedProductRemoved = true;
} else if (bgfi.lastModified() < pfi.lastModified()) {
@@ -569,7 +571,7 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters &paramet
}
Loader ldr(m_evalContext->engine(), m_logger);
- ldr.setSearchPaths(parameters.searchPaths);
+ ldr.setSearchPaths(parameters.searchPaths());
m_result.newlyResolvedProject = ldr.loadProject(parameters);
QMap<QString, ResolvedProductPtr> freshProductsByName;
diff --git a/src/lib/buildgraph/executor.cpp b/src/lib/buildgraph/executor.cpp
index b2990ce14..b34d52275 100644
--- a/src/lib/buildgraph/executor.cpp
+++ b/src/lib/buildgraph/executor.cpp
@@ -168,10 +168,10 @@ void Executor::setProducts(const QList<ResolvedProductPtr> &productsToBuild)
void Executor::doBuild()
{
- if (m_buildOptions.maxJobCount <= 0) {
- m_buildOptions.maxJobCount = BuildOptions::defaultMaxJobCount();
+ if (m_buildOptions.maxJobCount() <= 0) {
+ m_buildOptions.setMaxJobCount(BuildOptions::defaultMaxJobCount());
m_logger.qbsDebug() << "max job count not explicitly set, using value of "
- << m_buildOptions.maxJobCount;
+ << m_buildOptions.maxJobCount();
}
QBS_CHECK(m_state == ExecutorIdle);
m_leaves.clear();
@@ -194,17 +194,17 @@ void Executor::doBuild()
}
m_logger.qbsDebug() << QString::fromLocal8Bit("[EXEC] preparing executor for %1 jobs "
- "in parallel").arg(m_buildOptions.maxJobCount);
- addExecutorJobs(m_buildOptions.maxJobCount);
+ "in parallel").arg(m_buildOptions.maxJobCount());
+ addExecutorJobs(m_buildOptions.maxJobCount());
foreach (ExecutorJob * const job, m_availableJobs)
- job->setDryRun(m_buildOptions.dryRun);
+ job->setDryRun(m_buildOptions.dryRun());
initializeArtifactsState();
- Artifact::BuildState initialBuildState = m_buildOptions.changedFiles.isEmpty()
+ Artifact::BuildState initialBuildState = m_buildOptions.changedFiles().isEmpty()
? Artifact::Buildable : Artifact::Built;
QList<Artifact *> changedArtifacts;
- foreach (const QString &filePath, m_buildOptions.changedFiles) {
+ foreach (const QString &filePath, m_buildOptions.changedFiles()) {
QList<Artifact *> artifacts;
artifacts.append(m_project->buildData->lookupArtifacts(filePath));
if (artifacts.isEmpty()) {
@@ -420,7 +420,7 @@ void Executor::buildArtifact(Artifact *artifact)
}
// create the output directories
- if (!m_buildOptions.dryRun) {
+ if (!m_buildOptions.dryRun()) {
ArtifactList::const_iterator it = artifact->transformer->outputs.begin();
for (; it != artifact->transformer->outputs.end(); ++it) {
Artifact *output = *it;
@@ -486,7 +486,7 @@ void Executor::finishJob(ExecutorJob *job, bool success)
m_processingJobs.erase(it);
m_availableJobs.append(job);
- if (!success && !m_buildOptions.keepGoing)
+ if (!success && !m_buildOptions.keepGoing())
cancelJobs();
if (m_state == ExecutorRunning && m_progressObserver && m_progressObserver->canceled()) {
@@ -683,7 +683,7 @@ void Executor::runAutoMoc()
void Executor::onProcessError(const qbs::Error &err)
{
try {
- if (m_buildOptions.keepGoing) {
+ if (m_buildOptions.keepGoing()) {
Error fullWarning(err);
fullWarning.prepend(Tr::tr("Ignoring the following errors on user request:"));
emit reportWarning(fullWarning);
diff --git a/src/lib/buildgraph/jscommandexecutor.cpp b/src/lib/buildgraph/jscommandexecutor.cpp
index 8d07424db..9a2cbfa4a 100644
--- a/src/lib/buildgraph/jscommandexecutor.cpp
+++ b/src/lib/buildgraph/jscommandexecutor.cpp
@@ -105,8 +105,10 @@ public:
if (scriptEngine->hasUncaughtException()) {
result.success = false;
result.errorMessage = scriptEngine->uncaughtException().toString();
- result.errorLocation = m_jsCommand->codeLocation();
- result.errorLocation.line += scriptEngine->uncaughtExceptionLineNumber();
+ const CodeLocation &origLocation = m_jsCommand->codeLocation();
+ result.errorLocation = CodeLocation(origLocation.fileName(),
+ origLocation.line() + scriptEngine->uncaughtExceptionLineNumber(),
+ origLocation.column());
}
scriptEngine->popContext();
scriptEngine->clearExceptions();
diff --git a/src/lib/buildgraph/processcommandexecutor.cpp b/src/lib/buildgraph/processcommandexecutor.cpp
index 533feda26..a7f01270b 100644
--- a/src/lib/buildgraph/processcommandexecutor.cpp
+++ b/src/lib/buildgraph/processcommandexecutor.cpp
@@ -40,6 +40,7 @@
#include <tools/fileinfo.h>
#include <tools/hostosinfo.h>
#include <tools/processresult.h>
+#include <tools/processresult_p.h>
#include <tools/qbsassert.h>
#include <QDir>
@@ -192,28 +193,28 @@ QString ProcessCommandExecutor::filterProcessOutput(const QByteArray &_output,
void ProcessCommandExecutor::sendProcessOutput(bool success)
{
ProcessResult result;
- result.binary = m_program;
- result.arguments = m_arguments;
- result.workingDirectory = m_process.workingDirectory();
- if (result.workingDirectory.isEmpty())
- result.workingDirectory = QDir::currentPath();
- result.exitCode = m_process.exitCode();
- result.exitStatus = m_process.exitStatus();
- result.success = success;
+ result.d->executableFilePath = m_program;
+ result.d->arguments = m_arguments;
+ result.d->workingDirectory = m_process.workingDirectory();
+ if (result.workingDirectory().isEmpty())
+ result.d->workingDirectory = QDir::currentPath();
+ result.d->exitCode = m_process.exitCode();
+ result.d->exitStatus = m_process.exitStatus();
+ result.d->success = success;
QString tmp = filterProcessOutput(m_process.readAllStandardOutput(),
processCommand()->stdoutFilterFunction());
if (!tmp.isEmpty()) {
if (tmp.endsWith(QLatin1Char('\n')))
tmp.chop(1);
- result.stdOut = tmp.split(QLatin1Char('\n'));
+ result.d->stdOut = tmp.split(QLatin1Char('\n'));
}
tmp = filterProcessOutput(m_process.readAllStandardError(),
processCommand()->stderrFilterFunction());
if (!tmp.isEmpty()) {
if (tmp.endsWith(QLatin1Char('\n')))
tmp.chop(1);
- result.stdErr = tmp.split(QLatin1Char('\n'));
+ result.d->stdErr = tmp.split(QLatin1Char('\n'));
}
emit reportProcessResult(result);
diff --git a/src/lib/buildgraph/productinstaller.cpp b/src/lib/buildgraph/productinstaller.cpp
index 81d40f4c9..70031716b 100644
--- a/src/lib/buildgraph/productinstaller.cpp
+++ b/src/lib/buildgraph/productinstaller.cpp
@@ -48,10 +48,10 @@ ProductInstaller::ProductInstaller(const QList<ResolvedProductPtr> &products,
const InstallOptions &options, ProgressObserver *observer, const Logger &logger)
: m_products(products), m_options(options), m_observer(observer), m_logger(logger)
{
- if (!m_options.installRoot.isEmpty()) {
- QFileInfo installRootFileInfo(m_options.installRoot);
+ if (!m_options.installRoot().isEmpty()) {
+ QFileInfo installRootFileInfo(m_options.installRoot());
QBS_ASSERT(installRootFileInfo.isAbsolute(), /* just complain */);
- if (m_options.removeFirst) {
+ if (m_options.removeExistingInstallation()) {
const QString cfp = installRootFileInfo.canonicalFilePath();
if (cfp == QFileInfo(QDir::rootPath()).canonicalFilePath())
throw Error(Tr::tr("Refusing to remove root directory."));
@@ -65,19 +65,19 @@ ProductInstaller::ProductInstaller(const QList<ResolvedProductPtr> &products,
throw Error(Tr::tr("Cannot deduce install root, because there are no products."));
const ResolvedProductConstPtr &product = m_products.first();
- m_options.installRoot
- = product->properties->qbsPropertyValue(QLatin1String("sysroot")).toString();
- if (m_options.installRoot.isEmpty()) {
- m_options.installRoot = product->project->buildDirectory
- + QLatin1Char('/') + InstallOptions::defaultInstallRoot();
- } else if (m_options.removeFirst) {
+ m_options.setInstallRoot(product->properties
+ ->qbsPropertyValue(QLatin1String("sysroot")).toString());
+ if (m_options.installRoot().isEmpty()) {
+ m_options.setInstallRoot(product->project->buildDirectory
+ + QLatin1Char('/') + InstallOptions::defaultInstallRoot());
+ } else if (m_options.removeExistingInstallation()) {
throw Error(Tr::tr("Refusing to remove sysroot."));
}
}
void ProductInstaller::install()
{
- if (m_options.removeFirst)
+ if (m_options.removeExistingInstallation())
removeInstallRoot();
QList<const Artifact *> artifactsToInstall;
@@ -98,8 +98,8 @@ void ProductInstaller::install()
void ProductInstaller::removeInstallRoot()
{
- const QString nativeInstallRoot = QDir::toNativeSeparators(m_options.installRoot);
- if (m_options.dryRun) {
+ const QString nativeInstallRoot = QDir::toNativeSeparators(m_options.installRoot());
+ if (m_options.dryRun()) {
m_logger.qbsInfo() << Tr::tr("Would remove install root '%1'.").arg(nativeInstallRoot);
return;
}
@@ -107,9 +107,9 @@ void ProductInstaller::removeInstallRoot()
.arg(nativeInstallRoot);
QString errorMessage;
- if (!removeDirectoryWithContents(m_options.installRoot, &errorMessage)) {
+ if (!removeDirectoryWithContents(m_options.installRoot(), &errorMessage)) {
const QString fullErrorMessage = Tr::tr("Cannot remove install root '%1': %2")
- .arg(QDir::toNativeSeparators(m_options.installRoot), errorMessage);
+ .arg(QDir::toNativeSeparators(m_options.installRoot()), errorMessage);
handleError(fullErrorMessage);
}
}
@@ -120,12 +120,12 @@ void ProductInstaller::copyFile(const Artifact *artifact)
throw Error(Tr::tr("Installation canceled due to user request."));
const QString relativeInstallDir
= artifact->properties->qbsPropertyValue(QLatin1String("installDir")).toString();
- QString targetDir = m_options.installRoot;
+ QString targetDir = m_options.installRoot();
targetDir.append(QLatin1Char('/')).append(relativeInstallDir);
targetDir = QDir::cleanPath(targetDir);
const QString nativeFilePath = QDir::toNativeSeparators(artifact->filePath());
const QString nativeTargetDir = QDir::toNativeSeparators(targetDir);
- if (m_options.dryRun) {
+ if (m_options.dryRun()) {
m_logger.qbsInfo() << Tr::tr("Would copy file '%1' into target directory '%2'.")
.arg(nativeFilePath, nativeTargetDir);
return;
@@ -146,7 +146,7 @@ void ProductInstaller::copyFile(const Artifact *artifact)
void ProductInstaller::handleError(const QString &message)
{
- if (!m_options.keepGoing)
+ if (!m_options.keepGoing())
throw Error(message);
m_logger.qbsWarning() << message;
}
diff --git a/src/lib/buildgraph/projectbuilddata.cpp b/src/lib/buildgraph/projectbuilddata.cpp
index 3bd8843b4..ed46a088e 100644
--- a/src/lib/buildgraph/projectbuilddata.cpp
+++ b/src/lib/buildgraph/projectbuilddata.cpp
@@ -291,11 +291,11 @@ void BuildDataResolver::resolveProductBuildData(const ResolvedProductPtr &produc
}
//add qbsFile artifact
- Artifact *qbsFileArtifact = lookupArtifact(product, product->location.fileName);
+ Artifact *qbsFileArtifact = lookupArtifact(product, product->location.fileName());
if (!qbsFileArtifact) {
qbsFileArtifact = new Artifact(m_project);
qbsFileArtifact->artifactType = Artifact::SourceFile;
- qbsFileArtifact->setFilePath(product->location.fileName);
+ qbsFileArtifact->setFilePath(product->location.fileName());
qbsFileArtifact->properties = product->properties;
insertArtifact(product, qbsFileArtifact, m_logger);
}
diff --git a/src/lib/buildgraph/rulesapplicator.cpp b/src/lib/buildgraph/rulesapplicator.cpp
index a9781d10e..b5ec6ffde 100644
--- a/src/lib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/buildgraph/rulesapplicator.cpp
@@ -245,15 +245,15 @@ Artifact *RulesApplicator::createOutputArtifact(const RuleArtifactConstPtr &rule
+ "] -> [" + outputArtifact->fileTags.toStringList().join(", ") + "]";
e += QString(" while trying to apply: %1:%2:%3 %4\n")
- .arg(m_rule->script->location.fileName)
- .arg(m_rule->script->location.line)
- .arg(m_rule->script->location.column)
+ .arg(m_rule->script->location.fileName())
+ .arg(m_rule->script->location.line())
+ .arg(m_rule->script->location.column())
.arg(th);
e += QString(" was already defined in: %1:%2:%3 %4\n")
- .arg(outputArtifact->transformer->rule->script->location.fileName)
- .arg(outputArtifact->transformer->rule->script->location.line)
- .arg(outputArtifact->transformer->rule->script->location.column)
+ .arg(outputArtifact->transformer->rule->script->location.fileName())
+ .arg(outputArtifact->transformer->rule->script->location.line())
+ .arg(outputArtifact->transformer->rule->script->location.column())
.arg(th);
throw Error(e);
}
diff --git a/src/lib/buildgraph/transformer.cpp b/src/lib/buildgraph/transformer.cpp
index 5a8ff76a1..27ee4af5d 100644
--- a/src/lib/buildgraph/transformer.cpp
+++ b/src/lib/buildgraph/transformer.cpp
@@ -146,8 +146,8 @@ void Transformer::createCommands(const PrepareScriptConstPtr &script,
modulePropertiesUsedInPrepareScript = engine->properties();
if (Q_UNLIKELY(engine->hasUncaughtException()))
throw Error("evaluating prepare script: " + engine->uncaughtException().toString(),
- CodeLocation(script->location.fileName,
- script->location.line + engine->uncaughtExceptionLineNumber() - 1));
+ CodeLocation(script->location.fileName(),
+ script->location.line() + engine->uncaughtExceptionLineNumber() - 1));
qDeleteAll(commands);
commands.clear();
diff --git a/src/lib/language/language.cpp b/src/lib/language/language.cpp
index 86962b0eb..1fe2ababb 100644
--- a/src/lib/language/language.cpp
+++ b/src/lib/language/language.cpp
@@ -629,9 +629,12 @@ ResolvedProject::~ResolvedProject()
void ResolvedProject::load(PersistentPool &pool)
{
- location.fileName = pool.idLoadString();
- pool.stream() >> location.line;
- pool.stream() >> location.column;
+ const QString fileName = pool.idLoadString();
+ int line;
+ int column;
+ pool.stream() >> line;
+ pool.stream() >> column;
+ location = CodeLocation(fileName, line, column);
pool.stream() >> m_id;
pool.stream() >> platformEnvironment;
@@ -655,9 +658,9 @@ void ResolvedProject::load(PersistentPool &pool)
void ResolvedProject::store(PersistentPool &pool) const
{
- pool.storeString(location.fileName);
- pool.stream() << location.line;
- pool.stream() << location.column;
+ pool.storeString(location.fileName());
+ pool.stream() << location.line();
+ pool.stream() << location.column();
pool.stream() << m_id;
pool.stream() << platformEnvironment;
diff --git a/src/lib/language/loader.cpp b/src/lib/language/loader.cpp
index 54c670590..73e397ae2 100644
--- a/src/lib/language/loader.cpp
+++ b/src/lib/language/loader.cpp
@@ -84,7 +84,7 @@ void Loader::setSearchPaths(const QStringList &_searchPaths)
ResolvedProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
{
- QBS_CHECK(QFileInfo(parameters.projectFilePath).isAbsolute());
+ QBS_CHECK(QFileInfo(parameters.projectFilePath()).isAbsolute());
// At this point, we cannot set a sensible total effort, because we know nothing about
// the project yet. That's why we use a placeholder here, so the user at least
@@ -92,15 +92,14 @@ ResolvedProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
// we have enough information.
if (m_progressObserver) {
m_progressObserver->initialize(Tr::tr("Resolving project for configuration %1")
- .arg(ResolvedProject::deriveId(parameters.buildConfiguration)), 1);
+ .arg(ResolvedProject::deriveId(parameters.buildConfiguration())), 1);
}
ModuleLoaderResult loadResult
- = m_moduleLoader->load(parameters.projectFilePath,
- parameters.buildConfiguration,
+ = m_moduleLoader->load(parameters.projectFilePath(),
+ parameters.buildConfiguration(),
true);
- ResolvedProjectPtr project = m_projectResolver->resolve(loadResult, parameters.buildRoot,
- parameters.buildConfiguration);
- return project;
+ return m_projectResolver->resolve(loadResult, parameters.buildRoot(),
+ parameters.buildConfiguration());
}
QByteArray Loader::qmlTypeInfo()
diff --git a/src/lib/language/tst_language.cpp b/src/lib/language/tst_language.cpp
index 9b82ea70e..ec825f86a 100644
--- a/src/lib/language/tst_language.cpp
+++ b/src/lib/language/tst_language.cpp
@@ -57,7 +57,7 @@ TestLanguage::TestLanguage(ILogSink *logSink)
{
qsrand(QTime::currentTime().msec());
qRegisterMetaType<QList<bool> >("QList<bool>");
- defaultParameters.buildRoot = "/some/build/directory";
+ defaultParameters.setBuildRoot("/some/build/directory");
}
TestLanguage::~TestLanguage()
@@ -95,7 +95,7 @@ void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool *
*handled = true;
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject(projectFileName);
+ defaultParameters.setProjectFilePath(testProject(projectFileName));
project = loader->loadProject(defaultParameters);
QVERIFY(project);
} catch (const Error &e) {
@@ -126,8 +126,9 @@ void TestLanguage::initTestCase()
loader = new Loader(m_engine, m_logger);
loader->setSearchPaths(QStringList()
<< QLatin1String(SRCDIR "/../../share/qbs"));
- setConfigProperty(defaultParameters.buildConfiguration,
- QStringList() << "qbs" << "targetOS", "linux");
+ QVariantMap buildConfig = defaultParameters.buildConfiguration();
+ setConfigProperty(buildConfig, QStringList() << "qbs" << "targetOS", "linux");
+ defaultParameters.setBuildConfiguration(buildConfig);
QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute());
}
@@ -140,7 +141,7 @@ void TestLanguage::baseProperty()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("baseproperty.qbs");
+ defaultParameters.setProjectFilePath(testProject("baseproperty.qbs"));
project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -162,7 +163,7 @@ void TestLanguage::conditionalDepends()
ResolvedProductPtr product;
ResolvedModuleConstPtr dependency;
try {
- defaultParameters.projectFilePath = testProject("conditionaldepends.qbs");
+ defaultParameters.setProjectFilePath(testProject("conditionaldepends.qbs"));
project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -238,7 +239,7 @@ void TestLanguage::environmentVariable()
try {
const QByteArray productName = QByteArray("MyApp") + QByteArray::number(qrand());
qputenv("PRODUCT_NAME", productName);
- defaultParameters.projectFilePath = testProject("environmentvariable.qbs");
+ defaultParameters.setProjectFilePath(testProject("environmentvariable.qbs"));
project = loader->loadProject(defaultParameters);
qputenv("PRODUCT_NAME", QByteArray());
QVERIFY(project);
@@ -272,7 +273,7 @@ void TestLanguage::erroneousFiles()
QFETCH(QString, errorMessage);
QString fileName = QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs");
try {
- defaultParameters.projectFilePath = testProject("/erroneous/") + fileName;
+ defaultParameters.setProjectFilePath(testProject("/erroneous/") + fileName);
loader->loadProject(defaultParameters);
} catch (const Error &e) {
if (!e.toString().contains(errorMessage)) {
@@ -289,7 +290,7 @@ void TestLanguage::exports()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("exports.qbs");
+ defaultParameters.setProjectFilePath(testProject("exports.qbs"));
ResolvedProjectPtr project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -345,15 +346,15 @@ void TestLanguage::fileContextProperties()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("filecontextproperties.qbs");
+ defaultParameters.setProjectFilePath(testProject("filecontextproperties.qbs"));
project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
ResolvedProductPtr product = products.value("product1");
QVERIFY(product);
QVariantMap cfg = product->properties->value();
- QCOMPARE(cfg.value("narf").toString(), defaultParameters.projectFilePath);
- QString dirPath = QFileInfo(defaultParameters.projectFilePath).absolutePath();
+ QCOMPARE(cfg.value("narf").toString(), defaultParameters.projectFilePath());
+ QString dirPath = QFileInfo(defaultParameters.projectFilePath()).absolutePath();
QCOMPARE(cfg.value("zort").toString(), dirPath);
} catch (const Error &e) {
exceptionCaught = true;
@@ -406,7 +407,7 @@ void TestLanguage::groupName()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("groupname.qbs");
+ defaultParameters.setProjectFilePath(testProject("groupname.qbs"));
ResolvedProjectPtr project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -516,7 +517,7 @@ void TestLanguage::idUsage()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("idusage.qbs");
+ defaultParameters.setProjectFilePath(testProject("idusage.qbs"));
ResolvedProjectPtr project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -608,12 +609,12 @@ void TestLanguage::jsImportUsedInMultipleScopes()
bool exceptionCaught = false;
try {
- QVariantMap customBuildConfig = defaultParameters.buildConfiguration;
+ QVariantMap customBuildConfig = defaultParameters.buildConfiguration();
setConfigProperty(customBuildConfig, QStringList() << "qbs" << "buildVariant",
buildVariant);
SetupProjectParameters params = defaultParameters;
- params.projectFilePath = testProject("jsimportsinmultiplescopes.qbs");
- params.buildConfiguration = customBuildConfig;
+ params.setProjectFilePath(testProject("jsimportsinmultiplescopes.qbs"));
+ params.setBuildConfiguration(customBuildConfig);
ResolvedProjectPtr project = loader->loadProject(params);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -682,7 +683,7 @@ void TestLanguage::moduleScope()
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("modulescope.qbs");
+ defaultParameters.setProjectFilePath(testProject("modulescope.qbs"));
ResolvedProjectPtr project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -754,7 +755,7 @@ void TestLanguage::outerInGroup()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("outerInGroup.qbs");
+ defaultParameters.setProjectFilePath(testProject("outerInGroup.qbs"));
ResolvedProjectPtr project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -788,14 +789,14 @@ void TestLanguage::pathProperties()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("pathproperties.qbs");
+ defaultParameters.setProjectFilePath(testProject("pathproperties.qbs"));
project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
ResolvedProductPtr product = products.value("product1");
QVERIFY(product);
QVariantMap cfg = product->properties->value();
- QString projectFileDir = QFileInfo(defaultParameters.projectFilePath).absolutePath();
+ QString projectFileDir = QFileInfo(defaultParameters.projectFilePath()).absolutePath();
QCOMPARE(cfg.value("projectFileDir").toString(), projectFileDir);
QStringList filesInProjectFileDir = QStringList()
<< FileInfo::resolvePath(projectFileDir, "aboutdialog.h")
@@ -819,7 +820,7 @@ void TestLanguage::productConditions()
{
bool exceptionCaught = false;
try {
- defaultParameters.projectFilePath = testProject("productconditions.qbs");
+ defaultParameters.setProjectFilePath(testProject("productconditions.qbs"));
ResolvedProjectPtr project = loader->loadProject(defaultParameters);
QVERIFY(project);
QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
@@ -1106,7 +1107,7 @@ void TestLanguage::wildcards()
bool exceptionCaught = false;
ResolvedProductPtr product;
try {
- defaultParameters.projectFilePath = projectFilePath;
+ defaultParameters.setProjectFilePath(projectFilePath);
project = loader->loadProject(defaultParameters);
QVERIFY(project);
const QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
diff --git a/src/lib/lib.qbs b/src/lib/lib.qbs
index 39f097853..e5478858b 100644
--- a/src/lib/lib.qbs
+++ b/src/lib/lib.qbs
@@ -41,6 +41,7 @@ DynamicLibrary {
"jobs.cpp",
"project.cpp",
"projectdata.cpp",
+ "projectdata_p.h",
"propertymap_p.h",
"runenvironment.cpp",
]
@@ -250,6 +251,8 @@ DynamicLibrary {
"persistence.h",
"persistentobject.h",
"preferences.cpp",
+ "processresult.cpp",
+ "processresult_p.h",
"profile.cpp",
"progressobserver.cpp",
"progressobserver.h",
diff --git a/src/lib/logging/ilogsink.cpp b/src/lib/logging/ilogsink.cpp
index a9da808d8..0e8cc7f7a 100644
--- a/src/lib/logging/ilogsink.cpp
+++ b/src/lib/logging/ilogsink.cpp
@@ -29,7 +29,7 @@
#include "ilogsink.h"
#include <QByteArray>
-#include <QString>
+#include <QMutex>
namespace qbs {
@@ -62,17 +62,40 @@ QString logLevelName(LoggerLevel level)
return QString();
}
+class ILogSink::ILogSinkPrivate
+{
+public:
+ LoggerLevel logLevel;
+ QMutex mutex;
+};
+
+ILogSink::ILogSink() : d(new ILogSinkPrivate)
+{
+ d->logLevel = defaultLogLevel();
+}
+
ILogSink::~ILogSink()
{
+ delete d;
+}
+
+void ILogSink::setLogLevel(LoggerLevel level)
+{
+ d->logLevel = level;
+}
+
+LoggerLevel ILogSink::logLevel() const
+{
+ return d->logLevel;
}
void ILogSink::printMessage(LoggerLevel level, const QString &message, const QString &tag,
bool force)
{
if (force || willPrint(level)) {
- m_mutex.lock();
+ d->mutex.lock();
doPrintMessage(level, message, tag);
- m_mutex.unlock();
+ d->mutex.unlock();
}
}
diff --git a/src/lib/logging/ilogsink.h b/src/lib/logging/ilogsink.h
index dfaeeea3a..abb34aee7 100644
--- a/src/lib/logging/ilogsink.h
+++ b/src/lib/logging/ilogsink.h
@@ -31,8 +31,6 @@
#include "../tools/qbs_export.h"
-#include <QtGlobal>
-#include <QMutex>
#include <QString>
namespace qbs {
@@ -56,11 +54,11 @@ class QBS_EXPORT ILogSink
{
Q_DISABLE_COPY(ILogSink)
public:
- ILogSink() : m_logLevel(defaultLogLevel()) {}
+ ILogSink();
virtual ~ILogSink();
- void setLogLevel(LoggerLevel level) { m_logLevel = level; }
- LoggerLevel logLevel() const { return m_logLevel; }
+ void setLogLevel(LoggerLevel level);
+ LoggerLevel logLevel() const;
bool willPrint(LoggerLevel level) const { return level <= logLevel(); }
@@ -71,8 +69,8 @@ private:
virtual void doPrintMessage(LoggerLevel level, const QString &message,
const QString &tag) = 0;
- LoggerLevel m_logLevel;
- QMutex m_mutex;
+ class ILogSinkPrivate;
+ ILogSinkPrivate * const d;
};
} // namespace qbs
diff --git a/src/lib/tools/buildoptions.cpp b/src/lib/tools/buildoptions.cpp
index b9d2608ea..945302e83 100644
--- a/src/lib/tools/buildoptions.cpp
+++ b/src/lib/tools/buildoptions.cpp
@@ -28,9 +28,27 @@
****************************************************************************/
#include "buildoptions.h"
+#include <QSharedData>
#include <QThread>
namespace qbs {
+namespace Internal {
+
+class BuildOptionsPrivate : public QSharedData
+{
+public:
+ BuildOptionsPrivate() : maxJobCount(0), dryRun(false), keepGoing(false), logElapsedTime(false)
+ {
+ }
+
+ QStringList changedFiles;
+ int maxJobCount;
+ bool dryRun;
+ bool keepGoing;
+ bool logElapsedTime;
+};
+
+} // namespace Internal
/*!
* \class BuildOptions
@@ -41,12 +59,40 @@ namespace qbs {
/*!
* \brief Creates a \c BuildOptions object and initializes its members to sensible default values.
*/
-BuildOptions::BuildOptions()
- : maxJobCount(0)
- , dryRun(false)
- , keepGoing(false)
- , logElapsedTime(false)
+BuildOptions::BuildOptions() : d(new Internal::BuildOptionsPrivate)
+{
+}
+
+BuildOptions::BuildOptions(const BuildOptions &other) : d(other.d)
+{
+}
+
+BuildOptions &BuildOptions::operator=(const BuildOptions &other)
+{
+ d = other.d;
+ return *this;
+}
+
+BuildOptions::~BuildOptions()
+{
+}
+
+/*!
+ * \brief If non-empty, qbs pretends that only these files have changed.
+ * By default, this list is empty.
+ */
+QStringList BuildOptions::changedFiles() const
+{
+ return d->changedFiles;
+}
+
+/*!
+ * \brief If the given list is empty, qbs will pretend only the listed files are changed.
+ * \note The list elements must be absolute file paths.
+ */
+void BuildOptions::setChangedFiles(const QStringList &changedFiles)
{
+ d->changedFiles = changedFiles;
}
/*!
@@ -59,45 +105,95 @@ int BuildOptions::defaultMaxJobCount()
}
/*!
- * \variable BuildOptions::changedFiles
- * \brief if non-empty, makes qbs pretend that only these files have changed
+ * \brief Returns the maximum number of build commands to run concurrently.
+ * If the value is not valid (i.e. <= 0), a sensible one will be derived at build time
+ * from the number of available processor cores at build time.
+ * The default is 0.
+ * \sa BuildOptions::defaultMaxJobCount
*/
+int BuildOptions::maxJobCount() const
+{
+ return d->maxJobCount;
+}
- /*!
- * \variable BuildOptions::dryRun
- * \brief if true, qbs will not actually execute any commands, but just show what would happen
- * Note that the next call to build() on the same \c Project object will do nothing, since the
- * internal state needs to be updated the same way as if an actual build has happened. You'll
- * need to create a new \c Project object to do a real build.
- */
+/*!
+ * \brief Controls how many build commands can be run in parallel.
+ * A value <= 0 leaves the decision to qbs.
+ */
+void BuildOptions::setMaxJobCount(int jobCount)
+{
+ d->maxJobCount = jobCount;
+}
+
+/*!
+ * \brief Returns true iff qbs will not actually execute any commands, but just show what
+ * would happen.
+ * The default is false.
+ */
+bool BuildOptions::dryRun() const
+{
+ return d->dryRun;
+}
+
+/*!
+ * \brief Controls whether qbs will actually build something.
+ * If the argument is true, qbs will just emit information about what it would do. Otherwise,
+ * the build is actually done.
+ * \note After you build with this setting enabled, the next call to \c build() on the same
+ * \c Project object will do nothing, since the internal state needs to be updated the same way
+ * as if an actual build had happened. You'll need to create a new \c Project object to do
+ * a real build afterwards.
+ */
+void BuildOptions::setDryRun(bool dryRun)
+{
+ d->dryRun = dryRun;
+}
/*!
- * \variable BuildOptions::keepGoing
- * \brief if true, do not abort on errors if possible
+ * \brief Returns true iff a build will continue after an error.
* E.g. a failed compile command will result in a warning message being printed, instead of
* stopping the build process right away. However, there might still be fatal errors after which the
* build process cannot continue.
+ * The default is \c false.
*/
+bool BuildOptions::keepGoing() const
+{
+ return d->keepGoing;
+}
- /*!
- * \variable
- * \brief the maximum number of build commands to run concurrently
- * If the value is not valid (i.e. <= 0), a sensible one will be derived from the number of
- * available processor cores at build time.
- */
+/*!
+ * \brief Controls whether a qbs will try to continue building after an error has occurred.
+ */
+void BuildOptions::setKeepGoing(bool keepGoing)
+{
+ d->keepGoing = keepGoing;
+}
+
+/*!
+ * \brief Returns true iff the time the operation takes will be logged.
+ * The default is \c false.
+ */
+bool BuildOptions::logElapsedTime() const
+{
+ return d->logElapsedTime;
+}
+
+/*!
+ * \brief Controls whether the build time will be measured and logged.
+ */
+void BuildOptions::setLogElapsedTime(bool log)
+{
+ d->logElapsedTime = log;
+}
- /*!
- * \variable BuildOptions::logElapsedTime
- * \brief true iff the time the operation takes should be logged
- */
bool operator==(const BuildOptions &bo1, const BuildOptions &bo2)
{
- return bo1.changedFiles == bo2.changedFiles
- && bo1.dryRun == bo2.dryRun
- && bo1.keepGoing == bo2.keepGoing
- && bo1.logElapsedTime == bo2.logElapsedTime
- && bo1.maxJobCount == bo2.maxJobCount;
+ return bo1.changedFiles() == bo2.changedFiles()
+ && bo1.dryRun() == bo2.dryRun()
+ && bo1.keepGoing() == bo2.keepGoing()
+ && bo1.logElapsedTime() == bo2.logElapsedTime()
+ && bo1.maxJobCount() == bo2.maxJobCount();
}
} // namespace qbs
diff --git a/src/lib/tools/buildoptions.h b/src/lib/tools/buildoptions.h
index e0b806a6a..0f40abb9e 100644
--- a/src/lib/tools/buildoptions.h
+++ b/src/lib/tools/buildoptions.h
@@ -31,22 +31,38 @@
#include "qbs_export.h"
+#include <QSharedDataPointer>
#include <QStringList>
namespace qbs {
+namespace Internal { class BuildOptionsPrivate; }
class QBS_EXPORT BuildOptions
{
public:
BuildOptions();
+ BuildOptions(const BuildOptions &other);
+ BuildOptions &operator=(const BuildOptions &other);
+ ~BuildOptions();
+
+ QStringList changedFiles() const;
+ void setChangedFiles(const QStringList &changedFiles);
static int defaultMaxJobCount();
+ int maxJobCount() const;
+ void setMaxJobCount(int jobCount);
+
+ bool dryRun() const;
+ void setDryRun(bool dryRun);
+
+ bool keepGoing() const;
+ void setKeepGoing(bool keepGoing);
+
+ bool logElapsedTime() const;
+ void setLogElapsedTime(bool log);
- QStringList changedFiles;
- int maxJobCount;
- bool dryRun;
- bool keepGoing;
- bool logElapsedTime;
+private:
+ QSharedDataPointer<Internal::BuildOptionsPrivate> d;
};
bool operator==(const BuildOptions &bo1, const BuildOptions &bo2);
diff --git a/src/lib/tools/cleanoptions.cpp b/src/lib/tools/cleanoptions.cpp
index 0842b61e1..aa3279dd8 100644
--- a/src/lib/tools/cleanoptions.cpp
+++ b/src/lib/tools/cleanoptions.cpp
@@ -28,7 +28,23 @@
****************************************************************************/
#include "cleanoptions.h"
+#include <QSharedData>
+
namespace qbs {
+namespace Internal {
+
+class CleanOptionsPrivate : public QSharedData
+{
+public:
+ CleanOptionsPrivate() : cleanType(CleanOptions::CleanupAll), dryRun(false), keepGoing(false) {}
+
+ CleanOptions::CleanType cleanType;
+ bool dryRun;
+ bool keepGoing;
+ bool logElapsedTime;
+};
+
+}
/*!
* \class CleanOptions
@@ -36,19 +52,6 @@ namespace qbs {
* cleaning operations.
*/
- /*!
- * \variable CleanOptions::dryRun
- * \brief if true, qbs will not actually remove any files, but just show what would happen.
- */
-
-/*!
- * \variable CleanOptions::keepGoing
- * \brief if true, do not abort on errors
- * If a file cannot be removed, e.g. due to a permission problem, a warning will be printed and
- * cleaning will continue. If this flag is not set, then the operation will abort
- * immediately in case of an error.
- */
-
/*!
* \enum CleanOptions::CleanType
* This enum type specifies which kind of build artifacts to remove.
@@ -58,18 +61,95 @@ namespace qbs {
* would be left on the disk, but the .o files would be removed.
*/
+CleanOptions::CleanOptions() : d(new Internal::CleanOptionsPrivate)
+{
+}
+
+CleanOptions::CleanOptions(const CleanOptions &other) : d(other.d)
+{
+}
+
+CleanOptions &CleanOptions::operator=(const CleanOptions &other)
+{
+ d = other.d;
+ return *this;
+}
+
+CleanOptions::~CleanOptions()
+{
+}
+
/*!
- * \variable CleanOptions::cleanType
- * \brief what to remove
+ * \brief Returns information about which type of artifacts will be removed.
*/
+CleanOptions::CleanType CleanOptions::cleanType() const
+{
+ return d->cleanType;
+}
- /*!
- * \variable CleanOptions::logElapsedTime
- * \brief true iff the time the operation takes should be logged
- */
+/*!
+ * \brief Controls which kind of artifacts to remove.
+ * \sa CleanOptions::CleanType
+ */
+void CleanOptions::setCleanType(CleanOptions::CleanType cleanType)
+{
+ d->cleanType = cleanType;
+}
-CleanOptions::CleanOptions() : cleanType(CleanupAll), dryRun(false), keepGoing(false)
+/*!
+ * \brief Returns true iff qbs will not actually remove any files, but just show what would happen.
+ * The default is false.
+ */
+bool CleanOptions::dryRun() const
+{
+ return d->dryRun;
+}
+
+/*!
+ * \brief Controls whether clean-up will actually take place.
+ * If the argument is true, then qbs will emit information about which files would be removed
+ * instead of actually doing it.
+ */
+void CleanOptions::setDryRun(bool dryRun)
+{
+ d->dryRun = dryRun;
+}
+
+/*!
+ * Returns true iff clean-up will continue if an error occurs.
+ * The default is false.
+ */
+bool CleanOptions::keepGoing() const
+{
+ return d->dryRun;
+}
+
+/*!
+ * \brief Controls whether to abort on errors.
+ * If the argument is true, then if a file cannot be removed e.g. due to a permission problem,
+ * a warning will be printed and the clean-up will continue. If the argument is false,
+ * then the clean-up will abort immediately in case of an error.
+ */
+void CleanOptions::setKeepGoing(bool keepGoing)
+{
+ d->keepGoing = keepGoing;
+}
+
+/*!
+ * \brief Returns true iff the time the operation takes will be logged.
+ * The default is false.
+ */
+bool CleanOptions::logElapsedTime() const
+{
+ return d->logElapsedTime;
+}
+
+/*!
+ * \brief Controls whether the clean-up time will be measured and logged.
+ */
+void CleanOptions::setLogElapsedTime(bool log)
{
+ d->logElapsedTime = log;
}
} // namespace qbs
diff --git a/src/lib/tools/cleanoptions.h b/src/lib/tools/cleanoptions.h
index daa2d2f28..27325eb0b 100644
--- a/src/lib/tools/cleanoptions.h
+++ b/src/lib/tools/cleanoptions.h
@@ -31,21 +31,35 @@
#include "qbs_export.h"
+#include <QSharedDataPointer>
#include <QString>
namespace qbs {
+namespace Internal { class CleanOptionsPrivate; }
class QBS_EXPORT CleanOptions
{
public:
CleanOptions();
+ CleanOptions(const CleanOptions &other);
+ CleanOptions &operator=(const CleanOptions &other);
+ ~CleanOptions();
enum CleanType { CleanupAll, CleanupTemporaries };
+ CleanType cleanType() const;
+ void setCleanType(CleanType cleanType);
- CleanType cleanType;
- bool dryRun;
- bool keepGoing;
- bool logElapsedTime;
+ bool dryRun() const;
+ void setDryRun(bool dryRun);
+
+ bool keepGoing() const;
+ void setKeepGoing(bool keepGoing);
+
+ bool logElapsedTime() const;
+ void setLogElapsedTime(bool log);
+
+private:
+ QSharedDataPointer<Internal::CleanOptionsPrivate> d;
};
} // namespace qbs
diff --git a/src/lib/tools/codelocation.cpp b/src/lib/tools/codelocation.cpp
index d72cb78b1..e81953da3 100644
--- a/src/lib/tools/codelocation.cpp
+++ b/src/lib/tools/codelocation.cpp
@@ -31,33 +31,76 @@
#include <QDataStream>
#include <QDir>
#include <QRegExp>
+#include <QSharedData>
+#include <QString>
namespace qbs {
-CodeLocation::CodeLocation() : line(-1), column(-1)
-{}
+class CodeLocation::CodeLocationPrivate : public QSharedData
+{
+public:
+ QString fileName;
+ int line;
+ int column;
+};
+
+CodeLocation::CodeLocation() : d(new CodeLocationPrivate)
+{
+ d->line = d->column = -1;
+}
CodeLocation::CodeLocation(const QString &aFileName, int aLine, int aColumn)
- : fileName(aFileName),
- line(aLine),
- column(aColumn)
-{}
+ : d(new CodeLocationPrivate)
+{
+ d->fileName = aFileName;
+ d->line = aLine;
+ d->column = aColumn;
+}
+
+CodeLocation::CodeLocation(const CodeLocation &other) : d(other.d)
+{
+}
+
+CodeLocation &CodeLocation::operator=(const CodeLocation &other)
+{
+ d = other.d;
+ return *this;
+}
+
+CodeLocation::~CodeLocation()
+{
+}
+
+QString CodeLocation::fileName() const
+{
+ return d->fileName;
+}
+
+int CodeLocation::line() const
+{
+ return d->line;
+}
+
+int CodeLocation::column() const
+{
+ return d->column;
+}
bool CodeLocation::isValid() const
{
- return !fileName.isEmpty();
+ return !fileName().isEmpty();
}
QString CodeLocation::toString() const
{
QString str;
if (isValid()) {
- str = QDir::toNativeSeparators(fileName);
+ str = QDir::toNativeSeparators(fileName());
QString lineAndColumn;
- if (line > 0 && !str.contains(QRegExp(QLatin1String(":[0-9]+$"))))
- lineAndColumn += QLatin1Char(':') + QString::number(line);
- if (column > 0 && !str.contains(QRegExp(QLatin1String(":[0-9]+:[0-9]+$"))))
- lineAndColumn += QLatin1Char(':') + QString::number(column);
+ if (line() > 0 && !str.contains(QRegExp(QLatin1String(":[0-9]+$"))))
+ lineAndColumn += QLatin1Char(':') + QString::number(line());
+ if (column() > 0 && !str.contains(QRegExp(QLatin1String(":[0-9]+:[0-9]+$"))))
+ lineAndColumn += QLatin1Char(':') + QString::number(column());
str += lineAndColumn;
}
return str;
@@ -65,7 +108,8 @@ QString CodeLocation::toString() const
bool operator==(const CodeLocation &cl1, const CodeLocation &cl2)
{
- return cl1.fileName == cl2.fileName && cl1.line == cl2.line && cl1.column == cl2.column;
+ return cl1.fileName() == cl2.fileName() && cl1.line() == cl2.line()
+ && cl1.column() == cl2.column();
}
bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2)
@@ -75,17 +119,21 @@ bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2)
QDataStream &operator<<(QDataStream &s, const CodeLocation &o)
{
- s << o.fileName;
- s << o.line;
- s << o.column;
+ s << o.fileName();
+ s << o.line();
+ s << o.column();
return s;
}
QDataStream &operator>>(QDataStream &s, CodeLocation &o)
{
- s >> o.fileName;
- s >> o.line;
- s >> o.column;
+ QString fileName;
+ int line;
+ int column;
+ s >> fileName;
+ s >> line;
+ s >> column;
+ o = CodeLocation(fileName, line, column);
return s;
}
diff --git a/src/lib/tools/codelocation.h b/src/lib/tools/codelocation.h
index d0d9790ad..169cb21c2 100644
--- a/src/lib/tools/codelocation.h
+++ b/src/lib/tools/codelocation.h
@@ -32,10 +32,11 @@
#include "qbs_export.h"
-#include <QString>
+#include <QExplicitlySharedDataPointer>
QT_BEGIN_NAMESPACE
class QDataStream;
+class QString;
QT_END_NAMESPACE
namespace qbs {
@@ -45,13 +46,19 @@ class QBS_EXPORT CodeLocation
public:
CodeLocation();
CodeLocation(const QString &aFileName, int aLine = -1, int aColumn = -1);
+ CodeLocation(const CodeLocation &other);
+ CodeLocation &operator=(const CodeLocation &other);
+ ~CodeLocation();
+
+ QString fileName() const;
+ int line() const;
+ int column() const;
bool isValid() const;
QString toString() const;
-
- QString fileName;
- int line;
- int column;
+private:
+ class CodeLocationPrivate;
+ QExplicitlySharedDataPointer<CodeLocationPrivate> d;
};
QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2);
diff --git a/src/lib/tools/error.cpp b/src/lib/tools/error.cpp
index 38796d2c6..279b74b3d 100644
--- a/src/lib/tools/error.cpp
+++ b/src/lib/tools/error.cpp
@@ -29,10 +29,18 @@
#include "error.h"
+#include <QSharedData>
#include <QStringList>
namespace qbs {
+class ErrorData::ErrorDataPrivate : public QSharedData
+{
+public:
+ QString description;
+ CodeLocation codeLocation;
+};
+
/*!
* \class ErrorData
* \brief The \c ErrorData class describes (part of) an error resulting from a qbs operation.
@@ -40,20 +48,39 @@ namespace qbs {
* \sa Error
*/
-ErrorData::ErrorData()
+ErrorData::ErrorData() : d(new ErrorDataPrivate)
{
}
ErrorData::ErrorData(const QString &description, const CodeLocation &codeLocation)
- : m_description(description)
- , m_codeLocation(codeLocation)
+ : d(new ErrorDataPrivate)
+{
+ d->description = description;
+ d->codeLocation = codeLocation;
+}
+
+ErrorData::ErrorData(const ErrorData &rhs) : d(rhs.d)
+{
+}
+
+ErrorData &ErrorData::operator=(const ErrorData &other)
+{
+ d = other.d;
+ return *this;
+}
+
+ErrorData::~ErrorData()
{
}
-ErrorData::ErrorData(const ErrorData &rhs)
- : m_description(rhs.m_description)
- , m_codeLocation(rhs.m_codeLocation)
+QString ErrorData::description() const
{
+ return d->description;
+}
+
+CodeLocation ErrorData::codeLocation() const
+{
+ return d->codeLocation;
}
/*!
@@ -72,12 +99,19 @@ ErrorData::ErrorData(const ErrorData &rhs)
*/
QString ErrorData::toString() const
{
- QString str = m_codeLocation.toString();
+ QString str = codeLocation().toString();
if (!str.isEmpty())
str += QLatin1Char(' ');
- return str += m_description;
+ return str += description();
}
+
+class Error::ErrorPrivate : public QSharedData
+{
+public:
+ QList<ErrorData> items;
+};
+
/*!
* \class Error
* \brief Represents an error resulting from a qbs operation.
@@ -85,28 +119,37 @@ QString ErrorData::toString() const
* \sa ErrorData
*/
-Error::Error()
+Error::Error() : d(new ErrorPrivate)
{
}
-Error::Error(const Error &rhs)
- : m_data(rhs.m_data)
+Error::Error(const Error &rhs) : d(rhs.d)
{
}
-Error::Error(const QString &description, const CodeLocation &location)
+Error::Error(const QString &description, const CodeLocation &location) : d(new ErrorPrivate)
{
append(description, location);
}
+Error &Error::operator =(const Error &other)
+{
+ d = other.d;
+ return *this;
+}
+
+Error::~Error()
+{
+}
+
void Error::append(const QString &description, const CodeLocation &location)
{
- m_data.append(ErrorData(description, location));
+ d->items.append(ErrorData(description, location));
}
void Error::prepend(const QString &description, const CodeLocation &location)
{
- m_data.prepend(ErrorData(description, location));
+ d->items.prepend(ErrorData(description, location));
}
/*!
@@ -114,14 +157,14 @@ void Error::prepend(const QString &description, const CodeLocation &location)
* Most often, there will be one element in this list, but there can be more e.g. to illustrate
* how an error condition propagates through several source files.
*/
-const QList<ErrorData> &Error::entries() const
+QList<ErrorData> Error::entries() const
{
- return m_data;
+ return d->items;
}
void Error::clear()
{
- m_data.clear();
+ d->items.clear();
}
/*!
@@ -132,7 +175,7 @@ void Error::clear()
QString Error::toString() const
{
QStringList lines;
- foreach (const ErrorData &e, m_data)
+ foreach (const ErrorData &e, d->items)
lines.append(e.toString());
return lines.join(QLatin1String("\n"));
}
diff --git a/src/lib/tools/error.h b/src/lib/tools/error.h
index 28a703ba7..ef0515e22 100644
--- a/src/lib/tools/error.h
+++ b/src/lib/tools/error.h
@@ -30,28 +30,36 @@
#ifndef QBS_ERROR
#define QBS_ERROR
-#include <QMetaType>
-
#include "codelocation.h"
+#include <QExplicitlySharedDataPointer>
#include <QList>
+#include <QMetaType>
+#include <QSharedDataPointer>
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
namespace qbs {
+class CodeLocation;
class QBS_EXPORT ErrorData
{
public:
ErrorData();
- explicit ErrorData(const QString &description, const CodeLocation &codeLocation);
+ ErrorData(const QString &description, const CodeLocation &codeLocation);
ErrorData(const ErrorData &rhs);
+ ErrorData &operator=(const ErrorData &other);
+ ~ErrorData();
- const QString &description() const { return m_description; }
- CodeLocation codeLocation() const { return m_codeLocation; }
+ QString description() const;
+ CodeLocation codeLocation() const;
QString toString() const;
private:
- QString m_description;
- CodeLocation m_codeLocation;
+ class ErrorDataPrivate;
+ QExplicitlySharedDataPointer<ErrorDataPrivate> d;
};
class QBS_EXPORT Error
@@ -60,15 +68,18 @@ public:
Error();
Error(const Error &rhs);
Error(const QString &description, const CodeLocation &location = CodeLocation());
+ Error &operator=(const Error &other);
+ ~Error();
void append(const QString &description, const CodeLocation &location = CodeLocation());
void prepend(const QString &description, const CodeLocation &location = CodeLocation());
- const QList<ErrorData> &entries() const;
+ QList<ErrorData> entries() const;
void clear();
QString toString() const;
private:
- QList<ErrorData> m_data;
+ class ErrorPrivate;
+ QSharedDataPointer<ErrorPrivate> d;
};
} // namespace qbs
diff --git a/src/lib/tools/installoptions.cpp b/src/lib/tools/installoptions.cpp
index c63a92c7b..e6d7da509 100644
--- a/src/lib/tools/installoptions.cpp
+++ b/src/lib/tools/installoptions.cpp
@@ -28,7 +28,24 @@
****************************************************************************/
#include "installoptions.h"
+#include <QSharedData>
+
namespace qbs {
+namespace Internal {
+
+class InstallOptionsPrivate : public QSharedData
+{
+public:
+ InstallOptionsPrivate() : removeExisting(false), dryRun(false), keepGoing(false) {}
+
+ QString installRoot;
+ bool removeExisting;
+ bool dryRun;
+ bool keepGoing;
+ bool logElapsedTime;
+};
+
+} // namespace Internal
/*!
* \class InstallOptions
@@ -36,50 +53,128 @@ namespace qbs {
* install operations.
*/
- /*!
- * \variable InstallOptions::dryRun
- * \brief if true, qbs will not actually copy any files, but just show what would happen.
- */
+InstallOptions::InstallOptions() : d(new Internal::InstallOptionsPrivate)
+{
+}
+
+InstallOptions::InstallOptions(const InstallOptions &other) : d(other.d)
+{
+}
+
+InstallOptions &InstallOptions::operator=(const InstallOptions &other)
+{
+ d = other.d;
+ return *this;
+}
+
+InstallOptions::~InstallOptions()
+{
+}
/*!
- * \variable InstallOptions::keepGoing
- * \brief if true, do not abort on errors
- * If a file cannot be copied e.g. due to a permission problem, a warning will be printed and
- * the installation will continue. If this flag is not set, then the installation will abort
- * immediately in case of an error.
+ * \brief The default install root, relative to the build directory.
*/
+QString InstallOptions::defaultInstallRoot()
+{
+ return QLatin1String("install-root");
+}
/*!
- * \variable InstallOptions::installRoot
- * \brief the base directory for the installation
+ * Returns the base directory for the installation.
* All "qbs.installDir" paths are relative to this root. If the string is empty, the value of
* qbs.sysroot will be used. If that is also empty, the base directory is
* "<build dir>/install-root".
+ * The default is empty.
*/
+QString InstallOptions::installRoot() const
+{
+ return d->installRoot;
+}
- /*!
- * \variable InstallOptions::removeFirst
- * \brief if true, removes the installRoot before installing any files.
- * \note qbs may do some safety checks here and refuse to remove certain directories such as
- * a user's home directory. You should still be careful with this option, since it
- * deletes recursively.
- */
+/*!
+ * \brief Sets the base directory for the installation.
+ * \note The argument must either be an empty string or an absolute path to a directory
+ * (which might not yet exists, in which case it will be created).
+ */
+void InstallOptions::setInstallRoot(const QString &installRoot)
+{
+ d->installRoot = installRoot;
+}
- /*!
- * \variable InstallOptions::logElapsedTime
- * \brief true iff the time the operation takes should be logged
- */
+/*!
+ * \brief Returns true iff an existing installation will be removed prior to installing.
+ * The default is false.
+ */
+bool InstallOptions::removeExistingInstallation() const
+{
+ return d->removeExisting;
+}
-InstallOptions::InstallOptions() : removeFirst(false), dryRun(false), keepGoing(false)
+/*!
+ * Controls whether to remove an existing installation before installing.
+ * \note qbs may do some safety checks and refuse to remove certain directories such as
+ * a user's home directory. You should still be careful with this option, since it
+ * deletes recursively.
+ */
+void InstallOptions::setRemoveExistingInstallation(bool removeExisting)
{
+ d->removeExisting = removeExisting;
}
/*!
- * \brief The default install root, relative to the build directory.
+ * \brief Returns true iff qbs will not actually copy any files, but just show what would happen.
+ * The default is false.
*/
-QString InstallOptions::defaultInstallRoot()
+bool InstallOptions::dryRun() const
{
- return QLatin1String("install-root");
+ return d->dryRun;
+}
+
+/*!
+ * \brief Controls whether installation will actually take place.
+ * If the argument is true, then qbs will emit information about which files would be copied
+ * instead of actually doing it.
+ */
+void InstallOptions::setDryRun(bool dryRun)
+{
+ d->dryRun = dryRun;
+}
+
+/*!
+ * Returns true iff installation will continue if an error occurs.
+ * The default is false.
+ */
+bool InstallOptions::keepGoing() const
+{
+ return d->keepGoing;
+}
+
+/*!
+ * \brief Controls whether to abort on errors.
+ * If the argument is true, then if a file cannot be copied e.g. due to a permission problem,
+ * a warning will be printed and the installation will continue. If the argument is false,
+ * then the installation will abort immediately in case of an error.
+ */
+void InstallOptions::setKeepGoing(bool keepGoing)
+{
+ d->keepGoing = keepGoing;
+}
+
+/*!
+ * \brief Returns true iff the time the operation takes will be logged.
+ * The default is false.
+ */
+bool InstallOptions::logElapsedTime() const
+{
+ return d->logElapsedTime;
+}
+
+/*!
+ * \brief Controls whether the installation time will be measured and logged.
+ */
+void InstallOptions::setLogElapsedTime(bool logElapsedTime)
+{
+ d->logElapsedTime = logElapsedTime;
}
} // namespace qbs
diff --git a/src/lib/tools/installoptions.h b/src/lib/tools/installoptions.h
index 1f63b8c44..cf672c705 100644
--- a/src/lib/tools/installoptions.h
+++ b/src/lib/tools/installoptions.h
@@ -31,21 +31,38 @@
#include "qbs_export.h"
+#include <QSharedDataPointer>
#include <QString>
namespace qbs {
+namespace Internal { class InstallOptionsPrivate; }
class QBS_EXPORT InstallOptions
{
public:
InstallOptions();
+ InstallOptions(const InstallOptions &other);
+ InstallOptions &operator=(const InstallOptions &other);
+ ~InstallOptions();
static QString defaultInstallRoot();
- QString installRoot;
- bool removeFirst;
- bool dryRun;
- bool keepGoing;
- bool logElapsedTime;
+ QString installRoot() const;
+ void setInstallRoot(const QString &installRoot);
+
+ bool removeExistingInstallation() const;
+ void setRemoveExistingInstallation(bool removeExisting);
+
+ bool dryRun() const;
+ void setDryRun(bool dryRun);
+
+ bool keepGoing() const;
+ void setKeepGoing(bool keepGoing);
+
+ bool logElapsedTime() const;
+ void setLogElapsedTime(bool logElapsedTime);
+
+private:
+ QSharedDataPointer<Internal::InstallOptionsPrivate> d;
};
} // namespace qbs
diff --git a/src/lib/tools/processresult.cpp b/src/lib/tools/processresult.cpp
new file mode 100644
index 000000000..fe59962e0
--- /dev/null
+++ b/src/lib/tools/processresult.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "processresult.h"
+#include "processresult_p.h"
+
+/*!
+ * \class SetupProjectParameters
+ * \brief The \c ProcessResult class describes a finished qbs process command.
+ */
+
+namespace qbs {
+
+ProcessResult::ProcessResult() : d(new Internal::ProcessResultPrivate)
+{
+}
+
+ProcessResult::ProcessResult(const ProcessResult &other) : d(other.d)
+{
+}
+
+ProcessResult &ProcessResult::operator=(const ProcessResult &other)
+{
+ d = other.d;
+ return *this;
+}
+
+ProcessResult::~ProcessResult()
+{
+}
+
+/*!
+ * \brief Returns true iff the command finished successfully.
+ */
+bool ProcessResult::success() const
+{
+ return d->success;
+}
+
+/*!
+ * \brief Returns the file path of the executable that was run.
+ */
+QString ProcessResult::executableFilePath() const
+{
+ return d->executableFilePath;
+}
+
+/*!
+ * \brief Returns the command-line arguments with which the command was invoked.
+ */
+QStringList ProcessResult::arguments() const
+{
+ return d->arguments;
+}
+
+/*!
+ * \brief Returns the working directory of the invoked command.
+ */
+QString ProcessResult::workingDirectory() const
+{
+ return d->workingDirectory;
+}
+
+/*!
+ * \brief Returns the exit status of the command.
+ */
+QProcess::ExitStatus ProcessResult::exitStatus() const
+{
+ return d->exitStatus;
+}
+
+/*!
+ * \brief Returns the exit code of the command.
+ */
+int ProcessResult::exitCode() const
+{
+ return d->exitCode;
+}
+
+/*!
+ * \brief Returns the data the command wrote to the standard output channel.
+ */
+QStringList ProcessResult::stdOut() const
+{
+ return d->stdOut;
+}
+
+/*!
+ * \brief Returns the data the command wrote to the standard error channel.
+ */
+QStringList ProcessResult::stdErr() const
+{
+ return d->stdErr;
+}
+
+} // namespace qbs
diff --git a/src/lib/tools/processresult.h b/src/lib/tools/processresult.h
index 37d0d9e2f..a2efba863 100644
--- a/src/lib/tools/processresult.h
+++ b/src/lib/tools/processresult.h
@@ -31,25 +31,38 @@
#include "qbs_export.h"
+#include <QExplicitlySharedDataPointer>
#include <QMetaType>
#include <QProcess>
#include <QString>
#include <QStringList>
namespace qbs {
+namespace Internal {
+class ProcessCommandExecutor;
+class ProcessResultPrivate;
+}
-class QBS_EXPORT ProcessResult {
+class QBS_EXPORT ProcessResult
+{
+ friend class qbs::Internal::ProcessCommandExecutor;
public:
- bool success;
+ ProcessResult();
+ ProcessResult(const ProcessResult &other);
+ ProcessResult &operator=(const ProcessResult &other);
+ ~ProcessResult();
- QString binary;
- QStringList arguments;
- QString workingDirectory;
+ bool success() const;
+ QString executableFilePath() const;
+ QStringList arguments() const;
+ QString workingDirectory() const;
+ QProcess::ExitStatus exitStatus() const;
+ int exitCode() const;
+ QStringList stdOut() const;
+ QStringList stdErr() const;
- QProcess::ExitStatus exitStatus;
- int exitCode;
- QStringList stdOut;
- QStringList stdErr;
+private:
+ QExplicitlySharedDataPointer<Internal::ProcessResultPrivate> d;
};
} // namespace qbs
diff --git a/src/lib/tools/processresult_p.h b/src/lib/tools/processresult_p.h
new file mode 100644
index 000000000..0a4b443b9
--- /dev/null
+++ b/src/lib/tools/processresult_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef QBS_PROCESSRESULT_P_H
+#define QBS_PROCESSRESULT_P_H
+
+#include <QSharedData>
+#include <QStringList>
+#include <QProcess>
+
+namespace qbs {
+namespace Internal {
+class ProcessResultPrivate : public QSharedData
+{
+public:
+ bool success;
+
+ QString executableFilePath;
+ QStringList arguments;
+ QString workingDirectory;
+
+ QProcess::ExitStatus exitStatus;
+ int exitCode;
+ QStringList stdOut;
+ QStringList stdErr;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // Include guard.
diff --git a/src/lib/tools/qbsassert.cpp b/src/lib/tools/qbsassert.cpp
index 5fa53d5f4..d9e1f78d7 100644
--- a/src/lib/tools/qbsassert.cpp
+++ b/src/lib/tools/qbsassert.cpp
@@ -30,6 +30,8 @@
#include "qbsassert.h"
#include "error.h"
+#include <QString>
+
namespace qbs {
namespace Internal {
diff --git a/src/lib/tools/setupprojectparameters.cpp b/src/lib/tools/setupprojectparameters.cpp
index 399149607..406a5ffe4 100644
--- a/src/lib/tools/setupprojectparameters.cpp
+++ b/src/lib/tools/setupprojectparameters.cpp
@@ -29,57 +29,194 @@
#include "setupprojectparameters.h"
namespace qbs {
-
-SetupProjectParameters::SetupProjectParameters()
- : ignoreDifferentProjectFilePath(false), dryRun(false), logElapsedTime(false)
-{
-}
+namespace Internal {
/*!
* \class SetupProjectParameters
* \brief The \c SetupProjectParameters class comprises data required to set up a qbs project.
*/
+class SetupProjectParametersPrivate : public QSharedData
+{
+public:
+ SetupProjectParametersPrivate()
+ : ignoreDifferentProjectFilePath(false), dryRun(false), logElapsedTime(false)
+ {
+ }
+
+ QString projectFilePath;
+ QString buildRoot;
+ QStringList searchPaths;
+ QStringList pluginPaths;
+ QVariantMap buildConfiguration;
+ bool ignoreDifferentProjectFilePath;
+ bool dryRun;
+ bool logElapsedTime;
+};
+
+} // namespace Internal
+
+SetupProjectParameters::SetupProjectParameters() : d(new Internal::SetupProjectParametersPrivate)
+{
+}
+
+SetupProjectParameters::SetupProjectParameters(const SetupProjectParameters &other) : d(other.d)
+{
+}
+
+SetupProjectParameters::~SetupProjectParameters()
+{
+}
+
+SetupProjectParameters &SetupProjectParameters::operator=(const SetupProjectParameters &other)
+{
+ d = other.d;
+ return *this;
+}
+
/*!
- * \variable SetupProjectParameters::projectFilePath
- * \brief The absolute path to the qbs project file.
+ * \brief Returns the absolute path to the qbs project file.
* This file typically has a ".qbs" suffix.
*/
+QString SetupProjectParameters::projectFilePath() const
+{
+ return d->projectFilePath;
+}
+
+/*!
+ * \brief Sets the path to the main project file.
+ * \note The argument must be an absolute file path.
+ */
+void SetupProjectParameters::setProjectFilePath(const QString &projectFilePath)
+{
+ d->projectFilePath = projectFilePath;
+}
/*!
- * \variable SetupProjectParameters::buildRoot
- * \brief The base path of where to put the build artifacts.
+ * \brief Returns the base path of where to put the build artifacts and store the build graph.
+ */
+QString SetupProjectParameters::buildRoot() const
+{
+ return d->buildRoot;
+}
+
+/*!
+ * \brief Sets the base path of where to put the build artifacts and store the build graph.
* The same base path can be used for several build profiles of the same project without them
* interfering with each other.
* It might look as if this parameter would not be needed at the time of setting up the project,
- * but keep in mind that the project information might already exist on disk, in which case
+ * but keep in mind that the project information could already exist on disk, in which case
* loading it will be much faster than setting up the project from scratch.
+ * \note The argument must be an absolute path to a directory.
*/
+void SetupProjectParameters::setBuildRoot(const QString &buildRoot)
+{
+ d->buildRoot = buildRoot;
+}
/*!
- * \variable SetupProjectParameters::searchPaths
* \brief Where to look for modules and items to import.
*/
+QStringList SetupProjectParameters::searchPaths() const
+{
+ return d->searchPaths;
+}
+
+/*!
+ * \brief Sets the information about where to look for modules and items to import.
+ * \note The elements of the list must be absolute paths to directories.
+ */
+void SetupProjectParameters::setSearchPaths(const QStringList &searchPaths)
+{
+ d->searchPaths = searchPaths;
+}
/*!
- * \variable SetupProjectParameters::pluginPaths
* \brief Where to look for plugins.
*/
+QStringList SetupProjectParameters::pluginPaths() const
+{
+ return d->pluginPaths;
+}
+
+/*!
+ * \brief Sets the information about where to look for plugins.
+ * \note The elements of the list must be absolute paths to directories.
+ */
+void SetupProjectParameters::setPluginPaths(const QStringList &pluginPaths)
+{
+ d->pluginPaths = pluginPaths;
+}
/*!
- * \variable SetupProjectParameters::buildConfiguration
* \brief The collection of properties to use for resolving the project.
*/
+QVariantMap SetupProjectParameters::buildConfiguration() const
+{
+ return d->buildConfiguration;
+}
+
+/*!
+ * Sets the collection of properties to use for resolving the project.
+ */
+void SetupProjectParameters::setBuildConfiguration(const QVariantMap &buildConfiguration)
+{
+ d->buildConfiguration = buildConfiguration;
+}
+
+/*!
+ * \variable SetupProjectParameters::ignoreDifferentProjectFilePath
+ * \brief Returns true iff the saved build graph should be used even if its path to the
+ * project file is different from \c SetupProjectParameters::projectFilePath()
+ */
+bool SetupProjectParameters::ignoreDifferentProjectFilePath() const
+{
+ return d->ignoreDifferentProjectFilePath;
+}
+
+/*!
+ * \brief Controls whether the path to the main project file may be different from the one
+ * stored in a possible build graph file.
+ * The default is false.
+ */
+void SetupProjectParameters::setIgnoreDifferentProjectFilePath(bool doIgnore)
+{
+ d->ignoreDifferentProjectFilePath = doIgnore;
+}
/*!
- * \variable SetupProjectParameters::ignoreDifferentProjectFilePath
- * \brief true iff the saved build graph should be used even if its path to the project file
- * is different from \c projectFilePath
+ * \brief if true, qbs will not store the build graph of the resolved project.
*/
+bool SetupProjectParameters::dryRun() const
+{
+ return d->dryRun;
+}
/*!
- * \variable SetupProjectParameters::logElapsedTime
- * \brief true iff the time the operation takes should be logged
+ * \brief Controls whether the build graph will be stored.
+ * If the argument is true, qbs will not store the build graph after resolving the project.
+ * The default is false.
*/
+void SetupProjectParameters::setDryRun(bool dryRun)
+{
+ d->dryRun = dryRun;
+}
+
+ /*!
+ * \brief Returns true iff the time the operation takes should be logged
+ */
+bool SetupProjectParameters::logElapsedTime() const
+{
+ return d->logElapsedTime;
+}
+
+/*!
+ * Controls whether to log the time taken up for resolving the project.
+ * The default is false.
+ */
+void SetupProjectParameters::setLogElapsedTime(bool logElapsedTime)
+{
+ d->logElapsedTime = logElapsedTime;
+}
} // namespace qbs
diff --git a/src/lib/tools/setupprojectparameters.h b/src/lib/tools/setupprojectparameters.h
index 81adbf684..f38f6230c 100644
--- a/src/lib/tools/setupprojectparameters.h
+++ b/src/lib/tools/setupprojectparameters.h
@@ -31,24 +31,48 @@
#include "qbs_export.h"
+#include <QSharedDataPointer>
#include <QStringList>
#include <QVariantMap>
namespace qbs {
+namespace Internal { class SetupProjectParametersPrivate; }
class QBS_EXPORT SetupProjectParameters
{
public:
SetupProjectParameters();
+ SetupProjectParameters(const SetupProjectParameters &other);
+ ~SetupProjectParameters();
- QString projectFilePath;
- QString buildRoot;
- QStringList searchPaths;
- QStringList pluginPaths;
- QVariantMap buildConfiguration;
- bool ignoreDifferentProjectFilePath;
- bool dryRun;
- bool logElapsedTime;
+ SetupProjectParameters &operator=(const SetupProjectParameters &other);
+
+ QString projectFilePath() const;
+ void setProjectFilePath(const QString &projectFilePath);
+
+ QString buildRoot() const;
+ void setBuildRoot(const QString &buildRoot);
+
+ QStringList searchPaths() const;
+ void setSearchPaths(const QStringList &searchPaths);
+
+ QStringList pluginPaths() const;
+ void setPluginPaths(const QStringList &pluginPaths);
+
+ QVariantMap buildConfiguration() const;
+ void setBuildConfiguration(const QVariantMap &buildConfiguration);
+
+ bool ignoreDifferentProjectFilePath() const;
+ void setIgnoreDifferentProjectFilePath(bool doIgnore);
+
+ bool dryRun() const;
+ void setDryRun(bool dryRun);
+
+ bool logElapsedTime() const;
+ void setLogElapsedTime(bool logElapsedTime);
+
+private:
+ QSharedDataPointer<Internal::SetupProjectParametersPrivate> d;
};
} // namespace qbs
diff --git a/src/lib/tools/tools.pri b/src/lib/tools/tools.pri
index b7e7eaaa4..730641376 100644
--- a/src/lib/tools/tools.pri
+++ b/src/lib/tools/tools.pri
@@ -13,6 +13,7 @@ HEADERS += \
$$PWD/preferences.h \
$$PWD/profile.h \
$$PWD/processresult.h \
+ $$PWD/processresult_p.h \
$$PWD/progressobserver.h \
$$PWD/propertyfinder.h \
$$PWD/hostosinfo.h \
@@ -36,6 +37,7 @@ SOURCES += \
$$PWD/scripttools.cpp \
$$PWD/settings.cpp \
$$PWD/preferences.cpp \
+ $$PWD/processresult.cpp \
$$PWD/profile.cpp \
$$PWD/progressobserver.cpp \
$$PWD/propertyfinder.cpp \
diff --git a/tests/auto/cmdlineparser/tst_cmdlineparser.cpp b/tests/auto/cmdlineparser/tst_cmdlineparser.cpp
index cccbb636b..41a09d22a 100644
--- a/tests/auto/cmdlineparser/tst_cmdlineparser.cpp
+++ b/tests/auto/cmdlineparser/tst_cmdlineparser.cpp
@@ -70,8 +70,8 @@ private slots:
QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace);
QCOMPARE(parser.command(), BuildCommandType);
QCOMPARE(parser.products(), QStringList() << "blubb");
- QCOMPARE(parser.buildOptions().changedFiles.count(), 2);
- QVERIFY(parser.buildOptions().keepGoing);
+ QCOMPARE(parser.buildOptions().changedFiles().count(), 2);
+ QVERIFY(parser.buildOptions().keepGoing());
QVERIFY(parser.force());
QVERIFY(!parser.logTime());
QCOMPARE(parser.buildConfigurations().count(), 1);