Skip to content

Commit

Permalink
updated readme; moc example; use build_dir(); explicit version
Browse files Browse the repository at this point in the history
  • Loading branch information
Rochus Keller committed Oct 6, 2022
1 parent b55cb36 commit 4bc8355
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 13 deletions.
9 changes: 9 additions & 0 deletions BUSY
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,18 @@ let libqtxml * : Library {
}

######################################################################

let test_moc : Moc {
.sources += ./test.cpp
}

let test ! : Executable {
#.cflags_cc += "-g"
.sources += ./test.cpp
.deps += [ libqtcore /* libqtxml */ ]
if HAVE_OBJECT {
.deps += test_moc;
.include_dirs += build_dir()
}
.configs += core_client_config
}
96 changes: 93 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ The following features are available:
- regexp
- logging
- md5 and sha1 hash
- geometry, json, xmlstream, url
- rcc (resource compiler)
- geometry, json, url
- xml stream, sax and dom
- threads, processes
- shared memory
- application, command line
- objects and events
- rcc (resource compiler)
- moc (meta object compiler)
- library and plugins

Expand Down Expand Up @@ -77,7 +78,96 @@ The following features are available:
1. Download https://github.com/rochus-keller/LeanQt/archive/refs/heads/master.zip and unpack it to the root directory; rename the resulting directory to "LeanQt".
1. Download https://github.com/rochus-keller/BUSY/archive/refs/heads/master.zip and unpack it to the root directory; rename the resulting directory to "build".
1. Open a command line in the build directory and type `cc *.c -O2 -lm -O2 -o lua` or `cl /O2 /MD /Fe:lua.exe *.c` depending on whether you are on a Unix or Windows machine; wait a few seconds until the Lua executable is built.
1. Now type `lua build.lua ../Oberon`; wait a few minutes until the OBXMC executable is built; you find it in the output subdirectory.
1. Now type `./lua build.lua ../Oberon` (or `lua build.lua ../Oberon` on Windows); wait a few minutes until the OBXMC executable is built; you find it in the output subdirectory.

### BUSY moc support

