Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .github/scripts/check-deps-and-qt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,25 @@ qt_consumer() {
cd "$ROOT/tests/qt-consumer"
rm -rf target
mkdir -p target/ci
"$MCPP" build 2>&1 | tee target/ci/build.log
"$MCPP" build -v 2>&1 | tee target/ci/build.log
# lupdate writes the `.ts` in the package root and lrelease reads it after;
# neither claims the package's directory as a construction output.
local lu lr
lu=$(grep -n '/lupdate[^ ]* ' target/ci/build.log | head -1 | cut -d: -f1)
lr=$(grep -n '/lrelease[^ ]* ' target/ci/build.log | head -1 | cut -d: -f1)
[ -n "$lu" ] && [ -n "$lr" ] && [ "$lu" -lt "$lr" ] || fail "lupdate did not run before lrelease"
! grep -q 'output_dir' target/ci/build.log || fail "the build reports a construction directory over the package's sources"
echo "ok: lupdate updated the .ts before lrelease read it"
"$MCPP" run | tee target/ci/run.log
grep -qE "^qt-consumer: signal 42, resource 'greetings from rcc', translation 'hallo', Qt 6\." target/ci/run.log ||
fail "moc, rcc or lrelease did not reach the program"
find target -name 'qt_consumer_de.qm' | grep -q . || fail "no .qm was produced"
echo "ok: moc (header and inline), rcc and lrelease reached the program"
"$MCPP" build --profile dev -v > target/ci/second-build.log 2>&1 ||
{ cat target/ci/second-build.log; fail "the second build failed"; }
! grep -qE '/(lupdate|lrelease)[^ ]* ' target/ci/second-build.log ||
fail "a second build with nothing changed re-ran lupdate or lrelease"
echo "ok: a second build with nothing changed ran neither lupdate nor lrelease"
}

