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

parameterized tags and non-parameterized tags haven't the same behavior when tagging inside rules #6186

Closed
vicuna opened this issue Sep 20, 2013 · 5 comments

Comments

@vicuna
Copy link

vicuna commented Sep 20, 2013

Original bug ID: 6186
Reporter: jpdeplaix
Assigned to: @gasche
Status: resolved (set by @damiendoligez on 2017-02-24T15:08:33Z)
Resolution: suspended
Priority: normal
Severity: minor
Version: 4.01.0
Target version: later
Category: -for ocamlbuild use https://github.com/ocaml/ocamlbuild/issues
Tags: patch

Bug description

According 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 reproduce

myocamlbuild.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

File attachments

@vicuna
Copy link
Author

vicuna commented Sep 21, 2013

Comment author: @gasche

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.

@vicuna
Copy link
Author

vicuna commented Sep 21, 2013

Comment author: jpdeplaix

I were sure to have mentioned the workaround: kit-ty-kate/eliom@747e11c
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.

@vicuna
Copy link
Author

vicuna commented Sep 21, 2013

Comment author: @gasche

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.

@vicuna
Copy link
Author

vicuna commented Mar 18, 2014

Comment author: jpdeplaix

I just improved a little bit the workaround: ocsigen/eliom@c65bf98

@vicuna
Copy link
Author

vicuna commented Feb 24, 2017

Comment author: @damiendoligez

ocamlbuild is now a separate project that lives on GitHub.
PR transferred to ocaml/ocamlbuild#154

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants