-
Notifications
You must be signed in to change notification settings - Fork 105
Expand file tree
/
Copy pathdebuger_factory.lua
More file actions
273 lines (254 loc) · 7.9 KB
/
debuger_factory.lua
File metadata and controls
273 lines (254 loc) · 7.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
local fs = require 'bee.filesystem'
local sp = require 'bee.subprocess'
local platform_os = require 'frontend.platform_os'
local process_inject = require 'frontend.process_inject'
local useWSL = false
local useUtf8 = false
local function initialize(args)
useWSL = args.useWSL
useUtf8 = args.sourceCoding == "utf8"
end
local function towsl(s)
if not useWSL or not s:match "^%a:" then
return s
end
return s:gsub("\\", "/"):gsub("^(%a):", function(c)
return "/mnt/"..c:lower()
end)
end
local function getLuaVersion(args)
if args.luaVersion == "latest" then
return "lua-latest"
elseif args.luaVersion == "5.4" then
return "lua54"
elseif args.luaVersion == "5.3" then
return "lua53"
elseif args.luaVersion == "5.2" then
return "lua52"
elseif args.luaVersion == "5.1" then
return "lua51"
elseif args.luaVersion == "jit" then
return "luajit"
end
return "lua54"
end
local function Is64BitWindows()
-- https://docs.microsoft.com/en-us/archive/blogs/david.wang/howto-detect-process-bitness
return os.getenv "PROCESSOR_ARCHITECTURE" == "AMD64" or os.getenv "PROCESSOR_ARCHITEW6432" == "AMD64"
end
local function IsArm64Macos()
local f <close> = assert(io.popen("uname -v", "r"))
if f:read "l":match "RELEASE_ARM64" then
return true
end
end
local PLATFORM = {
["windows-x86"] = "win32-ia32",
["windows-x86_64"] = "win32-x64",
["linux-x86_64"] = "linux-x64",
["linux-arm64"] = "linux-arm64",
["android-arm64"] = "linux-arm64",
["macos-x86_64"] = "darwin-x64",
["macos-arm64"] = "darwin-arm64",
}
local function getLuaExe(args, dbg)
local OS = platform_os():lower()
local ARCH = args.luaArch
if OS == "windows" then
ARCH = ARCH or "x86_64"
if ARCH == "x86_64" and not Is64BitWindows() then
ARCH = "x86"
end
elseif OS == "linux" then
ARCH = ARCH or "x86_64"
elseif OS == "macos" then
if IsArm64Macos() then
ARCH = ARCH or "x86_64"
if ARCH == "x86" then
ARCH = "x86_64"
end
else
ARCH = "x86_64"
end
elseif OS == "android" then
ARCH = "arm64"
end
local platform = PLATFORM[OS.."-"..ARCH]
if platform then
local luaexe = dbg / "runtime"
/ platform
/ getLuaVersion(args)
/ (OS == "windows" and "lua.exe" or "lua")
if fs.exists(luaexe) then
return luaexe
end
end
return nil, ("No runtime (OS: %s, ARCH: %s) is found, you need to compile it yourself."):format(OS, ARCH)
end
local function bootstrapOption(option, luaexe, args)
option.cwd = (type(args.cwd) == "string") and args.cwd or luaexe:parent_path():string()
if type(args.env) == "table" then
option.env = args.env
end
end
local function bootstrapMakeExe(c, luaexe, args, address, dbg)
c[#c+1] = towsl(luaexe:string())
c[#c+1] = "-e"
local params = {}
params[#params+1] = address
if not useUtf8 then
params[#params+1] = 'ansi'
end
if args.luaVersion == "latest" then
params[#params+1] = 'latest'
end
local script = ("dofile[[%s]];DBG[[%s]]"):format(
(dbg / "script" / "launch.lua"):string(),
table.concat(params, "-")
)
local bash = platform_os():lower() ~= "windows"
if bash then
script = script:gsub('%[%[', '"'):gsub('%]%]', '"')
end
c[#c+1] = script
end
local function bootstrapMakeArgs(c, args)
if type(args.arg0) == "string" then
c[#c+1] = args.arg0
elseif type(args.arg0) == "table" then
for _, v in ipairs(args.arg0) do
if type(v) == "string" then
c[#c+1] = v
end
end
end
c[#c+1] = (type(args.program) == "string") and towsl(args.program) or ".lua"
if type(args.arg) == "string" then
c[#c+1] = args.arg
elseif type(args.arg) == "table" then
for _, v in ipairs(args.arg) do
if type(v) == "string" then
c[#c+1] = v
end
end
end
end
local function checkLuaExe(args, dbg)
if type(args.luaexe) == "string" then
local luaexe = fs.path(args.luaexe)
if not args.luaexe:find(package.config:sub(1,1), 1, true) then
return luaexe
end
if fs.exists(luaexe) then
return luaexe
end
if platform_os() == "Windows" and luaexe:equal_extension "" then
luaexe = fs.path(luaexe):replace_extension "exe"
if fs.exists(luaexe) then
return luaexe
end
end
return nil, ("No file `%s`."):format(args.luaexe)
end
return getLuaExe(args, dbg)
end
local function create_luaexe_in_terminal(_, args, dbg, address)
initialize(args)
local luaexe, err = checkLuaExe(args, dbg)
if not luaexe then
return nil, err
end
local option = {
kind = (args.console == "integratedTerminal") and "integrated" or "external",
title = args.name,
args = {},
--TODO: support argsCanBeInterpretedByShell
}
if useWSL then
option.args[1] = "wsl"
end
bootstrapOption(option, luaexe, args)
bootstrapMakeExe(option.args, luaexe, args, address, dbg)
bootstrapMakeArgs(option.args, args)
return option
end
local function create_luaexe_in_console(args, dbg, address)
initialize(args)
local luaexe, err = checkLuaExe(args, dbg)
if not luaexe then
return nil, err
end
local option = {
console = 'hide',
searchPath = true,
}
if useWSL then
local SystemRoot = (os.getenv "SystemRoot") or "C:\\WINDOWS"
option[1] = SystemRoot .. "\\sysnative\\wsl.exe"
end
bootstrapOption(option, luaexe, args)
bootstrapMakeExe(option, luaexe, args, address, dbg)
bootstrapMakeArgs(option, args)
return sp.spawn(option)
end
local function create_process_in_console(args, callback)
local need_resume = platform_os():lower() == "windows"
initialize(args)
local process, err = sp.spawn {
args.runtimeExecutable, args.runtimeArgs,
env = args.env,
console = 'new',
cwd = args.cwd or fs.path(args.runtimeExecutable):parent_path(),
suspended = true,
}
if not process then
return nil, err
end
if callback then
callback(process)
end
if args.inject ~= "none" then
local ok, errmsg = process_inject.inject(process, "launch", args)
if not ok then
if process:is_running() then
return nil, errmsg
else
return nil, "process is already exited:\n"..errmsg
end
end
end
if need_resume then
process:resume()
end
return process
end
local function create_process_in_terminal(client, args)
initialize(args)
local arguments = {}
if useWSL then
arguments[#arguments+1] = "wsl"
end
arguments[#arguments+1] = args.runtimeExecutable
if type(args.runtimeArgs) == "string" then
arguments[#arguments+1] = args.runtimeArgs
elseif type(args.runtimeArgs) == "table" then
for _, v in ipairs(args.runtimeArgs) do
arguments[#arguments+1] = v
end
end
local option = {
kind = (args.console == "integratedTerminal") and "integrated" or "external",
title = args.name,
env = args.env,
cwd = args.cwd or fs.path(args.runtimeExecutable):parent_path(),
args = arguments,
argsCanBeInterpretedByShell = client.arguments.supportsArgsCanBeInterpretedByShell and type(args.runtimeArgs) == "string",
}
return option
end
return {
create_luaexe_in_console = create_luaexe_in_console,
create_luaexe_in_terminal = create_luaexe_in_terminal,
create_process_in_console = create_process_in_console,
create_process_in_terminal = create_process_in_terminal,
}