Skip to content

Commit

Permalink
Preprocessor: move tools as subcommands inside wasm_of_ocaml
Browse files Browse the repository at this point in the history
  • Loading branch information
vouillon committed Feb 4, 2025
1 parent f7bc6c4 commit 530e7d7
Show file tree
Hide file tree
Showing 17 changed files with 393 additions and 386 deletions.
6 changes: 3 additions & 3 deletions compiler/bin-wasm_of_ocaml/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(executable
(name wasm_of_ocaml)
(public_name wasm_of_ocaml)
(executables
(names wasm_of_ocaml wasmoo_link_wasm)
(public_names wasm_of_ocaml -)
(package wasm_of_ocaml-compiler)
(libraries
jsoo_cmdline
Expand Down
4 changes: 2 additions & 2 deletions compiler/bin-wasm_of_ocaml/info.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ let make ~name ~doc ~description =
; `S "AUTHORS"
; `P "Jerome Vouillon, Hugo Heuzard."
; `S "LICENSE"
; `P "Copyright (C) 2010-2024."
; `P "Copyright (C) 2010-2025."
; `P
"js_of_ocaml is free software, you can redistribute it and/or modify it under \
"wasm_of_ocaml is free software, you can redistribute it and/or modify it under \
the terms of the GNU Lesser General Public License as published by the Free \
Software Foundation, with linking exception; either version 2.1 of the License, \
or (at your option) any later version."
Expand Down
110 changes: 110 additions & 0 deletions compiler/bin-wasm_of_ocaml/link_wasm.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
(* Wasm_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

open Cmdliner
open Js_of_ocaml_compiler.Stdlib
open Wasm_of_ocaml_compiler

type binaryen_options =
{ common : string list
; opt : string list
; merge : string list
}

type options =
{ input_modules : (string * string) list
; output_file : string
; variables : Preprocess.variables
; binaryen_options : binaryen_options
}

let options =
let input_modules =
let doc =
"Specify an input module with name $(i,NAME) in Wasm text file $(i,FILE)."
in
Arg.(
value
& pos_right 0 (pair ~sep:':' string string) []
& info [] ~docv:"NAME:FILE" ~doc)
in
let output_file =
let doc = "Specify the Wasm binary output file $(docv)." in
Arg.(required & pos 0 (some string) None & info [] ~docv:"WASM_FILE" ~doc)
in
let binaryen_options =
let doc = "Pass option $(docv) to binaryen tools" in
Arg.(value & opt_all string [] & info [ "binaryen" ] ~docv:"OPT" ~doc)
in
let opt_options =
let doc = "Pass option $(docv) to $(b,wasm-opt)" in
Arg.(value & opt_all string [] & info [ "binaryen-opt" ] ~docv:"OPT" ~doc)
in
let merge_options =
let doc = "Pass option $(docv) to $(b,wasm-merge)" in
Arg.(value & opt_all string [] & info [ "binaryen-merge" ] ~docv:"OPT" ~doc)
in
let build_t input_modules output_file variables common opt merge =
`Ok
{ input_modules; output_file; variables; binaryen_options = { common; opt; merge } }
in
let t =
Term.(
const build_t
$ input_modules
$ output_file
$ Preprocess.variable_options
$ binaryen_options
$ opt_options
$ merge_options)
in
Term.ret t

let link
{ input_modules; output_file; variables; binaryen_options = { common; merge; opt } } =
let inputs =
List.map
~f:(fun (module_name, file) ->
{ Wat_preprocess.module_name
; file
; source =
(if Link.Wasm_binary.check_file ~file
then File
else Contents (Js_of_ocaml_compiler.Fs.read_file file))
})
input_modules
in
Runtime.build
~link_options:(common @ merge)
~opt_options:(common @ opt)
~variables:(Preprocess.set_variables variables)
~inputs
~output_file

let info =
Info.make
~name:"link-wasm"
~doc:"Wasm linker"
~description:
"$(b,wasmoo_util link) is a Wasm linker. It takes as input a list of Wasm text \
files, preprocesses them, links them together, and outputs a single Wasm binary \
module"

let term = Cmdliner.Term.(const link $ options)

let command = Cmdliner.Cmd.v info term
19 changes: 19 additions & 0 deletions compiler/bin-wasm_of_ocaml/link_wasm.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(* Wasm_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

val command : unit Cmdliner.Cmd.t
152 changes: 152 additions & 0 deletions compiler/bin-wasm_of_ocaml/preprocess.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
(* Wasm_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

open Cmdliner
open Js_of_ocaml_compiler.Stdlib
open Wasm_of_ocaml_compiler

let () = Sys.catch_break true

let read_contents ch =
let buf = Buffer.create 65536 in
let b = Bytes.create 65536 in
let rec read () =
let n = input ch b 0 (Bytes.length b) in
if n > 0
then (
Buffer.add_subbytes buf b 0 n;
read ())
in
read ();
Buffer.contents buf

type variables =
{ enable : string list
; disable : string list
; set : (string * string) list
}

type options =
{ input_file : string option
; output_file : string option
; variables : variables
}

let variable_options =
let enable =
let doc = "Set preprocessor variable $(docv) to true." in
let arg =
Arg.(value & opt_all (list string) [] & info [ "enable" ] ~docv:"VAR" ~doc)
in
Term.(const List.flatten $ arg)
in
let disable =
let doc = "Set preprocessor variable $(docv) to false." in
let arg =
Arg.(value & opt_all (list string) [] & info [ "disable" ] ~docv:"VAR" ~doc)
in
Term.(const List.flatten $ arg)
in
let set =
let doc = "Set preprocessor variable $(i,VAR) to value $(i,VALUE)." in
let arg =
Arg.(
value
& opt_all (list (pair ~sep:'=' string string)) []
& info [ "set" ] ~docv:"VAR=VALUE" ~doc)
in
Term.(const List.flatten $ arg)
in
let build_t enable disable set = { enable; disable; set } in
Term.(const build_t $ enable $ disable $ set)

let options =
let input_file =
let doc =
"Use the Wasm text file $(docv) as input (default to the standard input)."
in
Arg.(value & pos 0 (some string) None & info [] ~docv:"INPUT_FILE" ~doc)
in
let output_file =
let doc = "Specify the output file $(docv) (default to the standard output)." in
Arg.(value & opt (some string) None & info [ "o" ] ~docv:"OUTPUT_FILE" ~doc)
in
let build_t input_file output_file variables =
`Ok { input_file; output_file; variables }
in
let t = Term.(const build_t $ input_file $ output_file $ variable_options) in
Term.ret t

let set_variables { enable; disable; set } =
List.map ~f:(fun nm -> nm, Wat_preprocess.Bool true) enable
@ List.map ~f:(fun nm -> nm, Wat_preprocess.Bool false) disable
@ List.map ~f:(fun (nm, v) -> nm, Wat_preprocess.String v) set

let preprocess { input_file; output_file; variables } =
let with_input f =
match input_file with
| None -> f stdin
| Some file ->
let ch = open_in file in
let res = f ch in
close_in ch;
res
in
let with_output f =
match output_file with
| Some "-" | None -> f stdout
| Some file -> Filename.gen_file file f
in
let contents = with_input read_contents in
let res =
Wat_preprocess.f
~filename:(Option.value ~default:"-" input_file)
~contents
~variables:(set_variables variables)
in
with_output (fun ch -> output_string ch res)

let term = Cmdliner.Term.(const preprocess $ options)

let info =
Info.make
~name:"preprocess"
~doc:"Wasm text file preprocessor"
~description:"$(b,wasmoo_util pp) is a Wasm text file preprocessor."

let command = Cmdliner.Cmd.v info term

(* Adapted from
https://github.com/ocaml/opam/blob/fbbe93c3f67034da62d28c8666ec6b05e0a9b17c/s
rc/client/opamArg.ml#L759 *)
let alias_command ?orig_name cmd term name =
let orig =
match orig_name with
| Some s -> s
| None -> Cmd.name cmd
in
let doc = Printf.sprintf "An alias for $(b,%s)." orig in
let man =
[ `S "DESCRIPTION"
; `P (Printf.sprintf "$(mname)$(b, %s) is an alias for $(mname)$(b, %s)." name orig)
; `P (Printf.sprintf "See $(mname)$(b, %s --help) for details." orig)
]
in
Cmd.v (Cmd.info name ~docs:"COMMAND ALIASES" ~doc ~man) term

let command_alias = alias_command ~orig_name:"preprocess" command term "pp"
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,11 @@ type variables =
; set : (string * string) list
}

type preprocess_options =
{ input_file : string option
; output_file : string option
; variables : variables
}

val preprocess_options : preprocess_options Cmdliner.Term.t

val preprocess_info : Cmdliner.Cmd.info

type binaryen_options =
{ common : string list
; opt : string list
; merge : string list
}

type link_options =
{ input_modules : (string * string) list
; output_file : string
; variables : variables
; binaryen_options : binaryen_options
}
val variable_options : variables Cmdliner.Term.t

val link_options : link_options Cmdliner.Term.t
val set_variables :
variables -> (string * Wasm_of_ocaml_compiler.Wat_preprocess.value) list

val link_info : Cmdliner.Cmd.info
val command : unit Cmdliner.Cmd.t

val info : Cmdliner.Cmd.info
val command_alias : unit Cmdliner.Cmd.t
8 changes: 7 additions & 1 deletion compiler/bin-wasm_of_ocaml/wasm_of_ocaml.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ let () =
(Cmdliner.Cmd.group
~default:Compile.term
(Compile.info "wasm_of_ocaml")
[ Link.command; Build_runtime.command; Compile.command ])
[ Link.command
; Build_runtime.command
; Compile.command
; Preprocess.command
; Preprocess.command_alias
; Link_wasm.command
])
with
| Ok (`Ok () | `Help | `Version) ->
if !warnings > 0 && !werror
Expand Down
Loading

0 comments on commit 530e7d7

Please sign in to comment.