1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

add MSVC C backend support; fix live code reloading on Windows; other Windows fixes

This commit is contained in:
Emily Hudson
2019-07-23 22:23:13 +01:00
committed by Alexander Medvednikov
parent 3cf8e18cf6
commit e25ea7f9dd
9 changed files with 1231 additions and 42 deletions

View File

@ -29,7 +29,7 @@ fn modules_path() string {
}
const (
SupportedPlatforms = ['windows', 'mac', 'linux', 'freebsd', 'openbsd', 'netbsd', 'dragonfly']
SupportedPlatforms = ['windows', 'mac', 'linux', 'freebsd', 'openbsd', 'netbsd', 'dragonfly', 'msvc']
ModPath = modules_path()
)
@ -41,6 +41,7 @@ enum OS {
openbsd
netbsd
dragonfly
msvc
}
enum Pass {
@ -189,9 +190,22 @@ fn (v mut V) compile() {
#include <inttypes.h> // int64_t etc
#ifdef _WIN32
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//#include <WinSock2.h>
//#include <WinSock2.h>
#ifdef _MSC_VER
// On MSVC these are the same (as long as /volatile:ms is passed)
#define _Atomic volatile
#endif
void pthread_mutex_lock(HANDLE *m) {
WaitForSingleObject(*m, INFINITE);
}
void pthread_mutex_unlock(HANDLE *m) {
ReleaseMutex(*m);
}
#else
#include <pthread.h>
#endif
@ -246,12 +260,22 @@ int load_so(byteptr);
void reload_so();
void init_consts();')
if v.pref.is_so {
cgen.genln('pthread_mutex_t live_fn_mutex;')
}
if v.pref.is_live {
cgen.genln('pthread_mutex_t live_fn_mutex = PTHREAD_MUTEX_INITIALIZER;')
if v.os != .windows && v.os != .msvc {
if v.pref.is_so {
cgen.genln('pthread_mutex_t live_fn_mutex;')
}
if v.pref.is_live {
cgen.genln('pthread_mutex_t live_fn_mutex = PTHREAD_MUTEX_INITIALIZER;')
}
} else {
if v.pref.is_so {
cgen.genln('HANDLE live_fn_mutex;')
}
if v.pref.is_live {
cgen.genln('HANDLE live_fn_mutex = 0;')
}
}
imports_json := v.table.imports.contains('json')
// TODO remove global UI hack
@ -386,8 +410,24 @@ string _STR_TMP(const char *fmt, ...) {
so_name := file_base + '.so'
// Need to build .so file before building the live application
// The live app needs to load this .so file on initialization.
vexe := os.args[0]
os.system('$vexe -o $file_base -shared $file')
mut vexe := os.args[0]
if os.user_os() == 'windows' {
vexe = vexe.replace('\\', '\\\\')
}
mut msvc := ''
if v.os == .msvc {
msvc = '-os msvc'
}
mut debug := ''
if v.pref.is_debug {
debug = '-debug'
}
os.system('$vexe $msvc $debug -o $file_base -shared $file')
cgen.genln('
void lfnmutex_print(char *s){
@ -397,7 +437,10 @@ void lfnmutex_print(char *s){
fflush(stderr);
}
}
')
if v.os != .windows && v.os != .msvc {
cgen.genln('
#include <dlfcn.h>
void* live_lib=0;
int load_so(byteptr path) {
@ -412,8 +455,28 @@ int load_so(byteptr path) {
return 0;
}
')
for so_fn in cgen.so_fns {
cgen.genln('$so_fn = dlsym(live_lib, "$so_fn"); ')
for so_fn in cgen.so_fns {
cgen.genln('$so_fn = dlsym(live_lib, "$so_fn"); ')
}
}
else {
cgen.genln('
void* live_lib=0;
int load_so(byteptr path) {
char cpath[1024];
sprintf(cpath, "./%s", path);
if (live_lib) FreeLibrary(live_lib);
live_lib = LoadLibraryA(cpath);
if (!live_lib) {
puts("open failed");
exit(1);
return 0;
}
')
for so_fn in cgen.so_fns {
cgen.genln('$so_fn = (void *)GetProcAddress(live_lib, "$so_fn"); ')
}
}
cgen.genln('return 1;
@ -434,8 +497,17 @@ void reload_so() {
//v -o bounce -shared bounce.v
sprintf(new_so_base, ".tmp.%d.${file_base}", _live_reloads);
#ifdef _WIN32
// We have to make this directory becuase windows WILL NOT
// do it for us
os__mkdir(string_all_before_last(tos2(new_so_base), tos2("/")));
#endif
#ifdef _MSC_VER
sprintf(new_so_name, "%s.dll", new_so_base);
#else
sprintf(new_so_name, "%s.so", new_so_base);
sprintf(compile_cmd, "$vexe -o %s -shared $file", new_so_base);
#endif
sprintf(compile_cmd, "$vexe $msvc -o %s -shared $file", new_so_base);
os__system(tos2(compile_cmd));
if( !os__file_exists(tos2(new_so_name)) ) {
@ -443,13 +515,17 @@ void reload_so() {
continue;
}
lfnmutex_print("reload_so locking...");
pthread_mutex_lock(&live_fn_mutex);
lfnmutex_print("reload_so locking...");
pthread_mutex_lock(&live_fn_mutex);
lfnmutex_print("reload_so locked");
live_lib = 0; // hack: force skipping dlclose/1, the code may be still used...
load_so(new_so_name);
load_so(new_so_name);
#ifndef _WIN32
unlink(new_so_name); // removing the .so file from the filesystem after dlopen-ing it is safe, since it will still be mapped in memory.
#else
_unlink(new_so_name);
#endif
//if(0 == rename(new_so_name, "${so_name}")){
// load_so("${so_name}");
//}
@ -485,7 +561,8 @@ void reload_so() {
'./' + v.out_name
}
$if windows {
cmd = v.out_name
cmd = v.out_name
cmd = cmd.replace('/', '\\')
}
if os.args.len > 3 {
cmd += ' ' + os.args.right(3).join(' ')
@ -569,8 +646,6 @@ fn (c &V) cc_windows_cross() {
}
println('Done!')
}
fn (v mut V) cc() {
// Cross compiling for Windows
@ -580,6 +655,11 @@ fn (v mut V) cc() {
return
}
}
if v.os == .msvc {
cc_msvc(v)
return
}
linux_host := os.user_os() == 'linux'
v.log('cc() isprod=$v.pref.is_prod outname=$v.out_name')
mut a := [v.pref.cflags, '-w'] // arguments for the C compiler
@ -752,7 +832,7 @@ fn (v &V) v_files_from_dir(dir string) []string {
if file.ends_with('_test.v') {
continue
}
if file.ends_with('_win.v') && v.os != .windows {
if file.ends_with('_win.v') && (v.os != .windows && v.os != .msvc) {
continue
}
if file.ends_with('_lin.v') && v.os != .linux {
@ -761,7 +841,7 @@ fn (v &V) v_files_from_dir(dir string) []string {
if file.ends_with('_mac.v') && v.os != .mac {
continue
}
if file.ends_with('_nix.v') && v.os == .windows {
if file.ends_with('_nix.v') && (v.os == .windows || v.os == .msvc) {
continue
}
res << '$dir/$file'
@ -1004,6 +1084,7 @@ fn new_v(args[]string) *V {
case 'openbsd': _os = .openbsd
case 'netbsd': _os = .netbsd
case 'dragonfly': _os = .dragonfly
case 'msvc': _os = .msvc
}
}
builtins := [