From 3a1cefffd7add4f6bea809832806ad7eceb9f5ac Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 6 Jul 2026 14:17:22 +1000 Subject: [PATCH] windows building support --- README.md | 27 ++++++ include/ground.h | 1 - meson.build | 8 +- src/Bytecode/Instruction/execute.c | 133 ++++++++++++++++++++++++++++- src/Program/preprocess.c | 2 +- x86_64-w64-mingw32.txt | 11 +++ 6 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 x86_64-w64-mingw32.txt diff --git a/README.md b/README.md index 0a9ef07..4cde3f3 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,33 @@ Install with: meson install -C builddir ``` +# Cross Compiling for Windows + +We all hate Windows, right? As much as we hate it, people still use it, so it's nice to be able to run our good software on their crappy platform. + +You'll need the cross compiler (install command is for Arch and derivatives): + +```sh +sudo pacman -S mingw-w64-gcc +``` + +First, cross compile libffi for Windows (look up a guide) and install it to `/usr/x86_64-w64-mingw32/`. + +Cross compile for Windows with the following commands: + +```sh +meson setup --cross-file x86_64-w64-mingw32.txt -Ddefault_library=static --prefix=/usr/x86_64-w64-mingw32/ windows-builddir +meson compile -C windows-builddir +``` + +If you'd like it to be installed as a library to link with (for example with Solstice), run + +```sh +meson install -C windows-builddir +``` + +This will install it to `/usr/x86_64-w64-mingw32/`, for convenient usage with other Windows cross compilation projects. + You may need to run `ldconfig` or reboot to update your ld cache. ## Bytecode Format diff --git a/include/ground.h b/include/ground.h index 7f7b932..aaeafd7 100644 --- a/include/ground.h +++ b/include/ground.h @@ -10,7 +10,6 @@ #ifdef _WIN32 // TODO: check if this works #include -#define PATH_MAX MAX_PATH #else #include #endif diff --git a/meson.build b/meson.build index 069ab11..a59c348 100644 --- a/meson.build +++ b/meson.build @@ -119,9 +119,14 @@ sources = files( 'src/Struct/addField.c', - 'src/linenoise/linenoise.c' + #'src/linenoise/linenoise.c' ) +if host_machine.system() != 'windows' + sources += ['src/linenoise/linenoise.c'] +endif + + cli_sources = files( 'src/cli/main.c' ) @@ -132,6 +137,7 @@ libffi = dependency('libffi', version : '>=3.0.0') install_headers('include/ground.h') +lib = library('ground', sources, include_directories : incdir, dependencies : libffi, install : true) lib = shared_library('ground', sources, include_directories : incdir, dependencies : libffi, install : true) pkg.generate(lib, diff --git a/src/Bytecode/Instruction/execute.c b/src/Bytecode/Instruction/execute.c index fc86f12..93e88e8 100644 --- a/src/Bytecode/Instruction/execute.c +++ b/src/Bytecode/Instruction/execute.c @@ -1,5 +1,7 @@ #include "../../../include/ground.h" +#ifndef _WIN32 #include "../../linenoise/linenoise.h" +#endif #include #include #include @@ -86,10 +88,16 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns return END( HEAP_GET(heap, instruction->args.at[0])->as.Int ); } INPUT: { +#ifdef _WIN32 + // TODO implement line input on Windows + HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String("")))); + return CONTINUE; +#else char* input = linenoise(""); HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input)))); free(input); return CONTINUE; +#endif } PRINT: { for (GroundSize i = 0; i < instruction->args.len; i++) { @@ -914,7 +922,98 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns return CONTINUE; } STRUCT: { - // no-op + GroundBytecodeStruct* gbs = &HEAP_GET(heap, instruction->args.at[0])->as.Struct; + // struct &structName &field OP $value &field OP $value &field OP $value... + // where: + // &field is the field to initialise + // OP is a numeric identifier: + // 0 -> none + // 1 -> init + // 2 -> set + // 3 -> attach closure to function + // $value is either a type reference (OP=0), a value reference (OP=1), or none (OP=2) + for (GroundSize i = 1; i < instruction->args.len; i++) { + GroundSize offset = instruction->args.at[i]; + i++; + switch (i) { + case 0: break; + case 1: { + i++; + GroundBytecodeValue* type = HEAP_GET(heap, instruction->args.at[i]); + switch (type->type.type) { + case GroundType_Struct: { + // TODO nested structs + break; + } + case GroundType_CoreType: { + switch (type->as.CoreType) { + case GroundType_Int: { + gbs->values[offset] = Ground.New.BytecodeValue(Ground.New.Value.Int(0)); + break; + } + case GroundType_Double: { + gbs->values[offset] = Ground.New.BytecodeValue(Ground.New.Value.Double(0.0)); + break; + } + case GroundType_String: { + gbs->values[offset] = Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(""))); + break; + } + case GroundType_Char: { + gbs->values[offset] = Ground.New.BytecodeValue(Ground.New.Value.Char(0)); + break; + } + case GroundType_Bool: { + gbs->values[offset] = Ground.New.BytecodeValue(Ground.New.Value.Bool(false)); + break; + } + default: break; // TODO implement all the other stuff + } + } + } + break; + } + case 2: { + i++; + gbs->values[offset] = Ground.Copy.BytecodeValue(HEAP_GET(heap, instruction->args.at[i])); + break; + } + case 3: { + GroundBytecodeFunction* function = &gbs->values[offset].as.Function; + if (function->closure == NULL) { + function->closure = malloc(sizeof(GroundBytecodeHeap)); + if (function->closure == NULL) { + Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute"); + Ground.Flags.error = true; + return CONTINUE; + } + } else { + free(function->closure->heap); + } + + function->closure->capacity = heap->capacity; + function->closure->len = heap->len; + function->closure->heap = malloc(sizeof(GroundBytecodeValue) * heap->capacity); + + if (function->closure->heap == NULL) { + Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute"); + Ground.Flags.error = true; + return CONTINUE; + } else { + // forget all values in previous closure + for (GroundSize i = 0; i < function->closure->len; i++) { + Ground.Free.BytecodeValue(&function->closure->heap[i]); + } + } + + for (GroundSize i = 0; i < heap->len; i++) { + function->closure->heap[i] = Ground.Copy.BytecodeValue(&heap->heap[i]); + } + + break; + } + } + } return CONTINUE; } ENDSTRUCT: { @@ -922,6 +1021,38 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns return CONTINUE; } INIT: { + GroundBytecodeValue* type = HEAP_GET(heap, instruction->args.at[1]); + switch (type->type.type) { + case GroundType_Struct: { + // TODO nested structs + break; + } + case GroundType_CoreType: { + switch (type->as.CoreType) { + case GroundType_Int: { + HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.Int(0))); + break; + } + case GroundType_Double: { + HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.Double(0.0))); + break; + } + case GroundType_String: { + HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String("")))); + break; + } + case GroundType_Char: { + HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.Char(0))); + break; + } + case GroundType_Bool: { + HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.Bool(false))); + break; + } + default: break; // TODO implement all the other stuff + } + } + } return CONTINUE; } GETFIELD: { diff --git a/src/Program/preprocess.c b/src/Program/preprocess.c index 018a0c1..98072cc 100644 --- a/src/Program/preprocess.c +++ b/src/Program/preprocess.c @@ -112,7 +112,7 @@ static void doStruct(GroundProgram* program, GroundProgram* newProgram, GroundSt GroundStruct gs = Ground.New.Struct(); // The aim is to compile an instruction which looks like this: - // struct &field OP $value &field OP $value &field OP $value... + // struct &structName &field OP $value &field OP $value &field OP $value... // where: // &field is the field to initialise // OP is a numeric identifier: diff --git a/x86_64-w64-mingw32.txt b/x86_64-w64-mingw32.txt new file mode 100644 index 0000000..dc27e8d --- /dev/null +++ b/x86_64-w64-mingw32.txt @@ -0,0 +1,11 @@ +[binaries] +c = 'x86_64-w64-mingw32-gcc' +ar = 'x86_64-w64-mingw32-ar' +exe_wrapper = 'wine' +pkg-config = 'pkg-config' + +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little'