From f2596591e598cdcd913b58fd0764a6efb247aca7 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 21 Sep 2023 17:37:49 +0300 Subject: [PATCH] New module pdftops. With Qt 6 copy and sign pdftops from brew. --- qbs/imports/VApp.qbs | 5 ++ qbs/imports/VToolApp.qbs | 2 - qbs/modules/macdeployqt/macdeployqt.qbs | 4 +- qbs/modules/pdftops/pdftops.qbs | 106 ++++++++++++++++++++++++ src/app/puzzle/puzzle.qbs | 22 +++-- src/app/valentina/valentina.qbs | 24 ++++-- src/libs/vlayout/vlayoutexporter.cpp | 51 ++++++++---- 7 files changed, 181 insertions(+), 33 deletions(-) create mode 100644 qbs/modules/pdftops/pdftops.qbs diff --git a/qbs/imports/VApp.qbs b/qbs/imports/VApp.qbs index 738a2565e..3c8941ef9 100644 --- a/qbs/imports/VApp.qbs +++ b/qbs/imports/VApp.qbs @@ -123,4 +123,9 @@ CppApplication { } fileTags: ["cpp_pch_src"] } + + Export { + Depends { name: "bundle"; condition: qbs.targetOS.contains("macos") } + Depends { name: "macdeployqt"; condition: qbs.targetOS.contains("macos") } + } } diff --git a/qbs/imports/VToolApp.qbs b/qbs/imports/VToolApp.qbs index 8c8687fbd..7d8280652 100644 --- a/qbs/imports/VToolApp.qbs +++ b/qbs/imports/VToolApp.qbs @@ -8,7 +8,6 @@ VApp { Depends { name: "i18nconfig"; } Depends { name: "i18n"; } Depends { name: "ib"; condition: qbs.targetOS.contains("macos") } - Depends { name: "macdeployqt"; condition: qbs.targetOS.contains("macos") } version: buildconfig.projectVersion install: true @@ -204,7 +203,6 @@ VApp { Properties { condition: qbs.targetOS.contains("macos") ib.appIconName: targetName - macdeployqt.targetApps: ["Tape", "Puzzle"] } Properties { diff --git a/qbs/modules/macdeployqt/macdeployqt.qbs b/qbs/modules/macdeployqt/macdeployqt.qbs index 45d7417f9..e0f19efea 100644 --- a/qbs/modules/macdeployqt/macdeployqt.qbs +++ b/qbs/modules/macdeployqt/macdeployqt.qbs @@ -87,10 +87,10 @@ Module { cmdArgs.push("-codesign=" + product.macdeployqt.signingIdentity); } - if (product.macdeployqt.targetApps !== undefined && !product.buildconfig.enableMultiBundle && product.primaryApp) + if (product.macdeployqt.targetApps !== undefined) { product.macdeployqt.targetApps.forEach(function(targetApp) { - cmdArgs.push("-executable=\"" + installRoot + "/" + product.targetName + ".app/Contents/MacOS/" + targetApp + "\""); + cmdArgs.push("-executable=" + FileInfo.joinPaths(installRoot, product.targetName + ".app", "Contents", "MacOS", targetApp)); }); } diff --git a/qbs/modules/pdftops/pdftops.qbs b/qbs/modules/pdftops/pdftops.qbs new file mode 100644 index 000000000..7540288e2 --- /dev/null +++ b/qbs/modules/pdftops/pdftops.qbs @@ -0,0 +1,106 @@ +import qbs.Process +import qbs.File +import qbs.FileInfo +import qbs.Utilities + +Module { + + additionalProductTypes: ["pdftops.bundled"] + + readonly property string pdftopsPath: pdftopsProbe.path + readonly property bool pdftopsPresent: pdftopsProbe.found + + Probe { + id: pdftopsProbe + + property string path + property string sourceDirectory: project.sourceDirectory + property string qtVersion: product.Qt.core.version + + configure: { + if (Utilities.versionCompare(qtVersion, "6") >= 0) { + var detector = new Process(); + try { + if (detector.exec("which", ["pdftops"]) === 0) { + var binPath = detector.readStdOut().trim(); // we can read only one time + if (detector.exec("realpath", [binPath]) === 0) { + path = detector.readStdOut().trim(); + console.info("Found pdftops at '" + path + "'."); + found = true; + } + } + } finally { + detector.close(); + } + } else { + var binPath = sourceDirectory + "/dist/macx/bin64/pdftops"; + if (product.qbs.architecture.contains("x86_64") && File.exists(binPath)) { + path = binPath; + found = true; + } + } + } + } + + Rule { + multiplex: true + inputs: ["pdftops.in"] + + prepare: { + var cmds = []; + + var src = input.filePath; + var dst = output.filePath; + var copyCmd = new Command("cp", [src, dst]); + copyCmd.highlight = 'filegen'; + copyCmd.description = "copying " + input.fileName; + cmds.push(copyCmd); + + if (!product.codesign.enableCodeSigning) + return cmds; + + var actualSigningIdentity = product.codesign._actualSigningIdentity; + if (!actualSigningIdentity) { + throw "No codesigning identities (i.e. certificate and private key pairs) matching “" + + product.codesign.signingIdentity + "” were found."; + } + + var args = ["--force", "--sign", actualSigningIdentity.SHA1]; + + // If signingTimestamp is undefined or empty, do not specify the flag at all - + // this uses the system-specific default behavior + var signingTimestamp = product.codesign.signingTimestamp; + if (signingTimestamp) { + // If signingTimestamp is an empty string, specify the flag but do + // not specify a value - this uses a default Apple-provided server + var flag = "--timestamp"; + if (signingTimestamp) + flag += "=" + signingTimestamp; + args.push(flag); + } + + args = args.concat(product.codesign.codesignFlags || []); + + args.push(output.filePath); + console.warn(args); + var cmdSign = new Command(product.codesign.codesignPath, args); + cmdSign.description = "codesign " + output.fileName + + " (" + actualSigningIdentity.subjectInfo.CN + ")"; + cmdSign.outputFilePath = output.filePath; + cmdSign.stderrFilterFunction = function(stderr) { + return stderr.replace(outputFilePath + ": replacing existing signature\n", ""); + }; + cmds.push(cmdSign); + + return cmds; + } + + Artifact { + filePath: FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix, + product.buildconfig.installAppPath, + product.targetName + ".app", "Contents", "MacOS", "pdftops") + fileTags: ["pdftops.bundled"] + } + } +} + diff --git a/src/app/puzzle/puzzle.qbs b/src/app/puzzle/puzzle.qbs index eaf2d715e..be4f6f083 100644 --- a/src/app/puzzle/puzzle.qbs +++ b/src/app/puzzle/puzzle.qbs @@ -14,6 +14,7 @@ VToolApp { Depends { name: "FervorLib" } Depends { name: "multibundle"; } Depends { name: "VGAnalyticsLib" } + Depends { name: "pdftops"; condition: qbs.targetOS.contains("macos") } // Explicitly link to libcrypto and libssl to avoid error: Failed to load libssl/libcrypto. // Use moduleProviders.qbspkgconfig.extraPaths to define the missing dependency. @@ -201,14 +202,23 @@ VToolApp { qbs.installDir: buildconfig.installBinaryPath } + Properties { + condition: qbs.targetOS.contains("macos") && buildconfig.enableMultiBundle + macdeployqt.targetApps: { + var apps = []; + + if (pdftops.pdftopsPresent) + apps.push("pdftops"); + + return apps; + } + } + Group { - condition: qbs.targetOS.contains("macos") && qbs.architecture.contains("x86_64") && buildconfig.enableMultiBundle + condition: qbs.targetOS.contains("macos") && buildconfig.enableMultiBundle && pdftops.pdftopsPresent name: "pdftops MacOS" - prefix: project.sourceDirectory + "/dist/macx/bin64/" - files: ["pdftops"] - fileTags: ["pdftops_dist_macx"] - qbs.install: true - qbs.installDir: buildconfig.installBinaryPath + files: [pdftops.pdftopsPath] + fileTags: ["pdftops.in"] } Group { diff --git a/src/app/valentina/valentina.qbs b/src/app/valentina/valentina.qbs index a06bcdc5d..556225ebf 100644 --- a/src/app/valentina/valentina.qbs +++ b/src/app/valentina/valentina.qbs @@ -15,6 +15,7 @@ VToolApp { Depends { name: "VFormatLib"; } Depends { name: "VMiscLib"; } Depends { name: "VGAnalyticsLib" } + Depends { name: "pdftops"; condition: qbs.targetOS.contains("macos") } Depends { name: "Tape"; condition: qbs.targetOS.contains("macos") && buildconfig.enableMultiBundle } Depends { name: "Puzzle"; condition: qbs.targetOS.contains("macos") && buildconfig.enableMultiBundle } @@ -44,7 +45,6 @@ VToolApp { } primaryApp: true - name: "Valentina" buildconfig.appTarget: qbs.targetOS.contains("macos") ? "Valentina" : "valentina" targetName: buildconfig.appTarget @@ -258,6 +258,20 @@ VToolApp { } } + Properties { + condition: qbs.targetOS.contains("macos") + macdeployqt.targetApps: { + var apps = []; + if (!buildconfig.enableMultiBundle) + apps.push("Tape", "Puzzle"); + + if (pdftops.pdftopsPresent) + apps.push("pdftops"); + + return apps; + } + } + Group { condition: qbs.targetOS.contains("windows") && (qbs.architecture.contains("x86_64") || qbs.architecture.contains("x86")) name: "pdftops Windows" @@ -268,12 +282,10 @@ VToolApp { } Group { - condition: qbs.targetOS.contains("macos") && qbs.architecture.contains("x86_64") name: "pdftops MacOS" - prefix: project.sourceDirectory + "/dist/macx/bin64/" - files: ["pdftops"] - qbs.install: true - qbs.installDir: buildconfig.installBinaryPath + condition: qbs.targetOS.contains("macos") && pdftops.pdftopsPresent + files: [pdftops.pdftopsPath] + fileTags: ["pdftops.in"] } Group { diff --git a/src/libs/vlayout/vlayoutexporter.cpp b/src/libs/vlayout/vlayoutexporter.cpp index 5f6e57082..01a63eac2 100644 --- a/src/libs/vlayout/vlayoutexporter.cpp +++ b/src/libs/vlayout/vlayoutexporter.cpp @@ -404,22 +404,34 @@ void VLayoutExporter::ExportToHPGL2(const QVector &details) const //--------------------------------------------------------------------------------------------------------------------- auto VLayoutExporter::SupportPDFConversion() -> bool { - QProcess proc; -#if defined(Q_OS_WIN) || defined(Q_OS_OSX) - // Seek pdftops in app bundle or near valentina.exe - proc.start(qApp->applicationDirPath() + QLatin1String("/") + *PDFTOPS, QStringList()); -#else - proc.start(*PDFTOPS, QStringList()); // Seek pdftops in standard path -#endif - - const int timeout = 15000; - if (proc.waitForStarted(timeout) && (proc.waitForFinished(timeout) || proc.state() == QProcess::NotRunning)) + auto Test = [](const QString &program) { - return true; - } + QProcess proc; + proc.start(program); - qDebug() << *PDFTOPS << "error" << proc.error() << proc.errorString(); - return false; + const int timeout = 15000; + if (proc.waitForStarted(timeout) && (proc.waitForFinished(timeout) || proc.state() == QProcess::NotRunning)) + { + return true; + } + + qDebug() << program << "error" << proc.error() << proc.errorString(); + return false; + }; + +#if defined(Q_OS_OSX) + // Seek pdftops in app bundle + bool found = Test(qApp->applicationDirPath() + QLatin1String("/") + *PDFTOPS); + if (not found) + { + found = Test(*PDFTOPS); + } + return found; +#elif defined(Q_OS_WIN) + return Test(qApp->applicationDirPath() + QLatin1String("/") + *PDFTOPS); +#else + return Test(*PDFTOPS); +#endif } //--------------------------------------------------------------------------------------------------------------------- @@ -436,9 +448,14 @@ void VLayoutExporter::PdfToPs(const QStringList ¶ms) QProcess proc; #if defined(Q_OS_MAC) - // Fix issue #594. Broken export on Mac. - proc.setWorkingDirectory(qApp->applicationDirPath()); - proc.start(QLatin1String("./") + *PDFTOPS, params); + if (QFileInfo::exists(qApp->applicationDirPath() + QLatin1String("/") + *PDFTOPS)) + { + proc.start(QLatin1String(qApp->applicationDirPath() + QLatin1String("/") + *PDFTOPS, params); + } + else + { + proc.start(*PDFTOPS, params); + } #else proc.start(*PDFTOPS, params); #endif