Merge branch 'master' into jsoo-cctx

This commit is contained in:
Rudi Grinberg 2018-07-31 08:56:35 +02:00 committed by GitHub
commit 5c93619b47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 188 additions and 83 deletions

View File

@ -5,6 +5,10 @@ next
passing in `--root` in conjunction with `--workspace` or `--config` would not
work correctly (#997, @rgrinberg)
- Add support for customizing env nodes in workspace files. The `env` stanza is
now allowed in toplevel position in the workspace file, or for individual
contexts. This feature requires `(dune lang 1.1)` (#1038, @rgrinberg)
1.0.1 (19/07/2018)
------------------

View File

@ -488,7 +488,7 @@ stanza is rejected by dune:
ocamllex
--------
``(ocamllex (<names>))`` is essentially a shorthand for:
``(ocamllex <names>)`` is essentially a shorthand for:
.. code:: scheme
@ -503,13 +503,13 @@ To use a different rule mode, use the long form:
.. code:: scheme
(ocamllex
(modules (<names>))
(modules <names>)
(mode <mode>))
ocamlyacc
---------
``(ocamlyacc (<names>))`` is essentially a shorthand for:
``(ocamlyacc <names>)`` is essentially a shorthand for:
.. code:: scheme
@ -524,7 +524,7 @@ To use a different rule mode, use the long form:
.. code:: scheme
(ocamlyacc
(modules (<names>))
(modules <names>)
(mode <mode>))
menhir
@ -1231,22 +1231,8 @@ follows:
js_of_ocaml
-----------
In ``library`` and ``executables`` stanzas, you can specify js_of_ocaml options
using ``(js_of_ocaml (<js_of_ocaml-options>))``.
``<js_of_ocaml-options>`` are all optional:
- ``(flags <flags>)`` to specify flags passed to ``js_of_ocaml``. This field
supports ``(:include ...)`` forms
- ``(javascript_files (<files-list>))`` to specify ``js_of_ocaml`` JavaScript
runtime files.
``<flags>`` is specified in the `Ordered set language`_.
The default value for ``(flags ...)`` depends on the selected build
profile. The build profile ``dev`` (the default) will enable sourcemap
and the pretty JavaScript output.
A :ref:`dune-jsoo-field` exists in executable and libraries stanzas that allows
one to customize options relevant to jsoo.
.. _user-actions:

View File

@ -20,6 +20,7 @@ Welcome to dune's documentation!
advanced-topics
configurator
menhir
jsoo
faq
known-issues
migration

83
doc/jsoo.rst Normal file
View File

@ -0,0 +1,83 @@
***********
js_of_ocaml
***********
js_of_ocaml_ is a compiler from OCaml to JavaScript. The compiler works by
translating OCaml bytecode to JS files. From here on, we'll abbreviate
js_of_ocaml to jsoo. The compiler can be installed with opam:
.. code:: bash
$ opam install js_of_ocaml-compiler
Compiling to JS
===============
Dune has full support building jsoo libraries and executables transparently.
There's no need to customize or enable anything to compile ocaml
libraries/executables to JS.
To build a JS executable, just define an executable as you would normally.
Consider this example:
.. code:: bash
echo 'print_endline "hello from js"' > foo.ml
With the following dune file:
.. code:: scheme
(executable (name foo))
And then request the ``.js`` target:
.. code:: bash
$ dune build ./foo.bc.js
$ node _build/default/foo.bc.js
hello from js
Similar targets are created for libraries, but we recommend sticking to the
executable targets.
.. _dune-jsoo-field:
``js_of_ocaml`` field
=====================
In ``library`` and ``executables`` stanzas, you can specify js_of_ocaml options
using ``(js_of_ocaml (<js_of_ocaml-options>))``.
``<js_of_ocaml-options>`` are all optional:
- ``(flags <flags>)`` to specify flags passed to ``js_of_ocaml``. This field
supports ``(:include ...)`` forms
- ``(javascript_files (<files-list>))`` to specify ``js_of_ocaml`` JavaScript
runtime files.
``<flags>`` is specified in the `Ordered set language`_.
The default value for ``(flags ...)`` depends on the selected build profile. The
build profile ``dev`` (the default) will enable sourcemap and the pretty
JavaScript output.
Separate Compilation
====================
Dune supports two modes of compilation
- Direct compilation of a bytecode program to JavaScript. This mode allows
js_of_ocaml to perform whole program deadcode elimination and whole program
inlining.
- Separate compilation, where compilation units are compiled to JavaScript
separately and then linked together. This mode is useful during development as
it builds more quickly.
The separate compilation mode will be selected when the build profile is
``dev``, which is the default. There is currently no other way to control this
behaviour.
.. _js_of_ocaml: http://ocsigen.org/js_of_ocaml/

View File

@ -136,7 +136,7 @@ Add this field to your ``library`` or ``executable`` stanzas:
.. code:: scheme
(preprocess (action (run %{bin:cppo} -V OCAML:%{ocaml_version} %{first-dep})))
(preprocess (action (run %{bin:cppo} -V OCAML:%{ocaml_version} %{input-file})))
Additionally, if you are include a ``config.h`` file, you need to
declare the dependency to this file via:
@ -154,7 +154,7 @@ Write this in your ``dune`` file:
(rule
(targets foo.ml)
(deps foo.cppo.ml <other files that foo.ml includes>)
(deps (:first-dep foo.cppo.ml) <other files that foo.ml includes>)
(action (run %{bin:cppo} %{first-dep} -o %{targets})))
Defining a library with C stubs
@ -192,8 +192,8 @@ compilation and link flags. Write this ``dune`` file:
(rule
(targets c_flags.sexp c_library_flags.sexp)
(deps config/discover.exe)
(action (run %{first-dep} -ocamlc %{OCAMLC})))
(deps (:discover config/discover.exe))
(action (run %{discover} -ocamlc %{OCAMLC})))
Then create a ``config`` subdirectory and write this ``dune`` file:
@ -240,8 +240,8 @@ To generate a file ``foo.ml`` using a program from another directory:
(rule
(targets foo.ml)
(deps ../generator/gen.exe)
(action (run %{first-dep} -o %{targets})))
(deps (:gen ../generator/gen.exe))
(action (run %{gen} -o %{targets})))
Defining tests
==============
@ -252,8 +252,8 @@ Write this in your ``dune`` file:
(alias
(name runtest)
(deps my-test-program.exe)
(action (run %{first-dep})))
(deps (:my-prog my-test-program.exe))
(action (run %{my-prog})))
And run the tests with:

