Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support #75

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions ext/duk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2900,6 +2900,27 @@ typedef struct duk_hthread duk_context;
#undef DUK_USE_COMPILER_STRING
#define DUK_USE_COMPILER_STRING "crystal/llvm"

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
int gettimeofday(struct timeval *tp, struct timezone *tzp)
{
static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);

SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;

GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t) file_time.dwLowDateTime);
time += ((uint64_t) file_time.dwHighDateTime) << 32;

tp->tv_sec = (long) ((time - EPOCH) / 10000000L);
tp->tv_usec = (long) (system_time.wMilliseconds * 1000);

return 0;
}
#endif

#define DUK_USE_EXEC_TIMEOUT_CHECK duk_cr_timeout
struct timeout_data {
struct timeval start;
Expand Down
49 changes: 49 additions & 0 deletions ext/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
set shell := ["bash", "-uc"]
set windows-shell := ["cmd.exe", "/c"]

cc := if os() == "windows" {
if `where gcc 2>NUL || exit 0` == "" {
if `where clang 2>NUL || exit 0` == "" {
error("cannot find C compiler")
} else {
trim(replace(`where clang`, "\\", "\\\\"))
}
} else {
replace(`where gcc`, "\\", "\\\\")
}
} else {
"cc"
}

cflags := "-pedantic -c -std=c99 -O2 -fstrict-aliasing -fomit-frame-pointer"
current := justfile_directory()
output := join(current, "..", "src", ".build")

[unix]
build:
mkdir -p {{output}}
{{cc}} -o {{output}}/libduktape.o {{current}}/duktape.c {{cflags}}

mkdir -p {{output}}/lib
ar rcs {{output}}/lib/libduktape.a {{output}}/libduktape.o

mkdir -p {{output}}/include
cp {{current}}/duktape.h {{current}}/duk_config.h {{output}}/include

[windows]
build compiler="{{cc}}":
mkdir {{output}}\lib
{{compiler}} -o {{output}}\lib\duktape.lib {{current}}\duktape.c {{cflags}} -fuse-ld=llvm-lib

mkdir {{output}}\include
copy {{current}}\duktape.h + {{current}}\duk_config.h {{output}}\include

[unix]
clean:
-rm -rf {{output}}
-rm -rf {{current}}/.crystal

[windows]
clean:
-rmdir /q /s {{output}}
-rmdir /q /s {{current}}\.crystal
49 changes: 49 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
set shell := ["bash", "-uc"]
set windows-shell := ["cmd.exe", "/c"]

current := invocation_directory()
crystal := if os() == "windows" { trim(`where crystal`) } else { trim(`which crystal`) }

default:
@just build

[unix]
all_spec output="{{current}}\\.build":
-mkdir -p {{current}}/.build
{{crystal}} build -o {{output}} spec/all_spec.cr --warnings all

[windows]
all_spec output="{{current}}/.build":
-mkdir {{current}}\.build
{{crystal}} build -o {{output}} spec\all_spec.cr --warnings all

[unix]
build output=".build/duktape":
-mkdir -p {{current}}/.build
{{crystal}} build -o {{output}} src/duktape.cr --warnings all

[windows]
build output=".build\\duktape":
-mkdir {{current}}\.build
{{crystal}} build -o {{output}} src\duktape.cr --warnings all

[unix]
clean:
-rm -rf {{current}}/.build
-rm -rf {{current}}/.crystal

[windows]
clean:
-rmdir /q /s {{current}}\.build
-rmdir /q /s {{current}}\.crystal

cleanlib:
@just -f {{current}}/ext/justfile clean
make -C {{current}}/ext -f Makefile.internal clean

libduktape:
cd ext
@just -f ext/justfile build

update:
make -C {{current}}/ext -f Makefile.internal update-duktape
4 changes: 2 additions & 2 deletions shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ authors:
- Jesse Doyle <[email protected]>

scripts:
postinstall: "make -C ext clean libduktape"
postinstall: make -C clean libduktape
Copy link
Owner

@jessedoyle jessedoyle Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -C flag changes the directory to the provided argument (ext) before running the targets.

As it currently stands, this may break the seamless postinstall for folks on non-windows platforms. Is there a way we can detect the environment from this shell command?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, yeah that should be make -C ext ....

Unfortunately there isn't, this is part of what makes Windows support difficult because Shards itself doesn't really have a concept of platform-specific script management. Some people have tried to work around this by having postinstall execute a Crystal file which handles platform-specific logic/configuration, but that may not be ideal here.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to have to get a VM running Windows to test this - can we invoke a shell script here instead of make directly? If so, what type of shell does it run on in Windows?

i.e.

postinstall: "./build/postinstall.sh"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows' shell would be command prompt (cmd) but that can't run shell scripts. The (Git) Bash interpreter also does not ship with Windows by default, so there would be no way to execute the postinstall script on Windows.


development_dependencies:
ameba:
github: veelenga/ameba
github: crystal-ameba/ameba
version: '~> 1.4'

crystal: '>= 0.35.1'
Expand Down
19 changes: 18 additions & 1 deletion src/lib_duktape.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,24 @@
#
# This is free software. Please see LICENSE for details.

@[Link(ldflags: "-L#{__DIR__}/.build/lib -L#{__DIR__}/.build/include -lduktape -lm")]
{% if flag?(:win32) %}
lib LibC
alias SusecondsT = LongLong

struct Timeval
tv_sec : TimeT
tv_usec : SusecondsT
end

fun gettimeofday(tp : Timeval*, timezone : Void*) : Int
end
{% end %}

{% if flag?(:win32) %}
@[Link(ldflags: "#{__DIR__}\\.build\\lib\\duktape.lib")]
{% else %}
@[Link(ldflags: "-L#{__DIR__}/.build/lib -L#{__DIR__}/.build/include -lduktape -lm")]
{% end %}
lib LibDUK
alias Context = Void*
alias Size = LibC::SizeT
Expand Down