windows building support
This commit is contained in:
27
README.md
27
README.md
@@ -13,6 +13,33 @@ Install with:
|
|||||||
meson install -C builddir
|
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.
|
You may need to run `ldconfig` or reboot to update your ld cache.
|
||||||
|
|
||||||
## Bytecode Format
|
## Bytecode Format
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO: check if this works
|
// TODO: check if this works
|
||||||
#include <minwindef.h>
|
#include <minwindef.h>
|
||||||
#define PATH_MAX MAX_PATH
|
|
||||||
#else
|
#else
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -119,9 +119,14 @@ sources = files(
|
|||||||
'src/Struct/addField.c',
|
'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(
|
cli_sources = files(
|
||||||
'src/cli/main.c'
|
'src/cli/main.c'
|
||||||
)
|
)
|
||||||
@@ -132,6 +137,7 @@ libffi = dependency('libffi', version : '>=3.0.0')
|
|||||||
|
|
||||||
install_headers('include/ground.h')
|
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)
|
lib = shared_library('ground', sources, include_directories : incdir, dependencies : libffi, install : true)
|
||||||
|
|
||||||
pkg.generate(lib,
|
pkg.generate(lib,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "../../../include/ground.h"
|
#include "../../../include/ground.h"
|
||||||
|
#ifndef _WIN32
|
||||||
#include "../../linenoise/linenoise.h"
|
#include "../../linenoise/linenoise.h"
|
||||||
|
#endif
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -86,10 +88,16 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return END( HEAP_GET(heap, instruction->args.at[0])->as.Int );
|
return END( HEAP_GET(heap, instruction->args.at[0])->as.Int );
|
||||||
}
|
}
|
||||||
INPUT: {
|
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("");
|
char* input = linenoise("");
|
||||||
HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input))));
|
HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input))));
|
||||||
free(input);
|
free(input);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
PRINT: {
|
PRINT: {
|
||||||
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
||||||
@@ -914,7 +922,98 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
STRUCT: {
|
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;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
ENDSTRUCT: {
|
ENDSTRUCT: {
|
||||||
@@ -922,6 +1021,38 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
INIT: {
|
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;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
GETFIELD: {
|
GETFIELD: {
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ static void doStruct(GroundProgram* program, GroundProgram* newProgram, GroundSt
|
|||||||
GroundStruct gs = Ground.New.Struct();
|
GroundStruct gs = Ground.New.Struct();
|
||||||
|
|
||||||
// The aim is to compile an instruction which looks like this:
|
// 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:
|
// where:
|
||||||
// &field is the field to initialise
|
// &field is the field to initialise
|
||||||
// OP is a numeric identifier:
|
// 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