Skip to content

Commit

Permalink
Merge branch 'main' into fix-5282
Browse files Browse the repository at this point in the history
  • Loading branch information
hhugo authored Jan 7, 2022
2 parents 587ddb7 + 3582988 commit 877e8e7
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 64 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Unreleased
- If an .ml file is not used by an executable, Dune no longer report
parsing error in this file (#4330, @jeremiedimino)

- Add support for sandboxing using hard links (#4360, @snowleopard)
- Add support for sandboxing using hard links (#4360, Andrey Mokhov)

- Fix dune crash when `subdir` is an absolute path (#4366, @anmonteiro)

Expand Down
26 changes: 13 additions & 13 deletions doc/jsoo.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.. _jsoo:

**********************
JavaScript compilation
JavaScript Compilation
**********************

js_of_ocaml_ is a compiler from OCaml to JavaScript. The compiler works by
translating OCaml bytecode to JS files. The compiler can be installed with opam:
Js_of_ocaml_ is a compiler from OCaml to JavaScript. The compiler works by
translating OCaml bytecode to JS files. The compiler can be installed with Opam:

.. code:: bash
Expand All @@ -14,8 +14,8 @@ translating OCaml bytecode to JS files. The compiler can be installed with opam:
Compiling to JS
===============

Dune has full support building js_of_ocaml libraries and executables transparently.
There's no need to customize or enable anything to compile ocaml
Dune has full support building Js_of_ocaml 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.
Expand All @@ -25,7 +25,7 @@ Consider this example:
echo 'print_endline "hello from js"' > foo.ml
With the following dune file:
With the following ``dune`` file:

.. code:: scheme
Expand All @@ -42,8 +42,8 @@ And then request the ``.js`` target:
Similar targets are created for libraries, but we recommend sticking to the
executable targets.

If you're using the js_of_ocaml syntax extension, you must remember to add the
appropriate ppx in the ``preprocess`` field:
If you're using the Js_of_ocaml syntax extension, you must remember to add the
appropriate PPX in the ``preprocess`` field:

.. code:: scheme
Expand All @@ -52,21 +52,21 @@ appropriate ppx in the ``preprocess`` field:
(modes js)
(preprocess (pps js_of_ocaml-ppx)))
Separate compilation
Separate Compilation
====================

Dune supports two modes of 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
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. It can also be explicitly sepcified
in an env stanza. See :ref:`dune-env` for more information.
is ``dev``, which is the default. It can also be explicitly specified
in an ``env`` stanza. See :ref:`dune-env` for more information.

.. _js_of_ocaml: http://ocsigen.org/js_of_ocaml/
50 changes: 25 additions & 25 deletions doc/sites.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.. _sites:

***************************************
How to load additional files at runtime
How to Load Additional Files at Runtime
***************************************

There are many ways for applications to load files at runtime and Dune provides
a well tested, key-in-hand portable system for doing so. The Dune model works by
a well-tested, key-in-hand portable system for doing so. The Dune model works by
defining ``sites`` where files will be installed and looked up at runtime. At
runtime, each site is associated to a list of directories which contain the
files added in the site.
Expand All @@ -17,7 +17,7 @@ without warning. It must be explicitly enabled in the ``dune-project`` file with
Sites
=====

Defining a site
Defining a Site
---------------

A site is defined in a package :ref:`package` in the ``dune-project`` file. It
Expand All @@ -34,11 +34,11 @@ consists of a name and a :ref:`section<install>` (e.g ``lib``, ``share``,
(name mygui)
(sites (share themes)))
Adding files to a site
Adding Files to a Site
----------------------

Here the package ``mygui`` defines a site named ``themes`` that will be located
in the section ``share``. This package can add files to this ``sites`` using the
in the section ``share``. This package can add files to this ``site`` using the
:ref:`install stanza<install>`:

.. code:: scheme
Expand Down Expand Up @@ -69,7 +69,7 @@ The package ``mygui`` must be present in the workspace or installed.

Two files should not be installed by different packages at the same destination.

Getting the locations of a site at runtime
Getting the Locations of a Site at Runtime
------------------------------------------

The executable ``mygui`` will be able to get the locations of the ``themes``
Expand Down Expand Up @@ -126,27 +126,27 @@ Then inside ``mygui.ml`` module the locations can be recovered and used:
Tests
-----

During tests the files are copied into the sites through the dependency
During tests, the files are copied into the sites through the dependency
``(package mygui)`` and ``(package mygui_material_theme)`` as for other files in
install stanza.

Installation
------------

Installation is done simply with ``dune install``, however if one want to
install this tool such that it is relocatable, one can use ``dune
Installation is done simply with ``dune install``; however, if one wants to
install this tool to make it relocatable, one can use ``dune
install --relocatable --prefix $dir``. The files will be copied to the directory
``$dir`` but the binary ``$dir/bin/mygui`` will find the site location relative
to its location. So even if the directory ``$dir`` is moved,
``themes_locations`` will be correct.

For installation trough opam, ``dune install`` must be invoked with the option
For installation trough Opam, ``dune install`` must be invoked with the option
``--create-install-files`` which creates an install file ``<pkg>.install`` and
copy the file that needs substitution to an intermediary directory. The
``<pkg>.opam`` file generated by dune :ref:`generate_opam_files` does the right
``<pkg>.opam`` file generated by Dune :ref:`generate_opam_files` does the right
invocation.

Implementation details
Implementation Details
----------------------

The main difficulty for sites is that their directories are found at different
Expand All @@ -158,22 +158,22 @@ locations at different times:
package the location is at the same time in ``_build`` and in the install prefix
of the second package.

With the last example we see that the location of a site is not always a single
directory, but can consist of a sequence of directories: ``["dir1" ; "dir2"]``.
With the last example, we see that the location of a site is not always a single
directory, but rather it can consist of a sequence of directories: ``["dir1" ; "dir2"]``.
So a lookup must first look into `dir1`, then into `dir2`.

.. _plugins:

Plugins and dynamic loading of packages
Plugins and Dynamic Loading of Packages
========================================

Dune allows to define and load plugins without having to deal with specific
compilation, installation directories, dependencies, or the Dynlink_ module.
Dune allows you to define and load plugins without having to deal with specific
compilation, installation directories, dependencies, or the ``Dynlink_`` module.

To define a plugin:

- The package defining the plugin interface must define a `site` where the
plugins must live. Traditionally, this is in ``(lib plugins)``, but it is just
plugins must live. Traditionally, this is in ``(lib plugins)``, but it's just
a convention.

- Define a library that each plugin must use to register itself (or otherwise
Expand All @@ -192,13 +192,13 @@ following components:

Inside package `app`:

- An executable `app`, that we intend to extend with plugins.
- An executable `app`, that we intend to extend with plugins

- A library `app.registration` which defines the plugin registration interface.
- A library `app.registration` which defines the plugin registration interface

- A generated module `Sites` which can load available plugins at runtime.
- A generated module `Sites` which can load available plugins at runtime

- An executable `app` that will use the module `Sites` to load all the plugins.
- An executable `app` that will use the module `Sites` to load all the plugins

Inside package `Plugin1`, we declare a plugin using the `app.registration` api and the
`plugin` stanza.
Expand All @@ -219,7 +219,7 @@ Directory structure
└── registration.ml
Main executable (C)
Main Executable (C)
^^^^^^^^^^^^^^^^^^^^^

- The ``dune-project`` file:
Expand Down Expand Up @@ -273,7 +273,7 @@ The generated module `sites` depends here also on the library
(* Execute the code registered by the plugins *)
let () = Queue.iter (fun f -> f ()) Registration.todo
The plugin "plugin1"
The Plugin "plugin1"
^^^^^^^^^^^^^^^^^^^^

- The ``plugin/dune-project`` file:
Expand Down Expand Up @@ -314,7 +314,7 @@ The plugin "plugin1"
print_endline "Registration of Plugin1";
Queue.add (fun () -> print_endline "Plugin1 is doing something...") Registration.todo
Running the example
Running the Example
^^^^^^^^^^^^^^^^^^^

.. code::
Expand Down
4 changes: 3 additions & 1 deletion otherlibs/stdune/digest.ml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ let path_with_stats ~allow_dirs path (stats : Stats_for_digest.t) :
Path_digest_result.t =
match stats.st_kind with
| S_REG ->
let executable = stats.st_perm land 0o100 <> 0 in
let executable =
Path.Permissions.test Path.Permissions.execute stats.st_perm
in
Dune_filesystem_stubs.Unix_error.Detailed.catch
(file_with_executable_bit ~executable)
path
Expand Down
15 changes: 12 additions & 3 deletions otherlibs/stdune/path.ml
Original file line number Diff line number Diff line change
Expand Up @@ -583,11 +583,20 @@ module Kind = struct
end

module Permissions = struct
let write = 0o222
type t =
{ current_user : int
; all_users : int
}

let execute = { current_user = 0o100; all_users = 0o111 }

let write = { current_user = 0o200; all_users = 0o222 }

let add t perm = perm lor t.current_user

let add ~mode perm = perm lor mode
let test t perm = perm land t.current_user <> 0

let remove ~mode perm = perm land lnot mode
let remove t perm = perm land lnot t.all_users
end

module Build = struct
Expand Down
18 changes: 13 additions & 5 deletions otherlibs/stdune/path.mli
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,22 @@ module Source : sig
end

module Permissions : sig
type t

(** Execute permissions. *)
val execute : t

(** Write permissions. *)
val write : int
val write : t

(** Add permissions to a given mask for the current user. *)
val add : t -> int -> int

(** Add [mode] permissions to a given mask. *)
val add : mode:int -> int -> int
(** Test permissions of a given mask for the current user. *)
val test : t -> int -> bool

(** Remove [mode] permissions from a given mask. *)
val remove : mode:int -> int -> int
(** Remove permissions from a given mask for all users. *)
val remove : t -> int -> int
end

module Build : sig
Expand Down
4 changes: 2 additions & 2 deletions src/dune_cache/local.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ module Target = struct
match Path.Build.lstat path with
| { Unix.st_kind = Unix.S_REG; st_perm; _ } ->
Path.Build.chmod path
~mode:(Path.Permissions.remove ~mode:Path.Permissions.write st_perm);
let executable = st_perm land 0o100 <> 0 in
~mode:(Path.Permissions.remove Path.Permissions.write st_perm);
let executable = Path.Permissions.test Path.Permissions.execute st_perm in
Some { path; executable }
| (exception _)
| _ ->
Expand Down
2 changes: 1 addition & 1 deletion src/dune_engine/cached_digest.ml
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ let refresh_and_remove_write_permissions ~allow_dirs path =
| exception Unix.Unix_error (ENOENT, _, _) -> Broken_symlink)
| S_REG ->
let perm =
Path.Permissions.remove ~mode:Path.Permissions.write stats.st_perm
Path.Permissions.remove Path.Permissions.write stats.st_perm
in
Path.chmod ~mode:perm path;
refresh ~allow_dirs { stats with st_perm = perm } path
Expand Down
2 changes: 1 addition & 1 deletion src/dune_engine/diff_promotion.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module File = struct

let do_promote ~correction_file ~dst =
Path.Source.unlink_no_err dst;
let chmod perms = perms lor 0o200 in
let chmod = Path.Permissions.add Path.Permissions.write in
Io.copy_file ~chmod
~src:(Path.build correction_file)
~dst:(Path.source dst) ()
Expand Down
3 changes: 2 additions & 1 deletion src/dune_engine/sandbox.ml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ let link_function ~(mode : Sandbox_mode.some) =
| Patch_back_source_tree ->
(* We need to let the action modify its dependencies, so we copy
dependencies and make them writable. *)
fun src dst -> Io.copy_file ~src ~dst ~chmod:(fun n -> n lor 0o200) ())
let chmod = Path.Permissions.add Path.Permissions.write in
fun src dst -> Io.copy_file ~src ~dst ~chmod ())

let link_deps t ~mode ~deps =
let link = Staged.unstage (link_function ~mode) in
Expand Down
6 changes: 5 additions & 1 deletion src/dune_engine/scheduler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,11 @@ let check_point =
t_opt () >>= function
| None -> Fiber.return ()
| Some t ->
check_cancelled t;
(* CR-someday amokhov: we used to call [check_cancelled t] here but that led
to a significant performance regression. Raising [Build_cancelled] saves
some unnecessary recomputation but also destroys early cutoffs. We should
change Memo to store previous successes to make such early cancellations
preserve the early cutoff behaviour. *)
Event.Queue.yield_if_there_are_pending_events t.events

let () = Memo.check_point := check_point
Expand Down
2 changes: 1 addition & 1 deletion src/dune_engine/target_promotion.ml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ let promote_target_if_not_up_to_date ~src ~src_digest ~dst ~promote_source
(* The file in the build directory might be read-only if it comes from the
shared cache. However, we want the file in the source tree to be
writable by the user, so we explicitly set the user writable bit. *)
let chmod n = n lor 0o200 in
let chmod = Path.Permissions.add Path.Permissions.write in
let+ () =
promote_source ~chmod ~delete_dst_if_it_is_a_directory:true ~src ~dst
in
Expand Down
Loading

0 comments on commit 877e8e7

Please sign in to comment.