aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@qt.io>2016-11-28 01:57:57 -0800
committerJake Petroules <jake.petroules@qt.io>2016-12-05 13:04:53 +0000
commitd5b4d35659265013d2695f9de87d661d8101280c (patch)
treec55b9aade6aaf95097791a528e67a26014627413
parent0ffae69bcaca623acc3efb3afc2c0def2aa67977 (diff)
Add support for building Inno Setup packages
[ChangeLog] Add support for building Inno Setup packages Task-number: QBS-936 Change-Id: I4cc8e2b39ad93a7aa307a38d88e3f61687c8d364 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--doc/reference/items/innosetup.qdoc39
-rw-r--r--doc/reference/modules/innosetup-module.qdoc161
-rw-r--r--share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs54
-rw-r--r--share/qbs/imports/qbs/base/InnoSetup.qbs34
-rw-r--r--share/qbs/modules/innosetup/InnoSetupModule.qbs142
-rw-r--r--tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss0
-rw-r--r--tests/auto/blackbox/testdata/innosetup/innosetup.qbs21
-rw-r--r--tests/auto/blackbox/testdata/innosetup/test.iss6
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp49
-rw-r--r--tests/auto/blackbox/tst_blackbox.h1
10 files changed, 507 insertions, 0 deletions
diff --git a/doc/reference/items/innosetup.qdoc b/doc/reference/items/innosetup.qdoc
new file mode 100644
index 000000000..1446bfb54
--- /dev/null
+++ b/doc/reference/items/innosetup.qdoc
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \contentspage list-of-items.html
+ \page innosetup-item.html
+ \previouspage group-item.html
+ \nextpage installpackage-item.html
+ \ingroup list-of-items
+
+ \title InnoSetup Item
+ \brief Represents a product that is an Inno Setup installer executable.
+
+ A \c InnoSetup item is a convenience item that has a dependency on the
+ \l{Module innosetup}{Inno Setup module} and whose type is \c{["innosetup.exe"]}.
+*/
diff --git a/doc/reference/modules/innosetup-module.qdoc b/doc/reference/modules/innosetup-module.qdoc
new file mode 100644
index 000000000..7f86ed072
--- /dev/null
+++ b/doc/reference/modules/innosetup-module.qdoc
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \contentspage index.html
+ \page innosetup-module.html
+ \ingroup list-of-modules
+
+ \title Module innosetup
+ \since 1.7
+ \brief Provides Inno Setup support.
+
+ The \c innosetup module contains properties and rules for building
+ EXE setup packages with \l{http://www.jrsoftware.org/isinfo.php}{Inno Setup}.
+ Inno Setup 5 and above are supported.
+
+ \note A typical Inno Setup Script includes an OutputBaseFilename command to set the filename
+ of the generated installer executable. However, \QBS overrides any OutputBaseFilename commands
+ found in the script by passing the /F option to the ISCC compiler, and therefore, you must use
+ the targetName property to set the filename. \QBS also overrides any Output commands by passing
+ the /O option to the ISCC compiler.
+
+ \section1 General Properties
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Since
+ \li Default
+ \li Description
+ \row
+ \li defines
+ \li \c{stringList}
+ \li 1.7
+ \li \c{undefined}
+ \li List of preprocessor macros that get passed to the compiler.
+ To set macro values use the following syntax:
+ \c{innosetup.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"']}
+ \row
+ \li includePaths
+ \li \c{pathList}
+ \li 1.7
+ \li \c{undefined}
+ \li List of include paths. Relative paths are considered to be relative to the .qbs product
+ file they are used in.
+ \row
+ \li verboseOutput
+ \li \c{bool}
+ \li 1.7
+ \li \c{false}
+ \li Whether to display verbose output from the Inno Setup compiler.
+ \row
+ \li compilerFlags
+ \li \c{stringList}
+ \li 1.7
+ \li \c{undefined}
+ \li Additional flags for the Inno Setup compiler.
+ \row
+ \li version
+ \li \c{string}
+ \li 1.7
+ \li \c{undefined}
+ \li The Inno Setup version.
+ Consists of three numbers separated by dots, for instance "5.5.9".
+ \row
+ \li versionMajor
+ \li \c{int}
+ \li 1.7
+ \li \c{versionParts[0]}
+ \li The Inno Setup major version.
+ \row
+ \li versionMinor
+ \li \c{int}
+ \li 1.7
+ \li \c{versionParts[1]}
+ \li The Inno Setup minor version.
+ \row
+ \li versionParts
+ \li \c{list}
+ \li 1.7
+ \li \c{empty}
+ \li The Inno Setup version as a list.
+ For instance, Inno Setup version 5.5.9 would correspond to a
+ value of \c[5, 5, 9].
+ \row
+ \li versionPatch
+ \li \c{int}
+ \li 1.7
+ \li \c{versionParts[2]}
+ \li The Inno Setup patch level.
+ \row
+ \li toolchainInstallPath
+ \li \c{path}
+ \li 1.7
+ \li determined automatically
+ \li Inno Setup installation directory.
+ Determined by searching the registry for the latest version.
+ This should not normally need to be changed.
+ \row
+ \li compilerName
+ \li \c{string}
+ \li 1.7
+ \li \c{"ISCC.exe"}
+ \li Name of the compiler binary.
+ This should not normally need to be changed.
+ \row
+ \li compilerPath
+ \li \c{string}
+ \li 1.7
+ \li \c{compilerName}
+ \li Full path of the compiler binary.
+ This should not normally need to be changed.
+ \endtable
+
+ \section1 Relevant File Tags
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"innosetup.iss"}
+ \li \c{"*.iss"}
+ \li 1.7
+ \li Source files with this tag identify Inno Setup Script files, which serve as inputs
+ to a rule invoking the Inno Setup Script Compiler.
+ \row
+ \li \c{"innosetup.exe"}
+ \li n/a
+ \li 1.7
+ \li The rule that creates Inno Setup executable files attaches this tag
+ (as well as the "application" tag) to its output artifact.
+ \endtable
+*/
diff --git a/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs b/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs
new file mode 100644
index 000000000..d0e756d19
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.Utilities
+
+PathProbe {
+ // Outputs
+ property var version
+
+ configure: {
+ var keySuffix = "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1";
+ var keys = [
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\" + keySuffix,
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\" + keySuffix
+ ];
+ for (var i in keys) {
+ var v = Utilities.getNativeSetting(keys[i], "DisplayVersion");
+ if (v) {
+ path = Utilities.getNativeSetting(keys[i], "InstallLocation");
+ version = v;
+ found = path && version;
+ return;
+ }
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/base/InnoSetup.qbs b/share/qbs/imports/qbs/base/InnoSetup.qbs
new file mode 100644
index 000000000..5ea076eb3
--- /dev/null
+++ b/share/qbs/imports/qbs/base/InnoSetup.qbs
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+Product {
+ Depends { name: "innosetup"; condition: qbs.targetOS.contains("windows") }
+ type: ["innosetup.exe"]
+}
diff --git a/share/qbs/modules/innosetup/InnoSetupModule.qbs b/share/qbs/modules/innosetup/InnoSetupModule.qbs
new file mode 100644
index 000000000..70e36f77b
--- /dev/null
+++ b/share/qbs/modules/innosetup/InnoSetupModule.qbs
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.FileInfo
+import qbs.ModUtils
+import qbs.Probes
+
+Module {
+ condition: qbs.targetOS.contains("windows")
+
+ Probes.InnoSetupProbe {
+ id: innoSetupProbe
+ }
+
+ property path toolchainInstallPath: innoSetupProbe.path
+ version: innoSetupProbe.version
+ property var versionParts: version ? version.split('.').map(function (item) { return parseInt(item, 10); }) : []
+ property int versionMajor: versionParts[0]
+ property int versionMinor: versionParts[1]
+ property int versionPatch: versionParts[2]
+
+ property string compilerName: "ISCC.exe"
+ property string compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
+
+ property bool verboseOutput: false
+ PropertyOptions {
+ name: "verboseOutput"
+ description: "display verbose output from the Inno Setup compiler"
+ }
+
+ property pathList includePaths
+ PropertyOptions {
+ name: "includePaths"
+ description: "directories to add to the include search path"
+ }
+
+ property stringList defines
+ PropertyOptions {
+ name: "defines"
+ description: "variables that are defined when using the Inno Setup compiler"
+ }
+
+ property stringList compilerFlags
+ PropertyOptions {
+ name: "compilerFlags"
+ description: "additional flags for the Inno Setup compiler"
+ }
+
+ readonly property string executableSuffix: ".exe"
+
+ validate: {
+ var validator = new ModUtils.PropertyValidator("innosetup");
+ validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath);
+ validator.setRequiredProperty("version", version);
+ validator.setRequiredProperty("versionMajor", versionMajor);
+ validator.setRequiredProperty("versionMinor", versionMinor);
+ validator.setRequiredProperty("versionPatch", versionPatch);
+ validator.addVersionValidator("version", version, 3, 3);
+ validator.addRangeValidator("versionMajor", versionMajor, 1);
+ validator.addRangeValidator("versionMinor", versionMinor, 0);
+ validator.addRangeValidator("versionPatch", versionPatch, 0);
+ validator.validate();
+ }
+
+ // Inno Setup Script
+ FileTagger {
+ patterns: ["*.iss"]
+ fileTags: ["innosetup.iss"]
+ }
+
+ Rule {
+ id: innoSetupCompiler
+ inputs: ["innosetup.iss"]
+
+ Artifact {
+ fileTags: ["innosetup.exe", "application"]
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ product.targetName
+ + ModUtils.moduleProperty(product, "executableSuffix"))
+ }
+
+ prepare: {
+ var i;
+ var args = [
+ "/O" + FileInfo.toNativeSeparators(FileInfo.path(output.filePath)),
+ "/F" + FileInfo.toNativeSeparators(FileInfo.completeBaseName(output.fileName))
+ ];
+
+ if (!ModUtils.moduleProperty(product, "verboseOutput"))
+ args.push("/Q");
+
+ var includePaths = ModUtils.moduleProperty(product, "includePaths");
+ for (i in includePaths)
+ args.push("/I" + FileInfo.toNativeSeparators(includePaths[i]));
+
+ // User-supplied defines
+ var defines = ModUtils.moduleProperty(product, "defines");
+ for (i in defines)
+ args.push("/D" + defines[i]);
+
+ // User-supplied flags
+ var flags = ModUtils.moduleProperty(product, "compilerFlags");
+ for (i in flags)
+ args.push(flags[i]);
+
+ args.push(FileInfo.toNativeSeparators(input.filePath));
+ var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args);
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.workingDirectory = FileInfo.path(input.filePath);
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss b/tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss
diff --git a/tests/auto/blackbox/testdata/innosetup/innosetup.qbs b/tests/auto/blackbox/testdata/innosetup/innosetup.qbs
new file mode 100644
index 000000000..5fe23a73e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/innosetup/innosetup.qbs
@@ -0,0 +1,21 @@
+import qbs
+import qbs.FileInfo
+
+Project {
+ InnoSetup {
+ name: "QbsSetup"
+ targetName: "qbs.setup.test"
+ version: "1.5"
+ files: [
+ "test.iss"
+ ]
+ innosetup.verboseOutput: true
+ innosetup.includePaths: ["inc"]
+ innosetup.defines: ["MyProgram=" + name, "MyProgramVersion=" + version]
+ innosetup.compilerFlags: ["/V9"]
+ }
+ InnoSetup {
+ name: "Example1"
+ files: [FileInfo.joinPaths(innosetup.toolchainInstallPath, "Examples", name + ".iss")]
+ }
+}
diff --git a/tests/auto/blackbox/testdata/innosetup/test.iss b/tests/auto/blackbox/testdata/innosetup/test.iss
new file mode 100644
index 000000000..f9f9195a6
--- /dev/null
+++ b/tests/auto/blackbox/testdata/innosetup/test.iss
@@ -0,0 +1,6 @@
+#include "qbsinc.iss"
+
+[Setup]
+AppName={#MyProgram}
+AppVersion={#MyProgramVersion}
+DefaultDirName={pf}\{#MyProgram}
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 989c59245..dbeb014ab 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -4022,6 +4022,55 @@ void TestBlackbox::infoPlist()
QVERIFY2(fileContents.contains("<key>NSPrincipalClass</key>"), fileContents.constData());
}
+static bool haveInnoSetup(const Profile &profile)
+{
+ if (profile.value("innosetup.toolchainInstallPath").isValid())
+ return true;
+
+ QStringList regKeys;
+ regKeys << QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1")
+ << QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1");
+
+ QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH")
+ .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts);
+
+ for (const QString &key : regKeys) {
+ QSettings settings(key, QSettings::NativeFormat);
+ QString str = settings.value(QLatin1String("InstallLocation")).toString();
+ if (!str.isEmpty())
+ paths.prepend(str);
+ }
+
+ for (const QString &path : paths) {
+ if (regularFileExists(QDir::fromNativeSeparators(path) +
+ HostOsInfo::appendExecutableSuffix(QLatin1String("/ISCC"))))
+ return true;
+ }
+
+ return false;
+}
+
+void TestBlackbox::innoSetup()
+{
+ Settings settings((QString()));
+ Profile profile(profileName(), &settings);
+
+ if (!haveInnoSetup(profile)) {
+ QSKIP("Inno Setup is not installed");
+ return;
+ }
+
+ QDir::setCurrent(testDataDir + "/innosetup");
+ QbsRunParameters params;
+ if (!HostOsInfo::isWindowsHost())
+ params.arguments << "qbs.targetOS:windows";
+ QCOMPARE(runQbs(params), 0);
+ QVERIFY(m_qbsStdout.contains("compiling test.iss"));
+ QVERIFY(m_qbsStdout.contains("compiling Example1.iss"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.setup.test.exe"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("Example1") + "/Example1.exe"));
+}
+
void TestBlackbox::assetCatalog()
{
QFETCH(bool, flatten);
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 4b5c410ac..019fd1aae 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -87,6 +87,7 @@ private slots:
void importingProduct();
void importsConflict();
void infoPlist();
+ void innoSetup();
void inputsFromDependencies();
void installable();
void installedApp();