Qt includes a powerful meta-object system which extends the capabilities of C++ (see https://doc.qt.io/qt-5/metaobjects.html). The most prominent feature is the signals and slots mechanism for inter-object communication. To make signals and slots work, a QObject descendant is marked with the `Q_OBJECT`, `signals` and `slots` macros and fed to the Meta-Object Compiler (moc) to generate additional code required by the meta-object system.

LeanQt can be compiled with QObject and `moc` support by setting the HAVE_OBJECT parameter to true. If so, the `moc` tool is automatically built and made available to BUSY based builds.

The BUSY build system used by LeanQt includes the [predeclared `Moc` action class](http://software.rochus-keller.ch/busy_spec.html#12625). Its only field is `sources` which is a list of files which need to be processed. The Moc instance is added to the `deps` list of the `Executable` or `Library` instance which has the effect that moc is called for each entry of `sources` and the resulting new .cpp files are automatically compiled and linked with the executable or library. Here is an example:

Assume we have this code in Example.h:

```
#include <QObject>
#include <QtDebug>
class Example : public QObject
{
Q_OBJECT
public:
Example(QObject* p = 0):QObject(p){}
~Example() { qDebug() << "done"; emit done(); }
signals:
void done();
public slots:
void hello() { qDebug() << "Hello from Example"; }
};
```

And this is the code in Example.cpp:

```
#include "Example.h"
#include <QCoreApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
qDebug() << "started";
Example* example = new Example();
QTimer t1;
t1.setSingleShot(true);
QObject::connect(&t1,SIGNAL(timeout()),example,SLOT(deleteLater()));
t1.start(2000);
QTimer t2;
t2.setSingleShot(true);
QObject::connect(&t2,SIGNAL(timeout()),example,SLOT(hello()));
t2.start(1000);
QObject::connect(example,SIGNAL(done()),&app,SLOT(quit()));
return app.exec();
}
```

Assuming the `Example` and `LeanQt` directories are in the same root directory we only need the following BUSY file to build the application:

```
submod qt = ../LeanQt (HAVE_OBJECT)
let moc : Moc {
.sources += ./Example.h
}
let example ! : Executable {
.sources += ./Example.cpp
.deps += [ qt.libqtcore moc ]
.configs += qt.core_client_config
}
```

Note that the space between `../LeanQt` and `(HAVE_OBJECT)` is significant (otherwise `(HAVE_OBJECT)` is considered part of the path).

Assuming the BUSY `build` directory is in the same root directory as `LeanQt` and `Example` we can run the build by just executing `lua build.lua ../Example` from the `build` directory (remember that BUSY itself has to first be built, see [here for more information](https://github.com/rochus-keller/BUSY/blob/main/README.md#build-steps)). The resulting executable can then be found in the `build/output` directory and run like `output/example`.

Here is a summary of the directory structure:
```
├─ build
│ └─ output
│ └─ qt
├─ LeanQt
└─ Example
```
This example links the executable with the static library version of LeanQt. If you instead prefer dynamic linking with LeanQt then just add `HAVE_SHARED` to the `submod` parameter list so it looks like `submod qt = ../LeanQt (HAVE_OBJECT,HAVE_SHARED)`. Before you rebuild, delete the `output` directory. The resulting shared library is in the `build/output/qt` directory (on Windows you have to e.g. move it to the `output` directory so the executable can find it).


### Additional Credits

Expand Down
1 change: 1 addition & 0 deletions Version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2022-10-06
4 changes: 4 additions & 0 deletions core/BUSY
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ let config * : Config {
.defines += "QT_NO_THREAD"
}

if !^HAVE_PROCESS {
.defines += "QT_NO_PROCESS"
}

if target_os == `win32 {
.defines += [ "UNICODE" "_UNICODE" ]
if target_toolchain == `msvc {
Expand Down
26 changes: 18 additions & 8 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,30 @@

class A : public QObject
{
Q_OBJECT
public:
A(QObject* p):QObject(p){}
~A() { qDebug() << "A destructed"; }
signals:
void sayHello();
};

class B : public QObject
{
Q_OBJECT
public:
B(QObject* p):QObject(p){}
~B() { qDebug() << "B destructed"; }
public slots:
void hello()
{
qDebug() << "hello from B";
}
};

#include "test.moc"
#endif

#ifndef QT_NO_THREAD

class TestThread : public QThread
{
public:
Expand All @@ -42,15 +50,13 @@ class TestThread : public QThread
protected:
void run()
{
QTextStream out(stdout);
for( int i = 0; i < 10; i++ )
{
out << title << " " << QDateTime::currentDateTime().toString(Qt::ISODate) << " " << i << endl << flush;
qDebug() << title << QDateTime::currentDateTime().toString(Qt::ISODate) << i;
msleep( qrand() % 1000 );
}
}
};

#endif

int main(int argc, char *argv[])
Expand All @@ -71,7 +77,7 @@ int main(int argc, char *argv[])
qDebug() << hello << QDateTime::currentDateTime().toString(Qt::ISODate) << str << l; // << v;
std::cout << str.toUtf8().constData() << " Hello World " << hello.constData() << std::endl;

#if 0
#ifndef QT_NO_PROCESS
#ifdef _WIN32
QProcess::execute("dir");
#else
Expand Down Expand Up @@ -115,7 +121,7 @@ int main(int argc, char *argv[])

#endif

#if 0 //ndef QT_NO_THREAD
#ifndef QT_NO_THREAD
TestThread a("A"), b("B"), c("C");
a.start();
b.start();
Expand All @@ -130,12 +136,16 @@ int main(int argc, char *argv[])
QPointer<A> ap = new A(0);
QPointer<B> bp = new B(ap);

qDebug() << "translate" << A::tr("Ürgöl");
A::connect(ap, SIGNAL(sayHello()), bp, SLOT(hello()));

qDebug() << "translate" << A::tr("Ölförderung");

QTimer t1;
t1.setSingleShot(true);
t1.connect(&t1,SIGNAL(timeout()),qApp,SLOT(quit()));
t1.start(2000);

ap->sayHello();

QTimer t2;
t2.setSingleShot(true);
Expand Down
2 changes: 1 addition & 1 deletion tools/moc/BUSY
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ let moc * : Executable {
.configs += ^core_client_config;
}
.include_dirs += .
moc_path = root_build_dir + relpath() + ./moc
moc_path = build_dir() + ./moc
}
2 changes: 1 addition & 1 deletion tools/rcc/BUSY
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ let rcc * : Executable {
}
}
.include_dirs += .
rcc_path = root_build_dir + relpath() + ./rcc
rcc_path = build_dir() + ./rcc
}

0 comments on commit 4bc8355

Please sign in to comment.