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

[WIP] Esy-enabled Windows Build #44

Closed
wants to merge 4 commits into from
Closed
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
12 changes: 12 additions & 0 deletions .ci/esy-build-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Cross-platform set of build steps for building esy projects

steps:
- task: NodeTool@0
inputs:
versionSpec: '8.9'
- script: npm install -g esy@0.6.2
displayName: 'npm install -g esy@0.6.2'
- script: esy install
displayName: 'esy install'
- script: esy build
displayName: 'esy build'
Copy link
Owner

Choose a reason for hiding this comment

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

Is it correct that these steps are running in cmd?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is correct that they are running in cmd - one of the main benefits of using esy, for me, is that I don't have to change how I work as a windows developer.

The set of steps described in esy-build-steps.yml is the same for OSX, Linux, and Windows - it's really nice to have a consistent workflow across all platforms:

  • Install esy (npm install -g esy)
  • Install dependencies (esy install)
  • Build (esy build)

5 changes: 5 additions & 0 deletions .ci/use-node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
steps:
- task: NodeTool@0
displayName: 'Use Node 8.x'
inputs:
versionSpec: 8.x
54 changes: 54 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

name: $(Build.SourceVersion)
jobs:
- job: Linux
timeoutInMinutes: 0
pool:
vmImage: 'Ubuntu 16.04'

variables:
STAGING_DIRECTORY: $(Build.StagingDirectory)
ESY__CACHE_INSTALL_PATH: /home/vsts/.esy/3_____________________________________________________________________/i
ESY__CACHE_SOURCE_TARBALL_PATH: /home/vsts/.esy/source/i
# ESY__NPM_ROOT: /opt/hostedtoolcache/node/8.14.0/x64/lib/node_modules/esy

steps:
- script: sudo apt-get install -y libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libgl1-mesa-dev libglu1-mesa-dev mesa-utils mesa-utils-extra ragel xvfb
- template: .ci/use-node.yml
- template: .ci/esy-build-steps.yml

- job: MacOS
timeoutInMinutes: 0
pool:
vmImage: 'macOS 10.13'

variables:
STAGING_DIRECTORY: $(Build.StagingDirectory)
ESY__CACHE_INSTALL_PATH: /Users/runner/.esy/3__________________________________________________________________/i
ESY__CACHE_SOURCE_TARBALL_PATH: /Users/runner/.esy/source/i
# ESY__NPM_ROOT: /usr/local/lib/node_modules/esy

steps:
- script: brew update
- script: brew install libtool libpng
- template: .ci/use-node.yml
- template: .ci/esy-build-steps.yml

- job: Windows
timeoutInMinutes: 0
pool:
vmImage: 'vs2017-win2016'

variables:
STAGING_DIRECTORY: $(Build.StagingDirectory)
ESY__CACHE_INSTALL_PATH: /C/Users/VssAdministrator/.esy/3_/i
ESY__CACHE_SOURCE_TARBALL_PATH: /C/Users/VssAdministrator/.esy/source/i
# ESY__NPM_ROOT: /C/npm/prefix/node_modules/esy

steps:
- template: .ci/use-node.yml
- template: .ci/esy-build-steps.yml
39 changes: 39 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "luv",
"version": "1.0.0",
"description": "libuv bindings for OCaml",
"license": "MIT",
"scripts": {
},
"esy": {
"build": [
[
"dune",
"build",
"-p",
"luv",
"-j",
"4"
]
],
"install": [
"esy-installer luv.install"
]
},
"dependencies": {
"@opam/dune": "^2.0.0",
"@opam/dune-configurator": "^2.0.0",
"ocaml": ">=4.2.0",
"@opam/ctypes": "0.15.1",
"@opam/ctypes-foreign": "0.4.0",
"esy-libuv": "github:revery-ui/esy-libuv#89d293b"
},
"resolutions": {
"@esy-ocaml/libffi": "esy-ocaml/libffi#c61127d",
"esy-cmake": "prometheansacrifice/esy-cmake#2a47392def"
},
"devDependencies": {
"ocaml": "~4.8.0",
"@opam/alcotest": "*"
}
}
41 changes: 41 additions & 0 deletions src/c/config/discover.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

type os =
| Windows
| Mac
| Linux
| Unknown

let uname () =
let ic = Unix.open_process_in "uname" in
let uname = input_line ic in
let () = close_in ic in
uname;;

let get_os =
match Sys.os_type with
| "Win32" -> Windows
| _ -> match uname () with
| "Darwin" -> Mac
| "Linux" -> Linux
| _ -> Unknown

