windows building support
This commit is contained in:
27
README.md
27
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
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#ifdef _WIN32
|
||||
// TODO: check if this works
|
||||
#include <minwindef.h>
|
||||
#define PATH_MAX MAX_PATH
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "../../../include/ground.h"
|
||||
#ifndef _WIN32
|
||||
#include "../../linenoise/linenoise.h"
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
@@ -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: {
|
||||
|
||||
@@ -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:
|
||||
|
||||
11
x86_64-w64-mingw32.txt
Normal file
11
x86_64-w64-mingw32.txt
Normal file
@@ -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'
|
||||
Reference in New Issue
Block a user