1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "runqttool.h"
5#include "fmt.h"
6
7#include "profileutils.h"
8
9#include <QtCore/qcoreapplication.h>
10#include <QtCore/qdir.h>
11#include <QtCore/qregularexpression.h>
12
13#include <cstdlib>
14#include <iostream>
15
16#ifdef Q_OS_UNIX
17#include <sys/wait.h>
18#endif
19
20static QString qtToolFilePath(const QString &toolName, QLibraryInfo::LibraryPath location)
21{
22 QString filePath = QLibraryInfo::path(p: location) + u'/' + toolName;
23#ifdef Q_OS_WIN
24 filePath.append(".exe"_L1);
25#endif
26 return QDir::cleanPath(path: filePath);
27}
28
29static void rtPrintErr(const QString &out)
30{
31 std::cerr << qUtf8Printable(out);
32}
33
34static QString shellQuoted(const QString &str)
35{
36 static QRegularExpression rx(QStringLiteral("\\s"));
37 QString result = str;
38 if (result.contains(re: rx)) {
39 const QLatin1Char dblqt('"');
40 result.prepend(c: dblqt);
41 result.append(c: dblqt);
42 }
43 return result;
44}
45
46static QStringList shellQuoted(const QStringList &strs)
47{
48 QStringList result;
49 result.reserve(asize: strs.size());
50 std::transform(first: strs.begin(), last: strs.end(), result: std::back_inserter(x&: result),
51 unary_op: static_cast<QString (*)(const QString &)>(&shellQuoted));
52 return result;
53}
54
55static QString commandLineForSystem(const QString &program,
56 const QStringList &arguments)
57{
58 return shellQuoted(str: program) + u' ' + shellQuoted(strs: arguments).join(sep: u' ');
59}
60
61static int runQtToolHelper(const QString &toolName, const QStringList &arguments,
62 QLibraryInfo::LibraryPath location)
63{
64 int exitCode = 0;
65 const QString commandLine = commandLineForSystem(program: qtToolFilePath(toolName, location), arguments);
66#if defined(Q_OS_WIN)
67 exitCode = _wsystem(reinterpret_cast<const wchar_t *>(commandLine.utf16()));
68#elif defined(Q_OS_UNIX)
69 int ret = std::system(qPrintable(commandLine));
70 exitCode = WEXITSTATUS(ret);
71#else
72 exitCode = std::system(qPrintable(commandLine));
73#endif
74 return exitCode;
75}
76
77void runQtTool(const QString &toolName, const QStringList &arguments,
78 QLibraryInfo::LibraryPath location)
79{
80 const int exitCode = runQtToolHelper(toolName, arguments, location);
81 if (exitCode != 0)
82 exit(status: exitCode);
83}
84
85static int runInternalQtToolHelper(const QString &toolName, const QStringList &arguments)
86{
87 return runQtToolHelper(toolName, arguments, location: QLibraryInfo::LibraryExecutablesPath);
88}
89
90void runInternalQtTool(const QString &toolName, const QStringList &arguments)
91{
92 const int exitCode = runInternalQtToolHelper(toolName, arguments);
93 if (exitCode != 0)
94 exit(status: exitCode);
95}
96
97std::unique_ptr<QTemporaryFile> createProjectDescription(QStringList args)
98{
99 std::unique_ptr<QTemporaryFile> file(new QTemporaryFile(QStringLiteral("XXXXXX.json")));
100 if (!file->open()) {
101 rtPrintErr(out: FMT::tr(sourceText: "Cannot create temporary file: %1\n").arg(a: file->errorString()));
102 exit(status: 1);
103 }
104 file->close();
105 args << QStringLiteral("-out") << file->fileName();
106 const int exitCode = runInternalQtToolHelper(QStringLiteral("lprodump"), arguments: args);
107 if (exitCode != 0) {
108 file.reset();
109 exit(status: exitCode);
110 }
111 return file;
112}
113

source code of qttools/src/linguist/shared/runqttool.cpp