Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006186OCamlOCamlbuild (the tool)public2013-09-20 17:392014-07-16 18:23
Reporterjpdeplaix 
Assigned Togasche 
PrioritynormalSeverityminorReproducibilityalways
StatusconfirmedResolutionopen 
PlatformOSOS Version
Product Version4.01.0 
Target Versionafter-4.02.0Fixed in Version 
Summary0006186: parameterized tags and non-parameterized tags haven't the same behavior when tagging inside rules
DescriptionAccording to the following test-case, we are not able to tag (with a parameterized tag) inside a rule, but it works outside a rule and with a non-parameterized tag.
Steps To Reproducemyocamlbuild.ml:
open Ocamlbuild_plugin

let () =
  rule "test..." ~dep:"%.byte" ~prod:"%.js"
    (fun env _ ->
       let dep = env "%.byte" in
       let prod = env "%.js" in
       tag_file prod ["opt(2)"; "test"];
       let tags = tags_of_pathname prod ++ "js_of_ocaml" in
       Cmd (S [A "js_of_ocaml"; T tags; A dep; A "-o"; A prod])
    )

let () =
  pflag ["js_of_ocaml"] "opt" (fun n -> S [A "-opt"; A n]);
  flag ["js_of_ocaml"; "test"] (A "-pretty")

$ touch test.ml
$ ocamlbuild -verbose 0 test.js
………
js_of_ocaml -pretty test.byte -o test.js

And if we add this at the end of the myocamlbuild.ml:
let () = tag_file "test.js" ["opt(1)"]

$ ocamlbuild -verbose 0 test.js
………
js_of_ocaml -pretty -opt 1 test.byte -o test.js
Tagspatch
Attached Filespatch file icon param_tags.patch [^] (397 bytes) 2013-09-21 18:17 [Show Content]

- Relationships

-  Notes
(0010389)
gasche (developer)
2013-09-21 14:03

Indeed, this surprising/buggy behavior has been present in ocamlbuild since the introduction of parametrized tags.

The "mental model" is that after everything is initialized (including the user plugin), ocamlbuild will "acknowledge" parametrized tags, that is look for all tags of the form "foo(bar)" that have been used somewhere (in a tag_file command, in the _tags file...), and execute the code of the corresponding parametrized tag with input "bar".

In your code, the tag "opt(2)" only appears dynamically when the rule is executed, and this is after this acknowledgment phase has run, so the tag does not take any meaning. In your workaround, you apply the tag at plugin execution time, so this works fine.

I'm not sure what is a good way to fix this.
(0010390)
jpdeplaix (reporter)
2013-09-21 18:25

I were sure to have mentioned the workaround: https://github.com/jpdeplaix/eliom/commit/747e11cd46422dafdb6886974120da9effe0ef99 [^]
My bad.

So, maybe we can call Param_tags.init inside Flags.of_tags(_list) or others functions that transforms tags into flags.

I've attached a fix. I don't know if it's the right way (maybe too much performances cost), but at least it fixes the issue.
(0010392)
gasche (developer)
2013-09-21 22:28

I don't think that would be correct, and I also doubt that your workaround is actually satisfying.

First, the current implementation of Param_tags.init is apparently designed to be called exactly once during ocamlbuild's initialization (that's explicitly mentioned in the comments). I don't understand the subtleties, but I would be weary of breaking this invariant.

More deeply, in OCamlbuild's current design, tags are purely data. They can be attached to a target either before or after being actually given a semantic by a `flag` or `pflag` call. Acknowledgment is supposed to happen after everything else, which means that both the semantics and the use-sites of tags are available, and it is possible to do some simple sanity checking. 4.00.1 only checks that the arity is correct (non-parametrized tags are not used parametrized, and vice versa) but trunk goes further with a "unused tags" warning. If you were to run Param_tags.init during each tag_file call, you would have false warnings due to sanity-checking running on tags that are attached to targets but have not yet be given a semantics.

I think one would need something more dynamic, such as automatically initializing tags at the moment they are used (that is when they appear in an actual command). The -plugin-tags feature already does something like that, and this is why I added Param_tags.partial_init before 4.01.


Something I was considering independently of this issue is to provide a Tags.declare command that would take a string representation of a tag, and return a tag value (which is a string, so that would be the identity, but with the possibility to do some sort of registration). Instead of

  flag ["ocaml"; "link"; "debug"] (A "-g");;

one would have something like

  let debug = Tag.declare "debug";;
  flag [ocaml; link; debug] (A "-g");;

The purported advantages were to avoid typos in flag declarations (getting the tag variable name wrong would result in a static error) and being able to warn when "unknown" tags are used (currently there is no notion of "unknown" tag). I think that could also help here.
(0011051)
jpdeplaix (reporter)
2014-03-18 16:46

I just improved a little bit the workaround: https://github.com/ocsigen/eliom/commit/c65bf98d88a4e65f1c399c507687cc9c02ba1467 [^]

- Issue History
Date Modified Username Field Change
2013-09-20 17:39 jpdeplaix New Issue
2013-09-21 14:03 gasche Note Added: 0010389
2013-09-21 14:03 gasche Assigned To => gasche
2013-09-21 14:03 gasche Status new => confirmed
2013-09-21 18:17 jpdeplaix File Added: param_tags.patch
2013-09-21 18:25 jpdeplaix Note Added: 0010390
2013-09-21 19:32 jpdeplaix Tag Attached: patch
2013-09-21 22:28 gasche Note Added: 0010392
2014-03-18 16:46 jpdeplaix Note Added: 0011051
2014-07-16 18:23 doligez Target Version => after-4.02.0


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker