mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
vsymlink: real Windows symbolic link, fallback to batch, make.bat updates (#5841)
This commit is contained in:
parent
f3a505b558
commit
f66967a88c
@ -1,11 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import v.pref
|
import v.pref
|
||||||
|
|
||||||
const (
|
|
||||||
hkey_current_user = voidptr(0x80000001)
|
|
||||||
hwnd_broadcast = voidptr(0xffff)
|
|
||||||
)
|
|
||||||
|
|
||||||
$if windows {
|
$if windows {
|
||||||
$if tinyc {
|
$if tinyc {
|
||||||
#flag -lAdvapi32
|
#flag -lAdvapi32
|
||||||
@ -14,15 +9,15 @@ $if windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main(){
|
fn main(){
|
||||||
|
vexe := pref.vexe_path()
|
||||||
$if windows {
|
$if windows {
|
||||||
setup_symlink_on_windows()
|
setup_symlink_windows(vexe)
|
||||||
} $else {
|
} $else {
|
||||||
setup_symlink_on_unix()
|
setup_symlink(vexe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_symlink_on_unix(){
|
fn setup_symlink(vexe string){
|
||||||
vexe := pref.vexe_path()
|
|
||||||
mut link_path := '/usr/local/bin/v'
|
mut link_path := '/usr/local/bin/v'
|
||||||
mut ret := os.exec('ln -sf $vexe $link_path') or {
|
mut ret := os.exec('ln -sf $vexe $link_path') or {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -45,40 +40,42 @@ fn setup_symlink_on_unix(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_symlink_on_windows(){
|
fn setup_symlink_windows(vexe string){
|
||||||
$if windows {
|
$if windows {
|
||||||
vexe := pref.vexe_path()
|
// Create a symlink in a new local folder (.\.bin\.v.exe)
|
||||||
// NB: Putting $vdir directly into PATH will also result in
|
// Puts `v` in %PATH% without polluting it with anything else (like make.bat).
|
||||||
// make.bat being global, which is NOT what we want.
|
// This will make `v` available on cmd.exe, PowerShell, and MinGW(MSYS)/WSL/Cygwin
|
||||||
//
|
|
||||||
// Instead, we create a small launcher v.bat, in a new local
|
vdir := os.real_path(os.dir(vexe))
|
||||||
// folder .bin/ . That .bin/ folder can then be put in PATH
|
vsymlinkdir := os.join_path(vdir, '.bin')
|
||||||
// without poluting it with anything else - just a `v`
|
|
||||||
// command will be available, similar to unix.
|
mut vsymlink := os.join_path(vsymlinkdir, 'v.exe')
|
||||||
//
|
|
||||||
// Creating a real NTFS symlink to the real executable was also
|
if !os.exists(vsymlinkdir) {
|
||||||
// tried, but then os.real_path( os.executable() ) returns the
|
os.mkdir_all(vsymlinkdir) // will panic if fails
|
||||||
// path to the symlink, unfortunately, unlike on posix systems
|
} else {
|
||||||
// ¯\_(ツ)_/¯
|
os.rm(vsymlink)
|
||||||
vdir := os.real_path(os.dir(vexe))
|
|
||||||
vsymlinkdir := os.join_path(vdir, '.bin')
|
|
||||||
vsymlinkbat := os.join_path(vsymlinkdir, 'v.bat')
|
|
||||||
if os.exists(vsymlinkbat) {
|
|
||||||
print('Batch script $vsymlinkbat already exists, checking system %PATH%...')
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
os.rmdir_all(vsymlinkdir)
|
// try to create a native symlink at .\.bin\v.exe
|
||||||
os.mkdir_all(vsymlinkdir)
|
os.symlink(vsymlink, vexe) or {
|
||||||
os.write_file(vsymlinkbat, '@echo off\n${vexe} %*')
|
// typically only fails if you're on a network drive (VirtualBox)
|
||||||
if !os.exists(vsymlinkbat) {
|
// do batch file creation instead
|
||||||
eprintln('Could not create $vsymlinkbat')
|
eprint('NOTE: Could not create a native symlink: $err')
|
||||||
exit(1)
|
eprintln('Creating a batch file instead...')
|
||||||
}
|
vsymlink = os.join_path(vsymlinkdir, 'v.bat')
|
||||||
else {
|
if os.exists(vsymlink) {
|
||||||
print('Created $vsymlinkbat, checking system %PATH%...')
|
os.rm(vsymlink)
|
||||||
}
|
}
|
||||||
|
os.write_file(vsymlink, '@echo off\n${vexe} %*')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !os.exists(vsymlink) {
|
||||||
|
warn_and_exit('Could not create $vsymlink')
|
||||||
|
}
|
||||||
|
|
||||||
|
print('Symlink $vsymlink to $vexe created.\n\nChecking system %PATH%...')
|
||||||
|
|
||||||
reg_sys_env_handle := get_reg_sys_env_handle() or {
|
reg_sys_env_handle := get_reg_sys_env_handle() or {
|
||||||
warn_and_exit(err)
|
warn_and_exit(err)
|
||||||
return
|
return
|
||||||
@ -104,7 +101,7 @@ fn setup_symlink_on_windows(){
|
|||||||
println('configured.')
|
println('configured.')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print('not configured.\nSetting system %PATH%...')
|
print('not configured.\nAdding symlink directory to system %PATH%...')
|
||||||
set_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or {
|
set_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or {
|
||||||
warn_and_exit(err)
|
warn_and_exit(err)
|
||||||
return
|
return
|
||||||
@ -115,12 +112,12 @@ fn setup_symlink_on_windows(){
|
|||||||
print('Letting running process know to update their Environment...')
|
print('Letting running process know to update their Environment...')
|
||||||
send_setting_change_msg('Environment') or {
|
send_setting_change_msg('Environment') or {
|
||||||
eprintln('\n' + err)
|
eprintln('\n' + err)
|
||||||
warn_and_exit('You might need to run this again to have `v` in your %PATH%')
|
warn_and_exit('You might need to run this again to have the `v` command in your %PATH%')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
println('finished.\n\nNote: restart your shell/IDE to load the new %PATH%.')
|
println('finished.\n\nNote: restart your shell/IDE to load the new %PATH%.')
|
||||||
println('\nAfter restarting your shell/IDE, give `v version` a try in another dir!')
|
println('After restarting your shell/IDE, give `v version` a try in another dir!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,14 +128,13 @@ fn warn_and_exit(err string) {
|
|||||||
|
|
||||||
// get the system environment registry handle
|
// get the system environment registry handle
|
||||||
fn get_reg_sys_env_handle() ?voidptr {
|
fn get_reg_sys_env_handle() ?voidptr {
|
||||||
$if windows {
|
$if windows { // wrap for cross-compile compat
|
||||||
// open the registry key
|
// open the registry key
|
||||||
reg_key_path := 'Environment'
|
reg_key_path := 'Environment'
|
||||||
reg_env_key := voidptr(0) // or HKEY (HANDLE)
|
reg_env_key := voidptr(0) // or HKEY (HANDLE)
|
||||||
if C.RegOpenKeyEx(hkey_current_user, reg_key_path.to_wide(), 0, 1 | 2, ®_env_key) != 0 {
|
if C.RegOpenKeyEx(os.hkey_current_user, reg_key_path.to_wide(), 0, 1 | 2, ®_env_key) != 0 {
|
||||||
return error('Could not open "$reg_key_path" in the registry')
|
return error('Could not open "$reg_key_path" in the registry')
|
||||||
}
|
}
|
||||||
|
|
||||||
return reg_env_key
|
return reg_env_key
|
||||||
}
|
}
|
||||||
return error('not on windows')
|
return error('not on windows')
|
||||||
@ -171,11 +167,11 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
|
|||||||
return error('not on windows')
|
return error('not on windows')
|
||||||
}
|
}
|
||||||
|
|
||||||
// broadcasts a message to all listening windows (explorer.exe in particular)
|
// Broadcasts a message to all listening windows (explorer.exe in particular)
|
||||||
// letting them know that the system environment has changed and should be reloaded
|
// letting them know that the system environment has changed and should be reloaded
|
||||||
fn send_setting_change_msg(message_data string) ?bool {
|
fn send_setting_change_msg(message_data string) ?bool {
|
||||||
$if windows {
|
$if windows {
|
||||||
if C.SendMessageTimeout(hwnd_broadcast, 0x001A, 0, message_data.to_wide(), 2, 5000, 0) == 0 {
|
if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) == 0 {
|
||||||
return error('Could not broadcast WM_SETTINGCHANGE')
|
return error('Could not broadcast WM_SETTINGCHANGE')
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
83
make.bat
83
make.bat
@ -2,8 +2,24 @@
|
|||||||
|
|
||||||
echo Building V
|
echo Building V
|
||||||
|
|
||||||
|
REM default tcc
|
||||||
|
set tcc_url=https://github.com/vlang/tccbin_win
|
||||||
|
set tcc_dir=%~dp0thirdparty\tcc
|
||||||
|
|
||||||
|
REM let a particular environment specify their own tcc
|
||||||
|
if "%TCC_GIT%" =="" goto :init
|
||||||
|
set tcc_url="%TCC_GIT%"
|
||||||
|
|
||||||
|
:init
|
||||||
|
REM initialize the log file with the failure message
|
||||||
set log_file=%TEMP%\v_make.bat.log
|
set log_file=%TEMP%\v_make.bat.log
|
||||||
set tcc_path=%~dp0thirdparty\tcc\
|
echo Failed to compile - Create an issue at 'https://github.com/vlang/v' with the following info:>%log_file%
|
||||||
|
echo.>>%log_file%
|
||||||
|
|
||||||
|
REM alleviate weird issues with this var
|
||||||
|
set cloned_tcc=
|
||||||
|
set ERRORLEVEL=
|
||||||
|
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
if "%~1"=="-local" goto :compile
|
if "%~1"=="-local" goto :compile
|
||||||
@ -21,12 +37,14 @@ if exist "vc" (
|
|||||||
|
|
||||||
:compile
|
:compile
|
||||||
REM option to force msvc, gcc or tcc
|
REM option to force msvc, gcc or tcc
|
||||||
if "%~1"=="-gcc" set force_gcc=1 & goto :gcc_strap
|
if "%~1"=="-gcc" set force_gcc=1 & goto :gcc_strap
|
||||||
if "%~2"=="-gcc" set force_gcc=1 & goto :gcc_strap
|
if "%~2"=="-gcc" set force_gcc=1 & goto :gcc_strap
|
||||||
if "%~1"=="-msvc" set force_msvc=1 & goto :msvc_strap
|
if "%~1"=="-msvc" set force_msvc=1 & goto :msvc_strap
|
||||||
if "%~2"=="-msvc" set force_msvc=1 & goto :msvc_strap
|
if "%~2"=="-msvc" set force_msvc=1 & goto :msvc_strap
|
||||||
if "%~1"=="-tcc" set force_tcc=1 & goto :tcc_strap
|
if "%~1"=="-tcc" set force_tcc=1 & goto :tcc_strap
|
||||||
if "%~2"=="-tcc" set force_tcc=1 & goto :tcc_strap
|
if "%~2"=="-tcc" set force_tcc=1 & goto :tcc_strap
|
||||||
|
if "%~1"=="-fresh_tcc" set force_tcc=1 & goto :fresh_tcc
|
||||||
|
if "%~2"=="-fresh_tcc" set force_tcc=1 & goto :fresh_tcc
|
||||||
|
|
||||||
:gcc_strap
|
:gcc_strap
|
||||||
echo.
|
echo.
|
||||||
@ -39,13 +57,14 @@ if %ERRORLEVEL% NEQ 0 (
|
|||||||
goto :msvc_strap
|
goto :msvc_strap
|
||||||
)
|
)
|
||||||
|
|
||||||
gcc -std=c99 -municode -w -o v.exe vc\v_win.c>>%log_file% 2>>&1
|
gcc -std=c99 -municode -w -o v.exe .\vc\v_win.c>>%log_file% 2>>&1
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
rem In most cases, compile errors happen because the version of GCC installed is too old
|
rem In most cases, compile errors happen because the version of GCC installed is too old
|
||||||
gcc --version>>%log_file% 2>>&1
|
gcc --version>>%log_file% 2>>&1
|
||||||
goto :compile_error
|
goto :compile_error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo ^> Compiling with .\v.exe self
|
||||||
v.exe self>>%log_file% 2>>&1
|
v.exe self>>%log_file% 2>>&1
|
||||||
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
||||||
goto :success
|
goto :success
|
||||||
@ -79,16 +98,20 @@ if exist "%InstallDir%\Common7\Tools\vsdevcmd.bat" (
|
|||||||
|
|
||||||
set ObjFile=.v.c.obj
|
set ObjFile=.v.c.obj
|
||||||
|
|
||||||
cl.exe /nologo /w /volatile:ms /Fo%ObjFile% /O2 /MD /D_VBOOTSTRAP vc\v_win.c user32.lib kernel32.lib advapi32.lib shell32.lib /link /NOLOGO /OUT:v.exe /INCREMENTAL:NO>>%log_file% 2>>&1
|
cl.exe /volatile:ms /Fo%ObjFile% /O2 /MD /D_VBOOTSTRAP vc\v_win.c user32.lib kernel32.lib advapi32.lib shell32.lib /link /nologo /out:v.exe /incremental:no>>%log_file% 2>>&1
|
||||||
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
||||||
|
|
||||||
|
echo ^> Compiling with .\v.exe self
|
||||||
v.exe -cc msvc self>>%log_file% 2>>&1
|
v.exe -cc msvc self>>%log_file% 2>>&1
|
||||||
del %ObjFile%
|
del %ObjFile%>>%log_file% 2>>&1
|
||||||
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
||||||
goto :success
|
goto :success
|
||||||
|
|
||||||
|
:fresh_tcc
|
||||||
|
rd /s /q %tcc_dir%
|
||||||
|
|
||||||
:clone_tcc
|
:clone_tcc
|
||||||
git clone --depth 1 --quiet https://github.com/vlang/tccbin_win %tcc_path%
|
git clone --depth 1 --quiet %tcc_url% %tcc_dir%
|
||||||
set cloned_tcc=1
|
set cloned_tcc=1
|
||||||
goto :tcc_strap
|
goto :tcc_strap
|
||||||
|
|
||||||
@ -98,31 +121,33 @@ echo Attempting to build v.c with TCC...
|
|||||||
|
|
||||||
where /q tcc
|
where /q tcc
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
if exist "%tcc_path%" (
|
if exist "%tcc_dir%" (
|
||||||
set tcc_exe=%tcc_path%tcc.exe
|
set tcc_exe=%tcc_dir%\tcc.exe
|
||||||
) else if "%cloned_tcc%"=="" (
|
) else if "%cloned_tcc%"=="" (
|
||||||
echo ^> TCC not found
|
echo ^> TCC not found
|
||||||
echo ^> Downloading TCC from https://github.com/vlang/tccbin_win
|
echo ^> Downloading TCC from %tcc_url%
|
||||||
goto :clone_tcc
|
goto :clone_tcc
|
||||||
) else (
|
) else (
|
||||||
echo ^> TCC not found, even after cloning
|
echo ^> TCC not found, even after cloning %cloned_tcc%
|
||||||
goto :error
|
goto :error
|
||||||
)
|
)
|
||||||
) else (
|
) else (
|
||||||
for /f "delims=" %%i in ('where tcc') do set tcc_exe=%%i
|
for /f "delims=" %%i in ('where tcc') do set tcc_exe=%%i
|
||||||
)
|
)
|
||||||
|
|
||||||
if exist "%tcc_path%" (
|
if exist "%tcc_dir%" (
|
||||||
if "%cloned_tcc%"=="" (
|
if "%cloned_tcc%"=="" (
|
||||||
echo ^> Updating prebuilt TCC...
|
echo ^> Updating prebuilt TCC...
|
||||||
pushd "%tcc_path%"
|
pushd "%tcc_dir%"\
|
||||||
git pull -q
|
git pull -q
|
||||||
popd
|
popd
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
call "%tcc_exe%" -std=c99 -municode -lws2_32 -lshell32 -ladvapi32 -bt10 -w -o v.exe vc\v_win.c
|
|
||||||
|
%tcc_exe% -std=c99 -municode -lws2_32 -lshell32 -ladvapi32 -bt10 -w -o v.exe vc\v_win.c
|
||||||
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
||||||
|
|
||||||
|
echo ^> Compiling with .\v.exe self
|
||||||
v.exe -cc "%tcc_exe%" self>>%log_file% 2>>&1
|
v.exe -cc "%tcc_exe%" self>>%log_file% 2>>&1
|
||||||
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
if %ERRORLEVEL% NEQ 0 goto :compile_error
|
||||||
goto :success
|
goto :success
|
||||||
@ -130,8 +155,6 @@ goto :success
|
|||||||
:compile_error
|
:compile_error
|
||||||
echo.
|
echo.
|
||||||
echo.
|
echo.
|
||||||
echo Failed to compile - Create an issue at 'https://github.com/vlang' with the following info:
|
|
||||||
echo.
|
|
||||||
type %log_file%
|
type %log_file%
|
||||||
del %log_file%
|
del %log_file%
|
||||||
goto :error
|
goto :error
|
||||||
@ -144,21 +167,23 @@ exit /b 1
|
|||||||
|
|
||||||
:success
|
:success
|
||||||
echo ^> V built successfully!
|
echo ^> V built successfully!
|
||||||
echo ^> To add V to your PATH, run `.\v symlink`.
|
echo ^> To add V to your PATH, run `.\v.exe symlink`.
|
||||||
del v_old.exe
|
del v_old.exe >>%log_file% 2>>&1
|
||||||
del %log_file%
|
del %log_file%
|
||||||
|
|
||||||
:version
|
:version
|
||||||
echo.
|
echo.
|
||||||
echo | set /p="V version: "
|
echo | set /p="V version: "
|
||||||
v.exe version
|
.\v.exe version
|
||||||
if "%cloned_tcc%" NEQ "" (
|
if "%cloned_tcc%" NEQ "" (
|
||||||
echo.
|
if "%force_tcc%" == "" (
|
||||||
echo WARNING: No C compiler was detected in your PATH. `tcc` was used temporarily
|
echo.
|
||||||
echo to build V, but it may have some bugs and may not work in all cases.
|
echo WARNING: No C compiler was detected in your PATH. `tcc` was used temporarily
|
||||||
echo A more advanced C compiler like GCC or MSVC is recommended.
|
echo to build V, but it may have some bugs and may not work in all cases.
|
||||||
echo https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows
|
echo A more advanced C compiler like GCC or MSVC is recommended.
|
||||||
echo.
|
echo https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows
|
||||||
|
echo.
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
@ -191,9 +191,17 @@ fn C._fileno(int) int
|
|||||||
fn C._get_osfhandle(fd int) C.intptr_t
|
fn C._get_osfhandle(fd int) C.intptr_t
|
||||||
|
|
||||||
|
|
||||||
|
fn C.GetModuleFileName() int
|
||||||
fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32
|
fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32
|
||||||
|
|
||||||
|
|
||||||
|
fn C.CreateFile() voidptr
|
||||||
|
fn C.CreateFileW(lpFilename &u16, dwDesiredAccess u32, dwShareMode u32, lpSecurityAttributes &u16, dwCreationDisposition u32, dwFlagsAndAttributes u32, hTemplateFile voidptr) u32
|
||||||
|
|
||||||
|
|
||||||
|
fn C.GetFinalPathNameByHandleW(hFile voidptr, lpFilePath &u16, nSize u32, dwFlags u32) int
|
||||||
|
|
||||||
|
|
||||||
fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool
|
fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool
|
||||||
|
|
||||||
|
|
||||||
@ -304,9 +312,6 @@ fn C.WriteConsole() voidptr
|
|||||||
fn C.WriteFile() voidptr
|
fn C.WriteFile() voidptr
|
||||||
|
|
||||||
|
|
||||||
fn C.GetModuleFileName() int
|
|
||||||
|
|
||||||
|
|
||||||
fn C._wchdir()
|
fn C._wchdir()
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,63 +2,67 @@ module os
|
|||||||
|
|
||||||
// Ref - winnt.h
|
// Ref - winnt.h
|
||||||
const (
|
const (
|
||||||
success = 0 // ERROR_SUCCESS
|
success = 0x0000 // ERROR_SUCCESS
|
||||||
error_insufficient_buffer = 130
|
error_insufficient_buffer = 0x0082
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
file_share_read = 1
|
handle_generic_read = 0x80000000
|
||||||
file_share_write = 2
|
handle_open_existing = 0x00000003
|
||||||
file_share_delete = 4
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
file_notify_change_file_name = 1
|
file_share_read = 0x01
|
||||||
file_notify_change_dir_name = 2
|
file_share_write = 0x02
|
||||||
file_notify_change_attributes = 4
|
file_share_delete = 0x04
|
||||||
file_notify_change_size = 8
|
|
||||||
file_notify_change_last_write = 16
|
|
||||||
file_notify_change_last_access = 32
|
|
||||||
file_notify_change_creation = 64
|
|
||||||
file_notify_change_security = 128
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
file_action_added = 1
|
file_notify_change_file_name = 0x01
|
||||||
file_action_removed = 2
|
file_notify_change_dir_name = 0x02
|
||||||
file_action_modified = 3
|
file_notify_change_attributes = 0x04
|
||||||
file_action_renamed_old_name = 4
|
file_notify_change_size = 0x08
|
||||||
file_action_renamed_new_name = 5
|
file_notify_change_last_write = 0x10
|
||||||
|
file_notify_change_last_access = 0x20
|
||||||
|
file_notify_change_creation = 0x40
|
||||||
|
file_notify_change_security = 0x80
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
file_attr_readonly = 0x1
|
file_action_added = 0x01
|
||||||
file_attr_hidden = 0x2
|
file_action_removed = 0x02
|
||||||
file_attr_system = 0x4
|
file_action_modified = 0x03
|
||||||
file_attr_directory = 0x10
|
file_action_renamed_old_name = 0x04
|
||||||
file_attr_archive = 0x20
|
file_action_renamed_new_name = 0x05
|
||||||
file_attr_device = 0x40
|
)
|
||||||
file_attr_normal = 0x80
|
|
||||||
file_attr_temporary = 0x100
|
const (
|
||||||
file_attr_sparse_file = 0x200
|
file_attr_readonly = 0x00000001
|
||||||
file_attr_reparse_point = 0x400
|
file_attr_hidden = 0x00000002
|
||||||
file_attr_compressed = 0x800
|
file_attr_system = 0x00000004
|
||||||
file_attr_offline = 0x1000
|
file_attr_directory = 0x00000010
|
||||||
file_attr_not_content_indexed = 0x2000
|
file_attr_archive = 0x00000020
|
||||||
file_attr_encrypted = 0x4000
|
file_attr_device = 0x00000040
|
||||||
file_attr_integrity_stream = 0x8000
|
file_attr_normal = 0x00000080
|
||||||
file_attr_virtual = 0x10000
|
file_attr_temporary = 0x00000100
|
||||||
file_attr_no_scrub_data = 0x20000
|
file_attr_sparse_file = 0x00000200
|
||||||
|
file_attr_reparse_point = 0x00000400
|
||||||
|
file_attr_compressed = 0x00000800
|
||||||
|
file_attr_offline = 0x00001000
|
||||||
|
file_attr_not_content_indexed = 0x00002000
|
||||||
|
file_attr_encrypted = 0x00004000
|
||||||
|
file_attr_integrity_stream = 0x00008000
|
||||||
|
file_attr_virtual = 0x00010000
|
||||||
|
file_attr_no_scrub_data = 0x00020000
|
||||||
// file_attr_recall_on_open = u32(0x...)
|
// file_attr_recall_on_open = u32(0x...)
|
||||||
// file_attr_recall_on_data_access = u32(0x...)
|
// file_attr_recall_on_data_access = u32(0x...)
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
file_type_disk = 0x1
|
file_type_unknown = 0x00
|
||||||
file_type_char = 0x2
|
file_type_disk = 0x01
|
||||||
file_type_pipe = 0x3
|
file_type_char = 0x02
|
||||||
|
file_type_pipe = 0x03
|
||||||
file_type_unknown = 0x0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -82,58 +86,79 @@ const (
|
|||||||
enable_window_input = 0x0008
|
enable_window_input = 0x0008
|
||||||
enable_virtual_terminal_input = 0x0200
|
enable_virtual_terminal_input = 0x0200
|
||||||
// Output Screen Buffer
|
// Output Screen Buffer
|
||||||
enable_processed_output = 0x0001
|
enable_processed_output = 0x01
|
||||||
enable_wrap_at_eol_output = 0x0002
|
enable_wrap_at_eol_output = 0x02
|
||||||
enable_virtual_terminal_processing = 0x0004
|
enable_virtual_terminal_processing = 0x04
|
||||||
disable_newline_auto_return = 0x0008
|
disable_newline_auto_return = 0x08
|
||||||
enable_lvb_grid_worldwide = 0x0010
|
enable_lvb_grid_worldwide = 0x10
|
||||||
)
|
)
|
||||||
|
|
||||||
// File modes
|
// File modes
|
||||||
const (
|
const (
|
||||||
o_rdonly = 0 // open the file read-only.
|
o_rdonly = 0x0000 // open the file read-only.
|
||||||
o_wronly = 1 // open the file write-only.
|
o_wronly = 0x0001 // open the file write-only.
|
||||||
o_rdwr = 2 // open the file read-write.
|
o_rdwr = 0x0002 // open the file read-write.
|
||||||
o_append = 0x0008 // append data to the file when writing.
|
o_append = 0x0008 // append data to the file when writing.
|
||||||
o_create = 0x0100 // create a new file if none exists.
|
o_create = 0x0100 // create a new file if none exists.
|
||||||
o_trunc = 0x0200 // truncate regular writable file when opened.
|
o_trunc = 0x0200 // truncate regular writable file when opened.
|
||||||
o_excl = 0x0400 // used with o_create, file must not exist.
|
o_excl = 0x0400 // used with o_create, file must not exist.
|
||||||
o_sync = 0 // open for synchronous I/O (ignored on Windows)
|
o_sync = 0x0000 // open for synchronous I/O (ignored on Windows)
|
||||||
o_noctty = 0 // make file non-controlling tty (ignored on Windows)
|
o_noctty = 0x0000 // make file non-controlling tty (ignored on Windows)
|
||||||
o_nonblock = 0 // don't block on opening file (ignored on Windows)
|
o_nonblock = 0x0000 // don't block on opening file (ignored on Windows)
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
status_access_violation = 0xC0000005
|
status_access_violation = 0xC0000005
|
||||||
status_in_page_error = 0xC0000006
|
status_in_page_error = 0xC0000006
|
||||||
status_invalid_handle = 0xC0000008
|
status_invalid_handle = 0xC0000008
|
||||||
status_invalid_parameter = 0xC000000D
|
status_invalid_parameter = 0xC000000D
|
||||||
status_no_memory = 0xC0000017
|
status_no_memory = 0xC0000017
|
||||||
status_illegal_instruction = 0xC000001D
|
status_illegal_instruction = 0xC000001D
|
||||||
status_noncontinuable_exception = 0xC0000025
|
status_noncontinuable_exception = 0xC0000025
|
||||||
status_invalid_disposition = 0xC0000026
|
status_invalid_disposition = 0xC0000026
|
||||||
status_array_bounds_exceeded = 0xC000008C
|
status_array_bounds_exceeded = 0xC000008C
|
||||||
status_float_denormal_operand = 0xC000008D
|
status_float_denormal_operand = 0xC000008D
|
||||||
status_float_divide_by_zero = 0xC000008E
|
status_float_divide_by_zero = 0xC000008E
|
||||||
status_float_inexact_result = 0xC000008F
|
status_float_inexact_result = 0xC000008F
|
||||||
status_float_invalid_operation = 0xC0000090
|
status_float_invalid_operation = 0xC0000090
|
||||||
status_float_overflow = 0xC0000091
|
status_float_overflow = 0xC0000091
|
||||||
status_float_stack_check = 0xC0000092
|
status_float_stack_check = 0xC0000092
|
||||||
status_float_underflow = 0xC0000093
|
status_float_underflow = 0xC0000093
|
||||||
status_integer_divide_by_zero = 0xC0000094
|
status_integer_divide_by_zero = 0xC0000094
|
||||||
status_integer_overflow = 0xC0000095
|
status_integer_overflow = 0xC0000095
|
||||||
status_privileged_instruction = 0xC0000096
|
status_privileged_instruction = 0xC0000096
|
||||||
status_stack_overflow = 0xC00000FD
|
status_stack_overflow = 0xC00000FD
|
||||||
status_dll_not_found = 0xC0000135
|
status_dll_not_found = 0xC0000135
|
||||||
status_ordinal_not_found = 0xC0000138
|
status_ordinal_not_found = 0xC0000138
|
||||||
status_entrypoint_not_found = 0xC0000139
|
status_entrypoint_not_found = 0xC0000139
|
||||||
status_control_c_exit = 0xC000013A
|
status_control_c_exit = 0xC000013A
|
||||||
status_dll_init_failed = 0xC0000142
|
status_dll_init_failed = 0xC0000142
|
||||||
status_float_multiple_faults = 0xC00002B4
|
status_float_multiple_faults = 0xC00002B4
|
||||||
status_float_multiple_traps = 0xC00002B5
|
status_float_multiple_traps = 0xC00002B5
|
||||||
status_reg_nat_consumption = 0xC00002C9
|
status_reg_nat_consumption = 0xC00002C9
|
||||||
status_heap_corruption = 0xC0000374
|
status_heap_corruption = 0xC0000374
|
||||||
status_stack_buffer_overrun = 0xC0000409
|
status_stack_buffer_overrun = 0xC0000409
|
||||||
status_invalid_cruntime_parameter = 0xC0000417
|
status_invalid_cruntime_parameter = 0xC0000417
|
||||||
status_assertion_failure = 0xC0000420
|
status_assertion_failure = 0xC0000420
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Windows Registry Constants
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
hkey_local_machine = voidptr(0x80000002)
|
||||||
|
hkey_current_user = voidptr(0x80000001)
|
||||||
|
|
||||||
|
key_query_value = 0x0001
|
||||||
|
key_set_value = 0x0002
|
||||||
|
key_enumerate_sub_keys = 0x0008
|
||||||
|
key_wow64_32key = 0x0200
|
||||||
|
)
|
||||||
|
|
||||||
|
// Windows Messages
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
hwnd_broadcast = voidptr(0xFFFF)
|
||||||
|
|
||||||
|
wm_settingchange = 0x001A
|
||||||
|
smto_abortifhung = 0x0002
|
||||||
|
)
|
29
vlib/os/os.v
29
vlib/os/os.v
@ -948,8 +948,30 @@ pub fn executable() string {
|
|||||||
}
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
max := 512
|
max := 512
|
||||||
mut result := &u16(vcalloc(max * 2)) // max_path_len * sizeof(wchar_t)
|
size := max * 2 // max_path_len * sizeof(wchar_t)
|
||||||
|
mut result := &u16(vcalloc(size))
|
||||||
len := C.GetModuleFileName(0, result, max)
|
len := C.GetModuleFileName(0, result, max)
|
||||||
|
// determine if the file is a windows symlink
|
||||||
|
attrs := C.GetFileAttributesW(result)
|
||||||
|
is_set := attrs & 0x400 // FILE_ATTRIBUTE_REPARSE_POINT
|
||||||
|
if is_set != 0 { // it's a windows symlink
|
||||||
|
// gets handle with GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
|
||||||
|
file := C.CreateFile(result, 0x80000000, 1, 0, 3, 0x80, 0)
|
||||||
|
if file != -1 {
|
||||||
|
final_path := &u16(vcalloc(size))
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
|
||||||
|
final_len := C.GetFinalPathNameByHandleW(file, final_path, size, 0)
|
||||||
|
if final_len < size {
|
||||||
|
ret := string_from_wide2(final_path, final_len)
|
||||||
|
// remove '\\?\' from beginning (see link above)
|
||||||
|
return ret[4..]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eprintln('os.executable() saw that the executable file path was too long')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
C.CloseHandle(file)
|
||||||
|
}
|
||||||
return string_from_wide2(result, len)
|
return string_from_wide2(result, len)
|
||||||
}
|
}
|
||||||
$if macos {
|
$if macos {
|
||||||
@ -1003,6 +1025,11 @@ fn executable_fallback() string {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
mut exepath := os.args[0]
|
mut exepath := os.args[0]
|
||||||
|
$if windows {
|
||||||
|
if !exepath.contains('.exe') {
|
||||||
|
exepath += '.exe'
|
||||||
|
}
|
||||||
|
}
|
||||||
if !os.is_abs_path(exepath) {
|
if !os.is_abs_path(exepath) {
|
||||||
if exepath.contains( os.path_separator ) {
|
if exepath.contains( os.path_separator ) {
|
||||||
exepath = os.join_path(os.wd_at_startup, exepath)
|
exepath = os.join_path(os.wd_at_startup, exepath)
|
||||||
|
Loading…
Reference in New Issue
Block a user