aboutsummaryrefslogtreecommitdiffstats
path: root/tutorial
diff options
context:
space:
mode:
Diffstat (limited to 'tutorial')
-rw-r--r--tutorial/LICENSE49
-rw-r--r--tutorial/chapter-1/app/app.qbs12
-rw-r--r--tutorial/chapter-1/app/main.c9
-rw-r--r--tutorial/chapter-1/myproject.qbs9
-rw-r--r--tutorial/chapter-2/app/app.qbs11
-rw-r--r--tutorial/chapter-2/app/main.c10
-rw-r--r--tutorial/chapter-2/lib/lib.c15
-rw-r--r--tutorial/chapter-2/lib/lib.h11
-rw-r--r--tutorial/chapter-2/lib/lib.qbs28
-rw-r--r--tutorial/chapter-2/myproject.qbs10
-rw-r--r--tutorial/chapter-3/app/app.qbs29
-rw-r--r--tutorial/chapter-3/app/main.c10
-rw-r--r--tutorial/chapter-3/lib/lib.c16
-rw-r--r--tutorial/chapter-3/lib/lib.h11
-rw-r--r--tutorial/chapter-3/lib/lib.qbs26
-rw-r--r--tutorial/chapter-3/lib/lib_global.h23
-rw-r--r--tutorial/chapter-3/myproject.qbs8
-rw-r--r--tutorial/chapter-4/app/app.qbs10
-rw-r--r--tutorial/chapter-4/app/main.c10
-rw-r--r--tutorial/chapter-4/lib/lib.c10
-rw-r--r--tutorial/chapter-4/lib/lib.h8
-rw-r--r--tutorial/chapter-4/lib/lib.qbs13
-rw-r--r--tutorial/chapter-4/lib/lib_global.h18
-rw-r--r--tutorial/chapter-4/myproject.qbs11
-rw-r--r--tutorial/chapter-4/qbs/imports/MyApplication.qbs23
-rw-r--r--tutorial/chapter-4/qbs/imports/MyLibrary.qbs21
-rw-r--r--tutorial/chapter-5/app/app.qbs6
-rw-r--r--tutorial/chapter-5/app/main.c10
-rw-r--r--tutorial/chapter-5/lib/lib.c10
-rw-r--r--tutorial/chapter-5/lib/lib.h8
-rw-r--r--tutorial/chapter-5/lib/lib.qbs9
-rw-r--r--tutorial/chapter-5/lib/lib_global.h18
-rw-r--r--tutorial/chapter-5/myproject.qbs15
-rw-r--r--tutorial/chapter-5/qbs/imports/MyApplication.qbs20
-rw-r--r--tutorial/chapter-5/qbs/imports/MyAutoTest.qbs7
-rw-r--r--tutorial/chapter-5/qbs/imports/MyLibrary.qbs17
-rw-r--r--tutorial/chapter-5/test/test.c22
-rw-r--r--tutorial/chapter-5/test/test.qbs9
-rw-r--r--tutorial/chapter-6/app/app.qbs6
-rw-r--r--tutorial/chapter-6/app/main.c10
-rw-r--r--tutorial/chapter-6/lib/lib.c10
-rw-r--r--tutorial/chapter-6/lib/lib.h8
-rw-r--r--tutorial/chapter-6/lib/lib.qbs9
-rw-r--r--tutorial/chapter-6/lib/lib_global.h18
-rw-r--r--tutorial/chapter-6/myproject.qbs35
-rw-r--r--tutorial/chapter-6/qbs/imports/MyApplication.qbs23
-rw-r--r--tutorial/chapter-6/qbs/imports/MyAutoTest.qbs3
-rw-r--r--tutorial/chapter-6/qbs/imports/MyLibrary.qbs18
-rw-r--r--tutorial/chapter-6/test/test.c18
-rw-r--r--tutorial/chapter-6/test/test.qbs5
-rw-r--r--tutorial/chapter-7/app/app.qbs6
-rw-r--r--tutorial/chapter-7/app/main.c10
-rw-r--r--tutorial/chapter-7/lib/lib.c10
-rw-r--r--tutorial/chapter-7/lib/lib.h8
-rw-r--r--tutorial/chapter-7/lib/lib.qbs60
-rw-r--r--tutorial/chapter-7/lib/lib_global.h18
-rw-r--r--tutorial/chapter-7/myproject.qbs27
-rw-r--r--tutorial/chapter-7/qbs/imports/MyApplication.qbs13
-rw-r--r--tutorial/chapter-7/qbs/imports/MyAutoTest.qbs3
-rw-r--r--tutorial/chapter-7/qbs/imports/MyLibrary.qbs25
-rw-r--r--tutorial/chapter-7/qbs/modules/mybuildconfig/mybuildconfig.qbs26
-rw-r--r--tutorial/chapter-7/test/test.c18
-rw-r--r--tutorial/chapter-7/test/test.qbs5
-rw-r--r--tutorial/chapter-8/app/app.qbs6
-rw-r--r--tutorial/chapter-8/app/main.c10
-rw-r--r--tutorial/chapter-8/lib/lib.c10
-rw-r--r--tutorial/chapter-8/lib/lib.h8
-rw-r--r--tutorial/chapter-8/lib/lib.qbs10
-rw-r--r--tutorial/chapter-8/lib/lib_global.h25
-rw-r--r--tutorial/chapter-8/myproject.qbs27
-rw-r--r--tutorial/chapter-8/qbs/imports/MyApplication.qbs10
-rw-r--r--tutorial/chapter-8/qbs/imports/MyAutoTest.qbs3
-rw-r--r--tutorial/chapter-8/qbs/imports/MyLibrary.qbs26
-rw-r--r--tutorial/chapter-8/qbs/modules/mybuildconfig/mybuildconfig.qbs25
-rw-r--r--tutorial/chapter-8/test/test.c18
-rw-r--r--tutorial/chapter-8/test/test.qbs5
-rw-r--r--tutorial/chapter-9/app/app.qbs9
-rw-r--r--tutorial/chapter-9/app/main.c14
-rw-r--r--tutorial/chapter-9/lib/lib.c10
-rw-r--r--tutorial/chapter-9/lib/lib.h8
-rw-r--r--tutorial/chapter-9/lib/lib.qbs10
-rw-r--r--tutorial/chapter-9/lib/lib_global.h25
-rw-r--r--tutorial/chapter-9/myproject.qbs32
-rw-r--r--tutorial/chapter-9/qbs/imports/MyApplication.qbs10
-rw-r--r--tutorial/chapter-9/qbs/imports/MyAutoTest.qbs3
-rw-r--r--tutorial/chapter-9/qbs/imports/MyLibrary.qbs26
-rw-r--r--tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs30
-rw-r--r--tutorial/chapter-9/test/test.c18
-rw-r--r--tutorial/chapter-9/test/test.qbs5
-rw-r--r--tutorial/chapter-9/version-header/version-header.qbs57
-rw-r--r--tutorial/chapter-9/version-header/version.h.in9
-rw-r--r--tutorial/tutorial.qbs5
92 files changed, 1408 insertions, 0 deletions
diff --git a/tutorial/LICENSE b/tutorial/LICENSE
new file mode 100644
index 000000000..d7cbbf160
--- /dev/null
+++ b/tutorial/LICENSE
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** Files in this directory are part of the Qbs tutorial.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use these files 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.
+**
+** BSD License Usage
+** Alternatively, you may use this these files under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/ \ No newline at end of file
diff --git a/tutorial/chapter-1/app/app.qbs b/tutorial/chapter-1/app/app.qbs
new file mode 100644
index 000000000..8d0831dc1
--- /dev/null
+++ b/tutorial/chapter-1/app/app.qbs
@@ -0,0 +1,12 @@
+//! [0]
+CppApplication {
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+ version: "1.0.0"
+
+ consoleApplication: true
+ install: true
+ installDebugInformation: true
+}
+//! [0]
diff --git a/tutorial/chapter-1/app/main.c b/tutorial/chapter-1/app/main.c
new file mode 100644
index 000000000..3f3560d25
--- /dev/null
+++ b/tutorial/chapter-1/app/main.c
@@ -0,0 +1,9 @@
+//! [0]
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, world\n");
+ return 0;
+}
+//! [0]
diff --git a/tutorial/chapter-1/myproject.qbs b/tutorial/chapter-1/myproject.qbs
new file mode 100644
index 000000000..b936f3738
--- /dev/null
+++ b/tutorial/chapter-1/myproject.qbs
@@ -0,0 +1,9 @@
+//! [0]
+Project {
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ references: [
+ "app/app.qbs"
+ ]
+}
+//! [0]
diff --git a/tutorial/chapter-2/app/app.qbs b/tutorial/chapter-2/app/app.qbs
new file mode 100644
index 000000000..a3ee757ab
--- /dev/null
+++ b/tutorial/chapter-2/app/app.qbs
@@ -0,0 +1,11 @@
+CppApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+ version: "1.0.0"
+
+ consoleApplication: true
+ install: true
+ installDebugInformation: true
+}
diff --git a/tutorial/chapter-2/app/main.c b/tutorial/chapter-2/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-2/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-2/lib/lib.c b/tutorial/chapter-2/lib/lib.c
new file mode 100644
index 000000000..9fe020ba2
--- /dev/null
+++ b/tutorial/chapter-2/lib/lib.c
@@ -0,0 +1,15 @@
+//! [0]
+
+// lib/lib.cpp
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
+
+//! [0]
diff --git a/tutorial/chapter-2/lib/lib.h b/tutorial/chapter-2/lib/lib.h
new file mode 100644
index 000000000..efc56ae0b
--- /dev/null
+++ b/tutorial/chapter-2/lib/lib.h
@@ -0,0 +1,11 @@
+//! [0]
+
+// lib/lib.h
+#ifndef LIB_H
+#define LIB_H
+
+const char *get_string();
+
+#endif // LIB_H
+
+//! [0]
diff --git a/tutorial/chapter-2/lib/lib.qbs b/tutorial/chapter-2/lib/lib.qbs
new file mode 100644
index 000000000..378d855a6
--- /dev/null
+++ b/tutorial/chapter-2/lib/lib.qbs
@@ -0,0 +1,28 @@
+//! [0]
+StaticLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ ]
+ version: "1.0.0"
+ install: true
+
+ //! [1]
+ Depends { name: 'cpp' }
+ cpp.defines: ['CRUCIAL_DEFINE']
+ //! [1]
+
+ //! [2]
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ }
+ //! [2]
+
+ //! [3]
+ Depends { name: 'bundle' }
+ bundle.isBundle: false
+ //! [3]
+}
+//! [0]
diff --git a/tutorial/chapter-2/myproject.qbs b/tutorial/chapter-2/myproject.qbs
new file mode 100644
index 000000000..17ef04ac9
--- /dev/null
+++ b/tutorial/chapter-2/myproject.qbs
@@ -0,0 +1,10 @@
+//! [0]
+Project {
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs"
+ ]
+}
+//! [0]
diff --git a/tutorial/chapter-3/app/app.qbs b/tutorial/chapter-3/app/app.qbs
new file mode 100644
index 000000000..bb7108581
--- /dev/null
+++ b/tutorial/chapter-3/app/app.qbs
@@ -0,0 +1,29 @@
+//! [1]
+// app/app.qbs
+import qbs.FileInfo
+
+CppApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+ version: "1.0.0"
+
+ consoleApplication: true
+ install: true
+
+ //! [0]
+ cpp.rpaths: {
+ if (!cpp.rpathOrigin)
+ return [];
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths("/", product.installDir),
+ FileInfo.joinPaths("/", "lib")))
+ ];
+ }
+ //! [0]
+}
+//! [1]
diff --git a/tutorial/chapter-3/app/main.c b/tutorial/chapter-3/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-3/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-3/lib/lib.c b/tutorial/chapter-3/lib/lib.c
new file mode 100644
index 000000000..1cbc5ef21
--- /dev/null
+++ b/tutorial/chapter-3/lib/lib.c
@@ -0,0 +1,16 @@
+
+//! [0]
+
+// lib/lib.cpp
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
+
+//! [0]
diff --git a/tutorial/chapter-3/lib/lib.h b/tutorial/chapter-3/lib/lib.h
new file mode 100644
index 000000000..772e1d82b
--- /dev/null
+++ b/tutorial/chapter-3/lib/lib.h
@@ -0,0 +1,11 @@
+#ifndef LIB_H
+#define LIB_H
+
+//! [0]
+// lib/lib.h
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+//! [0]
+
+#endif // LIB_H
diff --git a/tutorial/chapter-3/lib/lib.qbs b/tutorial/chapter-3/lib/lib.qbs
new file mode 100644
index 000000000..a52c29d97
--- /dev/null
+++ b/tutorial/chapter-3/lib/lib.qbs
@@ -0,0 +1,26 @@
+//! [0]
+// lib/lib.qbs
+
+DynamicLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ "lib_global.h",
+ ]
+ version: "1.0.0"
+ install: true
+
+ Depends { name: "cpp" }
+ cpp.defines: ["MYLIB_LIBRARY", "CRUCIAL_DEFINE"]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ }
+
+ Depends { name: "bundle" }
+ bundle.isBundle: false
+}
+//! [0]
diff --git a/tutorial/chapter-3/lib/lib_global.h b/tutorial/chapter-3/lib/lib_global.h
new file mode 100644
index 000000000..07b7978ef
--- /dev/null
+++ b/tutorial/chapter-3/lib/lib_global.h
@@ -0,0 +1,23 @@
+//! [0]
+// lib/lib_global.h
+
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MYLIB_DECL_EXPORT __declspec(dllexport)
+#define MYLIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MYLIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MYLIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MYLIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MYLIB_DECL_IMPORT
+#endif
+
+#endif // LIB_GLOBAL_H
+
+//! [0]
diff --git a/tutorial/chapter-3/myproject.qbs b/tutorial/chapter-3/myproject.qbs
new file mode 100644
index 000000000..152d6cce5
--- /dev/null
+++ b/tutorial/chapter-3/myproject.qbs
@@ -0,0 +1,8 @@
+Project {
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs"
+ ]
+}
diff --git a/tutorial/chapter-4/app/app.qbs b/tutorial/chapter-4/app/app.qbs
new file mode 100644
index 000000000..7051ff554
--- /dev/null
+++ b/tutorial/chapter-4/app/app.qbs
@@ -0,0 +1,10 @@
+//! [0]
+// app/app.qbs
+
+MyApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
+//! [0]
diff --git a/tutorial/chapter-4/app/main.c b/tutorial/chapter-4/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-4/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-4/lib/lib.c b/tutorial/chapter-4/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-4/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-4/lib/lib.h b/tutorial/chapter-4/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-4/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-4/lib/lib.qbs b/tutorial/chapter-4/lib/lib.qbs
new file mode 100644
index 000000000..1f7bf6e6b
--- /dev/null
+++ b/tutorial/chapter-4/lib/lib.qbs
@@ -0,0 +1,13 @@
+//! [0]
+// lib/lib.qbs
+
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ "lib_global.h",
+ ]
+ cpp.defines: base.concat(["CRUCIAL_DEFINE"])
+}
+//! [0]
diff --git a/tutorial/chapter-4/lib/lib_global.h b/tutorial/chapter-4/lib/lib_global.h
new file mode 100644
index 000000000..76cce8d36
--- /dev/null
+++ b/tutorial/chapter-4/lib/lib_global.h
@@ -0,0 +1,18 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MYLIB_DECL_EXPORT __declspec(dllexport)
+#define MYLIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MYLIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MYLIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MYLIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MYLIB_DECL_IMPORT
+#endif
+
+#endif // LIB_GLOBAL_H
diff --git a/tutorial/chapter-4/myproject.qbs b/tutorial/chapter-4/myproject.qbs
new file mode 100644
index 000000000..d429542e7
--- /dev/null
+++ b/tutorial/chapter-4/myproject.qbs
@@ -0,0 +1,11 @@
+//! [0]
+Project {
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs"
+ ]
+ qbsSearchPaths: "qbs"
+}
+//! [0]
diff --git a/tutorial/chapter-4/qbs/imports/MyApplication.qbs b/tutorial/chapter-4/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..e98794f3c
--- /dev/null
+++ b/tutorial/chapter-4/qbs/imports/MyApplication.qbs
@@ -0,0 +1,23 @@
+//! [0]
+// qbs/imports/MyApplication.qbs
+
+import qbs.FileInfo
+
+CppApplication {
+ version: "1.0.0"
+ consoleApplication: true
+ install: true
+
+ cpp.rpaths: {
+ if (!cpp.rpathOrigin)
+ return [];
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths("/", product.installDir),
+ FileInfo.joinPaths("/", "lib")))
+ ];
+ }
+}
+//! [0]
diff --git a/tutorial/chapter-4/qbs/imports/MyLibrary.qbs b/tutorial/chapter-4/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..c819fa38e
--- /dev/null
+++ b/tutorial/chapter-4/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,21 @@
+//! [0]
+// qbs/imports/MyLibrary.qbs
+
+DynamicLibrary {
+ version: "1.0.0"
+ install: true
+
+ Depends { name: 'cpp' }
+ property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY"
+ cpp.defines: [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ }
+
+ Depends { name: 'bundle' }
+ bundle.isBundle: false
+}
+//! [0]
diff --git a/tutorial/chapter-5/app/app.qbs b/tutorial/chapter-5/app/app.qbs
new file mode 100644
index 000000000..84c2430e4
--- /dev/null
+++ b/tutorial/chapter-5/app/app.qbs
@@ -0,0 +1,6 @@
+MyApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
diff --git a/tutorial/chapter-5/app/main.c b/tutorial/chapter-5/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-5/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-5/lib/lib.c b/tutorial/chapter-5/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-5/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-5/lib/lib.h b/tutorial/chapter-5/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-5/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-5/lib/lib.qbs b/tutorial/chapter-5/lib/lib.qbs
new file mode 100644
index 000000000..7c303c8aa
--- /dev/null
+++ b/tutorial/chapter-5/lib/lib.qbs
@@ -0,0 +1,9 @@
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ "lib_global.h",
+ ]
+ cpp.defines: base.concat(['CRUCIAL_DEFINE'])
+}
diff --git a/tutorial/chapter-5/lib/lib_global.h b/tutorial/chapter-5/lib/lib_global.h
new file mode 100644
index 000000000..76cce8d36
--- /dev/null
+++ b/tutorial/chapter-5/lib/lib_global.h
@@ -0,0 +1,18 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MYLIB_DECL_EXPORT __declspec(dllexport)
+#define MYLIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MYLIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MYLIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MYLIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MYLIB_DECL_IMPORT
+#endif
+
+#endif // LIB_GLOBAL_H
diff --git a/tutorial/chapter-5/myproject.qbs b/tutorial/chapter-5/myproject.qbs
new file mode 100644
index 000000000..66e32b220
--- /dev/null
+++ b/tutorial/chapter-5/myproject.qbs
@@ -0,0 +1,15 @@
+Project {
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ // ![0]
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ "test/test.qbs",
+ ]
+ // ![0]
+ qbsSearchPaths: "qbs"
+ AutotestRunner {
+ timeout: 60
+ }
+}
diff --git a/tutorial/chapter-5/qbs/imports/MyApplication.qbs b/tutorial/chapter-5/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..d8c4de25a
--- /dev/null
+++ b/tutorial/chapter-5/qbs/imports/MyApplication.qbs
@@ -0,0 +1,20 @@
+import qbs.FileInfo
+
+CppApplication {
+ version: "1.0.0"
+ consoleApplication: true
+ install: true
+ installDebugInformation: true
+
+ cpp.rpaths: {
+ if (!cpp.rpathOrigin)
+ return [];
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths("/", product.installDir),
+ FileInfo.joinPaths("/", "lib")))
+ ];
+ }
+}
diff --git a/tutorial/chapter-5/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-5/qbs/imports/MyAutoTest.qbs
new file mode 100644
index 000000000..bb6712e85
--- /dev/null
+++ b/tutorial/chapter-5/qbs/imports/MyAutoTest.qbs
@@ -0,0 +1,7 @@
+//! [0]
+// qbs/imports/MyAutoTest.qbs
+
+MyApplication {
+ type: base.concat(["autotest"])
+}
+//! [0]
diff --git a/tutorial/chapter-5/qbs/imports/MyLibrary.qbs b/tutorial/chapter-5/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..5e6c2687a
--- /dev/null
+++ b/tutorial/chapter-5/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,17 @@
+DynamicLibrary {
+ version: "1.0.0"
+ install: true
+
+ Depends { name: 'cpp' }
+ property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY"
+ cpp.defines: [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ }
+
+ Depends { name: 'bundle' }
+ bundle.isBundle: false
+}
diff --git a/tutorial/chapter-5/test/test.c b/tutorial/chapter-5/test/test.c
new file mode 100644
index 000000000..f3bdf646c
--- /dev/null
+++ b/tutorial/chapter-5/test/test.c
@@ -0,0 +1,22 @@
+//! [0]
+// test/test.c
+
+#include "lib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc > 2) {
+ printf("usage: test [value]\n");
+ return 1;
+ }
+ const char *expected = argc == 2 ? argv[1] : "Hello from library";
+ if (strcmp(get_string(), expected) != 0) {
+ printf("text differs\n");
+ return 1;
+ }
+ return 0;
+}
+//! [0] \ No newline at end of file
diff --git a/tutorial/chapter-5/test/test.qbs b/tutorial/chapter-5/test/test.qbs
new file mode 100644
index 000000000..1eab70c55
--- /dev/null
+++ b/tutorial/chapter-5/test/test.qbs
@@ -0,0 +1,9 @@
+//! [0]
+// test/test.qbs
+
+MyAutoTest {
+ Depends { name: "mylib" }
+ name: "mytest"
+ files: "test.c"
+}
+//! [0]
diff --git a/tutorial/chapter-6/app/app.qbs b/tutorial/chapter-6/app/app.qbs
new file mode 100644
index 000000000..84c2430e4
--- /dev/null
+++ b/tutorial/chapter-6/app/app.qbs
@@ -0,0 +1,6 @@
+MyApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
diff --git a/tutorial/chapter-6/app/main.c b/tutorial/chapter-6/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-6/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-6/lib/lib.c b/tutorial/chapter-6/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-6/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-6/lib/lib.h b/tutorial/chapter-6/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-6/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-6/lib/lib.qbs b/tutorial/chapter-6/lib/lib.qbs
new file mode 100644
index 000000000..7c303c8aa
--- /dev/null
+++ b/tutorial/chapter-6/lib/lib.qbs
@@ -0,0 +1,9 @@
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ "lib_global.h",
+ ]
+ cpp.defines: base.concat(['CRUCIAL_DEFINE'])
+}
diff --git a/tutorial/chapter-6/lib/lib_global.h b/tutorial/chapter-6/lib/lib_global.h
new file mode 100644
index 000000000..76cce8d36
--- /dev/null
+++ b/tutorial/chapter-6/lib/lib_global.h
@@ -0,0 +1,18 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MYLIB_DECL_EXPORT __declspec(dllexport)
+#define MYLIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MYLIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MYLIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MYLIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MYLIB_DECL_IMPORT
+#endif
+
+#endif // LIB_GLOBAL_H
diff --git a/tutorial/chapter-6/myproject.qbs b/tutorial/chapter-6/myproject.qbs
new file mode 100644
index 000000000..86537af23
--- /dev/null
+++ b/tutorial/chapter-6/myproject.qbs
@@ -0,0 +1,35 @@
+//! [0]
+Project {
+ property string version: "1.0.0"
+ property bool installDebugInformation: true
+ property bool withTests: false
+ property stringList autotestArguments: []
+ property stringList autotestWrapper: []
+
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ // ...
+ //! [0]
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ ]
+ qbsSearchPaths: "qbs"
+
+ //! [1]
+ SubProject {
+ filePath: "test/test.qbs"
+ Properties {
+ condition: parent.withTests
+ }
+ }
+ //! [1]
+
+ //! [2]
+ AutotestRunner {
+ condition: parent.withTests
+ arguments: parent.autotestArguments
+ wrapper: parent.autotestWrapper
+ }
+ //! [2]
+}
diff --git a/tutorial/chapter-6/qbs/imports/MyApplication.qbs b/tutorial/chapter-6/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..875bc10f3
--- /dev/null
+++ b/tutorial/chapter-6/qbs/imports/MyApplication.qbs
@@ -0,0 +1,23 @@
+import qbs.FileInfo
+
+//! [0]
+CppApplication {
+ version: project.version
+ consoleApplication: true
+ install: true
+ installDebugInformation: project.installDebugInformation
+ // ...
+ //! [0]
+
+ cpp.rpaths: {
+ if (!cpp.rpathOrigin)
+ return [];
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths("/", product.installDir),
+ FileInfo.joinPaths("/", "lib")))
+ ];
+ }
+}
diff --git a/tutorial/chapter-6/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-6/qbs/imports/MyAutoTest.qbs
new file mode 100644
index 000000000..ba420e4d2
--- /dev/null
+++ b/tutorial/chapter-6/qbs/imports/MyAutoTest.qbs
@@ -0,0 +1,3 @@
+MyApplication {
+ type: base.concat(["autotest"])
+}
diff --git a/tutorial/chapter-6/qbs/imports/MyLibrary.qbs b/tutorial/chapter-6/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..ef27bf57b
--- /dev/null
+++ b/tutorial/chapter-6/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,18 @@
+DynamicLibrary {
+ version: project.version
+ install: true
+ installDebugInformation: project.installDebugInformation
+
+ Depends { name: 'cpp' }
+ property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY"
+ cpp.defines: [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ }
+
+ Depends { name: 'bundle' }
+ bundle.isBundle: false
+}
diff --git a/tutorial/chapter-6/test/test.c b/tutorial/chapter-6/test/test.c
new file mode 100644
index 000000000..1fef24685
--- /dev/null
+++ b/tutorial/chapter-6/test/test.c
@@ -0,0 +1,18 @@
+#include "lib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc > 2) {
+ printf("usage: test [value]\n");
+ return 1;
+ }
+ const char *expected = argc == 2 ? argv[1] : "Hello from library";
+ if (strcmp(get_string(), expected) != 0) {
+ printf("text differs\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/tutorial/chapter-6/test/test.qbs b/tutorial/chapter-6/test/test.qbs
new file mode 100644
index 000000000..1e911da47
--- /dev/null
+++ b/tutorial/chapter-6/test/test.qbs
@@ -0,0 +1,5 @@
+MyAutoTest {
+ Depends { name: "mylib" }
+ name: "mytest"
+ files: "test.c"
+}
diff --git a/tutorial/chapter-7/app/app.qbs b/tutorial/chapter-7/app/app.qbs
new file mode 100644
index 000000000..84c2430e4
--- /dev/null
+++ b/tutorial/chapter-7/app/app.qbs
@@ -0,0 +1,6 @@
+MyApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
diff --git a/tutorial/chapter-7/app/main.c b/tutorial/chapter-7/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-7/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-7/lib/lib.c b/tutorial/chapter-7/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-7/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-7/lib/lib.h b/tutorial/chapter-7/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-7/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-7/lib/lib.qbs b/tutorial/chapter-7/lib/lib.qbs
new file mode 100644
index 000000000..eccf6844d
--- /dev/null
+++ b/tutorial/chapter-7/lib/lib.qbs
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ ]
+ Depends { name: 'cpp' }
+ cpp.defines: ['CRUCIAL_DEFINE']
+}
+
diff --git a/tutorial/chapter-7/lib/lib_global.h b/tutorial/chapter-7/lib/lib_global.h
new file mode 100644
index 000000000..76cce8d36
--- /dev/null
+++ b/tutorial/chapter-7/lib/lib_global.h
@@ -0,0 +1,18 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MYLIB_DECL_EXPORT __declspec(dllexport)
+#define MYLIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MYLIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MYLIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MYLIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MYLIB_DECL_IMPORT
+#endif
+
+#endif // LIB_GLOBAL_H
diff --git a/tutorial/chapter-7/myproject.qbs b/tutorial/chapter-7/myproject.qbs
new file mode 100644
index 000000000..aa7ec90bd
--- /dev/null
+++ b/tutorial/chapter-7/myproject.qbs
@@ -0,0 +1,27 @@
+Project {
+ property bool withTests: true
+ property bool installDebugInformation: true
+ property stringList autotestArguments: []
+ property stringList autotestWrapper: []
+
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ ]
+ qbsSearchPaths: "qbs"
+
+ SubProject {
+ filePath: "test/test.qbs"
+ Properties {
+ condition: parent.withTests
+ }
+ }
+
+ AutotestRunner {
+ condition: parent.withTests
+ arguments: parent.autotestArguments
+ wrapper: parent.autotestWrapper
+ }
+}
diff --git a/tutorial/chapter-7/qbs/imports/MyApplication.qbs b/tutorial/chapter-7/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..622c3f4be
--- /dev/null
+++ b/tutorial/chapter-7/qbs/imports/MyApplication.qbs
@@ -0,0 +1,13 @@
+//! [0]
+CppApplication {
+ Depends { name: "mybuildconfig" }
+ installDir: mybuildconfig.appInstallDir
+
+ version: "1.0.0"
+ // ...
+//! [0]
+
+ consoleApplication: true
+ install: true
+ installDebugInformation: project.installDebugInformation
+}
diff --git a/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs
new file mode 100644
index 000000000..1faecdc33
--- /dev/null
+++ b/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs
@@ -0,0 +1,3 @@
+MyApplication {
+ type: ["application", "autotest"]
+}
diff --git a/tutorial/chapter-7/qbs/imports/MyLibrary.qbs b/tutorial/chapter-7/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..7c130ba17
--- /dev/null
+++ b/tutorial/chapter-7/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,25 @@
+DynamicLibrary {
+ version: project.version
+ install: true
+ installDebugInformation: project.installDebugInformation
+//! [0]
+// qbs/imports/MyLibrary.qbs
+ // ...
+ Depends { name: "mybuildconfig" }
+ installDir: mybuildconfig.libInstallDir
+
+ Depends { name: "cpp" }
+ property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY"
+ cpp.defines: [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ // ...
+//! [0]
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ }
+
+ Depends { name: 'bundle' }
+ bundle.isBundle: false
+}
diff --git a/tutorial/chapter-7/qbs/modules/mybuildconfig/mybuildconfig.qbs b/tutorial/chapter-7/qbs/modules/mybuildconfig/mybuildconfig.qbs
new file mode 100644
index 000000000..73234bb0f
--- /dev/null
+++ b/tutorial/chapter-7/qbs/modules/mybuildconfig/mybuildconfig.qbs
@@ -0,0 +1,26 @@
+import qbs.FileInfo
+
+//! [1]
+//! [0]
+// qbs/modules/mybuildconfig.qbs
+Module {
+ property string appInstallDir: "bin"
+ property string libDirName: "lib"
+ property string libInstallDir: qbs.targetOS.contains("windows") ? appInstallDir : libDirName
+ //! [0]
+
+ Depends { name: "cpp" }
+
+ property bool enableRPath: true
+ property stringList libRPaths: {
+ if (enableRPath && cpp.rpathOrigin && product.installDir) {
+ return [FileInfo.joinPaths(cpp.rpathOrigin, FileInfo.relativePath(
+ FileInfo.joinPaths('/', product.installDir),
+ FileInfo.joinPaths('/', libInstallDir)))];
+ }
+ return [];
+ }
+
+ cpp.rpaths: libRPaths
+}
+//! [1]
diff --git a/tutorial/chapter-7/test/test.c b/tutorial/chapter-7/test/test.c
new file mode 100644
index 000000000..1fef24685
--- /dev/null
+++ b/tutorial/chapter-7/test/test.c
@@ -0,0 +1,18 @@
+#include "lib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc > 2) {
+ printf("usage: test [value]\n");
+ return 1;
+ }
+ const char *expected = argc == 2 ? argv[1] : "Hello from library";
+ if (strcmp(get_string(), expected) != 0) {
+ printf("text differs\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/tutorial/chapter-7/test/test.qbs b/tutorial/chapter-7/test/test.qbs
new file mode 100644
index 000000000..1e911da47
--- /dev/null
+++ b/tutorial/chapter-7/test/test.qbs
@@ -0,0 +1,5 @@
+MyAutoTest {
+ Depends { name: "mylib" }
+ name: "mytest"
+ files: "test.c"
+}
diff --git a/tutorial/chapter-8/app/app.qbs b/tutorial/chapter-8/app/app.qbs
new file mode 100644
index 000000000..84c2430e4
--- /dev/null
+++ b/tutorial/chapter-8/app/app.qbs
@@ -0,0 +1,6 @@
+MyApplication {
+ Depends { name: "mylib" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
diff --git a/tutorial/chapter-8/app/main.c b/tutorial/chapter-8/app/main.c
new file mode 100644
index 000000000..a560d1ba1
--- /dev/null
+++ b/tutorial/chapter-8/app/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "lib.h"
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ return 0;
+}
diff --git a/tutorial/chapter-8/lib/lib.c b/tutorial/chapter-8/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-8/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-8/lib/lib.h b/tutorial/chapter-8/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-8/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-8/lib/lib.qbs b/tutorial/chapter-8/lib/lib.qbs
new file mode 100644
index 000000000..e8cf9bdb9
--- /dev/null
+++ b/tutorial/chapter-8/lib/lib.qbs
@@ -0,0 +1,10 @@
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ ]
+ Depends { name: 'cpp' }
+ cpp.defines: ['CRUCIAL_DEFINE']
+}
+
diff --git a/tutorial/chapter-8/lib/lib_global.h b/tutorial/chapter-8/lib/lib_global.h
new file mode 100644
index 000000000..d830dd8ab
--- /dev/null
+++ b/tutorial/chapter-8/lib/lib_global.h
@@ -0,0 +1,25 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MY_LIB_DECL_EXPORT __declspec(dllexport)
+#define MY_LIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MY_LIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MY_LIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+// ![0]
+// lib/lib_global.h
+#if defined(MYLIB_STATIC_LIBRARY)
+#define MYLIB_EXPORT
+#else
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MY_LIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MY_LIB_DECL_IMPORT
+#endif
+#endif
+// ![0]
+
+#endif // LIB_GLOBAL_H \ No newline at end of file
diff --git a/tutorial/chapter-8/myproject.qbs b/tutorial/chapter-8/myproject.qbs
new file mode 100644
index 000000000..aa7ec90bd
--- /dev/null
+++ b/tutorial/chapter-8/myproject.qbs
@@ -0,0 +1,27 @@
+Project {
+ property bool withTests: true
+ property bool installDebugInformation: true
+ property stringList autotestArguments: []
+ property stringList autotestWrapper: []
+
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ ]
+ qbsSearchPaths: "qbs"
+
+ SubProject {
+ filePath: "test/test.qbs"
+ Properties {
+ condition: parent.withTests
+ }
+ }
+
+ AutotestRunner {
+ condition: parent.withTests
+ arguments: parent.autotestArguments
+ wrapper: parent.autotestWrapper
+ }
+}
diff --git a/tutorial/chapter-8/qbs/imports/MyApplication.qbs b/tutorial/chapter-8/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..11b3bfb54
--- /dev/null
+++ b/tutorial/chapter-8/qbs/imports/MyApplication.qbs
@@ -0,0 +1,10 @@
+CppApplication {
+ Depends { name: "mybuildconfig" }
+ version: "1.0.0"
+
+ cpp.rpaths: mybuildconfig.libRPaths
+ consoleApplication: true
+ installDir: mybuildconfig.appInstallDir
+ install: true
+ installDebugInformation: project.installDebugInformation
+}
diff --git a/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs
new file mode 100644
index 000000000..1faecdc33
--- /dev/null
+++ b/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs
@@ -0,0 +1,3 @@
+MyApplication {
+ type: ["application", "autotest"]
+}
diff --git a/tutorial/chapter-8/qbs/imports/MyLibrary.qbs b/tutorial/chapter-8/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..947706dd4
--- /dev/null
+++ b/tutorial/chapter-8/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,26 @@
+// ![0]
+Library {
+ Depends { name: "cpp" }
+ Depends { name: "mybuildconfig" }
+ type: mybuildconfig.staticBuild ? "staticlibrary" : "dynamiclibrary"
+ version: "1.0.0"
+ install: !mybuildconfig.staticBuild || mybuildconfig.installStaticLib
+ installDir: mybuildconfig.libInstallDir
+
+ readonly property string _nameUpper : name.replace(" ", "_").toUpperCase()
+ property string libraryMacro: _nameUpper + "_LIBRARY"
+ property string staticLibraryMacro: _nameUpper + "_STATIC_LIBRARY"
+ cpp.defines: mybuildconfig.staticBuild ? [staticLibraryMacro] : [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ cpp.defines: exportingProduct.mybuildconfig.staticBuild
+ ? [exportingProduct.staticLibraryMacro] : []
+ }
+
+ Depends { name: "bundle" }
+ bundle.isBundle: false
+}
+// ![0]
diff --git a/tutorial/chapter-8/qbs/modules/mybuildconfig/mybuildconfig.qbs b/tutorial/chapter-8/qbs/modules/mybuildconfig/mybuildconfig.qbs
new file mode 100644
index 000000000..0f13dde4d
--- /dev/null
+++ b/tutorial/chapter-8/qbs/modules/mybuildconfig/mybuildconfig.qbs
@@ -0,0 +1,25 @@
+import qbs.FileInfo
+
+Module {
+ Depends { name: "cpp" }
+
+ property string appInstallDir: "bin"
+ property string libDirName: "lib"
+ property string libInstallDir: qbs.targetOS.contains("windows") ? "bin" : libDirName
+ property bool staticBuild: false
+ property bool installStaticLib: true
+ property bool enableRPath: true
+
+ property stringList libRPaths: {
+ if (enableRPath && cpp.rpathOrigin && product.installDir) {
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths('/', product.installDir),
+ FileInfo.joinPaths('/', libDirName)))
+ ];
+ }
+ return [];
+ }
+}
diff --git a/tutorial/chapter-8/test/test.c b/tutorial/chapter-8/test/test.c
new file mode 100644
index 000000000..1fef24685
--- /dev/null
+++ b/tutorial/chapter-8/test/test.c
@@ -0,0 +1,18 @@
+#include "lib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc > 2) {
+ printf("usage: test [value]\n");
+ return 1;
+ }
+ const char *expected = argc == 2 ? argv[1] : "Hello from library";
+ if (strcmp(get_string(), expected) != 0) {
+ printf("text differs\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/tutorial/chapter-8/test/test.qbs b/tutorial/chapter-8/test/test.qbs
new file mode 100644
index 000000000..1e911da47
--- /dev/null
+++ b/tutorial/chapter-8/test/test.qbs
@@ -0,0 +1,5 @@
+MyAutoTest {
+ Depends { name: "mylib" }
+ name: "mytest"
+ files: "test.c"
+}
diff --git a/tutorial/chapter-9/app/app.qbs b/tutorial/chapter-9/app/app.qbs
new file mode 100644
index 000000000..837b66da3
--- /dev/null
+++ b/tutorial/chapter-9/app/app.qbs
@@ -0,0 +1,9 @@
+//! [0]
+MyApplication {
+ Depends { name: "mylib" }
+ Depends { name: "version_header" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
+//! [0]
diff --git a/tutorial/chapter-9/app/main.c b/tutorial/chapter-9/app/main.c
new file mode 100644
index 000000000..d6cefc2ff
--- /dev/null
+++ b/tutorial/chapter-9/app/main.c
@@ -0,0 +1,14 @@
+//![0]
+#include <lib.h>
+#include <version.h>
+
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ printf("ProductVersion = %s\n", kProductVersion);
+ return 0;
+}
+//![0]
diff --git a/tutorial/chapter-9/lib/lib.c b/tutorial/chapter-9/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-9/lib/lib.h b/tutorial/chapter-9/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-9/lib/lib.qbs b/tutorial/chapter-9/lib/lib.qbs
new file mode 100644
index 000000000..e8cf9bdb9
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib.qbs
@@ -0,0 +1,10 @@
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ ]
+ Depends { name: 'cpp' }
+ cpp.defines: ['CRUCIAL_DEFINE']
+}
+
diff --git a/tutorial/chapter-9/lib/lib_global.h b/tutorial/chapter-9/lib/lib_global.h
new file mode 100644
index 000000000..329b62fd3
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib_global.h
@@ -0,0 +1,25 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MY_LIB_DECL_EXPORT __declspec(dllexport)
+#define MY_LIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MY_LIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MY_LIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+// ![0]
+// lib/lib_global.h
+#if defined(MYLIB_STATIC_LIBRARY)
+#define MYLIB_EXPORT
+#else
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MY_LIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MY_LIB_DECL_IMPORT
+#endif
+#endif
+// ![0]
+
+#endif // LIB_GLOBAL_H
diff --git a/tutorial/chapter-9/myproject.qbs b/tutorial/chapter-9/myproject.qbs
new file mode 100644
index 000000000..fac217b71
--- /dev/null
+++ b/tutorial/chapter-9/myproject.qbs
@@ -0,0 +1,32 @@
+Project {
+ property string version: "1.0.0"
+ property bool withTests: true
+ property bool installDebugInformation: true
+ property stringList autotestArguments: []
+ property stringList autotestWrapper: []
+
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ //! [0]
+ // myproject.qbs
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ "version-header/version-header.qbs",
+ ]
+ //! [0]
+ qbsSearchPaths: "qbs"
+
+ SubProject {
+ filePath: "test/test.qbs"
+ Properties {
+ condition: parent.withTests
+ }
+ }
+
+ AutotestRunner {
+ condition: parent.withTests
+ arguments: parent.autotestArguments
+ wrapper: parent.autotestWrapper
+ }
+}
diff --git a/tutorial/chapter-9/qbs/imports/MyApplication.qbs b/tutorial/chapter-9/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..451065190
--- /dev/null
+++ b/tutorial/chapter-9/qbs/imports/MyApplication.qbs
@@ -0,0 +1,10 @@
+CppApplication {
+ Depends { name: "mybuildconfig" }
+ version: mybuildconfig.productVersion
+
+ cpp.rpaths: mybuildconfig.libRPaths
+ consoleApplication: true
+ installDir: mybuildconfig.appInstallDir
+ install: true
+ installDebugInformation: project.installDebugInformation
+}
diff --git a/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs
new file mode 100644
index 000000000..1faecdc33
--- /dev/null
+++ b/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs
@@ -0,0 +1,3 @@
+MyApplication {
+ type: ["application", "autotest"]
+}
diff --git a/tutorial/chapter-9/qbs/imports/MyLibrary.qbs b/tutorial/chapter-9/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..9f2590f50
--- /dev/null
+++ b/tutorial/chapter-9/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,26 @@
+// ![0]
+Library {
+ Depends { name: "cpp" }
+ Depends { name: "mybuildconfig" }
+ type: mybuildconfig.staticBuild ? "staticlibrary" : "dynamiclibrary"
+ version: mybuildconfig.productVersion
+ install: !mybuildconfig.staticBuild || mybuildconfig.installStaticLib
+ installDir: mybuildconfig.libInstallDir
+
+ readonly property string _nameUpper : name.replace(" ", "_").toUpperCase()
+ property string libraryMacro: _nameUpper + "_LIBRARY"
+ property string staticLibraryMacro: _nameUpper + "_STATIC_LIBRARY"
+ cpp.defines: mybuildconfig.staticBuild ? [staticLibraryMacro] : [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ cpp.defines: exportingProduct.mybuildconfig.staticBuild
+ ? [exportingProduct.staticLibraryMacro] : []
+ }
+
+ Depends { name: "bundle" }
+ bundle.isBundle: false
+}
+// ![0]
diff --git a/tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs b/tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs
new file mode 100644
index 000000000..7aed8f7eb
--- /dev/null
+++ b/tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs
@@ -0,0 +1,30 @@
+import qbs.FileInfo
+
+//! [0]
+// qbs/modules/mybuildconfig/mybuildconfig.qbs
+Module {
+ Depends { name: "cpp" }
+
+ property string productVersion: "1.0.0"
+ // ...
+ //! [0]
+ property string appInstallDir: "bin"
+ property string libDirName: "lib"
+ property string libInstallDir: qbs.targetOS.contains("windows") ? "bin" : libDirName
+ property bool staticBuild: false
+ property bool installStaticLib: true
+ property bool enableRPath: true
+
+ property stringList libRPaths: {
+ if (enableRPath && cpp.rpathOrigin && product.installDir) {
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths('/', product.installDir),
+ FileInfo.joinPaths('/', libDirName)))
+ ];
+ }
+ return [];
+ }
+}
diff --git a/tutorial/chapter-9/test/test.c b/tutorial/chapter-9/test/test.c
new file mode 100644
index 000000000..1fef24685
--- /dev/null
+++ b/tutorial/chapter-9/test/test.c
@@ -0,0 +1,18 @@
+#include "lib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc > 2) {
+ printf("usage: test [value]\n");
+ return 1;
+ }
+ const char *expected = argc == 2 ? argv[1] : "Hello from library";
+ if (strcmp(get_string(), expected) != 0) {
+ printf("text differs\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/tutorial/chapter-9/test/test.qbs b/tutorial/chapter-9/test/test.qbs
new file mode 100644
index 000000000..1e911da47
--- /dev/null
+++ b/tutorial/chapter-9/test/test.qbs
@@ -0,0 +1,5 @@
+MyAutoTest {
+ Depends { name: "mylib" }
+ name: "mytest"
+ files: "test.c"
+}
diff --git a/tutorial/chapter-9/version-header/version-header.qbs b/tutorial/chapter-9/version-header/version-header.qbs
new file mode 100644
index 000000000..0a416d572
--- /dev/null
+++ b/tutorial/chapter-9/version-header/version-header.qbs
@@ -0,0 +1,57 @@
+//! [5]
+// version-header/version-header.qbs
+//! [0]
+import qbs.TextFile
+
+Product {
+ name: "version_header"
+ type: "hpp"
+
+ Depends { name: "mybuildconfig" }
+//! [0]
+
+//! [1]
+ Group {
+ files: ["version.h.in"]
+ fileTags: ["version_h_in"]
+ }
+//! [1]
+
+//! [2]
+ Rule {
+ inputs: ["version_h_in"]
+ Artifact {
+ filePath: "version.h"
+ fileTags: "hpp"
+ }
+//! [2]
+//! [3]
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating " + output.fileName;
+ cmd.highlight = "codegen";
+ cmd.sourceCode = function() {
+ var file = new TextFile(input.filePath, TextFile.ReadOnly);
+ var content = file.readAll();
+
+ content = content.replace(
+ "${PRODUCT_VERSION}",
+ product.mybuildconfig.productVersion);
+
+ file = new TextFile(output.filePath, TextFile.WriteOnly);
+ file.write(content);
+ file.close();
+ }
+ return cmd;
+ }
+//! [3]
+ }
+
+//! [4]
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: exportingProduct.buildDirectory
+ }
+//! [4]
+}
+//! [5]
diff --git a/tutorial/chapter-9/version-header/version.h.in b/tutorial/chapter-9/version-header/version.h.in
new file mode 100644
index 000000000..2e6604967
--- /dev/null
+++ b/tutorial/chapter-9/version-header/version.h.in
@@ -0,0 +1,9 @@
+//! [0]
+// version-header/version.h.in
+#ifndef VERSION_H
+#define VERSION_H
+
+const char kProductVersion[] = "${PRODUCT_VERSION}";
+
+#endif // VERSION_H
+//! [0]
diff --git a/tutorial/tutorial.qbs b/tutorial/tutorial.qbs
new file mode 100644
index 000000000..0d2ae3514
--- /dev/null
+++ b/tutorial/tutorial.qbs
@@ -0,0 +1,5 @@
+Product {
+ files: [
+ "*/**",
+ ]
+}