let libPath = "-L" ^ (Sys.getenv "LIBUV_LIB_PATH")

let ccopt s = ["-ccopt"; s]
let cclib s = ["-cclib"; s]

let c_flags = ["-I"; (Sys.getenv "LIBUV_INCLUDE_PATH");]

let c_flags = match get_os with
| Linux -> c_flags @ ["-fPIC"]
| _ -> c_flags
;;

let flags =
[]
@ ccopt(libPath)
@ cclib("-luv")
;;

Configurator.V1.Flags.write_sexp "c_flags.sexp" c_flags;
Configurator.V1.Flags.write_sexp "flags.sexp" flags;
3 changes: 3 additions & 0 deletions src/c/config/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(executable
(name discover)
(libraries dune.configurator))
62 changes: 38 additions & 24 deletions src/c/dune
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,38 @@
(wrapped false)
(modules Luv_c_generated_functions)
(libraries ctypes luv_c_function_descriptions threads)
(flags (:include flags.sexp))
;(c_library_flags -ccopt -luv -ccopt -l/Users/bryphe/luv/_esy/default/store/i/esy_libuv-0effda09/lib)
;(library_flags -ccopt -luv -ccopt -l/Users/bryphe/luv/_esy/default/store/i/esy_libuv-0effda09/lib)
(foreign_stubs
(language c)
(names c_generated_functions helpers)
(include_dirs vendor/libuv/include))
(foreign_archives uv))
(flags (:include c_flags.sexp))
(names c_generated_functions helpers)))
; (include_dirs vendor/libuv/include))
; (foreign_archives uv))



; The vendored libuv.
(rule
(targets libuv.a dlluv.so)
(deps (source_tree vendor) link-gyp.ml copy-so.ml)
(action (progn
(run ocaml link-gyp.ml)
(chdir vendor/libuv
(run python3 gyp_uv.py -f make -Duv_library=static_library))
(setenv CFLAGS -fPIC
(setenv BUILDTYPE Release
(run make -C vendor/libuv/out libuv)))
(run cp vendor/libuv/out/Release/libuv.a libuv.a)
(chdir vendor/libuv
(run python3 gyp_uv.py -f make -Duv_library=shared_library))
(setenv CFLAGS -fPIC
(setenv BUILDTYPE Release
(run make -C vendor/libuv/out libuv)))
(run ocaml copy-so.ml))))

(data_only_dirs vendor)
; (rule
; (targets libuv.a dlluv.so)
; (deps (source_tree vendor) link-gyp.ml copy-so.ml)
; (action (progn
; (run ocaml link-gyp.ml)
; (chdir vendor/libuv
; (run python3 gyp_uv.py -f make -Duv_library=static_library))
; (setenv CFLAGS -fPIC
; (setenv BUILDTYPE Release
; (run make -C vendor/libuv/out libuv)))
; (run cp vendor/libuv/out/Release/libuv.a libuv.a)
; (chdir vendor/libuv
; (run python3 gyp_uv.py -f make -Duv_library=shared_library))
; (setenv CFLAGS -fPIC
; (setenv BUILDTYPE Release
; (run make -C vendor/libuv/out libuv)))
; (run ocaml copy-so.ml))))

;(data_only_dirs vendor)



Expand All @@ -55,16 +59,19 @@
(with-stdout-to generate_types_step_2.c
(run ./generate_types_start.exe)))

(rule (targets ctypes_path.txt)
(action (with-stdout-to %{targets} (run ocamlfind query ctypes))))

; Based partially on
; https://github.com/avsm/ocaml-yaml/blob/master/types/stubgen/jbuild#L20
(rule
(targets generate_types_step_2.exe)
(deps (:c generate_types_step_2.c) helpers.h)
(action (bash "\
%{cc} %{c} \
-I `dirname %{lib:ctypes:ctypes_cstubs_internals.h}` \
-I %{read-lines:ctypes_path.txt} \
-I %{ocaml_where} \
-I vendor/libuv/include -o %{targets}")))
-I %{env:LIBUV_INCLUDE_PATH=vendor/include/libuv} -o %{targets}")))

