Add compiler hint interface for packager (#175)
* add compiler hint addon interface * add architecture info in about dialog * detect user install * add qmake variable to control OpenConsole.exe preference * enable asan/hwasan option on all platforms for cross toolchain * fix lldb-server * force to lldb-server when using lldb-mi * add qt.conf for windows * add windows domain installer with compiler hint * add compiler hint for arch linux * fix mainwindow actionInterrupt visibility * update news * update arch linux packaging * update windows domain packaging * allow parallel packaging in windows domain installer * fix compiler set persistence in compiler hint interface
This commit is contained in:
parent
4c58ebf0ba
commit
e2e5c46820
|
@ -1,5 +1,6 @@
|
|||
/.vs
|
||||
/.vscode
|
||||
/assets
|
||||
/dist
|
||||
/packages/appimage/*/*.AppImage
|
||||
*.bak
|
||||
|
|
6
BUILD.md
6
BUILD.md
|
@ -78,6 +78,12 @@ For Windows 7 or later:
|
|||
| Qt.io + MSVC | ✔️ | ✔️ | ❌ |
|
||||
| vcpkg + MSVC | ✔️ | ✔️ | ❌ |
|
||||
|
||||
qmake variables:
|
||||
- `PREFIX`: where `$MAKE install` installs files to.
|
||||
- `WINDOWS_PREFER_OPENCONSOLE=ON` (make phase): prefer UTF-8 compatible `OpenConsole.exe`.
|
||||
- `OpenConsole.exe` is a part of Windows Terminal. UTF-8 input support was added in version 1.18.
|
||||
- `OpenConsole.exe` requires ConPTY, which was introduced in Windows 10 1809.
|
||||
|
||||
Notes for Windows on ARM:
|
||||
- Red Panda C++ can be built for ARM64 ABI only on Windows 11 ARM64, while it is supposed (but not tested) to run on Windows 10 ARM64.
|
||||
- ARM64EC (“emulation compatible”) host is not supported, i.e., Red Panda C++ cannot be built with ARM64EC toolchain.
|
||||
|
|
|
@ -78,6 +78,12 @@
|
|||
| Qt.io + MSVC | ✔️ | ✔️ | ❌ |
|
||||
| vcpkg + MSVC | ✔️ | ✔️ | ❌ |
|
||||
|
||||
qmake 变量:
|
||||
- `PREFIX`:`$MAKE install` 的安装路径。
|
||||
- `WINDOWS_PREFER_OPENCONSOLE=ON`(make 阶段):首选兼容 UTF-8 的 `OpenConsole.exe`。
|
||||
- `OpenConsole.exe` 是 Windows 终端的组件,在 1.18 版本加入了 UTF-8 输出支持。
|
||||
- `OpenConsole.exe` 需要 Windows 10 1809 加入的 ConPTY 接口。
|
||||
|
||||
关于 ARM 上的 Windows 的注记:
|
||||
- 小熊猫 C++ 只能在 Windows 11 ARM64 上构建 ARM64 版,成品应该能在 Windows 10 ARM64 上运行(但没有测试过)。
|
||||
- 不支持 ARM64EC(“仿真兼容”)主机,即不能用 ARM64EC 工具链构建小熊猫 C++。
|
||||
|
|
6
NEWS.md
6
NEWS.md
|
@ -36,6 +36,12 @@ Red Panda C++ Version 2.26
|
|||
- Enhancement: Better type induction for auto in foreach loop of maps.
|
||||
- Enhancement: Better contrast for scroller slider in dark theme.
|
||||
- Enhancement: Using lua script in themes.
|
||||
- Enhancement: Add compiler hint add-on interface for packager.
|
||||
- Enhancement: Loose some limit about platform/architecture (such as ASan).
|
||||
- Enhancement: add support for Windows user-wide installation.
|
||||
- Enhancement: add qmake variable to control preference of UTF-8 compatible OpenConsole.exe on Windows.
|
||||
- Enhancement: add Windows arm64 package.
|
||||
- Fix: Force to use debug server when debugging with lldb-mi to fix input/output on Windows.
|
||||
|
||||
Red Panda C++ Version 2.25
|
||||
|
||||
|
|
|
@ -59,6 +59,13 @@ isEmpty(TEST_VERSION) {
|
|||
} else {
|
||||
DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}-$${TEST_VERSION}\\\"
|
||||
}
|
||||
win32 {
|
||||
_WINDOWS_PREFER_OPENCONSOLE = $$(WINDOWS_PREFER_OPENCONSOLE)
|
||||
equals(_WINDOWS_PREFER_OPENCONSOLE, "ON") {
|
||||
DEFINES += WINDOWS_PREFER_OPENCONSOLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gcc {
|
||||
QMAKE_CXXFLAGS_RELEASE += -Werror=return-type
|
||||
|
|
|
@ -20,13 +20,37 @@
|
|||
#include <QApplication>
|
||||
#include <QPalette>
|
||||
#include <QStyleFactory>
|
||||
#include <QJsonValue>
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <lua/lua.hpp>
|
||||
|
||||
#include "utils.h"
|
||||
#include "settings.h"
|
||||
#include "thememanager.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// added in Windows 11 21H2, declare our version to support old SDKs.
|
||||
constexpr int win32_flag_UserEnabled = 0x00000001;
|
||||
|
||||
// added in Windows 11 21H2, use GetProcAddress to detect availability.
|
||||
using pGetMachineTypeAttributes_t = HRESULT (WINAPI *)(
|
||||
USHORT Machine, int *MachineTypeAttributes
|
||||
);
|
||||
|
||||
// added in Windows 10 1709, use GetProcAddress to detect availability.
|
||||
using pIsWow64GuestMachineSupported_t = HRESULT (WINAPI *)(
|
||||
USHORT WowGuestMachine, BOOL *MachineIsSupported
|
||||
);
|
||||
using pIsWow64Process2_t = BOOL (WINAPI *)(
|
||||
HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine
|
||||
);
|
||||
#endif
|
||||
|
||||
// C_Debug.debug(string) -> ()
|
||||
extern "C" int luaApi_Debug_debug(lua_State *L) noexcept {
|
||||
QString info = AddOn::RaiiLuaState::fetchString(L, 1);
|
||||
|
@ -78,3 +102,204 @@ extern "C" int luaApi_Desktop_systemStyle(lua_State *L) noexcept {
|
|||
AddOn::RaiiLuaState::push(L, AppTheme::initialStyle());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_FileSystem.exists(string) -> bool
|
||||
extern "C" int luaApi_FileSystem_exists(lua_State *L) noexcept {
|
||||
QString path = AddOn::RaiiLuaState::fetchString(L, 1);
|
||||
QFileInfo fileInfo(path);
|
||||
AddOn::RaiiLuaState::push(L, fileInfo.exists());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_FileSystem.isExecutable(string) -> bool
|
||||
extern "C" int luaApi_FileSystem_isExecutable(lua_State *L) noexcept {
|
||||
QString path = AddOn::RaiiLuaState::fetchString(L, 1);
|
||||
QFileInfo fileInfo(path);
|
||||
bool isExecutable = fileInfo.isFile() && fileInfo.isReadable() && fileInfo.isExecutable();
|
||||
AddOn::RaiiLuaState::push(L, isExecutable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_System.appArch() -> string
|
||||
extern "C" int luaApi_System_appArch(lua_State *L) noexcept {
|
||||
AddOn::RaiiLuaState::push(L, appArch());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_System.appDir() -> string
|
||||
extern "C" int luaApi_System_appDir(lua_State *L) noexcept {
|
||||
QString appDir = pSettings->dirs().appDir();
|
||||
AddOn::RaiiLuaState::push(L, appDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_System.appLibexecDir() -> string
|
||||
extern "C" int luaApi_System_appLibexecDir(lua_State *L) noexcept {
|
||||
QString appLibexecDir = pSettings->dirs().appLibexecDir();
|
||||
AddOn::RaiiLuaState::push(L, appLibexecDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_System.appResourceDir() -> string
|
||||
extern "C" int luaApi_System_appResourceDir(lua_State *L) noexcept {
|
||||
QString appResourceDir = pSettings->dirs().appResourceDir();
|
||||
AddOn::RaiiLuaState::push(L, appResourceDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C_System.osArch() -> string
|
||||
extern "C" int luaApi_System_osArch(lua_State *L) noexcept {
|
||||
AddOn::RaiiLuaState::push(L, osArch());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static QString qtArchitectureNormalization(const QString &arch) {
|
||||
// adjust QEMU user emulation arches to match QSysInfo::currentCpuArchitecture
|
||||
if (arch == "aarch64")
|
||||
return "arm64";
|
||||
if (arch.startsWith("ppc"))
|
||||
return "power" + arch.mid(3);
|
||||
if (arch == "sparc64")
|
||||
return "sparcv9";
|
||||
return arch;
|
||||
}
|
||||
|
||||
// C_System.supportedAppArchList() -> [string]
|
||||
extern "C" int luaApi_System_supportedAppArchList(lua_State *L) noexcept {
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QSet<QString> arches;
|
||||
pGetMachineTypeAttributes_t pGetMachineTypeAttributes =
|
||||
reinterpret_cast<pGetMachineTypeAttributes_t>(GetProcAddress(
|
||||
GetModuleHandleW(L"kernel32"), "GetMachineTypeAttributes"));
|
||||
if (pGetMachineTypeAttributes) {
|
||||
// the direct way
|
||||
int result;
|
||||
if (pGetMachineTypeAttributes(IMAGE_FILE_MACHINE_I386, &result) == 0 && result & win32_flag_UserEnabled)
|
||||
arches.insert("i386");
|
||||
if (pGetMachineTypeAttributes(IMAGE_FILE_MACHINE_AMD64, &result) == 0 && result & win32_flag_UserEnabled)
|
||||
arches.insert("x86_64");
|
||||
if (pGetMachineTypeAttributes(IMAGE_FILE_MACHINE_ARMNT, &result) == 0 && result & win32_flag_UserEnabled)
|
||||
arches.insert("arm");
|
||||
if (pGetMachineTypeAttributes(IMAGE_FILE_MACHINE_ARM64, &result) == 0 && result & win32_flag_UserEnabled)
|
||||
arches.insert("arm64");
|
||||
} else {
|
||||
pIsWow64GuestMachineSupported_t pIsWow64GuestMachineSupported =
|
||||
reinterpret_cast<pIsWow64GuestMachineSupported_t>(GetProcAddress(
|
||||
GetModuleHandleW(L"kernel32"), "IsWow64GuestMachineSupported"));
|
||||
pIsWow64Process2_t pIsWow64Process2 =
|
||||
reinterpret_cast<pIsWow64Process2_t>(GetProcAddress(
|
||||
GetModuleHandleW(L"kernel32"), "IsWow64Process2"));
|
||||
if (pIsWow64GuestMachineSupported && pIsWow64Process2) {
|
||||
// recent Windows 10, native + WoW64 arches
|
||||
// IsWow64Process2 returns real native architecture under xtajit, while GetNativeSystemInfo does not.
|
||||
USHORT processMachineResult, nativeMachineResult;
|
||||
if (pIsWow64Process2(GetCurrentProcess(), &processMachineResult, &nativeMachineResult))
|
||||
switch (nativeMachineResult) {
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
arches.insert("i386");
|
||||
break;
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
arches.insert("x86_64");
|
||||
break;
|
||||
case IMAGE_FILE_MACHINE_ARM64:
|
||||
arches.insert("arm64");
|
||||
break;
|
||||
}
|
||||
BOOL wow64SupportResult;
|
||||
if (pIsWow64GuestMachineSupported(IMAGE_FILE_MACHINE_I386, &wow64SupportResult) == S_OK && wow64SupportResult)
|
||||
arches.insert("i386");
|
||||
if (pIsWow64GuestMachineSupported(IMAGE_FILE_MACHINE_ARMNT, &wow64SupportResult) == S_OK && wow64SupportResult)
|
||||
arches.insert("arm");
|
||||
} else {
|
||||
// legacy Windows, hardcode
|
||||
SYSTEM_INFO si;
|
||||
GetNativeSystemInfo(&si);
|
||||
switch (si.wProcessorArchitecture) {
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
arches.insert("i386");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
arches.insert("i386");
|
||||
arches.insert("x86_64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: // undocumented but found in Qt source
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
// does Red Panda C++ run on IA-64?
|
||||
arches.insert("i386");
|
||||
arches.insert("ia64");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
QStringList result{arches.begin(), arches.end()};
|
||||
AddOn::RaiiLuaState::push(L, result);
|
||||
return 1;
|
||||
#elif defined(Q_OS_MACOS)
|
||||
QStringList result;
|
||||
if (QSysInfo::currentCpuArchitecture() == "arm64")
|
||||
result = QStringList{"arm64", "x86_64"};
|
||||
else if (QVersionNumber::fromString(QSysInfo::kernelVersion()) >= QVersionNumber(19, 0))
|
||||
// macOS 10.15+
|
||||
result = QStringList{"x86_64"};
|
||||
else
|
||||
result = QStringList{"i386", "x86_64"};
|
||||
AddOn::RaiiLuaState::push(L, result);
|
||||
return 1;
|
||||
#else
|
||||
QSet<QString> arches;
|
||||
arches.insert(QSysInfo::currentCpuArchitecture());
|
||||
arches.insert(QSysInfo::buildCpuArchitecture());
|
||||
|
||||
// read binfmt_misc registry
|
||||
QDir binfmt_misc("/proc/sys/fs/binfmt_misc");
|
||||
if (binfmt_misc.exists()) {
|
||||
QFileInfoList entries = binfmt_misc.entryInfoList(QDir::Files);
|
||||
for (const QFileInfo &entry : entries) {
|
||||
if (entry.fileName().startsWith("qemu-")) {
|
||||
QString arch = entry.fileName().mid(5);
|
||||
arches.insert(qtArchitectureNormalization(arch));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// workaround for Debian 10 Qt 5.11, better to be
|
||||
// QStringList result{arches.begin(), arches.end()};
|
||||
QStringList result = arches.toList();
|
||||
AddOn::RaiiLuaState::push(L, result);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// C_System.readRegistry(string, string) -> string|nil
|
||||
extern "C" int luaApi_System_readRegistry(lua_State *L) noexcept
|
||||
{
|
||||
QString subKey = AddOn::RaiiLuaState::fetchString(L, 1);
|
||||
QString name = AddOn::RaiiLuaState::fetchString(L, 2);
|
||||
QString value;
|
||||
bool success = readRegistry(HKEY_CURRENT_USER, subKey, name, value);
|
||||
if (success)
|
||||
AddOn::RaiiLuaState::push(L, value);
|
||||
else {
|
||||
success = readRegistry(HKEY_LOCAL_MACHINE, subKey, name, value);
|
||||
if (success)
|
||||
AddOn::RaiiLuaState::push(L, value);
|
||||
else
|
||||
AddOn::RaiiLuaState::push(L, nullptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// C_Util.format(string, ...) -> string
|
||||
extern "C" int luaApi_Util_format(lua_State *L) noexcept
|
||||
{
|
||||
QString s = AddOn::RaiiLuaState::fetchString(L, 1);
|
||||
int nArgs = lua_gettop(L);
|
||||
for (int i = 2; i <= nArgs; ++i) {
|
||||
QJsonValue arg = AddOn::RaiiLuaState::fetch(L, i);
|
||||
s = s.arg(arg.toString());
|
||||
}
|
||||
AddOn::RaiiLuaState::push(L, s);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -27,4 +27,19 @@ extern "C" int luaApi_Desktop_qtStyleList(lua_State *L) noexcept;
|
|||
extern "C" int luaApi_Desktop_systemAppMode(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_Desktop_systemStyle(lua_State *L) noexcept;
|
||||
|
||||
extern "C" int luaApi_FileSystem_exists(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_FileSystem_isExecutable(lua_State *L) noexcept;
|
||||
|
||||
extern "C" int luaApi_System_appArch(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_System_appDir(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_System_appLibexecDir(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_System_appResourceDir(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_System_osArch(lua_State *L) noexcept;
|
||||
extern "C" int luaApi_System_supportedAppArchList(lua_State *L) noexcept;
|
||||
#ifdef Q_OS_WINDOWS
|
||||
extern "C" int luaApi_System_readRegistry(lua_State *L) noexcept;
|
||||
#endif
|
||||
|
||||
extern "C" int luaApi_Util_format(lua_State *L) noexcept;
|
||||
|
||||
#endif // ADDON_API_H
|
||||
|
|
|
@ -37,7 +37,29 @@ static QMap<QString, QMap<QString, lua_CFunction>> apiGroups{
|
|||
{"systemAppMode", &luaApi_Desktop_systemAppMode}, // () -> string
|
||||
{"systemStyle", &luaApi_Desktop_systemStyle}, // () -> string
|
||||
}},
|
||||
};
|
||||
{"C_FileSystem",
|
||||
{
|
||||
{"exists", &luaApi_FileSystem_exists}, // (string) -> bool
|
||||
{"isExecutable", &luaApi_FileSystem_isExecutable}, // (string) -> bool
|
||||
}},
|
||||
{"C_System",
|
||||
{
|
||||
{"appArch", &luaApi_System_appArch}, // () -> string
|
||||
{"appDir", &luaApi_System_appDir}, // () -> string
|
||||
{"appLibexecDir", &luaApi_System_appLibexecDir}, // () -> string
|
||||
{"appResourceDir", &luaApi_System_appResourceDir}, // () -> string
|
||||
{"osArch", &luaApi_System_osArch}, // () -> string
|
||||
{"supportedAppArchList",
|
||||
&luaApi_System_supportedAppArchList}, // () -> string
|
||||
#ifdef Q_OS_WINDOWS
|
||||
{"readRegistry",
|
||||
&luaApi_System_readRegistry}, // (string, string) -> string|nil
|
||||
#endif
|
||||
}},
|
||||
{"C_Util",
|
||||
{
|
||||
{"format", &luaApi_Util_format}, // (string, ...) -> string
|
||||
}}};
|
||||
|
||||
static void registerApiGroup(RaiiLuaState &L, const QString &name) {
|
||||
L.push(apiGroups[name]);
|
||||
|
@ -80,7 +102,7 @@ QJsonValue SimpleExecutor::runScript(const QByteArray &script,
|
|||
|
||||
int retLoad = L.loadBuffer(script, name);
|
||||
if (retLoad != 0)
|
||||
throw LuaError("Lua script load error.");
|
||||
throw LuaError(QString("Lua script load error: %1.").arg(L.popString()));
|
||||
L.setHook(&luaHook_timeoutKiller, LUA_MASKCOUNT, 1'000'000); // ~5ms on early 2020s desktop CPUs
|
||||
L.setTimeStart();
|
||||
int callResult = L.pCall(0, 1, 0);
|
||||
|
@ -91,4 +113,15 @@ QJsonValue SimpleExecutor::runScript(const QByteArray &script,
|
|||
return L.fetch(1);
|
||||
}
|
||||
|
||||
CompilerHintExecutor::CompilerHintExecutor() : SimpleExecutor({"C_Debug", "C_Desktop", "C_FileSystem", "C_System", "C_Util"}) {}
|
||||
|
||||
QJsonObject CompilerHintExecutor::operator()(const QByteArray &script) {
|
||||
using namespace std::chrono_literals;
|
||||
QJsonValue result = SimpleExecutor::runScript(script, "compiler_hint.lua", 1s);
|
||||
if (result.isObject() || result.isNull())
|
||||
return result.toObject();
|
||||
else
|
||||
throw LuaError("Compiler hint script must return an object.");
|
||||
}
|
||||
|
||||
} // namespace AddOn
|
||||
|
|
|
@ -43,6 +43,12 @@ public:
|
|||
QJsonObject operator()(const QByteArray &script, const QString &name);
|
||||
};
|
||||
|
||||
class CompilerHintExecutor : private SimpleExecutor {
|
||||
public:
|
||||
CompilerHintExecutor();
|
||||
QJsonObject operator()(const QByteArray &script);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ADDON_EXECUTOR_H
|
||||
|
|
|
@ -70,7 +70,22 @@ QString RaiiLuaState::fetchString(int index)
|
|||
|
||||
QJsonValue RaiiLuaState::fetch(int index)
|
||||
{
|
||||
return fetchValueImpl(index, 0);
|
||||
return fetchValueImpl(mLua, index, 0);
|
||||
}
|
||||
|
||||
bool RaiiLuaState::fetchBoolean(lua_State *L, int index)
|
||||
{
|
||||
return lua_toboolean(L, index);
|
||||
}
|
||||
|
||||
long long RaiiLuaState::fetchInteger(lua_State *L, int index)
|
||||
{
|
||||
return lua_tointeger(L, index);
|
||||
}
|
||||
|
||||
double RaiiLuaState::fetchNumber(lua_State *L, int index)
|
||||
{
|
||||
return lua_tonumber(L, index);
|
||||
}
|
||||
|
||||
QString RaiiLuaState::fetchString(lua_State *L, int index)
|
||||
|
@ -78,6 +93,11 @@ QString RaiiLuaState::fetchString(lua_State *L, int index)
|
|||
return lua_tostring(L, index);
|
||||
}
|
||||
|
||||
QJsonValue RaiiLuaState::fetch(lua_State *L, int index)
|
||||
{
|
||||
return fetchValueImpl(L, index, 0);
|
||||
}
|
||||
|
||||
bool RaiiLuaState::popBoolean()
|
||||
{
|
||||
bool value = lua_toboolean(mLua, -1);
|
||||
|
@ -99,6 +119,13 @@ QJsonValue RaiiLuaState::pop()
|
|||
return value;
|
||||
}
|
||||
|
||||
QJsonValue RaiiLuaState::pop(lua_State *L)
|
||||
{
|
||||
QJsonValue value = fetch(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
void RaiiLuaState::push(decltype(nullptr))
|
||||
{
|
||||
lua_pushnil(mLua);
|
||||
|
@ -114,6 +141,16 @@ void RaiiLuaState::push(const QMap<QString, lua_CFunction> &value)
|
|||
}
|
||||
}
|
||||
|
||||
void RaiiLuaState::push(lua_State *L, decltype(nullptr))
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
void RaiiLuaState::push(lua_State *L, bool value)
|
||||
{
|
||||
lua_pushboolean(L, value);
|
||||
}
|
||||
|
||||
void RaiiLuaState::push(lua_State *L, const QString &value)
|
||||
{
|
||||
lua_pushstring(L, value.toUtf8().constData());
|
||||
|
@ -129,6 +166,16 @@ void RaiiLuaState::push(lua_State *L, const QStringList &value)
|
|||
}
|
||||
}
|
||||
|
||||
int RaiiLuaState::getTop()
|
||||
{
|
||||
return lua_gettop(mLua);
|
||||
}
|
||||
|
||||
int RaiiLuaState::getTop(lua_State *L)
|
||||
{
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
int RaiiLuaState::loadBuffer(const QByteArray &buff, const QString &name)
|
||||
{
|
||||
return luaL_loadbuffer(mLua, buff.constData(), buff.size(), name.toUtf8().constData());
|
||||
|
@ -166,15 +213,15 @@ LuaExtraState &RaiiLuaState::extraState(lua_State *lua) {
|
|||
return mExtraState[lua];
|
||||
}
|
||||
|
||||
QJsonValue RaiiLuaState::fetchTableImpl(int index, int depth)
|
||||
QJsonValue RaiiLuaState::fetchTableImpl(lua_State *L, int index, int depth)
|
||||
{
|
||||
if (depth == 1)
|
||||
// check stack size at first recursion to avoid multiple reallocations
|
||||
lua_checkstack(mLua, LUA_STACK_SIZE);
|
||||
lua_checkstack(L, LUA_STACK_SIZE);
|
||||
if (depth > TABLE_MAX_DEPTH)
|
||||
throw LuaError("Lua runtime error: table nested too deeply");
|
||||
|
||||
push(nullptr); // make sure lua_next starts at beginning
|
||||
push(L, nullptr); // make sure lua_next starts at beginning
|
||||
int newIndex = index < 0 ? index - 1 : index; // after push negative index changes
|
||||
|
||||
QJsonObject hashPart;
|
||||
|
@ -182,15 +229,15 @@ QJsonValue RaiiLuaState::fetchTableImpl(int index, int depth)
|
|||
|
||||
// here we take the fact that Lua iterates array part first
|
||||
bool processingArrayPart = true;
|
||||
while (lua_next(mLua, newIndex)) {
|
||||
QJsonValue v = pop();
|
||||
if (processingArrayPart && lua_isinteger(mLua, -1) && fetchInteger(-1) == arrayPart.size() + 1)
|
||||
while (lua_next(L, newIndex)) {
|
||||
QJsonValue v = pop(L);
|
||||
if (processingArrayPart && lua_isinteger(L, -1) && fetchInteger(L, -1) == arrayPart.size() + 1)
|
||||
// we are still in array part
|
||||
arrayPart.push_back(v);
|
||||
else {
|
||||
// we have stepped in hash part
|
||||
processingArrayPart = false;
|
||||
QString k = fetchString(-1);
|
||||
QString k = fetchString(L, -1);
|
||||
hashPart[k] = v;
|
||||
}
|
||||
}
|
||||
|
@ -212,22 +259,24 @@ QJsonValue RaiiLuaState::fetchTableImpl(int index, int depth)
|
|||
return {};
|
||||
}
|
||||
|
||||
QJsonValue RaiiLuaState::fetchValueImpl(int index, int depth)
|
||||
QJsonValue RaiiLuaState::fetchValueImpl(lua_State *L, int index, int depth)
|
||||
{
|
||||
if (lua_isnil(mLua, index))
|
||||
if (lua_isnil(L, index))
|
||||
return {};
|
||||
else if (lua_isboolean(mLua, index))
|
||||
return fetchBoolean(index);
|
||||
else if (lua_isinteger(mLua, index))
|
||||
return fetchInteger(index);
|
||||
else if (lua_isnumber(mLua, index))
|
||||
return fetchNumber(index);
|
||||
else if (lua_isstring(mLua, index))
|
||||
return fetchString(index);
|
||||
else if (lua_istable(mLua, index))
|
||||
return fetchTableImpl(index, depth + 1);
|
||||
else if (lua_isboolean(L, index))
|
||||
return fetchBoolean(L, index);
|
||||
else if (lua_isinteger(L, index))
|
||||
return fetchInteger(L, index);
|
||||
// lua_isnumber treats strings that can be converted to numbers as numbers
|
||||
// use lua_type to detect numbers
|
||||
else if (lua_type(L, index) == LUA_TNUMBER)
|
||||
return fetchNumber(L, index);
|
||||
else if (lua_isstring(L, index))
|
||||
return fetchString(L, index);
|
||||
else if (lua_istable(L, index))
|
||||
return fetchTableImpl(L, index, depth + 1);
|
||||
else
|
||||
throw LuaError(QString("Lua type error: unknown type %1.").arg(lua_typename(mLua, index)));
|
||||
throw LuaError(QString("Lua type error: unknown type %1.").arg(lua_typename(L, index)));
|
||||
}
|
||||
|
||||
QHash<lua_State *, LuaExtraState> RaiiLuaState::mExtraState;
|
||||
|
|
|
@ -64,7 +64,11 @@ public:
|
|||
QJsonObject fetchObject(int index);
|
||||
QJsonValue fetch(int index);
|
||||
|
||||
static bool fetchBoolean(lua_State *L, int index);
|
||||
static long long fetchInteger(lua_State *L, int index);
|
||||
static double fetchNumber(lua_State *L, int index);
|
||||
static QString fetchString(lua_State *L, int index);
|
||||
static QJsonValue fetch(lua_State *L, int index);
|
||||
|
||||
bool popBoolean();
|
||||
long long popInteger();
|
||||
|
@ -74,12 +78,19 @@ public:
|
|||
QJsonObject popObject();
|
||||
QJsonValue pop();
|
||||
|
||||
static QJsonValue pop(lua_State *L);
|
||||
|
||||
void push(decltype(nullptr));
|
||||
void push(const QMap<QString, lua_CFunction> &value);
|
||||
|
||||
static void push(lua_State *L, decltype(nullptr));
|
||||
static void push(lua_State *L, bool value);
|
||||
static void push(lua_State *L, const QString &value);
|
||||
static void push(lua_State *L, const QStringList &value);
|
||||
|
||||
int getTop();
|
||||
static int getTop(lua_State *L);
|
||||
|
||||
int loadBuffer(const QByteArray &buff, const QString &name);
|
||||
void openLibs();
|
||||
int pCall(int nargs, int nresults, int msgh);
|
||||
|
@ -91,8 +102,8 @@ public:
|
|||
static LuaExtraState &extraState(lua_State *lua);
|
||||
|
||||
private:
|
||||
QJsonValue fetchTableImpl(int index, int depth);
|
||||
QJsonValue fetchValueImpl(int index, int depth);
|
||||
static QJsonValue fetchTableImpl(lua_State *L, int index, int depth);
|
||||
static QJsonValue fetchValueImpl(lua_State *L, int index, int depth);
|
||||
|
||||
private:
|
||||
lua_State *mLua;
|
||||
|
|
|
@ -177,17 +177,13 @@ void CompilerInfo::prepareCompilerOptions()
|
|||
sl.append(QPair<QString,QString>("Strong","-strong"));
|
||||
sl.append(QPair<QString,QString>("All","-all"));
|
||||
addOption(CC_CMD_OPT_STACK_PROTECTOR , QObject::tr("Check for stack smashing attacks (-fstack-protector)"), groupName, false, false, true, "-fstack-protector", CompilerOptionType::Choice, sl);
|
||||
#if defined(Q_OS_UNIX)
|
||||
sl.clear();
|
||||
sl.append(QPair<QString,QString>("Address","address"));
|
||||
# ifdef __aarch64__
|
||||
sl.append(QPair<QString,QString>("Hardware-assisted Address","hwaddress"));
|
||||
# endif
|
||||
sl.append(QPair<QString,QString>("Hardware-assisted address (arm64 only)","hwaddress"));
|
||||
sl.append(QPair<QString,QString>("Thread","thread"));
|
||||
sl.append(QPair<QString,QString>("Leak","leak"));
|
||||
sl.append(QPair<QString,QString>("Undefined","undefined"));
|
||||
addOption(CC_CMD_OPT_ADDRESS_SANITIZER , QObject::tr("Enable Sanitizer (-fsanitize=)"), groupName, true, true, true, "-fsanitize=",CompilerOptionType::Choice,sl);
|
||||
#endif
|
||||
|
||||
// Output
|
||||
//groupName = QObject::tr("Output");
|
||||
|
|
|
@ -90,6 +90,8 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin
|
|||
setDebuggerType(DebuggerType::LLDB_MI);
|
||||
else
|
||||
setDebuggerType(DebuggerType::GDB);
|
||||
// force to lldb-server if using lldb-mi, which creates new console but does not bind inferior’s stdio to the new console on Windows.
|
||||
setUseDebugServer(pSettings->debugger().useGDBServer() || debuggerType() == DebuggerType::LLDB_MI);
|
||||
mExecuting = true;
|
||||
QString debuggerPath = compilerSet->debugger();
|
||||
//QFile debuggerProgram(debuggerPath);
|
||||
|
@ -112,7 +114,7 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin
|
|||
+tr("Please check the \"program\" page of compiler settings."));
|
||||
return false;
|
||||
}
|
||||
if (pSettings->debugger().useGDBServer()) {
|
||||
if (useDebugServer()) {
|
||||
if (!isTextAllAscii(compilerSet->debugServer())) {
|
||||
mExecuting = false;
|
||||
QMessageBox::critical(pMainWindow,
|
||||
|
@ -134,7 +136,7 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin
|
|||
}
|
||||
mMemoryModel->reset();
|
||||
mWatchModel->resetAllVarInfos();
|
||||
if (pSettings->debugger().useGDBServer()) {
|
||||
if (useDebugServer()) {
|
||||
//deleted when thread finished
|
||||
QStringList params;
|
||||
if (pSettings->executor().useParams())
|
||||
|
@ -561,6 +563,16 @@ void Debugger::fetchVarChildren(const QString &varName)
|
|||
}
|
||||
}
|
||||
|
||||
bool Debugger::useDebugServer() const
|
||||
{
|
||||
return mUseDebugServer;
|
||||
}
|
||||
|
||||
void Debugger::setUseDebugServer(bool newUseDebugServer)
|
||||
{
|
||||
mUseDebugServer = newUseDebugServer;
|
||||
}
|
||||
|
||||
bool Debugger::debugInfosUsingUTF8() const
|
||||
{
|
||||
return mDebugInfosUsingUTF8;
|
||||
|
@ -1391,7 +1403,7 @@ void DebugReader::runNextCmd()
|
|||
emit cmdFinished();
|
||||
}
|
||||
if (mCmdQueue.isEmpty()) {
|
||||
if (pSettings->debugger().useGDBServer() && mInferiorRunning && !mAsyncUpdated) {
|
||||
if (mDebugger->useDebugServer() && mInferiorRunning && !mAsyncUpdated) {
|
||||
mAsyncUpdated = true;
|
||||
QTimer::singleShot(50,this,&DebugReader::asyncUpdate);
|
||||
}
|
||||
|
@ -3062,7 +3074,16 @@ void DebugTarget::run()
|
|||
mErrorOccured = false;
|
||||
|
||||
//find first available port
|
||||
QStringList execArgs = QStringList{
|
||||
QStringList execArgs;
|
||||
if (mGDBServer.endsWith(LLDB_SERVER_PROGRAM))
|
||||
execArgs = QStringList{
|
||||
mGDBServer,
|
||||
"gdbserver",
|
||||
QString("localhost:%1").arg(mPort),
|
||||
mInferior,
|
||||
} + mArguments;
|
||||
else
|
||||
execArgs = QStringList{
|
||||
mGDBServer,
|
||||
QString("localhost:%1").arg(mPort),
|
||||
mInferior,
|
||||
|
|
|
@ -375,6 +375,9 @@ public:
|
|||
bool debugInfosUsingUTF8() const;
|
||||
void setDebugInfosUsingUTF8(bool newDebugInfosUsingUTF8);
|
||||
|
||||
bool useDebugServer() const;
|
||||
void setUseDebugServer(bool newUseDebugServer);
|
||||
|
||||
signals:
|
||||
void evalValueReady(const QString& s);
|
||||
void memoryExamineReady(const QStringList& s);
|
||||
|
@ -418,6 +421,7 @@ private:
|
|||
DebugTarget *mTarget;
|
||||
bool mForceUTF8;
|
||||
bool mDebugInfosUsingUTF8;
|
||||
bool mUseDebugServer;
|
||||
DebuggerType mDebuggerType;
|
||||
int mLeftPageIndexBackup;
|
||||
qint64 mLastLoadtime;
|
||||
|
|
|
@ -985,7 +985,8 @@ void MainWindow::applySettings()
|
|||
&& pSettings->executor().enableProblemSet());
|
||||
|
||||
ui->cbProblemCaseValidateType->setCurrentIndex((int)(pSettings->executor().problemCaseValidateType()));
|
||||
ui->actionInterrupt->setVisible(pSettings->debugger().useGDBServer());
|
||||
if (mDebugger != nullptr)
|
||||
ui->actionInterrupt->setVisible(mDebugger->useDebugServer());
|
||||
//icon sets for editors
|
||||
updateEditorSettings();
|
||||
updateDebuggerSettings();
|
||||
|
@ -2506,7 +2507,7 @@ void MainWindow::debug()
|
|||
mDebugger->sendCommand("-gdb-set", QString("print elements %1").arg(pSettings->debugger().arrayElements())); // limit array elements to 30
|
||||
mDebugger->sendCommand("-gdb-set", QString("print characters %1").arg(pSettings->debugger().characters())); // limit array elements to 300
|
||||
mDebugger->sendCommand("-environment-cd", QString("\"%1\"").arg(extractFileDir(filePath))); // restore working directory
|
||||
if (pSettings->debugger().useGDBServer()) {
|
||||
if (mDebugger->useDebugServer()) {
|
||||
mDebugger->sendCommand("-target-select",QString("remote localhost:%1").arg(pSettings->debugger().GDBServerPort()));
|
||||
if (!debugInferiorhasBreakpoint() || !debugEnabled) {
|
||||
mDebugger->sendCommand("-break-insert","-t main");
|
||||
|
@ -5165,8 +5166,7 @@ void MainWindow::disableDebugActions()
|
|||
|
||||
void MainWindow::enableDebugActions()
|
||||
{
|
||||
if (pSettings->debugger().useGDBServer())
|
||||
ui->actionInterrupt->setEnabled(mDebugger->inferiorRunning());
|
||||
ui->actionInterrupt->setEnabled(mDebugger->useDebugServer() && mDebugger->inferiorRunning());
|
||||
ui->actionStep_Into->setEnabled(!mDebugger->inferiorRunning());
|
||||
ui->actionStep_Over->setEnabled(!mDebugger->inferiorRunning());
|
||||
ui->actionStep_Out->setEnabled(!mDebugger->inferiorRunning());
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#ifdef Q_OS_LINUX
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
#ifdef ENABLE_LUA_ADDON
|
||||
# include "addon/executor.h"
|
||||
# include "addon/runtime.h"
|
||||
#endif
|
||||
|
||||
const char ValueToChar[28] = {'0', '1', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
||||
|
@ -1768,6 +1772,127 @@ Settings::CompilerSet::CompilerSet(const Settings::CompilerSet &set):
|
|||
|
||||
}
|
||||
|
||||
Settings::CompilerSet::CompilerSet(const QJsonObject &set) :
|
||||
mFullLoaded{true},
|
||||
mCCompiler{set["cCompiler"].toString()},
|
||||
mCppCompiler{set["cxxCompiler"].toString()},
|
||||
mMake{set["make"].toString()},
|
||||
mDebugger{set["debugger"].toString()},
|
||||
mResourceCompiler{set["resourceCompiler"].toString()},
|
||||
mDebugServer{set["debugServer"].toString()},
|
||||
|
||||
mBinDirs{}, // handle later
|
||||
mCIncludeDirs{}, // handle later
|
||||
mCppIncludeDirs{}, // handle later
|
||||
mLibDirs{}, // handle later
|
||||
mDefaultLibDirs{}, // handle later
|
||||
mDefaultCIncludeDirs{}, // handle later
|
||||
mDefaultCppIncludeDirs{}, // handle later
|
||||
|
||||
mDumpMachine{set["dumpMachine"].toString()},
|
||||
mVersion{set["version"].toString()},
|
||||
mType{set["type"].toString()},
|
||||
mName{set["name"].toString()},
|
||||
mTarget{set["target"].toString()},
|
||||
mCompilerType{}, // handle later
|
||||
|
||||
mUseCustomCompileParams{!set["customCompileParams"].toArray().isEmpty()},
|
||||
mUseCustomLinkParams{!set["customLinkParams"].toArray().isEmpty()},
|
||||
mCustomCompileParams{}, // handle later
|
||||
mCustomLinkParams{}, // handle later
|
||||
mAutoAddCharsetParams{!set["execCharset"].toString().isEmpty()},
|
||||
mExecCharset{}, // handle later
|
||||
mStaticLink{set["staticLink"].toBool()},
|
||||
mPersistInAutoFind{false},
|
||||
|
||||
mPreprocessingSuffix{set["preprocessingSuffix"].toString()},
|
||||
mCompilationProperSuffix{set["compilationProperSuffix"].toString()},
|
||||
mAssemblingSuffix{set["assemblingSuffix"].toString()},
|
||||
mExecutableSuffix{set["executableSuffix"].toString()},
|
||||
mCompilationStage{CompilationStage(set["compilationStage"].toInt())},
|
||||
mCompileOptions{} // handle later
|
||||
{
|
||||
for (const QJsonValue &dir : set["binDirs"].toArray())
|
||||
mBinDirs.append(dir.toString());
|
||||
for (const QJsonValue &dir : set["cIncludeDirs"].toArray())
|
||||
mCIncludeDirs.append(dir.toString());
|
||||
for (const QJsonValue &dir : set["cxxIncludeDirs"].toArray())
|
||||
mCppIncludeDirs.append(dir.toString());
|
||||
for (const QJsonValue &dir : set["libDirs"].toArray())
|
||||
mLibDirs.append(dir.toString());
|
||||
for (const QJsonValue &dir : set["defaultLibDirs"].toArray())
|
||||
mDefaultLibDirs.append(dir.toString());
|
||||
for (const QJsonValue &dir : set["defaultCIncludeDirs"].toArray())
|
||||
mDefaultCIncludeDirs.append(dir.toString());
|
||||
for (const QJsonValue &dir : set["defaultCxxIncludeDirs"].toArray())
|
||||
mDefaultCppIncludeDirs.append(dir.toString());
|
||||
|
||||
QString compilerType = set["compilerType"].toString();
|
||||
if (compilerType == "GCC") {
|
||||
mCompilerType = CompilerType::GCC;
|
||||
} else if (compilerType == "GCC_UTF8") {
|
||||
mCompilerType = CompilerType::GCC_UTF8;
|
||||
} else if (compilerType == "Clang") {
|
||||
mCompilerType = CompilerType::Clang;
|
||||
}
|
||||
#if ENABLE_SDCC
|
||||
else if (compilerType == "SDCC") {
|
||||
mCompilerType = CompilerType::SDCC;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
mCompilerType = CompilerType::Unknown;
|
||||
mFullLoaded = false;
|
||||
}
|
||||
|
||||
QStringList escapedCompileParams;
|
||||
for (const QJsonValue ¶m : set["customCompileParams"].toArray())
|
||||
escapedCompileParams.append(escapeArgument(param.toString(), false));
|
||||
mCustomCompileParams = escapedCompileParams.join(' ');
|
||||
QStringList escapedLinkParams;
|
||||
for (const QJsonValue ¶m : set["customLinkParams"].toArray())
|
||||
escapedLinkParams.append(escapeArgument(param.toString(), false));
|
||||
mCustomLinkParams = escapedLinkParams.join(' ');
|
||||
|
||||
if (!mAutoAddCharsetParams)
|
||||
mExecCharset = "UTF-8";
|
||||
else
|
||||
mExecCharset = set["execCharset"].toString();
|
||||
|
||||
const static QMap<QString, QString> optionMap = {
|
||||
{CC_CMD_OPT_OPTIMIZE, "ccCmdOptOptimize"},
|
||||
{CC_CMD_OPT_STD, "ccCmdOptStd"},
|
||||
{C_CMD_OPT_STD, "cCmdOptStd"},
|
||||
{CC_CMD_OPT_INSTRUCTION, "ccCmdOptInstruction"},
|
||||
|
||||
{CC_CMD_OPT_POINTER_SIZE, "ccCmdOptPointerSize"},
|
||||
|
||||
{CC_CMD_OPT_DEBUG_INFO, "ccCmdOptDebugInfo"},
|
||||
{CC_CMD_OPT_PROFILE_INFO, "ccCmdOptProfileInfo"},
|
||||
{CC_CMD_OPT_SYNTAX_ONLY, "ccCmdOptSyntaxOnly"},
|
||||
|
||||
{CC_CMD_OPT_INHIBIT_ALL_WARNING, "ccCmdOptInhibitAllWarning"},
|
||||
{CC_CMD_OPT_WARNING_ALL, "ccCmdOptWarningAll"},
|
||||
{CC_CMD_OPT_WARNING_EXTRA, "ccCmdOptWarningExtra"},
|
||||
{CC_CMD_OPT_CHECK_ISO_CONFORMANCE, "ccCmdOptCheckIsoConformance"},
|
||||
{CC_CMD_OPT_WARNING_AS_ERROR, "ccCmdOptWarningAsError"},
|
||||
{CC_CMD_OPT_ABORT_ON_ERROR, "ccCmdOptAbortOnError"},
|
||||
{CC_CMD_OPT_STACK_PROTECTOR, "ccCmdOptStackProtector"},
|
||||
{CC_CMD_OPT_ADDRESS_SANITIZER, "ccCmdOptAddressSanitizer"},
|
||||
|
||||
{CC_CMD_OPT_USE_PIPE, "ccCmdOptUsePipe"},
|
||||
{LINK_CMD_OPT_NO_LINK_STDLIB, "linkCmdOptNoLinkStdlib"},
|
||||
{LINK_CMD_OPT_NO_CONSOLE, "linkCmdOptNoConsole"},
|
||||
{LINK_CMD_OPT_STRIP_EXE, "linkCmdOptStripExe"},
|
||||
};
|
||||
for (const QString &key : optionMap.keys()) {
|
||||
const QString &jsonKey = optionMap[key];
|
||||
QString value = set[jsonKey].toString();
|
||||
if (!value.isEmpty())
|
||||
setCompileOption(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::CompilerSet::resetCompileOptionts()
|
||||
{
|
||||
mCompileOptions.clear();
|
||||
|
@ -2995,6 +3120,13 @@ Settings::PCompilerSet Settings::CompilerSets::addSet(const PCompilerSet &pSet)
|
|||
return p;
|
||||
}
|
||||
|
||||
Settings::PCompilerSet Settings::CompilerSets::addSet(const QJsonObject &set)
|
||||
{
|
||||
PCompilerSet p = std::make_shared<CompilerSet>(set);
|
||||
mList.push_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void set64_32Options(Settings::PCompilerSet pSet) {
|
||||
pSet->setCompileOption(CC_CMD_OPT_POINTER_SIZE,"32");
|
||||
}
|
||||
|
@ -3133,39 +3265,72 @@ Settings::CompilerSetList Settings::CompilerSets::clearSets()
|
|||
void Settings::CompilerSets::findSets()
|
||||
{
|
||||
CompilerSetList persisted = clearSets();
|
||||
// canonical paths that has been searched.
|
||||
// use canonical paths here to resolve symbolic links.
|
||||
QSet<QString> searched;
|
||||
|
||||
#ifdef ENABLE_LUA_ADDON
|
||||
QJsonObject compilerHint;
|
||||
if (
|
||||
QFile scriptFile(pSettings->dirs().appLibexecDir() + "/compiler_hint.lua");
|
||||
scriptFile.exists() && scriptFile.open(QFile::ReadOnly)
|
||||
) {
|
||||
QByteArray script = scriptFile.readAll();
|
||||
try {
|
||||
compilerHint = AddOn::CompilerHintExecutor{}(script);
|
||||
} catch (const AddOn::LuaError &e) {
|
||||
qDebug() << "Error in compiler_hint.lua:" << e.reason();
|
||||
}
|
||||
if (!compilerHint.empty()) {
|
||||
QJsonArray compilerList = compilerHint["compilerList"].toArray();
|
||||
for (const QJsonValue &value : compilerList) {
|
||||
addSet(value.toObject());
|
||||
}
|
||||
QJsonArray noSearch = compilerHint["noSearch"].toArray();
|
||||
QString canonicalPath;
|
||||
for (const QJsonValue &value : noSearch) {
|
||||
canonicalPath = QDir(value.toString()).canonicalPath();
|
||||
if (!canonicalPath.isEmpty())
|
||||
searched.insert(canonicalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString path = env.value("PATH");
|
||||
QStringList pathList = path.split(PATH_SEPARATOR);
|
||||
QString folder;
|
||||
#ifdef Q_OS_WIN
|
||||
pathList = QStringList{
|
||||
mSettings->dirs().appDir() + "/Clang64/bin",
|
||||
mSettings->dirs().appDir() + "/MinGW64/bin",
|
||||
mSettings->dirs().appDir() + "/MinGW32/bin",
|
||||
} + pathList;
|
||||
#endif
|
||||
QString folder, canonicalFolder;
|
||||
for (int i=pathList.count()-1;i>=0;i--) {
|
||||
folder = QFileInfo(pathList[i]).absoluteFilePath();
|
||||
if (searched.contains(folder))
|
||||
folder = QDir(pathList[i]).absolutePath();
|
||||
canonicalFolder = QDir(pathList[i]).canonicalPath();
|
||||
if (canonicalFolder.isEmpty())
|
||||
continue;
|
||||
searched.insert(folder);
|
||||
if (folder!="/bin") { // /bin/gcc is symbolic link to /usr/bin/gcc
|
||||
if (searched.contains(canonicalFolder))
|
||||
continue;
|
||||
searched.insert(canonicalFolder);
|
||||
// but use absolute path to search so compiler set can survive system upgrades.
|
||||
// during search:
|
||||
// /opt/gcc-13 -> /opt/gcc-13.1.0
|
||||
// after upgrade:
|
||||
// /opt/gcc-13 -> /opt/gcc-13.2.0
|
||||
addSets(folder);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
folder = includeTrailingPathDelimiter(mSettings->dirs().appDir())+"MinGW32"+QDir::separator()+"bin";
|
||||
folder = QFileInfo(folder).absoluteFilePath();
|
||||
if (!searched.contains(folder)) {
|
||||
addSets(folder);
|
||||
searched.insert(folder);
|
||||
}
|
||||
folder = includeTrailingPathDelimiter(mSettings->dirs().appDir())+"MinGW64"+QDir::separator()+"bin";
|
||||
folder = QFileInfo(folder).absoluteFilePath();
|
||||
if (!searched.contains(folder)) {
|
||||
addSets(folder);
|
||||
searched.insert(folder);
|
||||
}
|
||||
folder = includeTrailingPathDelimiter(mSettings->dirs().appDir())+"Clang64"+QDir::separator()+"bin";
|
||||
if (!searched.contains(folder)) {
|
||||
addSets(folder);
|
||||
searched.insert(folder);
|
||||
#ifdef ENABLE_LUA_ADDON
|
||||
if (
|
||||
// note that array index starts from 1 in Lua
|
||||
int preferCompilerInLua = compilerHint["preferCompiler"].toInt();
|
||||
preferCompilerInLua >= 1 && preferCompilerInLua <= (int)mList.size()
|
||||
) {
|
||||
mDefaultIndex = preferCompilerInLua - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3644,11 +3809,10 @@ void Settings::Environment::doLoad()
|
|||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
# if defined (__aarch64__) || defined(_M_ARM64)
|
||||
// the only native MinGW toolchain (LLVM-MinGW) does not have local codepage support
|
||||
# ifdef WINDOWS_PREFER_OPENCONSOLE
|
||||
// prefer UTF-8 compatible OpenConsole.exe
|
||||
mUseCustomTerminal = boolValue("use_custom_terminal", true);
|
||||
# else // x86 or x64
|
||||
# else
|
||||
mUseCustomTerminal = boolValue("use_custom_terminal", false);
|
||||
# endif
|
||||
#else // UNIX
|
||||
|
|
|
@ -1357,6 +1357,7 @@ public:
|
|||
explicit CompilerSet();
|
||||
explicit CompilerSet(const QString& compilerFolder, const QString& c_prog);
|
||||
explicit CompilerSet(const CompilerSet& set);
|
||||
explicit CompilerSet(const QJsonObject& set);
|
||||
|
||||
CompilerSet& operator= (const CompilerSet& ) = delete;
|
||||
CompilerSet& operator= (const CompilerSet&& ) = delete;
|
||||
|
@ -1562,6 +1563,7 @@ public:
|
|||
private:
|
||||
PCompilerSet addSet(const QString& folder, const QString& c_prog);
|
||||
PCompilerSet addSet(const PCompilerSet &pSet);
|
||||
PCompilerSet addSet(const QJsonObject &set);
|
||||
bool addSets(const QString& folder, const QString& c_prog);
|
||||
void savePath(const QString& name, const QString& path);
|
||||
void savePathList(const QString& name, const QStringList& pathList);
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
<translation><html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:600;">Red Panda C++</span></h1></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Based on Qt %1 (%2)</source>
|
||||
<translation>Com base em Qt %1 (%2)</translation>
|
||||
<source>Based on Qt %1 (%2) rodando em %3</source>
|
||||
<translation>Com base em Qt %1 (%2) executado em %3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Build time: %1 %2</source>
|
||||
|
|
|
@ -62,8 +62,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../widgets/aboutdialog.ui" line="35"/>
|
||||
<source>Based on Qt %1 (%2)</source>
|
||||
<translation>基于Qt %1 (%2)</translation>
|
||||
<source>Based on Qt %1 (%2) running on %3</source>
|
||||
<translation>基于 Qt %1 (%2) 运行于 %3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widgets/aboutdialog.ui" line="47"/>
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Based on Qt %1 (%2)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<source>Based on Qt %1 (%2) running on %3</source>
|
||||
<translation>基於 Qt %1 (%2) 執行於 %3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Build time: %1 %2</source>
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
using pIsWow64Process2_t = BOOL (WINAPI *)(
|
||||
HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine
|
||||
);
|
||||
#endif
|
||||
|
||||
QStringList splitProcessCommand(const QString &cmd)
|
||||
{
|
||||
QStringList result;
|
||||
|
@ -387,21 +393,19 @@ bool isGreenEdition()
|
|||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (!gIsGreenEditionInited) {
|
||||
QString keyString = QString("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\RedPanda-C++");
|
||||
QString value;
|
||||
if (!readRegistry(HKEY_LOCAL_MACHINE, keyString, "UninstallString", value)) {
|
||||
keyString = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\RedPanda-C++";
|
||||
if (!readRegistry(HKEY_LOCAL_MACHINE, keyString, "UninstallString", value)) {
|
||||
value="";
|
||||
}
|
||||
}
|
||||
if (!value.isEmpty()) {
|
||||
QString regPath = extractFileDir(value);
|
||||
|
||||
QString appPath = QApplication::instance()->applicationDirPath();
|
||||
gIsGreenEdition = excludeTrailingPathDelimiter(regPath).compare(excludeTrailingPathDelimiter(appPath),
|
||||
Qt::CaseInsensitive)!=0;
|
||||
}
|
||||
appPath = excludeTrailingPathDelimiter(appPath);
|
||||
QString keyString = R"(Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++)";
|
||||
QString systemInstallPath;
|
||||
readRegistry(HKEY_LOCAL_MACHINE, keyString, "UninstallString", systemInstallPath);
|
||||
if (!systemInstallPath.isEmpty())
|
||||
systemInstallPath = excludeTrailingPathDelimiter(extractFileDir(systemInstallPath));
|
||||
QString userInstallPath;
|
||||
readRegistry(HKEY_CURRENT_USER, keyString, "UninstallString", userInstallPath);
|
||||
if (!userInstallPath.isEmpty())
|
||||
userInstallPath = excludeTrailingPathDelimiter(extractFileDir(userInstallPath));
|
||||
gIsGreenEdition = appPath.compare(systemInstallPath, Qt::CaseInsensitive) != 0 &&
|
||||
appPath.compare(userInstallPath, Qt::CaseInsensitive) != 0;
|
||||
gIsGreenEditionInited = true;
|
||||
}
|
||||
return gIsGreenEdition;
|
||||
|
@ -747,3 +751,37 @@ QString defaultShell()
|
|||
return "sh";
|
||||
#endif
|
||||
}
|
||||
|
||||
QString appArch()
|
||||
{
|
||||
#ifdef _M_ARM64EC
|
||||
return "arm64ec";
|
||||
#else
|
||||
return QSysInfo::buildCpuArchitecture();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString osArch()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
pIsWow64Process2_t pIsWow64Process2 =
|
||||
reinterpret_cast<pIsWow64Process2_t>(GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process2"));
|
||||
if (pIsWow64Process2) {
|
||||
// IsWow64Process2 returns real native architecture under xtajit, while GetNativeSystemInfo does not.
|
||||
USHORT processMachineResult, nativeMachineResult;
|
||||
if (pIsWow64Process2(GetCurrentProcess(), &processMachineResult, &nativeMachineResult))
|
||||
switch (nativeMachineResult) {
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
return "i386";
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
return "x86_64";
|
||||
case IMAGE_FILE_MACHINE_ARM64:
|
||||
return "arm64";
|
||||
}
|
||||
return QSysInfo::currentCpuArchitecture();
|
||||
} else
|
||||
return QSysInfo::currentCpuArchitecture();
|
||||
#else
|
||||
return QSysInfo::currentCpuArchitecture();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -173,4 +173,7 @@ QString escapeArgument(const QString &arg, bool isFirstArg);
|
|||
|
||||
QString defaultShell();
|
||||
|
||||
QString appArch();
|
||||
QString osArch();
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
|
@ -31,25 +31,29 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
|||
|
||||
#if defined(__clang__) // Clang always pretends to be GCC/MSVC. Check it first.
|
||||
# if defined(_MSC_VER)
|
||||
QString templ = "Clang %1.%2.%3 MSVC ABI";
|
||||
QString templ = "Clang %1.%2.%3 %4 MSVC ABI";
|
||||
# elif defined(__apple_build_version__)
|
||||
QString templ = "Apple Clang %1.%2.%3";
|
||||
QString templ = "Apple Clang %1.%2.%3 %4";
|
||||
# else
|
||||
QString templ = "Clang %1.%2.%3";
|
||||
QString templ = "Clang %1.%2.%3 %4";
|
||||
# endif
|
||||
ui->lblQt->setText(ui->lblQt->text()
|
||||
.arg(qVersion())
|
||||
.arg(templ
|
||||
.arg(__clang_major__)
|
||||
.arg(__clang_minor__)
|
||||
.arg(__clang_patchlevel__)));
|
||||
.arg(__clang_patchlevel__)
|
||||
.arg(appArch()))
|
||||
.arg(osArch()));
|
||||
#elif defined(__GNUC__)
|
||||
ui->lblQt->setText(ui->lblQt->text()
|
||||
.arg(qVersion())
|
||||
.arg(QString("GCC %1.%2.%3")
|
||||
.arg(QString("GCC %1.%2.%3 %4")
|
||||
.arg(__GNUC__)
|
||||
.arg(__GNUC_MINOR__)
|
||||
.arg(__GNUC_PATCHLEVEL__)));
|
||||
.arg(__GNUC_PATCHLEVEL__)
|
||||
.arg(appArch()))
|
||||
.arg(osArch()));
|
||||
#elif defined(_MSC_VER)
|
||||
# if (_MSC_VER >= 1940)
|
||||
QString name = tr("Next Generation Microsoft Visual C++");
|
||||
|
@ -64,11 +68,13 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
|||
# endif
|
||||
ui->lblQt->setText(ui->lblQt->text()
|
||||
.arg(qVersion())
|
||||
.arg(name));
|
||||
.arg(name + " " + appArch())
|
||||
.arg(osArch()));
|
||||
#else
|
||||
ui->lblQt->setText(ui->lblQt->text()
|
||||
.arg(qVersion())
|
||||
.arg(tr("Non-GCC Compiler")));
|
||||
.arg(tr("Non-GCC Compiler"))
|
||||
.arg(osArch()));
|
||||
#endif
|
||||
ui->lblCompileTime->setText(ui->lblCompileTime->text()
|
||||
.arg(__DATE__, __TIME__));
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Based on Qt %1 (%2)</string>
|
||||
<string>Based on Qt %1 (%2) running on %3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -89,6 +89,7 @@ win32: {
|
|||
resources.files += platform/windows/installer-scripts/config.nsh
|
||||
resources.files += platform/windows/installer-scripts/config32.nsh
|
||||
resources.files += platform/windows/installer-scripts/config-clang.nsh
|
||||
resources.files += platform/windows/qt.conf
|
||||
resources.files += README.md
|
||||
resources.files += NEWS.md
|
||||
resources.files += LICENSE
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
# Add-on Interface (Unstable)
|
||||
|
||||
## Basic
|
||||
|
||||
- Add-on is a Lua script.
|
||||
- Values passed or returned to Red Panda C++ must be JSON compatible, i.e.,
|
||||
- `nil` (maps to `null`)
|
||||
- `boolean`
|
||||
- `number`
|
||||
- `string`
|
||||
- empty `table` (maps to `null`)
|
||||
- `table` with only array part (maps to `array`)
|
||||
- `table` with only hash part (maps to `object`)
|
||||
- Red Panda C++ APIs exposed to add-on are organized by groups.
|
||||
- Each group is a Lua table.
|
||||
- Each API is a function in the table.
|
||||
- Available API groups vary by add-on type.
|
||||
- Localization is handled by add-on. e.g.
|
||||
```lua
|
||||
local lang = C_Desktop.language()
|
||||
local localizedName = {
|
||||
en_US = "System",
|
||||
pt_BR = "Sistema",
|
||||
zh_CN = "系统",
|
||||
zh_TW = "系統",
|
||||
}
|
||||
return {
|
||||
name = localizedName[lang] or localizedName.en_US,
|
||||
-- ...
|
||||
}
|
||||
```
|
||||
|
||||
## Simple Add-on
|
||||
|
||||
A simple add-on is a Lua script that returns a single value.
|
||||
|
||||
### Compiler Hint Add-on
|
||||
|
||||
If `$appLibexecDir/compiler_hint.lua` exists, it will be executed as compiler hint add-on when searching for compiler.
|
||||
|
||||
Available API groups:
|
||||
- `C_Debug`
|
||||
- `C_Desktop`
|
||||
- `C_FileSystem`
|
||||
- `C_System`
|
||||
- `C_Util`
|
||||
|
||||
Return value schema:
|
||||
```typescript
|
||||
{
|
||||
// found compiler sets
|
||||
compilerList: [compilerSet],
|
||||
|
||||
// do not search in these directories anymore
|
||||
noSearch: [string],
|
||||
|
||||
// prefer compiler set index (in Lua, 1-based) in compilerList
|
||||
// 0 for no preference
|
||||
preferCompiler: number,
|
||||
}
|
||||
```
|
||||
|
||||
`compilerSet` schema:
|
||||
```typescript
|
||||
{
|
||||
name: string,
|
||||
|
||||
// internal
|
||||
dumpMachine: string, // e.g. "x86_64-linux-gnu", "x86_64-w64-mingw32"
|
||||
version: string, // e.g. "13.2.1", "17.0.6"
|
||||
type: string, // e.g. "TDM-GCC", "MinGW"
|
||||
target: string, // e.g. "x86_64", "aarch64"
|
||||
compilerType: string, // "GCC" or "Clang"
|
||||
|
||||
// general
|
||||
staticLink: boolean,
|
||||
customCompileParams: [string], // automatically sets useCustomCompileParams
|
||||
customLinkParams: [string], // automatically sets useCustomLinkParams
|
||||
execCharset: string, // automatically sets autoAddCharsetParams
|
||||
|
||||
// setting
|
||||
// - code generation
|
||||
ccCmdOptOptimize: string,
|
||||
ccCmdOptStd: string,
|
||||
cCmdOptStd: string,
|
||||
ccCmdOptInstruction: string,
|
||||
ccCmdOptPointerSize: string,
|
||||
ccCmdOptDebugInfo: string,
|
||||
ccCmdOptProfileInfo: string,
|
||||
ccCmdOptSyntaxOnly: string,
|
||||
// - warnings
|
||||
ccCmdOptInhibitAllWarning: string,
|
||||
ccCmdOptWarningAll: string,
|
||||
ccCmdOptWarningExtra: string,
|
||||
ccCmdOptCheckIsoConformance: string,
|
||||
ccCmdOptWarningAsError: string,
|
||||
ccCmdOptAbortOnError: string,
|
||||
ccCmdOptStackProtector: string,
|
||||
ccCmdOptAddressSanitizer: string,
|
||||
// - linker
|
||||
ccCmdOptUsePipe: string,
|
||||
linkCmdOptNoLinkStdlib: string,
|
||||
linkCmdOptNoConsole: string,
|
||||
linkCmdOptStripExe: string,
|
||||
|
||||
// directory
|
||||
binDirs: [string],
|
||||
cIncludeDirs: [string],
|
||||
cxxIncludeDirs: [string],
|
||||
libDirs: [string],
|
||||
defaultLibDirs: [string],
|
||||
defaultCIncludeDirs: [string],
|
||||
defaultCxxIncludeDirs: [string],
|
||||
|
||||
// program
|
||||
cCompiler: string,
|
||||
cxxCompiler: string,
|
||||
make: string,
|
||||
debugger: string,
|
||||
debugServer: string,
|
||||
resourceCompiler: string,
|
||||
|
||||
// output
|
||||
preprocessingSuffix: string,
|
||||
compilationProperSuffix: string,
|
||||
assemblingSuffix: string,
|
||||
executableSuffix: string,
|
||||
compilationStage: number,
|
||||
}
|
||||
```
|
||||
|
||||
## API Groups
|
||||
|
||||
### `C_Debug`
|
||||
|
||||
`C_Debug` is available to all add-on types.
|
||||
|
||||
- `C_Debug.debug`: `(message: string) -> ()`, print message to console (via `qDebug()`).
|
||||
|
||||
### `C_Desktop`
|
||||
|
||||
- `C_Desktop.desktopEnvironment`: `() -> string`, return desktop environment name.
|
||||
- `windows`: Windows (Win32 only)
|
||||
- `macos`: macOS
|
||||
- `xdg`: XDG-compliant desktop environment (e.g. GNOME, KDE Plasma)
|
||||
- `unknown`: other desktops or non-desktop environments (e.g. Windows UWP, Android)
|
||||
- `C_Desktop.language`: `() -> string`, return language code.
|
||||
- e.g. `en_US`, `zh_CN`
|
||||
- `C_Desktop.qtStyleList`: `() -> [string]`, return available Qt styles.
|
||||
- e.g. `{"breeze", "fusion", "windows"}`
|
||||
- `C_Desktop.systemAppMode`: `() -> string`, return system app mode.
|
||||
- `light`: light mode
|
||||
- `dark`: dark mode
|
||||
- `C_Desktop.systemStyle`: `() -> string`, return default Qt style.
|
||||
- e.g. `fusion`
|
||||
|
||||
### `C_FileSystem`
|
||||
|
||||
- `C_FileSystem.exists`: `(path: string) -> boolean`, return whether the path exists.
|
||||
- `C_FileSystem.isExecutable`: `(path: string) -> boolean`, return whether the path is executable.
|
||||
|
||||
### `C_System`
|
||||
|
||||
- `C_System.appArch`: `() -> string`, return the architecture of Red Panda C++, name following `QSysInfo`.
|
||||
- e.g. `i386`, `x86_64`, `arm`, `arm64`, `riscv64`, `loongarch64`
|
||||
- Though unsupprted, MSVC arm64ec is handled correctly (returns `arm64ec`)
|
||||
- `C_System.appDir`: `() -> string`, return the directory of Red Panda C++.
|
||||
- e.g. `/usr/bin`, `C:/Program Files/RedPanda-Cpp`
|
||||
- `C_System.appLibexecDir`: `() -> string`, return the libexec directory of Red Panda C++.
|
||||
- e.g. `/usr/libexec/RedPandaCPP`, `C:/Program Files/RedPanda-Cpp`
|
||||
- `C_System.appResourceDir`: `() -> string`, return the resource directory of Red Panda C++.
|
||||
- e.g. `/usr/share/RedPandaCPP`, `C:/Program Files/RedPanda-Cpp`
|
||||
- `C_System.osArch`: `() -> string`, return the architecture of the OS, name following `QSysInfo`.
|
||||
- e.g. `i386`, `x86_64`, `arm`, `arm64`
|
||||
- Windows arm64 is handled correctly even if Red Panda C++ runs under emulation
|
||||
- `C_System.supportedAppArchList`: `() -> [string]`, return supported application architectures by OS, name following `QSysInfo`.
|
||||
- e.g. `{"i386", "x86_64", "arm64"}`
|
||||
- Windows 10 1709 or later: accurate result
|
||||
- Legacy Windows: hardcoded
|
||||
- `{"i386", "x86_64"}` for x86_64 even though WoW64 is not available
|
||||
- macOS: accurate result supposed, but not tested
|
||||
- Linux: osArch + appArch + QEMU user mode emulation
|
||||
- No multilib detection. It’s packager’s responsibility to detect multilib support in `compiler_hint.lua`
|
||||
- other (BSD): osArch + appArch (no multilib)
|
||||
|
||||
Windows specific:
|
||||
|
||||
- `C_System.readRegistry`: `(subKey: string, name: string) -> string | nil`, read `subKey\name` from `HKEY_CURRENT_USER` and `HKEY_LOCAL_MACHINE` in order.
|
||||
- `name` can be empty string for default value
|
||||
|
||||
### `C_Util`
|
||||
|
||||
- `C_Util.format`: `(format: string, ...) -> string`, Qt-style string format, replace `%1`, `%2`, etc. with arguments.
|
|
@ -8,15 +8,41 @@ url="https://github.com/royqh1979/$_pkgname"
|
|||
license=('GPL3')
|
||||
depends=(qt5-base qt5-svg gcc gdb)
|
||||
makedepends=(qt5-tools)
|
||||
makedepends_x86_64=(mingw-w64-gcc)
|
||||
optdepends=(
|
||||
'clang: C/C++ compiler (alternative)'
|
||||
)
|
||||
optdepends_x86_64=(
|
||||
'mingw-w64-gcc: Windows C/C++ compiler'
|
||||
'wine: run Windows executable'
|
||||
'aarch64-linux-gnu-gcc: AArch64 C/C++ compiler'
|
||||
'qemu-user-static: run AArch64 executable'
|
||||
'qemu-user-static-binfmt: run AArch64 executable'
|
||||
)
|
||||
conflicts=("${_pkgname,,}")
|
||||
provides=("${_pkgname,,}")
|
||||
source=("$_pkgname.tar.gz")
|
||||
sha256sums=('SKIP')
|
||||
source=(
|
||||
"$_pkgname.tar.gz"
|
||||
'compiler_hint.lua'
|
||||
)
|
||||
sha256sums=(
|
||||
'SKIP'
|
||||
'SKIP'
|
||||
)
|
||||
|
||||
prepare() {
|
||||
sed -i '/CONFIG += ENABLE_LUA_ADDON/ { s/^#\s*// }' RedPanda-CPP/RedPandaIDE/RedPandaIDE.pro
|
||||
}
|
||||
|
||||
build() {
|
||||
local _utf8dir="$srcdir/$_pkgname/platform/windows/utf8"
|
||||
if [[ "$CARCH" == 'x86_64' ]]; then
|
||||
x86_64-w64-mingw32-gcc -Os -fno-exceptions -nodefaultlibs -nostdlib -c -o utf8init.x86_64.o "$_utf8dir/utf8init.cpp"
|
||||
x86_64-w64-mingw32-windres -O coff -o utf8manifest.x86_64.o "$_utf8dir/utf8manifest.rc"
|
||||
i686-w64-mingw32-gcc -Os -fno-exceptions -nodefaultlibs -nostdlib -c -o utf8init.i686.o "$_utf8dir/utf8init.cpp"
|
||||
i686-w64-mingw32-windres -O coff -o utf8manifest.i686.o "$_utf8dir/utf8manifest.rc"
|
||||
fi
|
||||
|
||||
mkdir redpanda-build
|
||||
cd redpanda-build
|
||||
qmake \
|
||||
|
@ -28,6 +54,16 @@ build() {
|
|||
}
|
||||
|
||||
package() {
|
||||
local _libexecdir="$pkgdir/usr/lib/RedPandaCPP"
|
||||
install -Dm644 "compiler_hint.lua" "$_libexecdir/compiler_hint.lua"
|
||||
|
||||
if [[ "$CARCH" == 'x86_64' ]]; then
|
||||
install -Dm644 "utf8init.x86_64.o" "$_libexecdir/x86_64-w64-mingw32/utf8init.o"
|
||||
install -Dm644 "utf8manifest.x86_64.o" "$_libexecdir/x86_64-w64-mingw32/utf8manifest.o"
|
||||
install -Dm644 "utf8init.i686.o" "$_libexecdir/i686-w64-mingw32/utf8init.o"
|
||||
install -Dm644 "utf8manifest.i686.o" "$_libexecdir/i686-w64-mingw32/utf8manifest.o"
|
||||
fi
|
||||
|
||||
cd redpanda-build
|
||||
make INSTALL_ROOT="$pkgdir" install
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ VERSION=$(git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g')
|
|||
sed "s/__VERSION__/$VERSION/g" packages/archlinux/PKGBUILD.in >"$TMP_FOLDER/PKGBUILD"
|
||||
|
||||
git archive --prefix="RedPanda-CPP/" -o "$TMP_FOLDER/RedPanda-CPP.tar.gz" HEAD
|
||||
cp packages/archlinux/compiler_hint.lua "$TMP_FOLDER/"
|
||||
|
||||
cd "$TMP_FOLDER"
|
||||
makepkg -s --noconfirm
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
local arch = C_System.osArch()
|
||||
local libexecDir = C_System.appLibexecDir()
|
||||
local lang = C_Desktop.language()
|
||||
|
||||
local nameMap = {
|
||||
systemGcc = {
|
||||
en_US = "System GCC",
|
||||
pt_BR = "GCC do sistema",
|
||||
zh_CN = "系统 GCC",
|
||||
zh_TW = "系統 GCC",
|
||||
},
|
||||
systemClang = {
|
||||
en_US = "System Clang",
|
||||
pt_BR = "Clang do sistema",
|
||||
zh_CN = "系统 Clang",
|
||||
zh_TW = "系統 Clang",
|
||||
},
|
||||
multilibGcc = {
|
||||
en_US = "Multilib GCC",
|
||||
pt_BR = "GCC multilib",
|
||||
zh_CN = "Multilib GCC",
|
||||
zh_TW = "Multilib GCC",
|
||||
},
|
||||
multilibClang = {
|
||||
en_US = "Multilib Clang",
|
||||
pt_BR = "Clang multilib",
|
||||
zh_CN = "Multilib Clang",
|
||||
zh_TW = "Multilib Clang",
|
||||
},
|
||||
crossGcc = {
|
||||
en_US = "Cross GCC",
|
||||
pt_BR = "GCC cruzado",
|
||||
zh_CN = "交叉编译 GCC",
|
||||
zh_TW = "交叉編譯 GCC",
|
||||
},
|
||||
mingwGcc = {
|
||||
en_US = "MinGW GCC",
|
||||
pt_BR = "GCC MinGW",
|
||||
zh_CN = "MinGW GCC",
|
||||
zh_TW = "MinGW GCC",
|
||||
},
|
||||
mingwClang = {
|
||||
en_US = "MinGW Clang",
|
||||
pt_BR = "Clang MinGW",
|
||||
zh_CN = "MinGW Clang",
|
||||
zh_TW = "MinGW Clang",
|
||||
},
|
||||
release = {
|
||||
en_US = ", release",
|
||||
pt_BR = ", lançamento",
|
||||
zh_CN = ",发布",
|
||||
zh_TW = ",發佈",
|
||||
},
|
||||
debug = {
|
||||
en_US = ", debug",
|
||||
pt_BR = ", depuração",
|
||||
zh_CN = ",调试",
|
||||
zh_TW = ",偵錯",
|
||||
},
|
||||
debugWithAsan = {
|
||||
en_US = ", debug with ASan",
|
||||
pt_BR = ", depuração com ASan",
|
||||
zh_CN = ",ASan 调试",
|
||||
zh_TW = ",ASan 偵錯",
|
||||
},
|
||||
}
|
||||
|
||||
function generateConfig(name, cCompiler, cxxCompiler, config)
|
||||
local commonOptions = {
|
||||
cCompiler = cCompiler,
|
||||
cxxCompiler = cxxCompiler,
|
||||
debugger = "/usr/bin/gdb",
|
||||
debugServer = "/usr/bin/gdbserver",
|
||||
make = "/usr/bin/make",
|
||||
compilerType = config.isClang and "Clang" or "GCC_UTF8",
|
||||
preprocessingSuffix = ".i",
|
||||
compilationProperSuffix = ".s",
|
||||
assemblingSuffix = ".o",
|
||||
executableSuffix = config.isMingw and ".exe" or "",
|
||||
compilationStage = 3,
|
||||
ccCmdOptUsePipe = "on",
|
||||
ccCmdOptWarningAll = "on",
|
||||
ccCmdOptWarningExtra = "on",
|
||||
ccCmdOptCheckIsoConformance = "on",
|
||||
binDirs = {"/usr/bin"},
|
||||
}
|
||||
if config.isMultilib then
|
||||
commonOptions.ccCmdOptPointerSize = "32"
|
||||
end
|
||||
if config.isMingw then
|
||||
commonOptions.resourceCompiler = "/usr/bin/" .. config.triplet .. "-windres"
|
||||
end
|
||||
if config.customCompileParams then
|
||||
commonOptions.customCompileParams = config.customCompileParams
|
||||
end
|
||||
if config.customLinkParams then
|
||||
commonOptions.customLinkParams = config.customLinkParams
|
||||
end
|
||||
local release = {
|
||||
name = name .. (nameMap.release[lang] or nameMap.release.en_US),
|
||||
staticLink = true,
|
||||
linkCmdOptStripExe = "on",
|
||||
ccCmdOptOptimize = "2",
|
||||
}
|
||||
local debug = {
|
||||
name = name .. (nameMap.debug[lang] or nameMap.debug.en_US),
|
||||
ccCmdOptDebugInfo = "on",
|
||||
}
|
||||
local debugWithAsan = {
|
||||
name = name .. (nameMap.debugWithAsan[lang] or nameMap.debugWithAsan.en_US),
|
||||
ccCmdOptDebugInfo = "on",
|
||||
ccCmdOptAddressSanitizer = "address",
|
||||
}
|
||||
for k, v in pairs(commonOptions) do
|
||||
release[k] = v
|
||||
debug[k] = v
|
||||
debugWithAsan[k] = v
|
||||
end
|
||||
return release, debug, debugWithAsan
|
||||
end
|
||||
|
||||
local compilerList = {}
|
||||
|
||||
do
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
nameMap.systemGcc[lang] or nameMap.systemGcc.en_US,
|
||||
"/usr/bin/gcc", "/usr/bin/g++",
|
||||
{}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
table.insert(compilerList, debugWithAsan)
|
||||
end
|
||||
|
||||
if C_FileSystem.isExecutable("/usr/bin/clang") then
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
nameMap.systemClang[lang] or nameMap.systemClang.en_US,
|
||||
"/usr/bin/clang", "/usr/bin/clang++",
|
||||
{isClang = true}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
table.insert(compilerList, debugWithAsan)
|
||||
end
|
||||
|
||||
-- with lib32-gcc-libs installed, system GCC and Clang can target 32-bit
|
||||
if arch == "x86_64" and C_FileSystem.isExecutable("/usr/lib32/libstdc++.so") then
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
nameMap.multilibGcc[lang] or nameMap.multilibGcc.en_US,
|
||||
"/usr/bin/gcc", "/usr/bin/g++",
|
||||
{isMultilib = true}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
table.insert(compilerList, debugWithAsan)
|
||||
if C_FileSystem.isExecutable("/usr/bin/clang") then
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
nameMap.multilibClang[lang] or nameMap.multilibClang.en_US,
|
||||
"/usr/bin/clang", "/usr/bin/clang++",
|
||||
{isClang = true, isMultilib = true}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
table.insert(compilerList, debugWithAsan)
|
||||
end
|
||||
end
|
||||
|
||||
-- cross GCC
|
||||
if (
|
||||
arch == "x86_64" and
|
||||
C_FileSystem.exists("/proc/sys/fs/binfmt_misc/qemu-aarch64") and
|
||||
C_FileSystem.isExecutable("/usr/bin/aarch64-linux-gnu-gcc")
|
||||
) then
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
(nameMap.crossGcc[lang] or nameMap.crossGcc.en_US) .. " aarch64",
|
||||
"/usr/bin/aarch64-linux-gnu-gcc", "/usr/bin/aarch64-linux-gnu-g++",
|
||||
{}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
end
|
||||
|
||||
-- with wine or WSL init registered in binfmt_misc, Windows binaries can run seamlessly
|
||||
if (
|
||||
arch == "x86_64" and (
|
||||
C_FileSystem.exists("/proc/sys/fs/binfmt_misc/DOSWin") or
|
||||
C_FileSystem.exists("/proc/sys/fs/binfmt_misc/WSLInterop")
|
||||
)
|
||||
) then
|
||||
if C_FileSystem.isExecutable("/usr/bin/x86_64-w64-mingw32-gcc") then
|
||||
local extraObjects = {
|
||||
utf8init = libexecDir .. "/x86_64-w64-mingw32/utf8init.o",
|
||||
utf8manifest = libexecDir .. "/x86_64-w64-mingw32/utf8manifest.o",
|
||||
}
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
(nameMap.mingwGcc[lang] or nameMap.mingwGcc.en_US) .. " x86_64",
|
||||
"/usr/bin/x86_64-w64-mingw32-gcc", "/usr/bin/x86_64-w64-mingw32-g++",
|
||||
{
|
||||
isMingw = true,
|
||||
triplet = "x86_64-w64-mingw32",
|
||||
customLinkParams = {extraObjects.utf8init, extraObjects.utf8manifest},
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
-- system Clang can target Windows
|
||||
if C_FileSystem.isExecutable("/usr/bin/clang") then
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
(nameMap.mingwClang[lang] or nameMap.mingwClang.en_US) .. " x86_64",
|
||||
"/usr/bin/clang", "/usr/bin/clang++",
|
||||
{
|
||||
isClang = true,
|
||||
isMingw = true,
|
||||
triplet = "x86_64-w64-mingw32",
|
||||
customCompileParams = {"-target", "x86_64-w64-mingw32"},
|
||||
customLinkParams = {
|
||||
"-target", "x86_64-w64-mingw32",
|
||||
extraObjects.utf8init, extraObjects.utf8manifest,
|
||||
"-lstdc++", "-lwinpthread",
|
||||
},
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
end
|
||||
end
|
||||
if C_FileSystem.isExecutable("/usr/bin/i686-w64-mingw32-gcc") then
|
||||
local extraObjects = {
|
||||
utf8init = libexecDir .. "/i686-w64-mingw32/utf8init.o",
|
||||
utf8manifest = libexecDir .. "/i686-w64-mingw32/utf8manifest.o",
|
||||
}
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
(nameMap.mingwGcc[lang] or nameMap.mingwGcc.en_US) .. " i686",
|
||||
"/usr/bin/i686-w64-mingw32-gcc", "/usr/bin/i686-w64-mingw32-g++",
|
||||
{
|
||||
isMingw = true,
|
||||
triplet = "i686-w64-mingw32",
|
||||
customLinkParams = {extraObjects.utf8init, extraObjects.utf8manifest},
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
-- system Clang can target Windows
|
||||
if C_FileSystem.isExecutable("/usr/bin/clang") then
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
(nameMap.mingwClang[lang] or nameMap.mingwClang.en_US) .. " i686",
|
||||
"/usr/bin/clang", "/usr/bin/clang++",
|
||||
{
|
||||
isClang = true,
|
||||
isMingw = true,
|
||||
triplet = "i686-w64-mingw32",
|
||||
customCompileParams = {"-target", "i686-w64-mingw32"},
|
||||
customLinkParams = {
|
||||
"-target", "i686-w64-mingw32",
|
||||
extraObjects.utf8init, extraObjects.utf8manifest,
|
||||
"-lstdc++", "-lwinpthread",
|
||||
},
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local result = {
|
||||
compilerList = compilerList,
|
||||
noSearch = {
|
||||
"/usr/bin",
|
||||
"/opt/cuda/bin",
|
||||
"/usr/lib/ccache/bin",
|
||||
},
|
||||
preferCompiler = 3, -- System GCC Debug with ASan
|
||||
}
|
||||
|
||||
return result
|
|
@ -0,0 +1,247 @@
|
|||
#!/bin/bash
|
||||
|
||||
case $MSYSTEM in
|
||||
MINGW32|CLANG32)
|
||||
_NATIVE_ARCH=i686
|
||||
_DISPLAY_ARCH=x86
|
||||
;;
|
||||
MINGW64|UCRT64|CLANG64)
|
||||
_NATIVE_ARCH=x86_64
|
||||
_DISPLAY_ARCH=x64
|
||||
;;
|
||||
CLANGARM64)
|
||||
_NATIVE_ARCH=aarch64
|
||||
_DISPLAY_ARCH=arm64
|
||||
;;
|
||||
*)
|
||||
echo "This script must be run from one of following MSYS2 shells:"
|
||||
echo " - MINGW32/CLANG32"
|
||||
echo " - MINGW64/UCRT64/CLANG64"
|
||||
echo " - CLANGARM64"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
GCC_VERSION="13.2.0"
|
||||
MINGW_VERSION="rt_v11-rev1"
|
||||
LLVM_MINGW_TAG="20231128"
|
||||
WINDOWS_TERMINAL_VERSION="1.18.3181.0"
|
||||
|
||||
_QMAKE="$MINGW_PREFIX/qt5-static/bin/qmake"
|
||||
_NSIS="/mingw32/bin/makensis"
|
||||
|
||||
_MINGW32_DIR="mingw32"
|
||||
_MINGW32_TRIPLET="i686-w64-mingw32"
|
||||
_MINGW32_ARCHIVE="i686-$GCC_VERSION-release-posix-dwarf-ucrt-$MINGW_VERSION.7z"
|
||||
_MINGW32_URL="https://github.com/niXman/mingw-builds-binaries/releases/download/$GCC_VERSION-$MINGW_VERSION/$_MINGW32_ARCHIVE"
|
||||
|
||||
_MINGW64_DIR="mingw64"
|
||||
_MINGW64_TRIPLET="x86_64-w64-mingw32"
|
||||
_MINGW64_ARCHIVE="x86_64-$GCC_VERSION-release-posix-seh-ucrt-$MINGW_VERSION.7z"
|
||||
_MINGW64_URL="https://github.com/niXman/mingw-builds-binaries/releases/download/$GCC_VERSION-$MINGW_VERSION/$_MINGW64_ARCHIVE"
|
||||
|
||||
_LLVM_DIR="llvm-mingw"
|
||||
_LLVM_ARCHES=("x86_64" "i686" "aarch64" "armv7")
|
||||
_LLVM_ORIGINAL_DIR="llvm-mingw-$LLVM_MINGW_TAG-ucrt-$_NATIVE_ARCH"
|
||||
_LLVM_ARCHIVE="$_LLVM_ORIGINAL_DIR.zip"
|
||||
_LLVM_URL="https://github.com/mstorsjo/llvm-mingw/releases/download/$LLVM_MINGW_TAG/$_LLVM_ARCHIVE"
|
||||
|
||||
_WINDOWS_TERMINAL_DIR="terminal-${WINDOWS_TERMINAL_VERSION}"
|
||||
_WINDOWS_TERMINAL_ARCHIVE="Microsoft.WindowsTerminal_${WINDOWS_TERMINAL_VERSION}_$_DISPLAY_ARCH.zip"
|
||||
_WINDOWS_TERMINAL_URL="https://github.com/microsoft/terminal/releases/download/v${WINDOWS_TERMINAL_VERSION}/${_WINDOWS_TERMINAL_ARCHIVE}"
|
||||
|
||||
_SRCDIR="$PWD"
|
||||
_ASSETSDIR="$PWD/assets"
|
||||
_BUILDDIR="$TEMP/$MINGW_PACKAGE_PREFIX-redpanda-build"
|
||||
_PKGDIR="$TEMP/$MINGW_PACKAGE_PREFIX-redpanda-pkg"
|
||||
_DISTDIR="$PWD/dist"
|
||||
|
||||
_REDPANDA_VERSION=$(sed -nr -e '/APP_VERSION\s*=/ s/APP_VERSION\s*=\s*(([0-9]+\.)*[0-9]+)\s*/\1/p' "$_SRCDIR"/Red_Panda_CPP.pro)
|
||||
_REDPANDA_TESTVERSION=$(sed -nr -e '/TEST_VERSION\s*=/ s/TEST_VERSION\s*=\s*([A-Za-z0-9]*)\s*/\1/p' "$_SRCDIR"/Red_Panda_CPP.pro)
|
||||
if [[ -n $_REDPANDA_TESTVERSION ]]; then
|
||||
_REDPANDA_VERSION="$_REDPANDA_VERSION.$_REDPANDA_TESTVERSION"
|
||||
fi
|
||||
|
||||
_CLEAN=0
|
||||
_SKIP_DEPS_CHECK=0
|
||||
_7Z_REPACK=0
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--clean)
|
||||
_CLEAN=1
|
||||
shift
|
||||
;;
|
||||
--skip-deps-check)
|
||||
_SKIP_DEPS_CHECK=1
|
||||
shift
|
||||
;;
|
||||
--7z)
|
||||
_7Z_REPACK=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
function check-deps() {
|
||||
# MSYS2’s `pacman -Q` is 100x slower than Arch Linux. Allow skipping the check.
|
||||
[[ $_SKIP_DEPS_CHECK -eq 1 ]] && return
|
||||
case $MSYSTEM in
|
||||
MINGW32|MINGW64|UCRT64)
|
||||
local compiler=gcc
|
||||
;;
|
||||
CLANG32|CLANG64|CLANGARM64)
|
||||
local compiler=clang
|
||||
;;
|
||||
esac
|
||||
local deps=(
|
||||
$MINGW_PACKAGE_PREFIX-{$compiler,make,qt5-static}
|
||||
mingw-w64-i686-nsis
|
||||
)
|
||||
[[ _7Z_REPACK -eq 1 ]] || deps+=("$MINGW_PACKAGE_PREFIX-7zip")
|
||||
for dep in "${deps[@]}"; do
|
||||
pacman -Q "$dep" >/dev/null 2>&1 || (
|
||||
echo "Missing dependency: $dep"
|
||||
exit 1
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
function prepare-dirs() {
|
||||
[[ $_CLEAN -eq 1 ]] && rm -rf "$_BUILDDIR" "$_PKGDIR" || true
|
||||
mkdir -p "$_ASSETSDIR" "$_BUILDDIR" "$_PKGDIR" "$_DISTDIR"
|
||||
}
|
||||
|
||||
function download-assets() {
|
||||
if [[ $_NATIVE_ARCH == i686 ]]; then
|
||||
[[ -f "$_ASSETSDIR/$_MINGW32_ARCHIVE" ]] || curl -L -o "$_ASSETSDIR/$_MINGW32_ARCHIVE" "$_MINGW32_URL"
|
||||
fi
|
||||
if [[ $_NATIVE_ARCH == x86_64 ]]; then
|
||||
[[ -f "$_ASSETSDIR/$_MINGW64_ARCHIVE" ]] || curl -L -o "$_ASSETSDIR/$_MINGW64_ARCHIVE" "$_MINGW64_URL"
|
||||
fi
|
||||
[[ -f "$_ASSETSDIR/$_LLVM_ARCHIVE" ]] || curl -L -o "$_ASSETSDIR/$_LLVM_ARCHIVE" "$_LLVM_URL"
|
||||
[[ -f "$_ASSETSDIR/$_WINDOWS_TERMINAL_ARCHIVE" ]] || curl -L -o "$_ASSETSDIR/$_WINDOWS_TERMINAL_ARCHIVE" "$_WINDOWS_TERMINAL_URL"
|
||||
}
|
||||
|
||||
function prepare-mingw() {
|
||||
local bit="$1"
|
||||
eval local mingw_dir="\$_MINGW${bit}_DIR"
|
||||
eval local mingw_archive="\$_MINGW${bit}_ARCHIVE"
|
||||
eval local mingw_triplet="\$_MINGW${bit}_TRIPLET"
|
||||
local mingw_dir="$_BUILDDIR/$mingw_dir"
|
||||
local mingw_lib_dir="$mingw_dir/$mingw_triplet/lib"
|
||||
local mingw_shared_dir="$mingw_dir/$mingw_triplet/bin"
|
||||
local mingw_include_dir="$mingw_dir/$mingw_triplet/include"
|
||||
if [[ ! -d "$mingw_dir" ]]; then
|
||||
bsdtar -C "$_BUILDDIR" -xf "$_ASSETSDIR/$mingw_archive"
|
||||
local old_path="$PATH"
|
||||
export PATH="$mingw_dir/bin:$PATH"
|
||||
{
|
||||
gcc -Os -fno-exceptions -nodefaultlibs -nostdlib -c -o "$mingw_lib_dir/utf8init.o" "$_SRCDIR/platform/windows/utf8/utf8init.cpp"
|
||||
windres -O coff -o "$mingw_lib_dir/utf8manifest.o" "$_SRCDIR/platform/windows/utf8/utf8manifest.rc"
|
||||
}
|
||||
export PATH="$old_path"
|
||||
fi
|
||||
}
|
||||
|
||||
function prepare-llvm-mingw() {
|
||||
local llvm_dir="$_BUILDDIR/$_LLVM_DIR"
|
||||
if [[ ! -d "$llvm_dir" ]]; then
|
||||
bsdtar -C "$_BUILDDIR" -xf "$_ASSETSDIR/$_LLVM_ARCHIVE"
|
||||
mv "$_BUILDDIR/$_LLVM_ORIGINAL_DIR" "$llvm_dir"
|
||||
local old_path="$PATH"
|
||||
export PATH="$llvm_dir/bin:$PATH"
|
||||
for arch in "${_LLVM_ARCHES[@]}"; do
|
||||
local triplet="$arch-w64-mingw32"
|
||||
local lib_dir="$llvm_dir/$triplet/lib"
|
||||
$triplet-clang -Os -fno-exceptions -nodefaultlibs -nostdlib -c -o "$lib_dir/utf8init.o" "$_SRCDIR/platform/windows/utf8/utf8init.cpp"
|
||||
$triplet-windres -O coff -o "$lib_dir/utf8manifest.o" "$_SRCDIR/platform/windows/utf8/utf8manifest.rc"
|
||||
|
||||
local msvc_triplet="$arch-pc-windows-msvc"
|
||||
local lib_dir="$llvm_dir/$msvc_triplet/lib"
|
||||
mkdir -p "$lib_dir"
|
||||
$triplet-clang -target $msvc_triplet -Os -fno-exceptions -nodefaultlibs -nostdlib -c -o "$lib_dir/utf8init.o" "$_SRCDIR/platform/windows/utf8/utf8init.cpp"
|
||||
$triplet-windres -O coff -o "$lib_dir/utf8manifest.o" "$_SRCDIR/platform/windows/utf8/utf8manifest.rc"
|
||||
done
|
||||
{
|
||||
local triplet="x86_64-w64-mingw32"
|
||||
local msvc_triplet="arm64ec-pc-windows-msvc"
|
||||
local lib_dir="$llvm_dir/$msvc_triplet/lib"
|
||||
mkdir -p "$lib_dir"
|
||||
$triplet-clang -target $msvc_triplet -Os -fno-exceptions -nodefaultlibs -nostdlib -c -o "$lib_dir/utf8init.o" "$_SRCDIR/platform/windows/utf8/utf8init.cpp"
|
||||
$triplet-windres -O coff -o "$lib_dir/utf8manifest.o" "$_SRCDIR/platform/windows/utf8/utf8manifest.rc"
|
||||
}
|
||||
export PATH="$old_path"
|
||||
fi
|
||||
}
|
||||
|
||||
function prepare-openconsole() {
|
||||
local windows_terminal_dir="$_BUILDDIR/$_WINDOWS_TERMINAL_DIR"
|
||||
if [[ ! -d "$windows_terminal_dir" ]]; then
|
||||
bsdtar -C "$_BUILDDIR" -xf "$_ASSETSDIR/$_WINDOWS_TERMINAL_ARCHIVE"
|
||||
fi
|
||||
}
|
||||
|
||||
function prepare-src() {
|
||||
cp "$_SRCDIR"/RedPandaIDE/RedPandaIDE.pro{,.bak}
|
||||
sed -i '/CONFIG += ENABLE_LUA_ADDON/ { s/^#\s*// }' "$_SRCDIR"/RedPandaIDE/RedPandaIDE.pro
|
||||
}
|
||||
|
||||
function restore-src() {
|
||||
mv "$_SRCDIR"/RedPandaIDE/RedPandaIDE.pro{.bak,}
|
||||
}
|
||||
|
||||
function build() {
|
||||
pushd "$_BUILDDIR"
|
||||
"$_QMAKE" PREFIX="$_PKGDIR" "$_SRCDIR"
|
||||
time mingw32-make WINDOWS_PREFER_OPENCONSOLE=ON -j$(nproc)
|
||||
mingw32-make install
|
||||
|
||||
cp "$_SRCDIR"/packages/msys/domain/{main.nsi,lang.nsh,compiler_hint.lua} "$_PKGDIR"
|
||||
cp "$_WINDOWS_TERMINAL_DIR/OpenConsole.exe" "$_PKGDIR"
|
||||
if [[ $_NATIVE_ARCH == i686 ]]; then
|
||||
[[ -d "$_PKGDIR/mingw32" ]] || cp -r "mingw32" "$_PKGDIR"
|
||||
fi
|
||||
if [[ $_NATIVE_ARCH == x86_64 ]]; then
|
||||
[[ -d "$_PKGDIR/mingw64" ]] || cp -r "mingw64" "$_PKGDIR"
|
||||
fi
|
||||
[[ -d "$_PKGDIR/llvm-mingw" ]] || cp -r "llvm-mingw" "$_PKGDIR"
|
||||
popd
|
||||
}
|
||||
|
||||
function package() {
|
||||
pushd "$_PKGDIR"
|
||||
"$_NSIS" -DVERSION="$_REDPANDA_VERSION" -DARCH="$_DISPLAY_ARCH" main.nsi &
|
||||
"$_NSIS" -DVERSION="$_REDPANDA_VERSION" -DARCH="$_DISPLAY_ARCH" -DUSER_MODE main.nsi &
|
||||
wait
|
||||
if [[ _7Z_REPACK -eq 1 ]]; then
|
||||
7z x "redpanda-cpp-$_REDPANDA_VERSION-$_DISPLAY_ARCH-user.exe" -o"RedPanda-CPP" -xr'!$PLUGINSDIR' -x"!uninstall.exe"
|
||||
7z a -t7z -mx=9 -ms=on -mqs=on -mf=BCJ2 -m0="LZMA2:d=128m:fb=273:c=2g" "redpanda-cpp-$_REDPANDA_VERSION-$_DISPLAY_ARCH.7z" "RedPanda-CPP"
|
||||
rm -rf "RedPanda-CPP"
|
||||
fi
|
||||
popd
|
||||
}
|
||||
|
||||
function dist() {
|
||||
cp "$_PKGDIR/redpanda-cpp-$_REDPANDA_VERSION-$_DISPLAY_ARCH-system.exe" "$_DISTDIR"
|
||||
cp "$_PKGDIR/redpanda-cpp-$_REDPANDA_VERSION-$_DISPLAY_ARCH-user.exe" "$_DISTDIR"
|
||||
[[ _7Z_REPACK -eq 1 ]] && cp "$_PKGDIR/redpanda-cpp-$_REDPANDA_VERSION-$_DISPLAY_ARCH.7z" "$_DISTDIR"
|
||||
}
|
||||
|
||||
check-deps
|
||||
prepare-dirs
|
||||
download-assets
|
||||
[[ $_NATIVE_ARCH == i686 ]] && prepare-mingw 32
|
||||
[[ $_NATIVE_ARCH == x86_64 ]] && prepare-mingw 64
|
||||
prepare-llvm-mingw
|
||||
prepare-openconsole
|
||||
prepare-src
|
||||
trap restore-src EXIT INT TERM
|
||||
build
|
||||
package
|
||||
dist
|
|
@ -0,0 +1,386 @@
|
|||
local arch = C_System.osArch()
|
||||
local appArch = C_System.appArch()
|
||||
local libexecDir = C_System.appLibexecDir()
|
||||
local lang = C_Desktop.language()
|
||||
local supportedAppArches = C_System.supportedAppArchList()
|
||||
|
||||
local gnuArchMap = {
|
||||
i386 = "i686",
|
||||
x86_64 = "x86_64",
|
||||
arm = "armv7",
|
||||
arm64 = "aarch64",
|
||||
}
|
||||
|
||||
local profileNameMap = {
|
||||
release = {
|
||||
en_US = "release",
|
||||
pt_BR = "lançamento",
|
||||
zh_CN = "发布",
|
||||
zh_TW = "發佈",
|
||||
},
|
||||
debug = {
|
||||
en_US = "debug",
|
||||
pt_BR = "depuração",
|
||||
zh_CN = "调试",
|
||||
zh_TW = "偵錯",
|
||||
},
|
||||
debugWithAsan = {
|
||||
en_US = "debug with ASan",
|
||||
pt_BR = "depuração com ASan",
|
||||
zh_CN = "ASan 调试",
|
||||
zh_TW = "ASan 偵錯",
|
||||
},
|
||||
}
|
||||
|
||||
local nameGenerator = {
|
||||
mingwGcc = function (lang, arch, profile, isUtf8)
|
||||
local template = {
|
||||
en_US = "MinGW GCC %1 in %2, %3",
|
||||
pt_BR = "GCC MinGW %1 em %2, %3",
|
||||
zh_CN = "%2 MinGW GCC %1,%3",
|
||||
zh_TW = "%2 MinGW GCC %1,%3",
|
||||
}
|
||||
local systemCodePage = {
|
||||
en_US = "system code page",
|
||||
pt_Br = "página de código do sistema",
|
||||
zh_CN = "系统代码页",
|
||||
zh_TW = "系統代碼頁",
|
||||
}
|
||||
return C_Util.format(
|
||||
template[lang] or template.en_US,
|
||||
gnuArchMap[arch],
|
||||
isUtf8 and "UTF-8" or systemCodePage[lang] or systemCodePage.en_US,
|
||||
profileNameMap[profile][lang] or profileNameMap[profile].en_US
|
||||
)
|
||||
end,
|
||||
clang = function (lang, arch, profile, isMingw)
|
||||
local template = {
|
||||
en_US = "%1 Clang %2, %3",
|
||||
pt_BR = "Clang %2 %1, %3",
|
||||
zh_CN = "%1 Clang %2,%3",
|
||||
zh_CN = "%1 Clang %2,%3",
|
||||
}
|
||||
local msvcCompatible = {
|
||||
en_US = "MSVC-compatible",
|
||||
pt_BR = "compatível com MSVC",
|
||||
zh_CN = "兼容 MSVC 的",
|
||||
zh_TW = "相容 MSVC 的",
|
||||
}
|
||||
return C_Util.format(
|
||||
template[lang] or template.en_US,
|
||||
isMingw and "LLVM-MinGW" or msvcCompatible[lang] or msvcCompatible.en_US,
|
||||
gnuArchMap[arch],
|
||||
profileNameMap[profile][lang] or profileNameMap[profile].en_US
|
||||
)
|
||||
end,
|
||||
}
|
||||
|
||||
function generateConfig(nameGen, programs, config)
|
||||
local commonOptions = {
|
||||
cCompiler = programs.cCompiler,
|
||||
cxxCompiler = programs.cxxCompiler,
|
||||
debugger = programs.debugger,
|
||||
debugServer = programs.debugServer,
|
||||
make = programs.make,
|
||||
resourceCompiler = programs.resourceCompiler,
|
||||
binDirs = programs.binDirs,
|
||||
compilerType = config.isClang and "Clang" or "GCC_UTF8",
|
||||
preprocessingSuffix = ".i",
|
||||
compilationProperSuffix = ".s",
|
||||
assemblingSuffix = ".o",
|
||||
executableSuffix = ".exe",
|
||||
compilationStage = 3,
|
||||
ccCmdOptUsePipe = "on",
|
||||
ccCmdOptWarningAll = "on",
|
||||
ccCmdOptWarningExtra = "on",
|
||||
ccCmdOptCheckIsoConformance = "on",
|
||||
}
|
||||
if programs.libDirs then
|
||||
commonOptions.libDirs = programs.libDirs
|
||||
end
|
||||
if config.isAnsi then
|
||||
commonOptions.execCharset = "SYSTEM"
|
||||
end
|
||||
if config.customCompileParams then
|
||||
commonOptions.customCompileParams = config.customCompileParams
|
||||
end
|
||||
if config.customLinkParams then
|
||||
commonOptions.customLinkParams = config.customLinkParams
|
||||
end
|
||||
local release = {
|
||||
name = nameGen(config.arch, "release"),
|
||||
staticLink = true,
|
||||
linkCmdOptStripExe = "on",
|
||||
ccCmdOptOptimize = "2",
|
||||
}
|
||||
local debug = {
|
||||
name = nameGen(config.arch, "debug"),
|
||||
ccCmdOptDebugInfo = "on",
|
||||
}
|
||||
local debugWithAsan = {
|
||||
name = nameGen(config.arch, "debugWithAsan"),
|
||||
ccCmdOptDebugInfo = "on",
|
||||
ccCmdOptAddressSanitizer = "address",
|
||||
}
|
||||
for k, v in pairs(commonOptions) do
|
||||
release[k] = v
|
||||
debug[k] = v
|
||||
debugWithAsan[k] = v
|
||||
end
|
||||
return release, debug, debugWithAsan
|
||||
end
|
||||
|
||||
function contains(t, v)
|
||||
for _, vv in ipairs(t) do
|
||||
if vv == v then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local compilerList = {}
|
||||
local noSearch = {}
|
||||
local preferCompiler = 0
|
||||
|
||||
function checkAndAddMingw(arch)
|
||||
local binDir
|
||||
local libDir
|
||||
local excludeBinDir
|
||||
if arch == "i386" then
|
||||
binDir = libexecDir .. "/mingw32/bin" -- must match case because Windows filesystem can be case sensitive
|
||||
libDir = libexecDir .. "/mingw32/i686-w64-mingw32/lib"
|
||||
excludeBinDir = libexecDir .. "/MinGW32/bin" -- workaround for path check
|
||||
elseif arch == "x86_64" then
|
||||
binDir = libexecDir .. "/mingw64/bin"
|
||||
libDir = libexecDir .. "/mingw64/x86_64-w64-mingw32/lib"
|
||||
excludeBinDir = libexecDir .. "/MinGW64/bin"
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
if not C_FileSystem.isExecutable(binDir .. "/gcc.exe") then
|
||||
return
|
||||
end
|
||||
|
||||
local programs = {
|
||||
cCompiler = binDir .. "/gcc.exe",
|
||||
cxxCompiler = binDir .. "/g++.exe",
|
||||
make = binDir .. "/mingw32-make.exe",
|
||||
debugger = binDir .. "/gdb.exe",
|
||||
debugServer = binDir .. "/gdbserver.exe",
|
||||
resourceCompiler = binDir .. "/windres.exe",
|
||||
binDirs = {binDir},
|
||||
}
|
||||
local extraObjects = {
|
||||
utf8init = libDir .. "/utf8init.o",
|
||||
utf8manifest = libDir .. "/utf8manifest.o",
|
||||
}
|
||||
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
function (arch, profile) return nameGenerator.mingwGcc(lang, arch, profile, true) end,
|
||||
programs,
|
||||
{
|
||||
arch = arch,
|
||||
customLinkParams = {extraObjects.utf8init, extraObjects.utf8manifest},
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
if preferCompiler == 0 then
|
||||
preferCompiler = 2
|
||||
end
|
||||
|
||||
release, debug, debugWithAsan = generateConfig(
|
||||
function (arch, profile) return nameGenerator.mingwGcc(lang, arch, profile, false) end,
|
||||
programs,
|
||||
{
|
||||
arch = arch,
|
||||
isAnsi = true,
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
|
||||
table.insert(noSearch, excludeBinDir)
|
||||
end
|
||||
|
||||
function checkAndAddClang()
|
||||
if not C_FileSystem.isExecutable(libexecDir .. "/llvm-mingw/bin/clang.exe") then
|
||||
return
|
||||
end
|
||||
|
||||
-- appArch is always debuggable
|
||||
local appTriplet = gnuArchMap[appArch] .. "-w64-mingw32"
|
||||
local binDir = libexecDir .. "/llvm-mingw/bin"
|
||||
local libDir = libexecDir .. "/llvm-mingw/" .. appTriplet .. "/lib"
|
||||
local programs = {
|
||||
cCompiler = binDir .. "/" .. appTriplet .. "-clang.exe",
|
||||
cxxCompiler = binDir .. "/" .. appTriplet .. "-clang++.exe",
|
||||
make = binDir .. "/mingw32-make.exe",
|
||||
debugger = binDir .. "/lldb-mi.exe",
|
||||
debugServer = binDir .. "/lldb-server.exe",
|
||||
resourceCompiler = binDir .. "/" .. appTriplet .. "-windres.exe",
|
||||
binDirs = {binDir},
|
||||
}
|
||||
local extraObjects = {
|
||||
utf8init = libDir .. "/utf8init.o",
|
||||
utf8manifest = libDir .. "/utf8manifest.o",
|
||||
}
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
function (arch, profile) return nameGenerator.clang(lang, arch, profile, true) end,
|
||||
programs,
|
||||
{
|
||||
arch = appArch,
|
||||
customLinkParams = {extraObjects.utf8init, extraObjects.utf8manifest},
|
||||
isClang = true,
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
if appArch ~= "arm64" then
|
||||
table.insert(compilerList, debugWithAsan)
|
||||
if preferCompiler == 0 then
|
||||
preferCompiler = 3
|
||||
end
|
||||
else
|
||||
if preferCompiler == 0 then
|
||||
preferCompiler = 2
|
||||
end
|
||||
end
|
||||
|
||||
for _, foreignArch in ipairs(supportedAppArches) do
|
||||
if foreignArch ~= appArch then
|
||||
local foreignTriplet = gnuArchMap[foreignArch] .. "-w64-mingw32"
|
||||
local libDir = libexecDir .. "/llvm-mingw/" .. foreignTriplet .. "/lib"
|
||||
local programs = {
|
||||
cCompiler = binDir .. "/" .. foreignTriplet .. "-clang.exe",
|
||||
cxxCompiler = binDir .. "/" .. foreignTriplet .. "-clang++.exe",
|
||||
make = binDir .. "/mingw32-make.exe",
|
||||
debugger = binDir .. "/lldb-mi.exe",
|
||||
debugServer = binDir .. "/lldb-server.exe",
|
||||
resourceCompiler = binDir .. "/" .. foreignTriplet .. "-windres.exe",
|
||||
binDirs = {binDir},
|
||||
}
|
||||
local extraObjects = {
|
||||
utf8init = libDir .. "/utf8init.o",
|
||||
utf8manifest = libDir .. "/utf8manifest.o",
|
||||
}
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
function (arch, profile) return nameGenerator.clang(lang, arch, profile, true) end,
|
||||
programs,
|
||||
{
|
||||
arch = foreignArch,
|
||||
customLinkParams = {extraObjects.utf8init, extraObjects.utf8manifest},
|
||||
isClang = true,
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(noSearch, binDir)
|
||||
|
||||
local llvmOrgPath = C_System.readRegistry([[Software\LLVM\LLVM]], "") or C_System.readRegistry([[Software\Wow6432Node\LLVM\LLVM]], "")
|
||||
if not llvmOrgPath then
|
||||
return
|
||||
end
|
||||
|
||||
local llvmOrgBinDir = llvmOrgPath .. "/bin"
|
||||
local msvcTriplet = gnuArchMap[appArch] .. "-pc-windows-msvc"
|
||||
local libDir = libexecDir .. "/llvm-mingw/" .. msvcTriplet .. "/lib"
|
||||
local programs = {
|
||||
cCompiler = llvmOrgBinDir .. "/clang.exe",
|
||||
cxxCompiler = llvmOrgBinDir .. "/clang++.exe",
|
||||
make = binDir .. "/mingw32-make.exe",
|
||||
debugger = binDir .. "/lldb-mi.exe",
|
||||
debugServer = binDir .. "/lldb-server.exe",
|
||||
resourceCompiler = binDir .. "/" .. appTriplet .. "-windres.exe",
|
||||
binDirs = {llvmOrgBinDir},
|
||||
libDirs = {libDir},
|
||||
}
|
||||
local extraObjects = {
|
||||
utf8init = libDir .. "/utf8init.o",
|
||||
utf8manifest = libDir .. "/utf8manifest.o",
|
||||
}
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
function (arch, profile) return nameGenerator.clang(lang, arch, profile, false) end,
|
||||
programs,
|
||||
{
|
||||
arch = appArch,
|
||||
customCompileParams = {
|
||||
"-target", msvcTriplet,
|
||||
"-fms-extensions",
|
||||
"-fms-compatibility",
|
||||
"-fdelayed-template-parsing",
|
||||
},
|
||||
customLinkParams = {
|
||||
"-target", msvcTriplet,
|
||||
extraObjects.utf8init, extraObjects.utf8manifest,
|
||||
},
|
||||
isClang = true,
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
table.insert(compilerList, debug)
|
||||
|
||||
for _, foreignArch in ipairs(supportedAppArches) do
|
||||
if foreignArch ~= appArch then
|
||||
local foreignTriplet = gnuArchMap[foreignArch] .. "-w64-mingw32"
|
||||
local msvcTriplet = gnuArchMap[foreignArch] .. "-pc-windows-msvc"
|
||||
local libDir = libexecDir .. "/llvm-mingw/" .. msvcTriplet .. "/lib"
|
||||
local programs = {
|
||||
cCompiler = llvmOrgBinDir .. "/clang.exe",
|
||||
cxxCompiler = llvmOrgBinDir .. "/clang++.exe",
|
||||
make = binDir .. "/mingw32-make.exe",
|
||||
debugger = binDir .. "/lldb-mi.exe",
|
||||
debugServer = binDir .. "/lldb-server.exe",
|
||||
resourceCompiler = binDir .. "/" .. foreignTriplet .. "-windres.exe",
|
||||
binDirs = {llvmOrgBinDir},
|
||||
libDirs = {libDir},
|
||||
}
|
||||
local extraObjects = {
|
||||
utf8init = libDir .. "/utf8init.o",
|
||||
utf8manifest = libDir .. "/utf8manifest.o",
|
||||
}
|
||||
local release, debug, debugWithAsan = generateConfig(
|
||||
function (arch, profile) return nameGenerator.clang(lang, arch, profile, false) end,
|
||||
programs,
|
||||
{
|
||||
arch = foreignArch,
|
||||
customCompileParams = {
|
||||
"-target", msvcTriplet,
|
||||
"-fms-extensions",
|
||||
"-fms-compatibility",
|
||||
"-fdelayed-template-parsing",
|
||||
},
|
||||
customLinkParams = {
|
||||
"-target", msvcTriplet,
|
||||
extraObjects.utf8init, extraObjects.utf8manifest,
|
||||
},
|
||||
isClang = true,
|
||||
}
|
||||
)
|
||||
table.insert(compilerList, release)
|
||||
end
|
||||
end
|
||||
table.insert(noSearch, llvmOrgBinDir)
|
||||
end
|
||||
|
||||
if appArch == "x86_64" then
|
||||
checkAndAddMingw("x86_64")
|
||||
checkAndAddClang()
|
||||
elseif appArch == "arm64" then
|
||||
checkAndAddClang()
|
||||
else
|
||||
checkAndAddMingw("i386")
|
||||
checkAndAddClang()
|
||||
end
|
||||
|
||||
local result = {
|
||||
compilerList = compilerList,
|
||||
noSearch = noSearch,
|
||||
preferCompiler = preferCompiler,
|
||||
}
|
||||
|
||||
return result
|
|
@ -0,0 +1,65 @@
|
|||
/* English 1033 */
|
||||
LangString MessageAppName 1033 "Red Panda C++"
|
||||
LangString Message64bitBuildWarning 1033 "Note: installing Red Panda C++ x86 on 64-bit OS. There are 64-bit builds."
|
||||
LangString MessageArm64BuildWarning 1033 "Note: installing Red Panda C++ x64 on ARM64. There is native ARM64 build."
|
||||
LangString MessageWin10v1809RecommendedWarning 1033 "Note: Windows 10 version 1809 or later recommeded."
|
||||
LangString Message64bitRequiredError 1033 "Unsupported operating system! 64-bit OS required."
|
||||
LangString MessageArm64RequiredError 1033 "Unsupported operating system! ARM64 OS required."
|
||||
LangString MessageWin7RequiredError 1033 "Unsupported operating system! Windows 7 or later required."
|
||||
LangString MessageWin11RequiredError 1033 "Unsupported operating system! Windows 11 or later required."
|
||||
LangString MessageSectionMain 1033 "The Red Panda C++ IDE (Integrated Development Environment)."
|
||||
LangString MessageSectionOpenConsole 1033 "UTF-8 compatible OpenConsole.exe terminal emulator from Windows Terminal."
|
||||
LangString MessageSectionMingw32 1033 "The MinGW GCC x86 compiler and associated tools, headers and libraries."
|
||||
LangString MessageSectionMingw64 1033 "The MinGW GCC x64 compiler and associated tools, headers and libraries."
|
||||
LangString MessageSectionLlvm 1033 "The LLVM MinGW compiler and associated tools, headers and libraries."
|
||||
LangString MessageSectionAssocs 1033 "Use Red Panda C++ as the default application for opening these types of files."
|
||||
LangString MessageSectionShortcuts 1033 "Create shortcuts to Red Panda C++ in various folders."
|
||||
LangString MessageSectionConfig 1033 "Remove all leftover configuration files from previous installs."
|
||||
LangString MessageUninstallText 1033 "This program will uninstall Red Panda C++, continue?"
|
||||
LangString MessageUninstallExisting 1033 "Red Panda C++ is already installed.$\n$\nClick OK to remove the previous version or Cancel to cancel the installation."
|
||||
LangString MessageRemoveConfig 1033 "Do you want to remove all the remaining configuration files?"
|
||||
LangString SectionMainName 1033 "Program files (required)"
|
||||
LangString SectionOpenConsoleName 1033 "OpenConsole.exe terminal emulator"
|
||||
LangString SectionMingw32Name 1033 "MinGW GCC x86 compiler"
|
||||
LangString SectionMingw64Name 1033 "MinGW GCC x64 compiler"
|
||||
LangString SectionLlvmName 1033 "LLVM MinGW compiler"
|
||||
LangString SectionAssocsName 1033 "Associate files to Red Panda C++"
|
||||
LangString SectionAssocExtNameBegin 1033 "Associate"
|
||||
LangString SectionAssocExtNameEnd 1033 "files to Red Panda C++"
|
||||
LangString SectionShortcutsName 1033 "Shortcuts"
|
||||
LangString SectionMenuLaunchName 1033 "Create Start Menu shortcuts"
|
||||
LangString SectionDesktopLaunchName 1033 "Create Desktop shortcut"
|
||||
LangString SectionConfigName 1033 "Remove old configuration files"
|
||||
|
||||
/* Simplified Chinese 2052 */
|
||||
LangString MessageAppName 2052 "小熊猫 C++"
|
||||
LangString Message64bitBuildWarning 2052 "提示:正在把 x86 小熊猫 C++ 安装到 64 位操作系统上。小熊猫 C++ 有 64 位版本。"
|
||||
LangString MessageArm64BuildWarning 2052 "提示:正在把 x64 小熊猫 C++ 安装到 ARM64 系统上。小熊猫 C++ 有原生 ARM64 版本。"
|
||||
LangString MessageWin10v1809RecommendedWarning 2052 "提示:建议使用 Windows 10 1809 或更高版本。"
|
||||
LangString Message64bitRequiredError 2052 "不支持的操作系统!需要 64 位操作系统。"
|
||||
LangString MessageArm64RequiredError 2052 "不支持的操作系统!需要 ARM64 操作系统。"
|
||||
LangString MessageWin7RequiredError 2052 "不支持的操作系统!需要 Windows 7 或更高版本。"
|
||||
LangString MessageWin11RequiredError 2052 "不支持的操作系统!需要 Windows 11 或更高版本。"
|
||||
LangString MessageSectionMain 2052 "小熊猫 C++ IDE(集成开发环境)。"
|
||||
LangString MessageSectionOpenConsole 2052 "兼容 UTF-8 的 OpenConsole.exe 终端模拟器,来自 Windows 终端。"
|
||||
LangString MessageSectionMingw32 2052 "MinGW GCC x86 编译器和相关的工具、头文件和库。"
|
||||
LangString MessageSectionMingw64 2052 "MinGW GCC x64 编译器和相关的工具、头文件和库。"
|
||||
LangString MessageSectionLlvm 2052 "LLVM MinGW 编译器和相关的工具、头文件和库。"
|
||||
LangString MessageSectionAssocs 2052 "使用小熊猫 C++ 打开这些文件。"
|
||||
LangString MessageSectionShortcuts 2052 "开始菜单和快捷方式。"
|
||||
LangString MessageSectionConfig 2052 "删除之前安装遗留的所有配置文件。"
|
||||
LangString MessageUninstallText 2052 "将要删除小熊猫 C++,是否继续?"
|
||||
LangString MessageUninstallExisting 2052 "本机上已经安装了旧版本小熊猫 C++。 $\n$\n点击“确定”以将其删除并继续,或者“取消”中止安装。"
|
||||
LangString MessageRemoveConfig 2052 "你想要删除所有的配置文件吗?"
|
||||
LangString SectionMainName 2052 "程序文件(必需)"
|
||||
LangString SectionOpenConsoleName 2052 "OpenConsole.exe 终端模拟器"
|
||||
LangString SectionMingw32Name 2052 "MinGW GCC x86 编译器"
|
||||
LangString SectionMingw64Name 2052 "MinGW GCC x64 编译器"
|
||||
LangString SectionLlvmName 2052 "LLVM MinGW 编译器"
|
||||
LangString SectionAssocsName 2052 "关联文件到小熊猫C++"
|
||||
LangString SectionAssocExtNameBegin 2052 "将"
|
||||
LangString SectionAssocExtNameEnd 2052 "文件关联到小熊猫 C++"
|
||||
LangString SectionShortcutsName 2052 "快捷方式"
|
||||
LangString SectionMenuLaunchName 2052 "创建开始菜单程序项"
|
||||
LangString SectionDesktopLaunchName 2052 "创建桌面快捷方式"
|
||||
LangString SectionConfigName 2052 "删除原有配置文件"
|
|
@ -0,0 +1,456 @@
|
|||
####################################################################
|
||||
# Startup
|
||||
|
||||
CRCCheck on
|
||||
SetCompressor /SOLID /FINAL lzma
|
||||
SetCompressorDictSize 128
|
||||
SetDatablockOptimize on
|
||||
Unicode True
|
||||
|
||||
!ifdef USER_MODE
|
||||
!define MODE "user"
|
||||
!else
|
||||
!define MODE "system"
|
||||
!endif
|
||||
!define FINALNAME "redpanda-cpp-${VERSION}-${ARCH}-${MODE}.exe"
|
||||
!define DISPLAY_NAME "Red Panda C++ ${VERSION} (${ARCH} ${MODE})"
|
||||
|
||||
!include "x64.nsh"
|
||||
!include "WinVer.nsh"
|
||||
!include "MUI2.nsh"
|
||||
!include "lang.nsh"
|
||||
|
||||
!define MUI_CUSTOMFUNCTION_GUIINIT myGuiInit
|
||||
|
||||
####################################################################
|
||||
# Installer Attributes
|
||||
|
||||
Name "${DISPLAY_NAME}"
|
||||
OutFile "${FINALNAME}"
|
||||
Caption "${DISPLAY_NAME}"
|
||||
|
||||
LicenseData "LICENSE"
|
||||
|
||||
!ifdef USER_MODE
|
||||
RequestExecutionLevel user
|
||||
InstallDir "$LOCALAPPDATA\RedPanda-CPP"
|
||||
!else
|
||||
RequestExecutionLevel admin
|
||||
!if "${ARCH}" == "x86"
|
||||
InstallDir "$PROGRAMFILES\RedPanda-CPP"
|
||||
!else
|
||||
InstallDir "$PROGRAMFILES64\RedPanda-CPP"
|
||||
!endif
|
||||
!endif
|
||||
|
||||
####################################################################
|
||||
# Interface Settings
|
||||
|
||||
ShowInstDetails show
|
||||
AutoCloseWindow false
|
||||
SilentInstall normal
|
||||
SetOverwrite try
|
||||
XPStyle on
|
||||
ManifestDPIAware true
|
||||
|
||||
InstType "Full" ;1
|
||||
InstType "Minimal" ;2
|
||||
|
||||
## Remember the installer language
|
||||
!ifdef USER_MODE
|
||||
!define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
|
||||
!else
|
||||
!define MUI_LANGDLL_REGISTRY_ROOT "HKLM"
|
||||
!endif
|
||||
!define MUI_LANGDLL_REGISTRY_KEY "Software\RedPanda-C++"
|
||||
!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
|
||||
|
||||
####################################################################
|
||||
# Pages
|
||||
|
||||
!define MUI_ICON "devcpp.ico"
|
||||
!define MUI_UNICON "devcpp.ico"
|
||||
!define MUI_ABORTWARNING
|
||||
!define MUI_LANGDLL_ALLLANGUAGES
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\RedPandaIDE.exe"
|
||||
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
|
||||
!insertmacro MUI_PAGE_LICENSE "LICENSE"
|
||||
!insertmacro MUI_PAGE_COMPONENTS
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
####################################################################
|
||||
# Languages
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "SimpChinese"
|
||||
|
||||
####################################################################
|
||||
# Files, by option section
|
||||
|
||||
Section "$(SectionMainName)" SectionMain
|
||||
SectionIn 1 2 RO
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Allways create an uninstaller
|
||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||
!ifdef USER_MODE
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "DisplayName" "Red Panda C++"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "InstallLocation" "$INSTDIR"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "UninstallString" "$INSTDIR\uninstall.exe"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "DisplayVersion" "${VERSION}"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "DisplayIcon" "$INSTDIR\RedPandaIDE.exe"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "Publisher" "Roy Qu (royqh1979@gmail.com)"
|
||||
!else
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "DisplayName" "Red Panda C++"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "InstallLocation" "$INSTDIR"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "UninstallString" "$INSTDIR\uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "DisplayVersion" "${VERSION}"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "DisplayIcon" "$INSTDIR\RedPandaIDE.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "Publisher" "Roy Qu (royqh1979@gmail.com)"
|
||||
!endif
|
||||
|
||||
; Write required files
|
||||
File "RedPandaIDE.exe"
|
||||
File "consolepauser.exe"
|
||||
File "redpanda-win-git-askpass.exe"
|
||||
File "astyle.exe"
|
||||
File "qt.conf"
|
||||
File "LICENSE"
|
||||
File "NEWS.md"
|
||||
File "README.md"
|
||||
File "compiler_hint.lua"
|
||||
|
||||
; Write required paths
|
||||
SetOutPath $INSTDIR\templates
|
||||
File /nonfatal /r "templates\*"
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionOpenConsoleName)" SectionOpenConsole
|
||||
SectionIn 1
|
||||
SetOutPath $INSTDIR
|
||||
File "OpenConsole.exe"
|
||||
SectionEnd
|
||||
|
||||
!if "${ARCH}" == "x86"
|
||||
Section "$(SectionMingw32Name)" SectionMingw32
|
||||
SectionIn 1
|
||||
SetOutPath $INSTDIR\mingw32
|
||||
File /nonfatal /r "mingw32\*"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
!if "${ARCH}" == "x64"
|
||||
Section "$(SectionMingw64Name)" SectionMingw64
|
||||
SectionIn 1
|
||||
SetOutPath $INSTDIR\mingw64
|
||||
File /nonfatal /r "mingw64\*"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
Section "$(SectionLlvmName)" SectionLlvm
|
||||
SectionIn 1
|
||||
SetOutPath $INSTDIR\llvm-mingw
|
||||
File /nonfatal /r "llvm-mingw\*"
|
||||
SectionEnd
|
||||
|
||||
####################################################################
|
||||
# File association
|
||||
SectionGroup "$(SectionAssocsName)" SectionAssocs
|
||||
Section "$(SectionAssocExtNameBegin) .dev $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".dev" "" "DevCpp.dev"
|
||||
WriteRegStr HKCR "DevCpp.dev" "" "Dev-C++ Project File"
|
||||
WriteRegStr HKCR "DevCpp.dev\DefaultIcon" "" '$0,3'
|
||||
WriteRegStr HKCR "DevCpp.dev\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .c $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".c" "" "DevCpp.c"
|
||||
WriteRegStr HKCR "DevCpp.c" "" "C Source File"
|
||||
WriteRegStr HKCR "DevCpp.c\DefaultIcon" "" '$0,4'
|
||||
WriteRegStr HKCR "DevCpp.c\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .cpp $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".cpp" "" "DevCpp.cpp"
|
||||
WriteRegStr HKCR "DevCpp.cpp" "" "C++ Source File"
|
||||
WriteRegStr HKCR "DevCpp.cpp\DefaultIcon" "" '$0,5'
|
||||
WriteRegStr HKCR "DevCpp.cpp\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .cxx $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".cxx" "" "DevCpp.cxx"
|
||||
WriteRegStr HKCR "DevCpp.cxx" "" "C++ Source File"
|
||||
WriteRegStr HKCR "DevCpp.cxx\DefaultIcon" "" '$0,5'
|
||||
WriteRegStr HKCR "DevCpp.cxx\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .cc $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".cc" "" "DevCpp.cc"
|
||||
WriteRegStr HKCR "DevCpp.cc" "" "C++ Source File"
|
||||
WriteRegStr HKCR "DevCpp.cc\DefaultIcon" "" '$0,5'
|
||||
WriteRegStr HKCR "DevCpp.cc\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .hxx $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".hxx" "" "DevCpp.hxx"
|
||||
WriteRegStr HKCR "DevCpp.hxx" "" "C++ Header File"
|
||||
WriteRegStr HKCR "DevCpp.hxx\DefaultIcon" "" '$0,7'
|
||||
WriteRegStr HKCR "DevCpp.hxx\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .h $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".h" "" "DevCpp.h"
|
||||
WriteRegStr HKCR "DevCpp.h" "" "C Header File"
|
||||
WriteRegStr HKCR "DevCpp.h\DefaultIcon" "" '$0,6'
|
||||
WriteRegStr HKCR "DevCpp.h\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionAssocExtNameBegin) .hpp $(SectionAssocExtNameEnd)"
|
||||
SectionIn 1
|
||||
|
||||
StrCpy $0 $INSTDIR\RedPandaIDE.exe
|
||||
WriteRegStr HKCR ".hpp" "" "DevCpp.hpp"
|
||||
WriteRegStr HKCR "DevCpp.hpp" "" "C++ Header File"
|
||||
WriteRegStr HKCR "DevCpp.hpp\DefaultIcon" "" '$0,7'
|
||||
WriteRegStr HKCR "DevCpp.hpp\Shell\Open\Command" "" '$0 "%1"'
|
||||
SectionEnd
|
||||
SectionGroupEnd
|
||||
|
||||
####################################################################
|
||||
# Shortcuts
|
||||
SectionGroup "$(SectionShortcutsName)" SectionShortcuts
|
||||
Section "$(SectionMenuLaunchName)" SectionMenuLaunch
|
||||
SectionIn 1 2
|
||||
|
||||
StrCpy $0 $SMPROGRAMS ; start menu Programs folder
|
||||
CreateDirectory "$0\$(MessageAppName)"
|
||||
CreateShortCut "$0\$(MessageAppName)\$(MessageAppName).lnk" "$INSTDIR\RedPandaIDE.exe"
|
||||
CreateShortCut "$0\$(MessageAppName)\License.lnk" "$INSTDIR\LICENSE"
|
||||
CreateShortCut "$0\$(MessageAppName)\Uninstall $(MessageAppName).lnk" "$INSTDIR\uninstall.exe"
|
||||
SectionEnd
|
||||
|
||||
Section "$(SectionDesktopLaunchName)" SectionDesktopLaunch
|
||||
SectionIn 1 2
|
||||
|
||||
CreateShortCut "$DESKTOP\$(MessageAppName).lnk" "$INSTDIR\RedPandaIDE.exe"
|
||||
SectionEnd
|
||||
SectionGroupEnd
|
||||
|
||||
!ifdef USER_MODE
|
||||
Section "$(SectionConfigName)" SectionConfig
|
||||
RMDir /r "$APPDATA\RedPandaIDE"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
####################################################################
|
||||
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionMain} "$(MessageSectionMain)"
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionOpenConsole} "$(MessageSectionOpenConsole)"
|
||||
!if "${ARCH}" == "x86"
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionMingw32} "$(MessageSectionMingw32)"
|
||||
!endif
|
||||
!if "${ARCH}" == "x64"
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionMingw64} "$(MessageSectionMingw64)"
|
||||
!endif
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionLlvm} "$(MessageSectionLlvm)"
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionShortcuts} "$(MessageSectionShortcuts)"
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionAssocs} "$(MessageSectionAssocs)"
|
||||
!ifdef USER_MODE
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionConfig} "$(MessageSectionConfig)"
|
||||
!endif
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
|
||||
####################################################################
|
||||
# Functions, utilities
|
||||
|
||||
Function .onInit
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
!if "${ARCH}" != "x86"
|
||||
SetRegView 64
|
||||
!endif
|
||||
!ifdef USER_MODE
|
||||
SetShellVarContext current
|
||||
!else
|
||||
SetShellVarContext all
|
||||
!endif
|
||||
${IfNot} ${AtLeastBuild} 17763 ; OpenConsole.exe requires Windows 10 v1809 ConPTY
|
||||
!if "${ARCH}" == "x86"
|
||||
${OrIfNot} ${IsNativeIA32} ; OpenConsole.exe x86 only works on x86, while x64 works on arm64
|
||||
!endif
|
||||
SectionSetFlags ${SectionOpenConsole} ${SF_RO}
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function myGuiInit
|
||||
${IfNot} ${AtLeastWin7}
|
||||
MessageBox MB_OK|MB_ICONSTOP "$(MessageWin7RequiredError)"
|
||||
Abort
|
||||
${EndIf}
|
||||
${IfNot} ${AtLeastBuild} 17763
|
||||
MessageBox MB_OK|MB_ICONSTOP "$(MessageWin10v1809RecommendedWarning)"
|
||||
${EndIf}
|
||||
!if "${ARCH}" == "x86"
|
||||
${If} ${IsNativeAMD64}
|
||||
${OrIf} ${IsNativeARM64}
|
||||
# note user if installing x86 on 64-bit OS
|
||||
MessageBox MB_OK|MB_ICONINFORMATION "$(Message64bitBuildWarning)"
|
||||
${EndIf}
|
||||
!else if "${ARCH}" == "x64"
|
||||
${If} ${IsNativeIA32}
|
||||
MessageBox MB_OK|MB_ICONSTOP "$(Message64bitRequiredError)"
|
||||
Abort
|
||||
${ElseIf} ${IsNativeARM64}
|
||||
# x64 can be installed on arm64 ...
|
||||
MessageBox MB_OK|MB_ICONINFORMATION "$(MessageArm64BuildWarning)"
|
||||
# ... but only works since Windows 11
|
||||
${IfNot} ${AtLeastBuild} 22000
|
||||
MessageBox MB_OK|MB_ICONSTOP "$(MessageWin11RequiredError)"
|
||||
Abort
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
!else if "${ARCH}" == "arm64"
|
||||
${IfNot} ${IsNativeARM64}
|
||||
MessageBox MB_OK|MB_ICONSTOP "$(MessageArm64RequiredError)"
|
||||
Abort
|
||||
${EndIf}
|
||||
!endif
|
||||
|
||||
SetRegView 32
|
||||
Call UninstallExisting
|
||||
SetRegView 64
|
||||
Call UninstallExisting
|
||||
!if "${ARCH}" == "x86"
|
||||
SetRegView 32
|
||||
!endif
|
||||
FunctionEnd
|
||||
|
||||
Function .onSelChange
|
||||
${IfNot} ${AtLeastBuild} 17763
|
||||
!if "${ARCH}" == "x86"
|
||||
${OrIfNot} ${IsNativeIA32}
|
||||
!endif
|
||||
SectionSetFlags ${SectionOpenConsole} ${SF_RO}
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function un.onInit
|
||||
!insertmacro MUI_UNGETLANGUAGE
|
||||
!if "${ARCH}" != "x86"
|
||||
SetRegView 64
|
||||
!endif
|
||||
!ifdef USER_MODE
|
||||
SetShellVarContext current
|
||||
!else
|
||||
SetShellVarContext all
|
||||
!endif
|
||||
FunctionEnd
|
||||
|
||||
Function UninstallExisting
|
||||
!ifdef USER_MODE
|
||||
ReadRegStr $R0 HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "UninstallString"
|
||||
!else
|
||||
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++" "UninstallString"
|
||||
!endif
|
||||
${If} $R0 != ""
|
||||
GetFullPathName $R1 "$R0\.." ; remove \uninstall.exe
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||
"$(MessageUninstallExisting)" \
|
||||
IDOK uninst
|
||||
Abort
|
||||
uninst:
|
||||
ClearErrors
|
||||
ExecWait '"$R0" /S _?=$R1'
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
####################################################################
|
||||
# uninstall
|
||||
|
||||
UninstallText "$(MessageUninstallText)"
|
||||
ShowUninstDetails show
|
||||
|
||||
Section "Uninstall"
|
||||
; Remove uninstaller
|
||||
Delete "$INSTDIR\uninstall.exe"
|
||||
|
||||
; Remove start menu stuff
|
||||
Delete "$SMPROGRAMS\$(MessageAppName)\$(MessageAppName).lnk"
|
||||
Delete "$SMPROGRAMS\$(MessageAppName)\License.lnk"
|
||||
Delete "$SMPROGRAMS\$(MessageAppName)\Uninstall $(MessageAppName).lnk"
|
||||
RMDir "$SMPROGRAMS\$(MessageAppName)"
|
||||
|
||||
; Remove desktop stuff
|
||||
Delete "$QUICKLAUNCH\$(MessageAppName).lnk"
|
||||
Delete "$DESKTOP\$(MessageAppName).lnk"
|
||||
|
||||
DeleteRegKey HKCR "DevCpp.dev"
|
||||
DeleteRegKey HKCR "DevCpp.c"
|
||||
DeleteRegKey HKCR "DevCpp.cpp"
|
||||
DeleteRegKey HKCR "DevCpp.cxx"
|
||||
DeleteRegKey HKCR "DevCpp.cc"
|
||||
DeleteRegKey HKCR "DevCpp.h"
|
||||
DeleteRegKey HKCR "DevCpp.hpp"
|
||||
DeleteRegKey HKCR "DevCpp.hxx"
|
||||
|
||||
Delete "$INSTDIR\NEWS.md"
|
||||
Delete "$INSTDIR\RedPandaIDE.exe"
|
||||
Delete "$INSTDIR\consolepauser.exe"
|
||||
Delete "$INSTDIR\OpenConsole.exe"
|
||||
Delete "$INSTDIR\redpanda-win-git-askpass.exe"
|
||||
Delete "$INSTDIR\astyle.exe"
|
||||
Delete "$INSTDIR\qt.conf"
|
||||
Delete "$INSTDIR\LICENSE"
|
||||
Delete "$INSTDIR\README.md"
|
||||
Delete "$INSTDIR\compiler_hint.lua"
|
||||
|
||||
RMDir /r "$INSTDIR\templates"
|
||||
RMDir /r "$INSTDIR\mingw32"
|
||||
RMDir /r "$INSTDIR\mingw64"
|
||||
RMDir /r "$INSTDIR\llvm-mingw"
|
||||
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove registry keys
|
||||
!ifdef USER_MODE
|
||||
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++"
|
||||
DeleteRegKey HKCU "Software\RedPanda-C++"
|
||||
!else
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RedPanda-C++"
|
||||
DeleteRegKey HKLM "Software\RedPanda-C++"
|
||||
!endif
|
||||
|
||||
!ifdef USER_MODE
|
||||
MessageBox MB_YESNO "$(MessageRemoveConfig)" /SD IDNO IDNO SkipRemoveConfig
|
||||
RMDir /r "$APPDATA\RedPandaIDE"
|
||||
SkipRemoveConfig:
|
||||
!endif
|
||||
SectionEnd
|
|
@ -0,0 +1,2 @@
|
|||
[Platforms]
|
||||
WindowsArguments = darkmode=2,fontengine=freetype
|
|
@ -0,0 +1,25 @@
|
|||
extern "C" {
|
||||
unsigned __stdcall GetConsoleCP() noexcept;
|
||||
unsigned __stdcall GetConsoleOutputCP() noexcept;
|
||||
int __stdcall SetConsoleCP(unsigned) noexcept;
|
||||
int __stdcall SetConsoleOutputCP(unsigned) noexcept;
|
||||
}
|
||||
|
||||
constexpr int CP_UTF8 = 65001;
|
||||
|
||||
struct __utf8init_t {
|
||||
unsigned saved_input_cp;
|
||||
unsigned saved_output_cp;
|
||||
|
||||
__utf8init_t() noexcept {
|
||||
saved_input_cp = GetConsoleCP();
|
||||
saved_output_cp = GetConsoleOutputCP();
|
||||
SetConsoleCP(CP_UTF8);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
}
|
||||
|
||||
~__utf8init_t() noexcept {
|
||||
SetConsoleCP(saved_input_cp);
|
||||
SetConsoleOutputCP(saved_output_cp);
|
||||
}
|
||||
} __utf8init;
|
|
@ -0,0 +1,12 @@
|
|||
1 24 MOVEABLE PURE DISCARDABLE
|
||||
BEGIN
|
||||
"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>"
|
||||
"<assembly manifestVersion=""1.0"" xmlns=""urn:schemas-microsoft-com:asm.v1"">"
|
||||
"<assemblyIdentity type=""win32"" name=""..."" version=""6.0.0.0""/>"
|
||||
"<application>"
|
||||
"<windowsSettings>"
|
||||
"<activeCodePage xmlns=""http://schemas.microsoft.com/SMI/2019/WindowsSettings"">UTF-8</activeCodePage>"
|
||||
"</windowsSettings>"
|
||||
"</application>"
|
||||
"</assembly>"
|
||||
END
|
Loading…
Reference in New Issue