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

Add support for passing arguments to instrumentation backends #3932

Merged
merged 4 commits into from
Nov 12, 2020
Merged
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
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ Unreleased
- `dune describe` now also includes information about executables in addition to
that of libraries. (#3892, #3895, @nojb)

- instrumentations backends can now receive arguments via `(instrumentation
(backend <name> <args>))`. (#3906, #3932, @nojb)

2.7.1 (2/09/2020)
-----------------

Expand Down
6 changes: 4 additions & 2 deletions doc/instrumentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ executable stanza:
(library
(name ...)
(instrumentation
(backend <name>)))
(backend <name> <args>)))

The backend ``<name>`` can be passed arguments using ``<args>``.

This field can be repeated multiple times in order to support various
backends. For instance:
Expand All @@ -33,7 +35,7 @@ backends. For instance:
(library
(name foo)
(modules foo)
(instrumentation (backend bisect_ppx))
(instrumentation (backend bisect_ppx --bisect-silent yes))
(instrumentation (backend landmarks)))

This will instruct Dune that when either the ``bisect_ppx`` or ``landmarks``
Expand Down
10 changes: 8 additions & 2 deletions src/dune_rules/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,21 @@ module Buildable = struct
located
(multi_field "instrumentation"
( Dune_lang.Syntax.since Stanza.syntax (2, 7)
>>> fields (field "backend" (located Lib_name.decode)) ))
>>> fields
(field "backend"
(let+ libname = located Lib_name.decode
and+ flags = repeat String_with_vars.decode in
(libname, flags))) ))
in
let preprocess =
let init =
let f libname = Preprocess.With_instrumentation.Ordinary libname in
Module_name.Per_item.map preprocess ~f:(Preprocess.map ~f)
in
List.fold_left instrumentation
~f:(Preprocess.Per_module.add_instrumentation ~loc:loc_instrumentation)
~f:(fun accu (instrumentation, flags) ->
Preprocess.Per_module.add_instrumentation accu
~loc:loc_instrumentation ~flags instrumentation)
~init
in
let foreign_stubs =
Expand Down
7 changes: 3 additions & 4 deletions src/dune_rules/preprocess.ml
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,18 @@ module Per_module = struct
else
No_preprocessing

let add_instrumentation t ~loc libname =
let add_instrumentation t ~loc ~flags:flags' libname =
Per_module.map t ~f:(fun pp ->
match pp with
| No_preprocessing ->
let pps = [ With_instrumentation.Instrumentation_backend libname ] in
let flags = [] in
let staged = false in
Pps { loc; pps; flags; staged }
Pps { loc; pps; flags = flags'; staged }
| Pps { loc; pps; flags; staged } ->
let pps =
With_instrumentation.Instrumentation_backend libname :: pps
in
Pps { loc; pps; flags; staged }
Pps { loc; pps; flags = flags @ flags'; staged }
Copy link
Member

@bobzhang bobzhang Jun 23, 2021

Choose a reason for hiding this comment

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

This seems to be wrong when I have an instrumentation backend and pps at the same time.
In that case, when instrumentation is off, that flags are still passed to pps which caused a build error
@jeremiedimino

Copy link

Choose a reason for hiding this comment

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

It indeed looks like we are adding instrumentation flags unconditionally. Thanks @bobzhang for uncovering this and pin-pointing the root of the issue. Do you mind opening an issue about this so that we can track it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See #4770

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fix merged, will be in 2.9

Copy link

Choose a reason for hiding this comment

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

Great, thanks @nojb for the prompt fix!

| Action (loc, _)
| Future_syntax loc ->
User_error.raise ~loc
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/preprocess.mli
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ module Per_module : sig
val add_instrumentation :
With_instrumentation.t t
-> loc:Loc.t
-> flags:String_with_vars.t list
-> Loc.t * Lib_name.t
-> With_instrumentation.t t

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
let hello () = print_endline "Hello, Dune!"
let hello s = print_endline (Printf.sprintf "Hello from %s!" s)
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
open Ast_helper
open Longident

let place = ref None

let impl str =
let arg =
match !place with
| None -> Exp.ident (Location.mknoloc (Lident "__MODULE__"))
| Some s -> Exp.constant (Const.string s)
in
Str.eval
(Exp.apply (Exp.ident (Location.mknoloc (Ldot (Lident "Hello", "hello"))))
[Nolabel, Exp.construct (Location.mknoloc (Lident "()")) None]) :: str
[Nolabel, arg]) :: str

open Ppxlib

let () =
Driver.add_arg "-place" (Arg.String (fun s -> place := Some s))
~doc:"PLACE where to say hello from"

let () =
Driver.register_transformation_using_ocaml_current_ast ~impl "hello"
33 changes: 23 additions & 10 deletions test/blackbox-tests/test-cases/instrumentation.t/run.t
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
$ cat >dune-project <<EOF
> (lang dune 2.7)
> (wrapped_executables false)
> EOF

"Hello" is an instrumentation backend that instruments by printing "Hello,
Expand All @@ -18,7 +19,7 @@ Dune!" at the beginning of the module.
> EOF

$ cat >mylib.ml <<EOF
> let f () = print_endline "Mylib"
> let f () = ()
> EOF

$ cat >main.ml <<EOF
Expand All @@ -30,16 +31,14 @@ message.

$ dune build
$ _build/default/main.exe
Mylib

This should print the instrumentation message twice, once for "main" and once
for "mylib":

$ dune build --instrument-with hello
$ _build/default/main.exe
Hello, Dune!
Hello, Dune!
Mylib
Hello from Mylib!
Hello from Main!

An empty file:

Expand All @@ -61,14 +60,27 @@ We rebuild with instrumentation via the CLI.
We get the message.

$ _build/default/main.exe
Hello, Dune!
Hello from Main!

We also check that we can pass arguments to the ppx.

$ cat >dune <<EOF
> (executable
> (name main)
> (modules main)
> (instrumentation (backend hello -place Spain)))
> EOF

$ dune build --instrument-with hello
$ _build/default/main.exe
Hello from Spain!

Can also enable with an environment variable.

$ DUNE_INSTRUMENT_WITH=hello dune build

$ _build/default/main.exe
Hello, Dune!
Hello from Spain!

Instrumentation can also be controlled by using the dune-workspace file.

Expand All @@ -80,7 +92,7 @@ Instrumentation can also be controlled by using the dune-workspace file.
$ dune build

$ _build/default/main.exe
Hello, Dune!
Hello from Spain!

It can also be controlled on a per-context scope.

Expand All @@ -92,7 +104,7 @@ It can also be controlled on a per-context scope.
$ dune build

$ _build/coverage/main.exe
Hello, Dune!
Hello from Spain!

Per-context setting takes precedence over per-workspace setting.

Expand All @@ -119,6 +131,7 @@ Next, we check the backend can be used when it is installed.
> EOF
$ cat >installed/dune-project <<EOF
> (lang dune 2.7)
> (wrapped_executables false)
> EOF
$ cat >installed/dune <<EOF
> (executable
Expand All @@ -130,4 +143,4 @@ Next, we check the backend can be used when it is installed.
$ OCAMLPATH=$PWD/_install/lib dune build --root installed
Entering directory 'installed'
$ installed/_build/default/main.exe
Hello, Dune!
Hello from Main!