(rule
(with-stdout-to luv_c_generated_types.ml
Expand Down Expand Up @@ -96,3 +103,10 @@
(rule
(with-stdout-to luv_c_generated_functions.ml
(run ./generate_ml_functions.exe luv_stub)))


(rule
(targets c_flags.sexp flags.sexp)
(deps (:discover config/discover.exe))
(action (run %{discover})))

8 changes: 8 additions & 0 deletions src/c/generate_c_functions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@


let () =

(* Include headers necessary for Windows *)
if Sys.win32 then
(* Setting a WINVER to Vista+ is necessary to get types like AI_ADDRCONFIG *)
(print_endline "#define WINVER 0x0600";
print_endline "#define _WIN32_WINNT 0x0600";
print_endline "#include <ws2tcpip.h>");

Comment on lines +9 to +14
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There were some headers we need to pull in to get some APIs (like AI_ADDRCONFIG). They were introduced in Vista, so we have to set the WINVER and _WIN32_WINNT values to 0x0600 (Vista)

print_endline "#include <memory.h>";
print_endline "#include <caml/mlvalues.h>";
print_endline "#include <caml/socketaddr.h>";
Expand Down
10 changes: 8 additions & 2 deletions src/c/generate_types_start.ml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
(* This file is part of Luv, released under the MIT license. See LICENSE.md for
details, or visit https://github.com/aantron/luv/blob/master/LICENSE.md. *)



let () =

(* Include headers necessary for Windows *)
if Sys.win32 then
(* Setting a WINVER to Vista+ is necessary to get types like AI_ADDRCONFIG *)
(print_endline "#define WINVER 0x0600";
print_endline "#define _WIN32_WINNT 0x0600";
print_endline "#include <ws2tcpip.h>");

print_endline "#include <caml/mlvalues.h>";
print_endline "#include <caml/socketaddr.h>";
print_endline "#include <uv.h>";
Expand Down
8 changes: 5 additions & 3 deletions src/c/luv_c_type_descriptions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ struct
module Option =
struct
let block_signal = constant "UV_LOOP_BLOCK_SIGNAL" int
let sigprof = constant "SIGPROF" int
let sigprof = match Sys.win32 with
| false -> constant "SIGPROF" int
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure the best way to handle this, but SIGPROF isn't defined on Windows.

| true -> constant "0" int
end

type t = [ `Loop ] structure
Expand Down Expand Up @@ -398,9 +400,9 @@ struct
let iwoth = constant "S_IWOTH" int
let ixoth = constant "S_IXOTH" int

let isuid = constant "S_ISUID" int
(*let isuid = constant "S_ISUID" int
let isgid = constant "S_ISGID" int
let isvtx = constant "S_ISVTX" int
let isvtx = constant "S_ISVTX" int*)
end

module Dirent =
Expand Down
6 changes: 4 additions & 2 deletions src/file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,11 @@ struct
| `IWOTH
| `IXOTH

(* TODO: Not supported on Windows
| `ISUID
| `ISGID
| `ISVTX
*)
Comment on lines +124 to +128
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Likewise - several of these file constants were not defined on Windows.


| `NUMERIC of int
]
Expand All @@ -144,9 +146,9 @@ struct
| `IWOTH -> iwoth
| `IXOTH -> ixoth

| `ISUID -> isuid
(*| `ISUID -> isuid
| `ISGID -> isgid
| `ISVTX -> isvtx
| `ISVTX -> isvtx*)

| `NUMERIC i -> i

Expand Down
2 changes: 2 additions & 0 deletions src/file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,11 @@ sig
| `IWOTH
| `IXOTH

(* TODO: Not supported on Windows.
| `ISUID
| `ISGID
| `ISVTX
*)

| `NUMERIC of int
]
Expand Down
4 changes: 2 additions & 2 deletions test/test_helpers.mli
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@



val check_success_result : string -> ('a, Luv.Error.t) Result.result -> 'a
val check_success_result : string -> ('a, Luv.Error.t) result -> 'a
val check_error_result :
string -> Luv.Error.t -> (_, Luv.Error.t) Result.result -> unit
string -> Luv.Error.t -> (_, Luv.Error.t) result -> unit
val check_error_code : string -> Luv.Error.t -> Luv.Error.t -> unit

val check_not_null : string -> _ Ctypes.ptr -> unit
Expand Down
10 changes: 5 additions & 5 deletions test/tester.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@
let () =
Alcotest.run "luv" (List.flatten [
Error.tests;
Version.tests;
(*Version.tests;*)
Loop.tests;
Timer.tests;
Loop_watcher.tests;
Async.tests;
Poll.tests;
Signal.tests;
TCP.tests;
(*TCP.tests;*)
Pipe.tests;
UDP.tests;
(*UDP.tests;*)
TTY.tests;
File.tests;
(*File.tests;
Process.tests;
FS_event.tests;
FS_poll.tests;
DNS.tests;
Thread_.tests;
Misc.tests;
Misc.tests;*)
])