View File

@ -379,6 +379,13 @@ The build profile can be selected in the ``dune-workspace`` file by write a
Note that the command line option ``--profile`` has precedence over this stanza.
env
~~~
The ``env`` stanza can be used to set the base environment for all contexts in
this workspace. This environment has the lowest precedence of all other ``env``
stanzas. The syntax for this stanza is the same dune's :ref:`dune-env` stanza.
context
~~~~~~~
@ -407,6 +414,10 @@ context or can be the description of an opam switch, as follows:
context. This has precedence over the command line option
``--profile``
- ``(env <env>)`` to set the environment for a particular context. This is of
higher precedence than the toplevel ``env`` stanza in the workspace file. This
field the same options as the :ref:`dune-env` stanza.
Both ``(default ...)`` and ``(opam ...)`` accept a ``targets`` field in order to
setup cross compilation. See :ref:`advanced-cross-compilation` for more
information.
@ -420,29 +431,6 @@ For rare cases where this is not what you want, you can force dune to use a
different build contexts for merlin by adding the field ``(merlin)`` to this
context.
Building JavaScript with js_of_ocaml
====================================
Dune knows how to generate a JavaScript version of an executable
(``<name>.bc.js``) using the js_of_ocaml compiler (the ``js_of_ocaml-compiler``
opam package must be installed).
It supports two modes of compilation:
- Direct compilation of a bytecode program to JavaScript. This mode allows
js_of_ocaml to perform whole program deadcode elimination and whole program
inlining.
- Separate compilation, where compilation units are compiled to JavaScript
separately and then linked together. This mode is useful during development as
it builds more quickly.
The separate compilation mode will be selected when the build profile is
``dev``, which is the default. There is currently no other way to control this
behaviour.
See the section about :ref:`dune-jsoo` for passing custom flags to the
js_of_ocaml compiler
Distributing Projects
=====================

View File

