mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
windows: use CreateProcess for os.exec
This commit is contained in:
parent
d57c0cfde0
commit
86447c1301
@ -82,7 +82,6 @@ pub fn main() {
|
|||||||
pub fn (ts mut TestSession) test() {
|
pub fn (ts mut TestSession) test() {
|
||||||
ok := term.ok_message('OK')
|
ok := term.ok_message('OK')
|
||||||
fail := term.fail_message('FAIL')
|
fail := term.fail_message('FAIL')
|
||||||
cmd_needs_quoting := (os.user_os() == 'windows')
|
|
||||||
show_stats := '-stats' in ts.vargs.split(' ')
|
show_stats := '-stats' in ts.vargs.split(' ')
|
||||||
ts.benchmark = benchmark.new_benchmark()
|
ts.benchmark = benchmark.new_benchmark()
|
||||||
for dot_relative_file in ts.files {
|
for dot_relative_file in ts.files {
|
||||||
@ -93,8 +92,7 @@ pub fn (ts mut TestSession) test() {
|
|||||||
}
|
}
|
||||||
tmpc_filepath := file.replace('.v', '.tmp.c')
|
tmpc_filepath := file.replace('.v', '.tmp.c')
|
||||||
|
|
||||||
mut cmd := '"$ts.vexe" $ts.vargs "$file"'
|
cmd := '"$ts.vexe" $ts.vargs "$file"'
|
||||||
if cmd_needs_quoting { cmd = '"$cmd"' }
|
|
||||||
|
|
||||||
ts.benchmark.step()
|
ts.benchmark.step()
|
||||||
if show_stats {
|
if show_stats {
|
||||||
|
@ -145,7 +145,7 @@ fn find_vs(vswhere_dir string, host_arch string) ?VsInstallation {
|
|||||||
// If its not there then end user needs to update their visual studio
|
// If its not there then end user needs to update their visual studio
|
||||||
// installation!
|
// installation!
|
||||||
|
|
||||||
res := os.exec('""$vswhere_dir\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath"') or {
|
res := os.exec('"$vswhere_dir\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') or {
|
||||||
return error(err)
|
return error(err)
|
||||||
}
|
}
|
||||||
// println('res: "$res"')
|
// println('res: "$res"')
|
||||||
@ -348,7 +348,7 @@ pub fn (v mut V) cc_msvc() {
|
|||||||
|
|
||||||
args := a.join(' ')
|
args := a.join(' ')
|
||||||
|
|
||||||
cmd := '""$r.full_cl_exe_path" $args"'
|
cmd := '"$r.full_cl_exe_path" $args'
|
||||||
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
||||||
// Also the double quotes at the start ARE needed.
|
// Also the double quotes at the start ARE needed.
|
||||||
if v.pref.show_c_cmd || v.pref.is_verbose {
|
if v.pref.show_c_cmd || v.pref.is_verbose {
|
||||||
@ -410,7 +410,7 @@ fn build_thirdparty_obj_file_with_msvc(path string, moduleflags []CFlag) {
|
|||||||
|
|
||||||
btarget := moduleflags.c_options_before_target_msvc()
|
btarget := moduleflags.c_options_before_target_msvc()
|
||||||
atarget := moduleflags.c_options_after_target_msvc()
|
atarget := moduleflags.c_options_after_target_msvc()
|
||||||
cmd := '""$msvc.full_cl_exe_path" /volatile:ms /Zi /DNDEBUG $include_string /c $btarget $cfiles $atarget /Fo"$obj_path""'
|
cmd := '"$msvc.full_cl_exe_path" /volatile:ms /Zi /DNDEBUG $include_string /c $btarget $cfiles $atarget /Fo"$obj_path"'
|
||||||
//NB: the quotes above ARE balanced.
|
//NB: the quotes above ARE balanced.
|
||||||
println('thirdparty cmd line: $cmd')
|
println('thirdparty cmd line: $cmd')
|
||||||
res := os.exec(cmd) or {
|
res := os.exec(cmd) or {
|
||||||
|
26
vlib/os/os.v
26
vlib/os/os.v
@ -388,32 +388,6 @@ pub:
|
|||||||
//stderr string // TODO
|
//stderr string // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec starts the specified command, waits for it to complete, and returns its output.
|
|
||||||
pub fn exec(cmd string) ?Result {
|
|
||||||
if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
|
||||||
return error(';, &&, || and \\n are not allowed in shell commands')
|
|
||||||
}
|
|
||||||
pcmd := '$cmd 2>&1'
|
|
||||||
f := vpopen(pcmd)
|
|
||||||
if isnil(f) {
|
|
||||||
return error('exec("$cmd") failed')
|
|
||||||
}
|
|
||||||
buf := [1000]byte
|
|
||||||
mut res := ''
|
|
||||||
for C.fgets(*char(buf), 1000, f) != 0 {
|
|
||||||
res += tos(buf, vstrlen(buf))
|
|
||||||
}
|
|
||||||
res = res.trim_space()
|
|
||||||
exit_code := vpclose(f)
|
|
||||||
//if exit_code != 0 {
|
|
||||||
//return error(res)
|
|
||||||
//}
|
|
||||||
return Result {
|
|
||||||
output: res
|
|
||||||
exit_code: exit_code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `system` works like `exec()`, but only returns a return code.
|
// `system` works like `exec()`, but only returns a return code.
|
||||||
pub fn system(cmd string) int {
|
pub fn system(cmd string) int {
|
||||||
if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
||||||
|
@ -60,4 +60,28 @@ pub fn mkdir(path string) {
|
|||||||
C.mkdir(path.str, 511)// S_IRWXU | S_IRWXG | S_IRWXO
|
C.mkdir(path.str, 511)// S_IRWXU | S_IRWXG | S_IRWXO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exec starts the specified command, waits for it to complete, and returns its output.
|
||||||
|
pub fn exec(cmd string) ?Result {
|
||||||
|
if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
||||||
|
return error(';, &&, || and \\n are not allowed in shell commands')
|
||||||
|
}
|
||||||
|
pcmd := '$cmd 2>&1'
|
||||||
|
f := vpopen(pcmd)
|
||||||
|
if isnil(f) {
|
||||||
|
return error('exec("$cmd") failed')
|
||||||
|
}
|
||||||
|
buf := [1000]byte
|
||||||
|
mut res := ''
|
||||||
|
for C.fgets(*char(buf), 1000, f) != 0 {
|
||||||
|
res += tos(buf, vstrlen(buf))
|
||||||
|
}
|
||||||
|
res = res.trim_space()
|
||||||
|
exit_code := vpclose(f)
|
||||||
|
//if exit_code != 0 {
|
||||||
|
//return error(res)
|
||||||
|
//}
|
||||||
|
return Result {
|
||||||
|
output: res
|
||||||
|
exit_code: exit_code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,6 +37,42 @@ mut:
|
|||||||
wFinderFlags u16
|
wFinderFlags u16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ProcessInformation {
|
||||||
|
mut:
|
||||||
|
hProcess voidptr
|
||||||
|
hThread voidptr
|
||||||
|
dwProcessId u32
|
||||||
|
dwThreadId u32
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StartupInfo {
|
||||||
|
mut:
|
||||||
|
cb u32
|
||||||
|
lpReserved &u16
|
||||||
|
lpDesktop &u16
|
||||||
|
lpTitle &u16
|
||||||
|
dwX u32
|
||||||
|
dwY u32
|
||||||
|
dwXSize u32
|
||||||
|
dwYSize u32
|
||||||
|
dwXCountChars u32
|
||||||
|
dwYCountChars u32
|
||||||
|
dwFillAttribute u32
|
||||||
|
dwFlags u32
|
||||||
|
wShowWindow u16
|
||||||
|
cbReserved2 u16
|
||||||
|
lpReserved2 byteptr
|
||||||
|
hStdInput voidptr
|
||||||
|
hStdOutput voidptr
|
||||||
|
hStdError voidptr
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SecurityAttributes {
|
||||||
|
mut:
|
||||||
|
nLength u32
|
||||||
|
lpSecurityDescriptor voidptr
|
||||||
|
bInheritHandle bool
|
||||||
|
}
|
||||||
|
|
||||||
fn init_os_args(argc int, argv &byteptr) []string {
|
fn init_os_args(argc int, argv &byteptr) []string {
|
||||||
mut args := []string
|
mut args := []string
|
||||||
@ -189,3 +225,64 @@ pub fn get_error_msg(code int) string {
|
|||||||
}
|
}
|
||||||
return string_from_wide(_ptr_text)
|
return string_from_wide(_ptr_text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exec starts the specified command, waits for it to complete, and returns its output.
|
||||||
|
pub fn exec(cmd string) ?Result {
|
||||||
|
if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
||||||
|
return error(';, &&, || and \\n are not allowed in shell commands')
|
||||||
|
}
|
||||||
|
mut child_stdin := &u32(0)
|
||||||
|
mut child_stdout_read := &u32(0)
|
||||||
|
mut child_stdout_write := &u32(0)
|
||||||
|
mut sa := SecurityAttributes {}
|
||||||
|
sa.nLength = sizeof(C.SECURITY_ATTRIBUTES)
|
||||||
|
sa.bInheritHandle = true
|
||||||
|
|
||||||
|
create_pipe_result := C.CreatePipe(&child_stdout_read, &child_stdout_write, &sa, 0)
|
||||||
|
if create_pipe_result == 0 {
|
||||||
|
error_msg := get_error_msg(int(C.GetLastError()))
|
||||||
|
return error('exec failed (CreatePipe): $error_msg')
|
||||||
|
}
|
||||||
|
set_handle_info_result := C.SetHandleInformation(child_stdout_read, C.HANDLE_FLAG_INHERIT, 0)
|
||||||
|
if set_handle_info_result == 0 {
|
||||||
|
error_msg := get_error_msg(int(C.GetLastError()))
|
||||||
|
panic('exec failed (SetHandleInformation): $error_msg')
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_info := ProcessInformation{}
|
||||||
|
mut start_info := StartupInfo{}
|
||||||
|
start_info.cb = sizeof(C.PROCESS_INFORMATION)
|
||||||
|
start_info.hStdInput = child_stdin
|
||||||
|
start_info.hStdOutput = child_stdout_write
|
||||||
|
start_info.hStdError = child_stdout_write
|
||||||
|
start_info.dwFlags = u32(C.STARTF_USESTDHANDLES)
|
||||||
|
command_line := [32768]u16
|
||||||
|
C.ExpandEnvironmentStrings(cmd.to_wide(), &command_line, 32768)
|
||||||
|
create_process_result := C.CreateProcess(0, command_line, 0, 0, C.TRUE, 0, 0, 0, &start_info, &proc_info)
|
||||||
|
if create_process_result == 0 {
|
||||||
|
error_msg := get_error_msg(int(C.GetLastError()))
|
||||||
|
return error('exec failed (CreateProcess): $error_msg')
|
||||||
|
}
|
||||||
|
C.CloseHandle(child_stdin)
|
||||||
|
C.CloseHandle(child_stdout_write)
|
||||||
|
buf := [1000]byte
|
||||||
|
mut bytes_read := 0
|
||||||
|
mut read_data := ''
|
||||||
|
for {
|
||||||
|
readfile_result := C.ReadFile(child_stdout_read, buf, 1000, &bytes_read, 0)
|
||||||
|
read_data += tos(buf, bytes_read)
|
||||||
|
if (readfile_result == 0 || bytes_read == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read_data = read_data.trim_space()
|
||||||
|
exit_code := 0
|
||||||
|
C.WaitForSingleObject(proc_info.hProcess, C.INFINITE)
|
||||||
|
C.GetExitCodeProcess(proc_info.hProcess, &exit_code)
|
||||||
|
C.CloseHandle(proc_info.hProcess)
|
||||||
|
C.CloseHandle(proc_info.hThread)
|
||||||
|
return Result {
|
||||||
|
output: read_data
|
||||||
|
exit_code: exit_code
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user