2024-01-21 18:02:51 +08:00
|
|
|
|
global function apiVersion(): ApiVersion
|
|
|
|
|
return {
|
|
|
|
|
kind = "compiler_hint",
|
|
|
|
|
major = 0,
|
2024-03-07 15:55:51 +08:00
|
|
|
|
minor = 2,
|
2024-01-21 18:02:51 +08:00
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local gnuArchMap: {string:string} = {
|
|
|
|
|
i386 = "i686",
|
|
|
|
|
x86_64 = "x86_64",
|
|
|
|
|
arm64 = "aarch64",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local profileNameMap: {string:{string:string}} = {
|
|
|
|
|
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 function nameGeneratorMingwGcc(lang: string, arch: string, profile: string, isUtf8: boolean): string
|
|
|
|
|
local template: {string:string} = {
|
|
|
|
|
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: {string:string} = {
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
local function nameGeneratorClang(lang: string, arch: string, profile: string, isMingw: boolean): string
|
|
|
|
|
local template: {string:string} = {
|
|
|
|
|
en_US = "%1 Clang %2, %3",
|
|
|
|
|
pt_BR = "Clang %2 %1, %3",
|
|
|
|
|
zh_CN = "%1 Clang %2,%3",
|
|
|
|
|
zh_TW = "%1 Clang %2,%3",
|
|
|
|
|
}
|
|
|
|
|
local msvcCompatible: {string:string} = {
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
local function mergeCompilerSet(compilerSet: CompilerHint.CompilerSet, other: CompilerHint.CompilerSet)
|
|
|
|
|
local c = compilerSet as {string:any}
|
|
|
|
|
local o = other as {string:any}
|
|
|
|
|
for k, v in pairs(o) do
|
|
|
|
|
c[k] = v
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local record Programs
|
|
|
|
|
cCompiler: string
|
|
|
|
|
cxxCompiler: string
|
|
|
|
|
make: string
|
|
|
|
|
debugger: string
|
|
|
|
|
debugServer: string
|
|
|
|
|
resourceCompiler: string
|
|
|
|
|
binDirs: {string}
|
|
|
|
|
libDirs: {string} | nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local record Config
|
|
|
|
|
arch: string
|
|
|
|
|
isAnsi: boolean | nil
|
|
|
|
|
isClang: boolean | nil
|
|
|
|
|
customCompileParams: {string} | nil
|
|
|
|
|
customLinkParams: {string} | nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function generateConfig(
|
|
|
|
|
nameGen: (function (arch: string, profile: string): string),
|
|
|
|
|
programs: Programs,
|
|
|
|
|
config: Config
|
|
|
|
|
): CompilerHint.CompilerSet, CompilerHint.CompilerSet, CompilerHint.CompilerSet
|
|
|
|
|
local commonOptions : CompilerHint.CompilerSet = {
|
|
|
|
|
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: CompilerHint.CompilerSet = {
|
|
|
|
|
name = nameGen(config.arch, "release"),
|
|
|
|
|
staticLink = true,
|
|
|
|
|
linkCmdOptStripExe = "on",
|
|
|
|
|
ccCmdOptOptimize = "2",
|
|
|
|
|
}
|
|
|
|
|
local debug_: CompilerHint.CompilerSet = {
|
|
|
|
|
name = nameGen(config.arch, "debug"),
|
|
|
|
|
ccCmdOptDebugInfo = "on",
|
|
|
|
|
}
|
|
|
|
|
local debugWithAsan: CompilerHint.CompilerSet = {
|
|
|
|
|
name = nameGen(config.arch, "debugWithAsan"),
|
|
|
|
|
ccCmdOptDebugInfo = "on",
|
|
|
|
|
ccCmdOptAddressSanitizer = "address",
|
|
|
|
|
}
|
|
|
|
|
mergeCompilerSet(release, commonOptions)
|
|
|
|
|
mergeCompilerSet(debug_, commonOptions)
|
|
|
|
|
mergeCompilerSet(debugWithAsan, commonOptions)
|
|
|
|
|
return release, debug_, debugWithAsan
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
global function main(): CompilerHint
|
|
|
|
|
local appArch = C_System.appArch()
|
|
|
|
|
local libexecDir = C_System.appLibexecDir()
|
|
|
|
|
local lang = C_Desktop.language()
|
|
|
|
|
local supportedAppArches = C_System.supportedAppArchList()
|
|
|
|
|
|
|
|
|
|
local compilerList = {}
|
|
|
|
|
local noSearch = {}
|
|
|
|
|
local preferCompiler = 0
|
|
|
|
|
|
|
|
|
|
local function checkAndAddMingw(arch: string)
|
|
|
|
|
local binDir: string
|
|
|
|
|
local libDir: string
|
|
|
|
|
local excludeBinDir: string
|
|
|
|
|
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: 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},
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-19 17:18:34 +08:00
|
|
|
|
if C_FileSystem.exists(libDir .. "/libutf8.a") then
|
|
|
|
|
local release, debug_, _ = generateConfig(
|
|
|
|
|
function (arch_: string, profile: string): string
|
|
|
|
|
return nameGeneratorMingwGcc(lang, arch_, profile, true)
|
|
|
|
|
end,
|
|
|
|
|
programs,
|
|
|
|
|
{
|
|
|
|
|
arch = arch,
|
|
|
|
|
customLinkParams = {"-Wl,--whole-archive", "-lutf8", "-Wl,--no-whole-archive"},
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
table.insert(compilerList, release)
|
|
|
|
|
table.insert(compilerList, debug_)
|
|
|
|
|
if preferCompiler == 0 then
|
|
|
|
|
preferCompiler = 2
|
|
|
|
|
end
|
2024-01-21 18:02:51 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-02-19 17:18:34 +08:00
|
|
|
|
do
|
|
|
|
|
local release, debug_, _ = generateConfig(
|
|
|
|
|
function (arch_: string, profile: string): string
|
|
|
|
|
return nameGeneratorMingwGcc(lang, arch_, profile, false)
|
|
|
|
|
end,
|
|
|
|
|
programs,
|
|
|
|
|
{
|
|
|
|
|
arch = arch,
|
|
|
|
|
isAnsi = true,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
table.insert(compilerList, release)
|
|
|
|
|
table.insert(compilerList, debug_)
|
|
|
|
|
if preferCompiler == 0 then
|
|
|
|
|
preferCompiler = 2
|
|
|
|
|
end
|
|
|
|
|
end
|
2024-01-21 18:02:51 +08:00
|
|
|
|
|
|
|
|
|
table.insert(noSearch, excludeBinDir)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function checkAndAddClang()
|
|
|
|
|
if not C_FileSystem.isExecutable(libexecDir .. "/llvm-mingw/bin/clang.exe") then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local binDir = libexecDir .. "/llvm-mingw/bin"
|
|
|
|
|
local appTriplet = gnuArchMap[appArch] .. "-w64-mingw32"
|
2024-02-19 17:18:34 +08:00
|
|
|
|
local appDllDir = libexecDir .. "/llvm-mingw/" .. appTriplet .. "/bin"
|
2024-01-21 18:02:51 +08:00
|
|
|
|
do
|
|
|
|
|
-- appArch is always debuggable
|
|
|
|
|
local programs: 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",
|
2024-02-19 17:18:34 +08:00
|
|
|
|
binDirs = {binDir, appDllDir},
|
2024-01-21 18:02:51 +08:00
|
|
|
|
}
|
|
|
|
|
local release, debug_, debugWithAsan = generateConfig(
|
|
|
|
|
function (arch_: string, profile: string): string
|
|
|
|
|
return nameGeneratorClang(lang, arch_, profile, true)
|
|
|
|
|
end,
|
|
|
|
|
programs,
|
|
|
|
|
{
|
|
|
|
|
arch = appArch,
|
|
|
|
|
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
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for _, foreignArch in ipairs(supportedAppArches) do
|
2024-02-19 17:18:34 +08:00
|
|
|
|
local gnuArch = gnuArchMap[foreignArch]
|
|
|
|
|
if foreignArch ~= appArch and gnuArch ~= nil then
|
|
|
|
|
local foreignTriplet = gnuArch .. "-w64-mingw32"
|
|
|
|
|
local foreignDllDir = libexecDir .. "/llvm-mingw/" .. foreignTriplet .. "/bin"
|
2024-01-21 18:02:51 +08:00
|
|
|
|
local programs: 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",
|
2024-02-19 17:18:34 +08:00
|
|
|
|
binDirs = {binDir, foreignDllDir},
|
2024-01-21 18:02:51 +08:00
|
|
|
|
}
|
|
|
|
|
local release, _, _ = generateConfig(
|
|
|
|
|
function (arch_: string, profile: string): string
|
|
|
|
|
return nameGeneratorClang(lang, arch_, profile, true)
|
|
|
|
|
end,
|
|
|
|
|
programs,
|
|
|
|
|
{
|
|
|
|
|
arch = foreignArch,
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
local msvcTriplet = gnuArchMap[appArch] .. "-pc-windows-msvc"
|
|
|
|
|
local libDir = libexecDir .. "/llvm-mingw/" .. msvcTriplet .. "/lib"
|
|
|
|
|
local programs: 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 release, debug_, _ = generateConfig(
|
|
|
|
|
function (arch: string, profile: string): string
|
|
|
|
|
return nameGeneratorClang(lang, arch, profile, false)
|
|
|
|
|
end,
|
|
|
|
|
programs,
|
|
|
|
|
{
|
|
|
|
|
arch = appArch,
|
|
|
|
|
customCompileParams = {
|
|
|
|
|
"-target", msvcTriplet,
|
|
|
|
|
"-fms-extensions",
|
|
|
|
|
"-fms-compatibility",
|
|
|
|
|
"-fdelayed-template-parsing",
|
|
|
|
|
},
|
|
|
|
|
customLinkParams = {
|
|
|
|
|
"-target", msvcTriplet,
|
|
|
|
|
},
|
|
|
|
|
isClang = true,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
table.insert(compilerList, release)
|
|
|
|
|
table.insert(compilerList, debug_)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for _, foreignArch in ipairs(supportedAppArches) do
|
2024-02-19 17:18:34 +08:00
|
|
|
|
local gnuArch = gnuArchMap[foreignArch]
|
|
|
|
|
if foreignArch ~= appArch and gnuArch ~= nil then
|
|
|
|
|
local foreignTriplet = gnuArch .. "-w64-mingw32"
|
2024-01-21 18:02:51 +08:00
|
|
|
|
local msvcTriplet = gnuArchMap[foreignArch] .. "-pc-windows-msvc"
|
|
|
|
|
local libDir = libexecDir .. "/llvm-mingw/" .. msvcTriplet .. "/lib"
|
|
|
|
|
local programs: 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 release, _, _ = generateConfig(
|
|
|
|
|
function (arch: string, profile: string): string
|
|
|
|
|
return nameGeneratorClang(lang, arch, profile, false)
|
|
|
|
|
end,
|
|
|
|
|
programs,
|
|
|
|
|
{
|
|
|
|
|
arch = foreignArch,
|
|
|
|
|
customCompileParams = {
|
|
|
|
|
"-target", msvcTriplet,
|
|
|
|
|
"-fms-extensions",
|
|
|
|
|
"-fms-compatibility",
|
|
|
|
|
"-fdelayed-template-parsing",
|
|
|
|
|
},
|
|
|
|
|
customLinkParams = {
|
|
|
|
|
"-target", msvcTriplet,
|
|
|
|
|
},
|
|
|
|
|
isClang = true,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
table.insert(compilerList, release)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
table.insert(noSearch, llvmOrgBinDir)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if appArch == "x86_64" then
|
|
|
|
|
checkAndAddMingw("x86_64")
|
2024-02-19 17:18:34 +08:00
|
|
|
|
checkAndAddMingw("i386")
|
2024-01-21 18:02:51 +08:00
|
|
|
|
checkAndAddClang()
|
|
|
|
|
elseif appArch == "arm64" then
|
|
|
|
|
checkAndAddClang()
|
2024-02-19 17:18:34 +08:00
|
|
|
|
checkAndAddMingw("x86_64")
|
|
|
|
|
checkAndAddMingw("i386")
|
2024-01-21 18:02:51 +08:00
|
|
|
|
else
|
|
|
|
|
checkAndAddMingw("i386")
|
|
|
|
|
checkAndAddClang()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local result = {
|
|
|
|
|
compilerList = compilerList,
|
|
|
|
|
noSearch = noSearch,
|
|
|
|
|
preferCompiler = preferCompiler,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
end
|