diff options
Diffstat (limited to 'tutorial')
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: [ + "*/**", + ] +} |