qt_widgets_consumer() {
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ CI measures the rest:

```toml
[build-dependencies.mcpp]
plugins = { version = "0.13.0", features = ["deps-vcpkg"], host-module = true, tools = ["mcpp-deps"] }
plugins = { version = "0.13.1", features = ["deps-vcpkg"], host-module = true, tools = ["mcpp-deps"] }
```

```cpp
Expand Down Expand Up @@ -944,7 +944,7 @@ default unless `cache_args` names another.

```toml
[build-dependencies.mcpp]
plugins = { version = "0.13.0", features = ["rules-qt-xim"], host-module = true }
plugins = { version = "0.13.1", features = ["rules-qt-xim"], host-module = true }

[build]
sources = ["src/*.cpp", "res/*.qrc", "i18n/*.ts", "ui/*.ui"]
Expand Down Expand Up @@ -974,7 +974,7 @@ int main() {
| `private_modules` | modules whose private headers are included |
| `moc`, `moc_headers` | `moc_scan::project_headers` (default) scans the package's headers by content; `moc_scan::listed` takes `moc_headers` only |
| `forms`, `resources` | `.ui` and `.qrc` files beside those in `[build] sources` |
| `i18n` | `.ts` files beside those in `[build] sources`; `update_sources` runs `lupdate` as a `prepare` action, whose output directory is the `.ts` files', before `lrelease`; `tr_function_alias`; `deploy_to` (default `translations`); `out_dir`, where `lrelease` writes (default `<out dir>/qt/translations`) |
| `i18n` | `.ts` files beside those in `[build] sources`; `update_sources` runs `lupdate` before `lrelease`, as an action whose output is the `.ts` file it rewrites; `tr_function_alias`; `deploy_to` (default `translations`); `out_dir`, where `lrelease` writes (default `<out dir>/qt/translations`) |
| `deploy_plugins` | plugin directories placed beside the program; default `platforms` |
| `deploy_software_gl` | Windows: `opengl32sw.dll` and `d3dcompiler_47.dll` beside the program |
| `root`, `extra_roots` | an SDK, and further prefixes |
Expand Down
4 changes: 2 additions & 2 deletions mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "plugins"
namespace = "mcpp"
version = "0.13.0"
version = "0.13.1"
description = "Official mcpp build plugins: rule packages under mcpp.rules.*, build-time utilities under mcpp.tools.*, each member selected by a feature"
license = "Apache-2.0"
authors = ["mcpp-community"]
Expand Down Expand Up @@ -653,7 +653,7 @@ main = "tools/embed_main.cpp"
# it by a release.
#
# [build-dependencies.mcpp]
# plugins = { version = "0.13.0", features = ["deps-vcpkg"],
# plugins = { version = "0.13.1", features = ["deps-vcpkg"],
# host-module = true, tools = ["mcpp-deps"] }
[targets.mcpp-deps]
kind = "bin"
Expand Down
33 changes: 13 additions & 20 deletions rules/qt.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@
// declares nothing, so the plan succeeds and the build is where it fails.
//
// `lupdate` REWRITES SOURCES, so it is off unless `translations::update_sources`
// asks for it; then it is a `prepare` action whose stamp `lrelease` waits for,
// the order Qt's Visual Studio integration runs them in.
// asks for it; then it is an action whose output is the `.ts` file itself, and
// `lrelease` reads that file, the order Qt's Visual Studio integration runs
// them in.

module;
#include <cctype>
Expand Down Expand Up @@ -447,7 +448,7 @@ inline bool compile(options opt = {}) {
const std::string desc = "MOC " + in.filename().string();
mcpp::action a;
a.id = id.c_str();
a.role = "source";
a.role = mcpp::roles::source;
a.description = desc.c_str();
a.depfile = dep.c_str();
a.arg(moc.c_str()).arg(src.c_str()).arg("-o").arg(out.c_str())
Expand Down Expand Up @@ -477,7 +478,7 @@ inline bool compile(options opt = {}) {
const std::string desc = "UIC " + fs::path(f).filename().string();
mcpp::action a;
a.id = id.c_str();
a.role = "source";
a.role = mcpp::roles::source;
a.description = desc.c_str();
a.arg(uic.c_str()).arg(in.c_str()).arg("-o").arg(out.c_str())
.input(in.c_str()).output(out.c_str()).submit();
Expand Down Expand Up @@ -505,7 +506,7 @@ inline bool compile(options opt = {}) {
mcpp::rerun_if_changed(in.c_str());
mcpp::action a;
a.id = id.c_str();
a.role = "source";
a.role = mcpp::roles::source;
a.description = desc.c_str();
a.arg(rcc.c_str()).arg("--name").arg(stem.c_str()).arg(in.c_str()).arg("-o").arg(out.c_str())
.input(in.c_str());
Expand Down Expand Up @@ -545,37 +546,29 @@ inline bool compile(options opt = {}) {
const fs::path qmDir = opt.i18n.out_dir.empty() ? gen / "translations"
: detail::absolute_from_root(opt.i18n.out_dir);
const std::string qm = generic(qmDir / (stem + ".qm"));
std::string stamp;
if (opt.i18n.update_sources) {
stamp = generic(gen / (stem + ".lupdate.stamp"));
const std::string id = "qt:lupdate:" + stem;
const std::string desc = "LUPDATE " + file.filename().string();
mcpp::action u;
u.id = id.c_str();
// Construction, not validation (SPEC-007 R3.4): lupdate
// rewrites the `.ts` files in their directory, which lrelease
// reads, so it is a `prepare` whose output directory is theirs.
u.role = mcpp::roles::prepare;
// The file lupdate writes is named before it runs, so the action
// names it as its output (SPEC-007 R3.2) and needs neither a
// stamp nor a `prepare` directory. `lrelease` takes the same file
// as its input, which orders the two.
u.role = mcpp::roles::source;
u.description = desc.c_str();
u.arg(lupdate.c_str()).arg("-silent").arg("-extensions").arg("cpp,h,hpp,ixx,cppm");
for (auto const& a : opt.i18n.tr_function_alias) u.arg("-tr-function-alias").arg(a.c_str());
for (auto const& s : sources) u.arg(s.c_str()).input(s.c_str());
// The stamp is written by mcpp when lupdate succeeds (a
// prepare's command need not write its own); `lrelease` takes it as an
// input, so it reads the `.ts` lupdate has rewritten.
// `output_dir` keeps the pointer it is given, unlike `arg()`,
// so the string is a local that outlives `submit()`.
const std::string tsDir = generic(file.parent_path());
u.arg("-ts").arg(in.c_str()).output(stamp.c_str()).output_dir(tsDir.c_str()).submit();
u.arg("-ts").arg(in.c_str()).output(in.c_str()).submit();
}
const std::string id = "qt:lrelease:" + stem;
const std::string desc = "LRELEASE " + file.filename().string();
mcpp::action r;
r.id = id.c_str();
r.role = "source";
r.role = mcpp::roles::source;
r.description = desc.c_str();
r.arg(lrelease.c_str()).arg("-silent").arg(in.c_str()).arg("-qm").arg(qm.c_str()).input(in.c_str());
if (!stamp.empty()) r.input(stamp.c_str());
r.output(qm.c_str()).submit();
mcpp::deploy(qm.c_str(), opt.i18n.deploy_to.c_str());
}
Expand Down
2 changes: 1 addition & 1 deletion src/plugins.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export namespace mcpp::plugins {
//
// One package, one version: the number lives in mcpp.toml, and the CI step
// `the collection states its own version` compares the two.
inline constexpr std::string_view version = "0.13.0";
inline constexpr std::string_view version = "0.13.1";

} // namespace mcpp::plugins

Expand Down
3 changes: 3 additions & 0 deletions tests/qt-consumer/build.mcpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ int main() {
mcpp::rules::qt::options o;
o.modules = { "Core" };
o.deploy_plugins = {};
// lupdate brings the `.ts` up to date with src/ before lrelease reads it.
// The committed file is lupdate's own output, so a build leaves it as is.
o.i18n.update_sources = true;
return mcpp::rules::qt::compile(o) ? 0 : 1;
}
7 changes: 5 additions & 2 deletions tests/qt-consumer/mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
# src/counter.h declares a Q_OBJECT class -> moc
# src/main.cpp includes "main.moc" -> moc, inline
# res/app.qrc names res/greeting.txt -> rcc
# i18n/qt_consumer_de.ts -> lrelease, deployed
# qt_consumer_de.ts updated from src/ by lupdate -> lrelease, deployed
# under translations/
#
# The `.ts` sits in the package root, as it does in GalTranslPP, so lupdate
# writes one file there and claims no directory.
#
# and the program prints what each produced: a signal delivered to a slot, a
# resource read through `:/`, and a string translated by the `.qm` it loaded
# from beside itself. `widgets/` is the second fixture, for Qt Widgets, `.ui`
Expand Down Expand Up @@ -39,7 +42,7 @@ plugins = { path = "../..", features = ["rules-qt-xim"], host-module = true }
# on the MSVC ABI the static CRT; a PE image resolves its imports per DLL, so
# Qt's DLLs keep their own CRT.
cxx_runtime = "toolchain-coupled"
sources = ["src/*.cpp", "res/*.qrc", "i18n/*.ts"]
sources = ["src/*.cpp", "res/*.qrc", "*.ts"]

[targets.qt-consumer]
kind = "bin"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<context>
<name>main</name>
<message>
<location filename="src/main.cpp" line="43"/>
<source>hello</source>
<translation>hallo</translation>
</message>
Expand Down
Loading