aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2021-11-05 16:13:03 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2022-02-04 11:29:03 +0000
commitcb3d7e862c69c59e3b0111e19ace157be07acb88 (patch)
tree216be539d04d3819fefb6f21e7d46c334570ac84 /src
parent38757a783a5a89f35a12184e77550017ee52d32e (diff)
Long live Open Watcom toolchain
This patch adds basic support for the Open Watcom toolchain. This patch uses the `owcc` compiler (supplied with the toolchain), which is a wrapper that supports the POSIX standard. Reason is that the native OW compiler and linker has a limitations in the command line arguments (e.g. they have wrong quotes handling and so on). This patch supports both the latest official version v1.9 and also its fork v2.0. Also added the CI autotests for the version v2.0 for the Windows host. These autotests only perform a limited number of tests (only the bare-metal tests) due to the following toolchain limitations: * The toolchain does not have STL support (there seems to be some kind of the partial support in the form of separate legacy STL ports). * The toolchain support something compatible with the C++98 standard. * The toolchain does not support the shared libraries on Linux hosts. These limitations make it impossible or unjustified to reuse most of the available tests (it requires a lot of work). There was also an attempt to set up CI for tests on Linux host, but for some reason the toolchain installer crashes on CI (although it works fine on a local PC with Ubuntu). Change-Id: Iecf76f51f0b09d31a89683f786b9cd7a825f235e Reviewed-by: Ivan Komissarov <ABBAPOH@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/app/qbs-setup-toolchains/CMakeLists.txt2
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp6
-rw-r--r--src/app/qbs-setup-toolchains/probe.h2
-rw-r--r--src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro2
-rw-r--r--src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs2
-rw-r--r--src/app/qbs-setup-toolchains/watcomprobe.cpp200
-rw-r--r--src/app/qbs-setup-toolchains/watcomprobe.h58
7 files changed, 270 insertions, 2 deletions
diff --git a/src/app/qbs-setup-toolchains/CMakeLists.txt b/src/app/qbs-setup-toolchains/CMakeLists.txt
index bb287be52..64347cd6c 100644
--- a/src/app/qbs-setup-toolchains/CMakeLists.txt
+++ b/src/app/qbs-setup-toolchains/CMakeLists.txt
@@ -20,6 +20,8 @@ set(SOURCES
probe.h
sdccprobe.cpp
sdccprobe.h
+ watcomprobe.cpp
+ watcomprobe.h
xcodeprobe.cpp
xcodeprobe.h
)
diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp
index 5a04232e1..ceb95948b 100644
--- a/src/app/qbs-setup-toolchains/probe.cpp
+++ b/src/app/qbs-setup-toolchains/probe.cpp
@@ -46,6 +46,7 @@
#include "keilprobe.h"
#include "msvcprobe.h"
#include "sdccprobe.h"
+#include "watcomprobe.h"
#include "xcodeprobe.h"
#include <logging/translator.h>
@@ -123,6 +124,8 @@ QString toolchainTypeFromCompilerName(const QString &compilerName)
return QStringLiteral("cosmic");
if (isDmcCompiler(compilerName))
return QStringLiteral("dmc");
+ if (isWatcomCompiler(compilerName))
+ return QStringLiteral("watcom");
return {};
}
@@ -144,6 +147,7 @@ void probe(Settings *settings)
sdccProbe(settings, profiles);
cosmicProbe(settings, profiles);
dmcProbe(settings, profiles);
+ watcomProbe(settings, profiles);
if (profiles.empty()) {
qStderr << Tr::tr("Could not detect any toolchains. No profile created.") << Qt::endl;
@@ -187,6 +191,8 @@ void createProfile(const QString &profileName, const QString &toolchainType,
createCosmicProfile(compiler, settings, profileName);
else if (toolchain.contains(QLatin1String("dmc")))
createDmcProfile(compiler, settings, profileName);
+ else if (toolchain.contains(QLatin1String("watcom")))
+ createWatcomProfile(compiler, settings, profileName);
else
throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type."));
}
diff --git a/src/app/qbs-setup-toolchains/probe.h b/src/app/qbs-setup-toolchains/probe.h
index e97530285..827171fb2 100644
--- a/src/app/qbs-setup-toolchains/probe.h
+++ b/src/app/qbs-setup-toolchains/probe.h
@@ -80,8 +80,6 @@ int extractVersion(const QByteArray &macroDump, const QByteArray &keyToken);
bool isSameExecutable(const QString &exe1, const QString &exe2);
using MacrosMap = QMap<QString, QString>;
-using DefinesList = QVector<QByteArray>;
-
MacrosMap dumpMacros(const std::function<QStringList()> &func);
#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro
index 1ae1c710d..69d6552ee 100644
--- a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro
+++ b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro
@@ -13,6 +13,7 @@ HEADERS += \
msvcprobe.h \
probe.h \
sdccprobe.h \
+ watcomprobe.h \
xcodeprobe.h \
SOURCES += \
@@ -27,6 +28,7 @@ SOURCES += \
msvcprobe.cpp \
probe.cpp \
sdccprobe.cpp \
+ watcomprobe.cpp \
xcodeprobe.cpp \
mingw {
diff --git a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs
index 2daf916e9..6987f3717 100644
--- a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs
+++ b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs
@@ -23,6 +23,8 @@ QbsApp {
"probe.h",
"sdccprobe.cpp",
"sdccprobe.h",
+ "watcomprobe.cpp",
+ "watcomprobe.h",
"xcodeprobe.cpp",
"xcodeprobe.h",
]
diff --git a/src/app/qbs-setup-toolchains/watcomprobe.cpp b/src/app/qbs-setup-toolchains/watcomprobe.cpp
new file mode 100644
index 000000000..9765f7424
--- /dev/null
+++ b/src/app/qbs-setup-toolchains/watcomprobe.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "watcomprobe.h"
+#include "probe.h"
+
+#include "../shared/logging/consolelogger.h"
+
+#include <logging/translator.h>
+
+#include <tools/hostosinfo.h>
+#include <tools/profile.h>
+
+#include <QtCore/qdir.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qregularexpression.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qtemporaryfile.h>
+
+using namespace qbs;
+using Internal::HostOsInfo;
+using Internal::Tr;
+
+static QStringList knownWatcomCompilerNames()
+{
+ return {QStringLiteral("owcc")};
+}
+
+static QStringList dumpOutput(const QFileInfo &compiler, const QStringList &keys)
+{
+ const QString filePath = QDir(QDir::tempPath()).absoluteFilePath(
+ QLatin1String("watcom-dump.c"));
+ QFile fakeIn(filePath);
+ if (!fakeIn.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text)) {
+ qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2")
+ .arg(fakeIn.fileName(), fakeIn.errorString());
+ return QStringList{};
+ }
+ fakeIn.write("#define VALUE_TO_STRING(x) #x\n");
+ fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n");
+ fakeIn.write("#define VAR_NAME_VALUE(var) \"#define \" #var\" \"VALUE(var)\n");
+ for (const QString &key : keys) {
+ fakeIn.write("#if defined(" + key.toLatin1() + ")\n");
+ fakeIn.write("#pragma message (VAR_NAME_VALUE(" + key.toLatin1() + "))\n");
+ fakeIn.write("#endif\n");
+ }
+ fakeIn.close();
+ QProcess p;
+ p.start(compiler.absoluteFilePath(), {QDir::toNativeSeparators(filePath)});
+ p.waitForFinished(3000);
+ fakeIn.remove();
+ const QStringList lines = QString::fromUtf8(p.readAllStandardOutput())
+ .split(QRegularExpression(QLatin1String("\\r?\\n")));
+ return lines;
+}
+
+static QString guessWatcomArchitecture(const QFileInfo &compiler)
+{
+ const QStringList keys = {QStringLiteral("__I86__"), QStringLiteral("__386__")};
+ const auto macros = dumpMacros([&compiler, &keys]() { return dumpOutput(compiler, keys); });
+ for (auto index = 0; index < keys.count(); ++index) {
+ const auto &key = keys.at(index);
+ if (macros.contains(key) && macros.value(key) == QLatin1String("1")) {
+ switch (index) {
+ case 0:
+ return QLatin1String("x86_16");
+ case 1:
+ return QLatin1String("x86");
+ default:
+ break;
+ }
+ }
+ }
+ return QLatin1String("unknown");
+}
+
+static Profile createWatcomProfileHelper(const ToolchainInstallInfo &info,
+ Settings *settings,
+ QString profileName = QString())
+{
+ const QFileInfo compiler = info.compilerPath;
+ const QString architecture = guessWatcomArchitecture(compiler);
+
+ // In case the profile is auto-detected.
+ if (profileName.isEmpty()) {
+ if (!info.compilerVersion.isValid()) {
+ profileName = QStringLiteral("watcom-unknown-%1").arg(architecture);
+ } else {
+ const QString version = info.compilerVersion.toString(QLatin1Char('_'),
+ QLatin1Char('_'));
+ profileName = QStringLiteral("watcom-%1-%2").arg(version, architecture);
+ }
+ }
+
+ Profile profile(profileName, settings);
+ profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath());
+ profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("watcom"));
+ if (!architecture.isEmpty())
+ profile.setValue(QStringLiteral("qbs.architecture"), architecture);
+
+ qbsInfo() << Tr::tr("Profile '%1' created for '%2'.")
+ .arg(profile.name(), compiler.absoluteFilePath());
+ return profile;
+}
+
+static Version dumpWatcomVersion(const QFileInfo &compiler)
+{
+ const QStringList keys = {QStringLiteral("__WATCOMC__"),
+ QStringLiteral("__WATCOM_CPLUSPLUS__")};
+ const auto macros = dumpMacros([&compiler, &keys]() { return dumpOutput(compiler, keys); });
+ for (const auto &macro : macros) {
+ const int verCode = macro.toInt();
+ return Version{(verCode - 1100) / 100,
+ (verCode / 10) % 10,
+ ((verCode % 10) > 0) ? (verCode % 10) : 0};
+ }
+ qbsWarning() << Tr::tr("No __WATCOMC__ or __WATCOM_CPLUSPLUS__ tokens was found"
+ " in the compiler dump");
+ return Version{};
+}
+
+static std::vector<ToolchainInstallInfo> installedWatcomsFromPath()
+{
+ std::vector<ToolchainInstallInfo> infos;
+ const auto compilerNames = knownWatcomCompilerNames();
+ for (const QString &compilerName : compilerNames) {
+ const QFileInfo watcomPath(findExecutable(
+ HostOsInfo::appendExecutableSuffix(compilerName)));
+ if (!watcomPath.exists())
+ continue;
+ const Version version = dumpWatcomVersion(watcomPath);
+ infos.push_back({watcomPath, version});
+ }
+ std::sort(infos.begin(), infos.end());
+ return infos;
+}
+
+bool isWatcomCompiler(const QString &compilerName)
+{
+ return Internal::any_of(knownWatcomCompilerNames(), [compilerName](const QString &knownName) {
+ return compilerName.contains(knownName);
+ });
+}
+
+void createWatcomProfile(const QFileInfo &compiler, Settings *settings, QString profileName)
+{
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createWatcomProfileHelper(info, settings, std::move(profileName));
+}
+
+void watcomProbe(Settings *settings, std::vector<Profile> &profiles)
+{
+ qbsInfo() << Tr::tr("Trying to detect WATCOM toolchains...");
+
+ const std::vector<ToolchainInstallInfo> allInfos = installedWatcomsFromPath();
+ if (allInfos.empty()) {
+ qbsInfo() << Tr::tr("No WATCOM toolchains found.");
+ return;
+ }
+
+ qbs::Internal::transform(allInfos, profiles, [settings](const auto &info) {
+ return createWatcomProfileHelper(info, settings); });
+}
diff --git a/src/app/qbs-setup-toolchains/watcomprobe.h b/src/app/qbs-setup-toolchains/watcomprobe.h
new file mode 100644
index 000000000..26e75bbc3
--- /dev/null
+++ b/src/app/qbs-setup-toolchains/watcomprobe.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBS_SETUPTOOLCHAINS_WATCOMPROBE_H
+#define QBS_SETUPTOOLCHAINS_WATCOMPROBE_H
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+class QFileInfo;
+QT_END_NAMESPACE
+
+namespace qbs {
+class Profile;
+class Settings;
+} // namespace qbs
+
+bool isWatcomCompiler(const QString &compilerName);
+void createWatcomProfile(const QFileInfo &compiler, qbs::Settings *settings, QString profileName);
+void watcomProbe(qbs::Settings *settings, std::vector<qbs::Profile> &profiles);
+
+#endif // Header guard