From 99a9a6572ad5d974c1ce1a9a1cbfb751f589cce9 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 1 Jul 2019 11:01:48 +0200 Subject: [PATCH] lots of Windows fixes and cross compilation for Windows --- compiler/main.v | 81 ++++++++++++++++++++++++- compiler/parser.v | 3 +- vlib/os/os.v | 56 ++++++++++++++---- vlib/os/os_mac.v | 3 + vlib/os/types_win.v | 140 -------------------------------------------- vlib/time/time.v | 5 ++ 6 files changed, 132 insertions(+), 156 deletions(-) create mode 100644 vlib/os/os_mac.v delete mode 100644 vlib/os/types_win.v diff --git a/compiler/main.v b/compiler/main.v index 11c15a3ac9..9e2676d78c 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -412,7 +412,84 @@ string _STR_TMP(const char *fmt, ...) { } } +fn (c &V) cc_windows_cross() { + if !c.out_name.ends_with('.exe') { + c.out_name = c.out_name + '.exe' + } + mut args := '-o $c.out_name -w -L. ' + // -I flags + for flag in c.table.flags { + if !flag.starts_with('-l') { + args += flag + args += ' ' + } + } + mut libs := '' + if c.pref.build_mode == DEFAULT_MODE { + libs = '$TmpPath/vlib/builtin.o' + if !os.file_exists(libs) { + println('`builtin.o` not found') + exit(1) + } + for imp in c.table.imports { + libs += ' $TmpPath/vlib/${imp}.o' + } + } + args += ' $c.out_name_c ' + // -l flags (libs) + for flag in c.table.flags { + if flag.starts_with('-l') { + args += flag + args += ' ' + } + } + println('Cross compiling for Windows...') + winroot := '$TmpPath/winroot' + if !os.dir_exists(winroot) { + winroot_url := 'https://github.com/vlang/v/releases/download/v0.1.10/winroot.zip' + println('"$winroot" not found. Download it from $winroot_url and save in $TmpPath') + exit(1) + +} + mut obj_name := c.out_name + obj_name = obj_name.replace('.exe', '') + obj_name = obj_name.replace('.o.o', '.o') + mut include := '-I $winroot/include ' + cmd := 'clang -o $obj_name -w $include -m32 -c -target x86_64-win32 $TmpPath/$c.out_name_c' + if c.pref.show_c_cmd { + println(cmd) + } + if os.system(cmd) != 0 { + println('Cross compilation for Windows failed. Make sure you have clang installed.') + exit(1) + } + if c.pref.build_mode != BUILD { + link_cmd := 'lld-link $obj_name $winroot/lib/libcmt.lib ' + + '$winroot/lib/libucrt.lib $winroot/lib/kernel32.lib $winroot/lib/libvcruntime.lib ' + + '$winroot/lib/uuid.lib' + if c.pref.show_c_cmd { + println(link_cmd) + } + + if os.system(link_cmd) != 0 { + println('Cross compilation for Windows failed. Make sure you have lld linker installed.') + exit(1) +} + // os.rm(obj_name) + } + println('Done!') +} + + + fn (v mut V) cc() { + // Cross compiling for Windows + if v.os == WINDOWS { + $if !windows { + v.cc_windows_cross() + return + } + } linux_host := os.user_os() == 'linux' v.log('cc() isprod=$v.pref.is_prod outname=$v.out_name') mut a := ['-w', '-march=native']// arguments for the C compiler @@ -530,7 +607,7 @@ mut args := '' '$sysroot/lib/x86_64-linux-gnu/libm-2.28.a ' + '/usr/lib/x86_64-linux-gnu/crti.o ' + obj_file + - ' /usr/lib/x86_64-linux-gnu/libv.so ' + + ' /usr/lib/x86_64-linux-gnu/libc.so ' + '/usr/lib/x86_64-linux-gnu/crtn.o') println(ress) if ress.contains('error:') { @@ -569,7 +646,7 @@ fn (v &V) v_files_from_dir(dir string) []string { if file.ends_with('_lin.v') && v.os != LINUX { continue } - if file.ends_with('_mav.v') && v.os != MAC { + if file.ends_with('_mac.v') && v.os != MAC { lin_file := file.replace('_mav.v', '_lin.v') // println('lin_file="$lin_file"') // If there are both _mav.v and _lin.v, don't use _mav.v diff --git a/compiler/parser.v b/compiler/parser.v index 1d71ecc177..39b0417b68 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -810,7 +810,8 @@ fn (p mut Parser) get_type() string { // "typ" not found? try "pkg__typ" if t.name == '' && !p.builtin_pkg { // && !p.first_run() { - if !typ.contains('array_') && p.pkg != 'main' && !typ.contains('__') { + if !typ.contains('array_') && p.pkg != 'main' && !typ.contains('__') && + !typ.starts_with('[') { typ = p.prepend_pkg(typ) } t = p.table.find_type(typ) diff --git a/vlib/os/os.v b/vlib/os/os.v index 2e8d567a43..9def06a69f 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -6,11 +6,24 @@ module os #include #include -#include -#include +//#include #include //#include // for backtrace_symbols_fd +/* +struct dirent { + d_ino int + d_off int + d_reclen u16 + d_type byte + d_name [256]byte +} +*/ + +struct C.dirent { + d_name byteptr +} + const ( args = []string MAX_PATH = 4096 @@ -20,6 +33,10 @@ const ( FILE_ATTRIBUTE_DIRECTORY = 16 // Windows ) +import const ( + INVALID_FILE_ATTRIBUTES +) + struct FILE { } @@ -50,10 +67,10 @@ struct C.DIR { } -struct C.dirent { - d_name byteptr +//struct C.dirent { + //d_name byteptr -} +//} struct C.sigaction { mut: @@ -302,15 +319,22 @@ pub fn file_exists(path string) bool { } pub fn dir_exists(path string) bool { - dir := C.opendir(path.cstr()) - res := !isnil(dir) - if res { - C.closedir(dir) - } - return res + $if windows { + attr := int(C.GetFileAttributes(path.cstr())) + println('ATTR =$attr') + return attr == FILE_ATTRIBUTE_DIRECTORY + } + $else { + dir := C.opendir(path.cstr()) + res := !isnil(dir) + if res { + C.closedir(dir) + } + return res + } } -// `mkdir` creates a new directory with the specified path. +// mkdir creates a new directory with the specified path. pub fn mkdir(path string) { $if windows { path = path.replace('/', '\\') @@ -321,7 +345,7 @@ pub fn mkdir(path string) { } } -// `rm` removes file in `path`. +// rm removes file in `path`. pub fn rm(path string) { $if windows { // os.system2('del /f $path') @@ -530,6 +554,11 @@ pub fn getwd() string { } pub fn ls(path string) []string { + $if windows { + return []string +} +$else { + mut res := []string dir := C.opendir(path.str) if isnil(dir) { @@ -550,6 +579,7 @@ pub fn ls(path string) []string { } C.closedir(dir) return res +} } fn log(s string) { diff --git a/vlib/os/os_mac.v b/vlib/os/os_mac.v new file mode 100644 index 0000000000..3d553e42d7 --- /dev/null +++ b/vlib/os/os_mac.v @@ -0,0 +1,3 @@ +module os + +#include diff --git a/vlib/os/types_win.v b/vlib/os/types_win.v deleted file mode 100644 index de0349d2f6..0000000000 --- a/vlib/os/types_win.v +++ /dev/null @@ -1,140 +0,0 @@ -module os - -// Ref - https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types - -type BOOL bool -type BOOLEAN BOOL - -// A byte (8 bits) -type BYTE u8 - -// An 8-bit Windows (ANSI) character. -type CHAR u8 - -// An 16-bit Windows character. -type WCHAR u16 - -// A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal. -type INT i32 - -// A signed integer type for pointer precision. -type INT_PTR INT* - -// A pointer to an INT (INT32). -type PINT INT* - -// A 8-bit signed integer. -type INT8 i8 - -// // A pointer to an INT8. -type PINT8 INT8* - -// A 16-bit signed integer. -type INT16 i16 - -// // A pointer to an INT16. -type PINT16 INT16* - -// A 32-bit signed integer. -type INT32 i32 - -// A pointer to an INT32. -type PINT32 INT32* - -// A 64-bit signed integer. -type INT64 i64 - -// A pointer to an INT64. -type PINT64 INT64* - -// An unsigned INT. The range is 0 through 4294967295 decimal. -type UINT u32 - -// An unsigned INT_PTR. -type UINT_PTR UINT* - -// An unsigned INT8. -type UINT8 u8 - -// An unsigned INT16. -type UINT16 u16 - -// An unsigned INT32. -type UINT32 u32 - -// An unsigned INT64. -type UINT64 u64 - -// A 16-bit unsigned integer. The range is 0 through 65535 decimal. -type WORD u16 - -// A pointer to an WORD. -type LPWORD WORD* - -// A 32-bit unsigned integer. The range is 0 through 4294967295 decimal. -type DWORD u32 - -// A pointer to an DWORD. -type DWORD_PTR DWORD* -type LPDWORD DWORD* - -// A 64-bit unsigned integer. The range is 0 through 18446744073709551615 decimal. -type DWORDLONG u64 -type PDWORDLONG DWORDLONG* - -// A 32-bit unsigned integer. -type DWORD32 u32 -type PDWORD32 DWORD32* - -// A 64-bit unsigned integer. -type DWORD64 u64 -type PDWORD64 DWORD64* - -// A floating-point variable. -type FLOAT f32 -type FLOAT64 f64 -type PFLOAT FLOAT* - -// A 32-bit signed integer. The range is 2147483648 through 2147483647 decimal. -type LONG i32 -type LONG_PTR LONG* -type LPLONG LONG* - -// A 64-bit signed integer. The range is 9223372036854775808 through 9223372036854775807 decimal. -type LONGLONG i64 -type LONG32 i32 -type LONG64 i64 - -// A pointer to a BOOL. -type LPBOOL BOOL* - -// A pointer to a BYTE. -type LPBYTE BYTE* - -// An 8-bit Windows (ANSI) character. For more information, see Character Sets Used By Fonts. -type LPCSTR CHAR* - -// A 16-bit Unicode character. For more information, see Character Sets Used By Fonts. -type LPWSTR WCHAR* - -// A pointer to an CHAR. -type PCHAR CHAR* - -// A pointer to an BYTE. -type PBYTE BYTE* - -// -// Descriptor -// - -// A handle to an object. -type HANDLE C.HANDLE // voidptr? - -// A pointer to a HANDLE. -type PHANDLE *HANDLE - -// A handle to a registry key. -type HKEY HANDLE - -// A pointer to a HKEY. -type PHKEY *HKEY diff --git a/vlib/time/time.v b/vlib/time/time.v index 49f592bff8..b4d765b8fd 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -303,7 +303,12 @@ pub fn sleep(seconds int) { } pub fn usleep(n int) { +$if windows { + //C._usleep(n) +} +$else { C.usleep(n) +} } pub fn sleep_ms(n int) {