@ -18,6 +18,13 @@ module Kind = struct
])
end
module Env_nodes = struct
type t =
{ context: Dune_env.Stanza.t option
; workspace: Dune_env.Stanza.t option
}
end
type t =
{ name : string
; kind : Kind.t
@ -26,7 +33,7 @@ type t =
; for_host : t option
; implicit : bool
; build_dir : Path.t
; env_node : Dune_env.Stanza.t option
; env_nodes : Env_nodes.t
; path : Path.t list
; toplevel_path : Path.t option
; ocaml_bin : Path.t
@ -131,7 +138,7 @@ let ocamlpath_sep =
else
Bin.path_sep
let create ~(kind : Kind.t) ~path ~env ~env_node ~name ~merlin ~targets
let create ~(kind : Kind.t) ~path ~env ~env_nodes ~name ~merlin ~targets
~profile () =
let opam_var_cache = Hashtbl.create 128 in
(match kind with
@ -334,7 +341,7 @@ let create ~(kind : Kind.t) ~path ~env ~env_node ~name ~merlin ~targets
; kind
; profile
; merlin
; env_node
; env_nodes
; for_host = host
; build_dir
; path
@ -410,11 +417,11 @@ let create ~(kind : Kind.t) ~path ~env ~env_node ~name ~merlin ~targets
let opam_config_var t var = opam_config_var ~env:t.env ~cache:t.opam_var_cache var
let default ?(merlin=true) ~env_node ~env ~targets () =
create ~kind:Default ~path:Bin.path ~env ~env_node ~name:"default"
let default ?(merlin=true) ~env_nodes ~env ~targets () =
create ~kind:Default ~path:Bin.path ~env ~env_nodes ~name:"default"
~merlin ~targets ()
let create_for_opam ?root ~env ~env_node ~targets ~profile ~switch ~name
let create_for_opam ?root ~env ~env_nodes ~targets ~profile ~switch ~name
?(merlin=false) () =
match Bin.opam with
| None -> Utils.program_not_found "opam"
@ -452,16 +459,23 @@ let create_for_opam ?root ~env ~env_node ~targets ~profile ~switch ~name
| Some s -> Bin.parse_path s
in
let env = Env.extend env ~vars in
create ~kind:(Opam { root; switch }) ~profile ~targets ~path ~env ~env_node
create ~kind:(Opam { root; switch }) ~profile ~targets ~path ~env ~env_nodes
~name ~merlin ()
let create ?merlin ~env def =
let create ?merlin ?workspace_env ~env def =
let env_nodes context =
{ Env_nodes.
context
; workspace = workspace_env
}
in
match (def : Workspace.Context.t) with
| Default { targets; profile; env = env_node ; loc = _ } ->
default ~env ~env_node ~profile ~targets ?merlin ()
default ~env ~env_nodes:(env_nodes env_node) ~profile ~targets ?merlin ()
| Opam { base = { targets ; profile ; env = env_node ; loc = _ }
; name; switch; root; merlin = _ } ->
create_for_opam ?root ~env_node ~env ~profile ~switch ~name ?merlin ~targets ()
create_for_opam ?root ~env_nodes:(env_nodes env_node) ~env ~profile
~switch ~name ?merlin ~targets ()
let which t s = which ~cache:t.which_cache ~path:t.path s

View File

@ -30,6 +30,13 @@ module Kind : sig
type t = Default | Opam of Opam.t
end
module Env_nodes : sig
type t =
{ context: Dune_env.Stanza.t option
; workspace: Dune_env.Stanza.t option
}
end
type t =
{ name : string
; kind : Kind.t
@ -51,7 +58,7 @@ type t =
build_dir : Path.t
; (** env node that this context was initialized with *)
env_node : Dune_env.Stanza.t option
env_nodes : Env_nodes.t
; (** [PATH] *)
path : Path.t list
@ -125,6 +132,7 @@ val compare : t -> t -> Ordering.t
val create
: ?merlin:bool
-> ?workspace_env:Dune_env.Stanza.t
-> env:Env.t
-> Workspace.Context.t
-> t list Fiber.t

View File

@ -73,7 +73,8 @@ let setup ?(log=Log.no_log)
Fiber.parallel_map workspace.contexts ~f:(fun ctx_def ->
let name = Workspace.Context.name ctx_def in
Context.create ctx_def ~env ~merlin:(workspace.merlin_context = Some name))
Context.create ?workspace_env:workspace.env
ctx_def ~env ~merlin:(workspace.merlin_context = Some name))
>>= fun contexts ->
let contexts = List.concat contexts in
List.iter contexts ~f:(fun (ctx : Context.t) ->

View File

@ -612,18 +612,24 @@ let create
}
in
let context_env_node = lazy (
let config =
match context.env_node with
| Some s -> s
| None -> { loc = Loc.none; rules = [] }
let make ~inherit_from ~config =
{ Env_node.
dir = context.build_dir
; scope = Scope.DB.find_by_dir scopes context.build_dir
; ocaml_flags = None
; inherit_from
; config
}
in
{ Env_node.
dir = context.build_dir
; inherit_from = None
; scope = Scope.DB.find_by_dir scopes context.build_dir
; config
; ocaml_flags = None
}
match context.env_nodes with
| { context = None; workspace = None } ->
make ~config:{ loc = Loc.none; rules = [] } ~inherit_from:None
| { context = Some config; workspace = None }
| { context = None; workspace = Some config } ->
make ~config ~inherit_from:None
| { context = Some context ; workspace = Some workspace } ->
make ~config:context
~inherit_from:(Some (lazy (make ~inherit_from:None ~config:workspace)))
) in
List.iter stanzas
~f:(fun { Dir_with_jbuild. ctx_dir; scope; stanzas; _ } ->

View File

@ -5,6 +5,11 @@ open Stanza.Of_sexp
for simplicity *)
let syntax = Stanza.syntax
let env_field =
field_o "env"
(Syntax.since syntax (1, 1) >>= fun () ->
Dune_env.Stanza.t)
module Context = struct
module Target = struct
type t =
@ -49,7 +54,7 @@ module Context = struct
}
let t ~profile =
field_o "env" Dune_env.Stanza.t >>= fun env ->
env_field >>= fun env ->
field "targets" (list Target.t) ~default:[Target.Native]
>>= fun targets ->
field "profile" string ~default:profile
@ -148,22 +153,25 @@ end
type t =
{ merlin_context : string option
; contexts : Context.t list
; env : Dune_env.Stanza.t option
}
include Versioned_file.Make(struct type t = unit end)
let () = Lang.register syntax ()
let t ?x ?profile:cmdline_profile () =
env_field >>= fun env ->
field "profile" string ~default:Config.default_build_profile
>>= fun profile ->
let profile = Option.value cmdline_profile ~default:profile in
multi_field "context" (Context.t ~profile ~x)
>>= fun contexts ->
let defined_names = ref String.Set.empty in
let { merlin_context; contexts } =
let { merlin_context; contexts; env } =
let init =
{ merlin_context = None
; contexts = []
; env
}
in
List.fold_left contexts ~init ~f:(fun t ctx ->
@ -178,7 +186,7 @@ let t ?x ?profile:cmdline_profile () =
Loc.fail (Context.loc ctx)
"you can only have one context for merlin"
| Opam { merlin = true; _ }, None ->
{ merlin_context = Some name; contexts = ctx :: t.contexts }
{ merlin_context = Some name; contexts = ctx :: t.contexts; env = None }
| _ ->
{ t with contexts = ctx :: t.contexts })
in
@ -200,6 +208,7 @@ let t ?x ?profile:cmdline_profile () =
return
{ merlin_context
; contexts = List.rev contexts
; env
}
let t ?x ?profile () = fields (t ?x ?profile ())
@ -207,6 +216,7 @@ let t ?x ?profile () = fields (t ?x ?profile ())
let default ?x ?profile () =
{ merlin_context = Some "default"
; contexts = [Context.default ?x ?profile ()]
; env = None
}
let load ?x ?profile p =

View File

@ -38,6 +38,7 @@ end
type t =
{ merlin_context : string option
; contexts : Context.t list
; env : Dune_env.Stanza.t option
}
val load : ?x:string -> ?profile:string -> Path.t -> t

View File

@ -1,6 +1,5 @@
$ cat dune-project
cat: dune-project: No such file or directory
[1]
$ [ -e dune-project ] || echo File does not exist
File does not exist
$ mkdir src
$ echo '(alias (name runtest) (action (progn)))' > src/dune
$ dune build

View File

@ -53,6 +53,6 @@ Workspaces also allow you to set the env for a context:
Entering directory 'workspace-env'
(
(flags (-w -40 -machin))
(ocamlc_flags (-g))
(ocamlc_flags (-g -verbose))
(ocamlopt_flags (-g))
)

View File

@ -1 +1 @@
(lang dune 1.0)
(lang dune 1.1)

View File

@ -1,4 +1,8 @@
(lang dune 1.0)
(lang dune 1.1)
(env
(default
(ocamlc_flags (:standard -verbose))))
(context
(default