When dune complains like:
File "_unknown_", line 1, characters 0-0:
Error: File unavailable:
/home/ali/repos/coq-dpdgraph/_build/install/default/lib/coq-dpdgraph/META
What should I do to fix it?
The error goes away if I redo the build shortly after
Here is the project in question: https://github.com/coq-community/coq-dpdgraph/pull/101
What dune version is this? We saw this bug with the cache and symlinks
Another obvious bug in that error is that the failed rule doesn't have a proper location.
@Ali Caglayan do you want to try and fix the location bug?
That was 3.1
@Rudi Grinberg Not sure where to start with that one.
Ali Caglayan said:
Rudi Grinberg Not sure where to start with that one.
Should be in install_rules.ml
. Look for Gen_meta.gen
and the most adjacent call to add_rule
that creates the rule for the META
. The location is likely not passed in. We should pass the location of the corresponding library stanza there.
@Rudi Grinberg I've patched dune to pass the location, here is the difference:
File "_unknown_", line 1, characters 0-0:
*** Error: in file dpdgraph.v, could not find META.coq-dpdgraph.
File "dune", line 44, characters 0-205:
44 | (coq.theory
45 | (name dpdgraph)
46 | (package coq-dpdgraph)
47 | (synopsis "Compute dependencies between Coq objects (definitions, theorems) and produce graphs")
48 | (libraries coq-dpdgraph.plugin)
49 | (flags -w +default))
*** Error: in file dpdgraph.v, could not find META.coq-dpdgraph.
It is not particularly useful here tbh
Can I make it more useful?
Or I guess you weren't intending to fix the bug, but rather report the location better.
You can. You can push a custom error message onto the stack. But what's this error about? What would you replace the message with instead?
In that case, I found a few other discarded locations before a add_rule
. Should I try to add those in as well?
Rudi Grinberg said:
You can. You can push a custom error message onto the stack. But what's this error about? What would you replace the message with instead?
Yeah I guess the real bug is in coq.theory here
Ali Caglayan said:
In that case, I found a few other discarded locations before a
add_rule
. Should I try to add those in as well?
Sure, if you can add a sensible location then it's always welcome.
@Rudi Grinberg Do you know about https://github.com/coq/coq/issues/15952?
I wonder if I can fix that too, not sure where to look tho.
Hmm I think this is https://github.com/ocaml/dune/issues/4039
Too unrelated to what I am doing probably
If you understand how flambda’s compilation is supposed to work, the fix should be easy on dune’s side. I think we just lack people with flambda experience on the dune team.
I don't particularly see how flambda causes this warning in the first place however. My knowledge of flambda is superficial at best.
Ali Caglayan said:
I don't particularly see how flambda causes this warning in the first place however. My knowledge of flambda is superficial at best.
I haven't fixed this issue for the same reason. I don't know enough about flambda and I don't use it myself. Personally, I'm waiting for flambda2 to come out before investing my time in it.
But this is really two bugs right? One bug with the location and one with whatever flambda is causing. I don't particularly care about the latter but perhaps I can fix the first.
I don't think the bad location is from dune. We don't use _none_
, we use _unknown_
or <none>
. At least as far as I remember.
Hmm ok then there is not much to be done I guess
I'm no flambda expert but the error makes some sense (and why would it change with flambda 2?): Cross-module inlining extends dependencies on interfaces to also depend on object files.
For Coq users, not using flambda means losing on the order of 20% performance on Coq build times (beware: wide error bars across projects, and I don't have recent measurements)
it was suggested here that plugins that want to compile both the OCaml side with Dune and compile at least one Coq file to expose the plugin should be split into two opam packages if they want to avoid the problems with coqdep
and META (File "_unknown_", line 1, characters 0-0
).
I think this will introduce a large overhead for the whole Coq ecosystem and is not workable. In essence, it would be better to "backport" these plugins to use regular coq_makefile again so that they can be kept in a single package and avoid the coqdep error. I estimate this would be less work than maintaining two packages for all plugins that want to use Dune.
I estimate this would be less work than maintaining two packages for all plugins that want to use Dune.
Could you describe the work of the work two packages instead of one might involve? I do it all the time and it's fairly easy.
To be clear, we are talking about dune packages and not the opam packge
What's the difference?
for every release, you have to add two packages to the repo and they have to be tested independently. If we remove one of the packages in the future when the issue is solved, all projects that depend on the removed package will break
What I mean is that the dune file might have "two packages" but the opam release only has one.
Because they would be packaged together
I don't really understand how that would work, are you saying the opam package should run two dune install commands?
Karl Palmskog said:
for every release, you have to add two packages to the repo and they have to be tested independently. If we remove one of the packages in the future when the issue is solved, all projects that depend on the removed package will break
You can add a constraint so that they're always the same version. How do you add packages when making a release? It's just one dune-release command invocation regardless of how many packages you have.
there are very few projects that actually use dune-release unfortunately
but isn't there some opam build
clause hacking we could use to avoid having two package definitions?
in case of coq-dpdgraph, the Coq theory consists of a single line of code, so couldn't one do two dune build
invocations with different parameters?
Karl Palmskog said:
but isn't there some opam
build
clause hacking we could use to avoid having two package definitions?
Not likely. The issue is that the plugin wants the META file which requires building the entire package. The plugin itself is part of the package so it's a cycle.
we are going to need something like that [build command sequence] for the plugins in Coq's CI anyway (since it doesn't use opam)
Karl Palmskog said:
in case of coq-dpdgraph, the Coq theory consists of a single line of code, so couldn't one do two
dune build
invocations with different parameters?
If it's a single line, why does it need to exist at all?
the single line of code in the .v
file is what exposes the plugin to Coq users, as opposed to OCaml programmers.
but I'm not sure I fully understand how Dune sees packaging. For example, let's say I've written a test suite that has both OCaml tests and Coq-level tests. I would have to refactor that test suite into different directories, if OCaml and Coq sides live in different packages, right?
what would happen if I do something like this in my opam package:
build: [
["dune" "build" "-p" "dunepackage1" "-j" jobs]
["dune" "build" "-p" "dunepackage2" "-j" jobs]
]
run-test: [
["dune" "runtest" "-p" "dunepackage1" "-j" jobs]
["dune" "runtest" "-p" "dunepackage2" "-j" jobs]
]
Is there anything fundamental that goes wrong then?
finally, if one only has a single Coq file, isn't it an option to add a custom rule that calls coqc
(eliding coqdep)?
another reason for the overhead of split packages is that our custom solution for generating opam package definitions currently doesn't support generating two or more packages in a single repo. This is a limitation that we have planned to remove but haven't gotten to yet.
At the Dune side, we need to add metadata to our opam files that are currently not recognized by Dune, so specifying the opam packages in Dune is also not a straightforward solution.
At the Dune side, we need to add metadata to our opam files that are currently not recognized by Dune, so specifying the opam packages in Dune is also not a straightforward solution.
What kind of metadata is that?
example:
tags: [
"category:Miscellaneous/Coq Extensions"
"keyword:dependency graph"
"keyword:dependency analysis"
"logpath:dpdgraph"
"date:2022-05-16"
]
But you know you could write .opam
files, dune doesn't prevent you from doing that.
Though we could support writing tags
in dune-project files too
Rudi Grinberg said:
But you know you could write
.opam
files, dune doesn't prevent you from doing that.
You mean this? https://dune.readthedocs.io/en/stable/opam.html#opam-template
That could be used as well. Though it's not really necessary. Dune only generates opam files only if you ask it to
sure, we can write custom .opam
ourselves (and we do, most of the time). I'm just laying out the reasons it can be costly to split plugins into two opam packages right now. I really like using Dune, but for "old" plugins that seemingly build fine with coq_makefile
, it's not a straightforward choice to split packages just to get to use Dune without running into the coqdep issue.
With that said, if I wrote a new plugin, I probably wouldn't mind splitting up front.
if Dune adds support for tags
into dune-project
, that would lower the barrier for splitting, though
Right but you don't even have to do that. You just have a project.opam.template
which contains only the tags field and dune will fill the rest with the generated parts.
that's one more metadata file to keep track of, in addition to, in many cases: coq-package.opam
, meta.yml
, dune
, dune-project
Karl Palmskog said:
finally, if one only has a single Coq file, isn't it an option to add a custom rule that calls
coqc
(eliding coqdep)?
We can absolutely do this by the way.
I think we just need to specify the install rules too.
Something like
(rule
(deps file.v)
(targets file.vo)
(action (run %{bin:coqc} file.v))
)
And then make an install rule for the coq-contrib folder or wherever it is supposed to install
That way we don't call coqdep (since we don't need to).
@Karl Palmskog Would you like me to have a go?
@Ali Caglayan OK, feel free to do this in the coq-master+dune
branch for coq-dpdgraph. This is to me the best solution there, with only a single Coq theory file with just the module declaration.
just remember that it should live in the dpdgraph
namespace (dpdgraph.dpdgraph
)
FTR here is what the install looks like:
_build/install/
└── default
├── bin
│ ├── dpd2dot -> ../../../default/dpd2dot.exe
│ └── dpdusage -> ../../../default/dpdusage.exe
├── doc
│ └── coq-dpdgraph
│ ├── CHANGES.md -> ../../../../default/CHANGES.md
│ ├── LICENSE -> ../../../../default/LICENSE
│ └── README.md -> ../../../../default/README.md
└── lib
├── coq
│ └── user-contrib
│ └── dpdgraph
│ ├── dpdgraph.cmxs -> ../../../../../../default/dpdgraph.cmxs
│ ├── dpdgraph.v -> ../../../../../../default/dpdgraph.v
│ └── dpdgraph.vo -> ../../../../../../default/dpdgraph.vo
└── coq-dpdgraph
├── dune-package -> ../../../../default/coq-dpdgraph.dune-package
├── META -> ../../../../default/META.coq-dpdgraph
├── opam -> ../../../../default/coq-dpdgraph.opam
└── plugin
├── dpdgraph.a -> ../../../../../default/dpdgraph.a
├── dpdgraph.cma -> ../../../../../default/dpdgraph.cma
├── dpdgraph.cmi -> ../../../../../default/.dpdgraph.objs/byte/dpdgraph.cmi
├── dpdgraph.cmt -> ../../../../../default/.dpdgraph.objs/byte/dpdgraph.cmt
├── dpdgraph.cmx -> ../../../../../default/.dpdgraph.objs/native/dpdgraph.cmx
├── dpdgraph.cmxa -> ../../../../../default/dpdgraph.cmxa
├── dpdgraph.cmxs -> ../../../../../default/dpdgraph.cmxs
├── dpdgraph__Graphdepend.cmi -> ../../../../../default/.dpdgraph.objs/byte/dpdgraph__Graphdepend.cmi
├── dpdgraph__Graphdepend.cmt -> ../../../../../default/.dpdgraph.objs/byte/dpdgraph__Graphdepend.cmt
├── dpdgraph__Graphdepend.cmx -> ../../../../../default/.dpdgraph.objs/native/dpdgraph__Graphdepend.cmx
├── dpdgraph.ml -> ../../../../../default/dpdgraph.ml-gen
├── dpdgraph__Searchdepend.cmi -> ../../../../../default/.dpdgraph.objs/byte/dpdgraph__Searchdepend.cmi
├── dpdgraph__Searchdepend.cmt -> ../../../../../default/.dpdgraph.objs/byte/dpdgraph__Searchdepend.cmt
├── dpdgraph__Searchdepend.cmx -> ../../../../../default/.dpdgraph.objs/native/dpdgraph__Searchdepend.cmx
├── graphdepend.ml -> ../../../../../default/graphdepend.ml
└── searchdepend.ml -> ../../../../../default/searchdepend.ml
that looks correct to me
Looks like the cmxs is also provided
I think the duplication of the cmxs is by design
Won't that rule compile the .v file too early?
By the way that was the coq.theory install
I'm gonna replicate that by hand now
That is, won't that let dune call coqc before the plugin is built? Is that okay?
for this to work, I think the .vo
has to depend on the .cmxs
Ok so we have
(rule
(deps dpdgraph.v dpdgraph.cmxs)
(targets dpdgraph.vo)
(action (run %{bin:coqc} dpdgraph.v)))
This works.
Now we need an install rule
Oh actually I think I need to pass some more flags to coqc
-Q . dpdgraph right?
I put dpdgraph.v
into theories
, so if you are in the root, I recommend -R theories dpdgraph
to follow the old convention
I just realized that I didn't check out your branch properly
Everything seems to be working fine
0:-)
Those issues with META seem to only happen when you mix .v files with the .ml files
But now that there are separate theories and src dir everything looks ok
well, I said before I couldn't replicate the error when I split into src
and theories
(which is best practice anyway). But I don't know why that solves the coqdep problem, because everything is still in the same opam/Dune package (coq-dpdgraph
)
@Rudi Grinberg Any idea what might be going on?
Having a look at the dune code, there seems to be an explicit dep on mllpack for the coqdep rule.
I suspect this is buggy when the directories coincide like in this case
Ali Caglayan said:
Rudi Grinberg Any idea what might be going on?
no idea.
I looked at the content of the branch now with dune build --verbose
, and it never even calls coqdep
after the split into separate theories
dir.
maybe it's an optimization that a directory with only one .v
file never needs a coqdep
call?
we have no such optimization
as far as I know at least
No it is being called
DUNE_CACHE=disabled dune build --display=short
coqpp src/graphdepend.ml
coqpp src/searchdepend.ml
ocamlyacc src/dpd_parse.{ml,mli}
ocamllex src/dpd_lex.ml
coqdep theories/dpdgraph.v.d
ocamlc src/.dpdgraph.objs/byte/dpdgraph.{cmi,cmo,cmt}
ocamldep src/.dpdgraph.objs/searchdepend.ml.d
ocamldep src/.dpd2dot.eobjs/dpd2dot.ml.d
ocamldep src/.dpdgraph.objs/graphdepend.ml.d
ocamlc src/.dpd_lex.objs/byte/dpd_lex__.{cmi,cmo,cmt}
ocamlc src/.version.objs/byte/version.{cmi,cmo,cmt}
ocamlopt src/.dpdgraph.objs/native/dpdgraph.{cmx,o}
ocamldep src/.dpd_lex.objs/dpd_parse.ml.d
ocamlc src/version.cma
ocamldep src/.dpd_lex.objs/dpd_lex.ml.d
ocamldep src/.dpd_lex.objs/dpd_parse.mli.d
ocamldep src/.dpd2dot.eobjs/dpd_dot.ml.d
ocamlopt src/.dpd_lex.objs/native/dpd_lex__.{cmx,o}
ocamlopt src/.version.objs/native/version.{cmx,o}
ocamlc src/.dpd2dot.eobjs/byte/dune__exe.{cmi,cmo,cmt}
ocamlc src/.dpdgraph.objs/byte/dpdgraph__Searchdepend.{cmi,cmo,cmt}
ocamlopt src/version.{a,cmxa}
ocamlopt src/.dpd2dot.eobjs/native/dune__exe.{cmx,o}
ocamlc src/.dpd_compute.objs/byte/dpd_compute.{cmi,cmo,cmt}
ocamlc src/dpd_compute.cma
ocamlc src/.dpd_lex.objs/byte/dpd_lex__Dpd_parse.{cmi,cmti}
ocamlopt src/version.cmxs
ocamlc src/.dpd_lex.objs/byte/dpd_lex__Dpd_parse.{cmo,cmt}
ocamlc src/.dpd_lex.objs/byte/dpd_lex.{cmi,cmo,cmt}
ocamlc src/dpd_lex.cma
ocamlopt src/.dpd_lex.objs/native/dpd_lex__Dpd_parse.{cmx,o}
ocamlopt src/.dpdgraph.objs/native/dpdgraph__Searchdepend.{cmx,o}
ocamlc src/.dpdgraph.objs/byte/dpdgraph__Graphdepend.{cmi,cmo,cmt}
ocamlc src/.dpdusage.eobjs/byte/dune__exe__Dpdusage.{cmi,cmo,cmt}
ocamlopt src/.dpd_lex.objs/native/dpd_lex.{cmx,o}
ocamlc src/dpdgraph.cma
ocamlc src/.dpd2dot.eobjs/byte/dune__exe__Dpd_dot.{cmi,cmo,cmt}
ocamlopt src/.dpd_compute.objs/native/dpd_compute.{cmx,o}
ocamlopt src/dpd_lex.{a,cmxa}
ocamlc src/.dpd2dot.eobjs/byte/dune__exe__Dpd2dot.{cmi,cmo,cmt}
ocamlopt src/dpd_compute.{a,cmxa}
ocamlopt src/.dpdusage.eobjs/native/dune__exe__Dpdusage.{cmx,o}
ocamlopt src/dpd_lex.cmxs
ocamlopt src/.dpd2dot.eobjs/native/dune__exe__Dpd2dot.{cmx,o}
ocamlopt src/dpd_compute.cmxs
ocamlopt src/.dpd2dot.eobjs/native/dune__exe__Dpd_dot.{cmx,o}
ocamlopt src/.dpdgraph.objs/native/dpdgraph__Graphdepend.{cmx,o}
ocamlopt src/dpdgraph.{a,cmxa}
ocamlopt src/dpdgraph.cmxs
ocamlopt src/dpdusage.exe
ocamlopt src/dpd2dot.exe
coqc theories/.dpdgraph.aux,theories/dpdgraph.{glob,vo}
Very early on in fact
right, I misspotted, it's seemingly being called first? ("Running[1]")
Here is the coqdep rule in dune:
let coqdep_rule (cctx : _ Context.t) ~source_rule ~file_flags coq_module =
(* coqdep needs the full source + plugin's mlpack to be present :( *)
let source = Coq_module.source coq_module in
let file_flags =
[ Command.Args.S file_flags
; As [ "-dyndep"; "opt" ]
; Dep (Path.build source)
]
in
let stdout_to = Coq_module.dep_file ~obj_dir:cctx.dir coq_module in
(* Coqdep has to be called in the stanza's directory *)
let open Action_builder.With_targets.O in
Action_builder.with_no_targets cctx.mlpack_rule
>>> Action_builder.(with_no_targets (goal source_rule))
>>> Command.run ~dir:(Path.build cctx.dir) ~stdout_to cctx.coqdep file_flags
As you can see by <s>Emilio's</s> Rudi's sad face comment that is the issue (Actually I don't know who wrote the comment the git blame says Rudi)
Coq_module is a complicated coq dep handling module
I think the bug is in there due to incorrect prefix handling
in the case .v file and .ml files are in the same dir there is no prefix
What's "prefix handling" in this case?
Whatever this is:
module Module = struct
(* We keep prefix and name separated as the handling of `From Foo Require
Bar.` may benefit from it. *)
type t =
{ source : Path.Build.t
; prefix : string list
; name : Name.t
}
let compare { source; prefix; name } t =
let open Ordering.O in
let= () = Path.Build.compare source t.source in
let= () = List.compare prefix t.prefix ~compare:String.compare in
Name.compare name t.name
let to_dyn { source; prefix; name } =
Dyn.record
[ ("source", Path.Build.to_dyn source)
; ("prefix", Dyn.list Dyn.string prefix)
; ("name", Name.to_dyn name)
]
end
hmm, could it be something even more trivial in this case? The output of coqdep is actually not needed here
so even though the coqdep call gives an error, the build works fine
@Karl Palmskog does every coq plugin have the same one file boilerplate?
Not necessarily
no, some have much more stuff and mix plugin with theory at the Coq level (reflective tactics)
Some even have none
Okay, but this is the "minimum", right?
Hmm, I guess not.
some people even skip providing the single .v
file
this means that everyone that wants to use the plugin has to do Declare Module ...
in their local Coq file
Would it make sense to encode plugin best practices into dune? That is to add a stanza to define a plugin that would take care of these things. It seems pretty bad from the end user's perspective to know all this arbitrary variety can exist
we consider this bad practice, and it raises coqdep warnings for the plugin user project
I'm all for encoding best practices into Dune, such as splitting the Coq theory and OCaml source into different directories
Karl Palmskog said:
we consider this bad practice, and it raises coqdep warnings for the plugin user project
With .v or without .v?
Karl Palmskog said:
I'm all for encoding best practices into Dune, such as splitting the Coq theory and OCaml source into different directories
Of course, the story gets a little complicated when people want to mix extraction and ml code tho.
the project which uses the plugin that does not have a Coq theory gets a coqdep
warning in its .v
files that have Declare Module ...
Karl Palmskog said:
the project which uses the plugin that does not have a Coq theory gets a
coqdep
warning in its.v
files that haveDeclare Module ...
Which warning is this specifically?
Something like these?
*** Warning: in file bugs/bug_3612.v, declared ML module ./plugins/ltac/ltac_plugin has not been found!
*** Warning: in file bugs/bug_3649.v, declared ML module ./plugins/ltac/ltac_plugin has not been found!
*** Warning: in file bugs/bug_4121.v, declared ML module ./plugins/ltac/ltac_plugin has not been found!
*** Warning: in file micromega/witness_tactics.v, declared ML module ./plugins/micromega/micromega_plugin has not been found!
coqdep doesn't actually care about the contents of a plugin, it just points. When the file it is pointing to doesn't exist it emits a warning.
Ali Caglayan said:
Karl Palmskog said:
I'm all for encoding best practices into Dune, such as splitting the Coq theory and OCaml source into different directories
Of course, the story gets a little complicated when people want to mix extraction and ml code tho.
That should always be possible, right? The extraction stanza is special cased so this stuff can be avoided
I think the warning was about missing dependencies, yes, "has not been found"
yes, I used extraction to build a plugin with Dune just fine, with the src
/theories
layout...
Karl Palmskog said:
I think the warning was about missing dependencies, yes, "has not been found"
I'm thinking that this is really a coqdep bug that these warnings get emitted. If coqc can find the plugin coqdep pointed to no problem, then coqdep ought to have found it too.
IIRC coqdep is checking for an mllpack file wherever it was looking but even if you give an existing plugin it complains
OK, my best diagnosis here is that a single-Coq-file-in-separate-directory plugin avoids the error due to the .d
file never being used anyway, and hence it doesn't matter that it's missing
What are mlpack files used for?
according to Emilio, they are just boilerplate to get around coqdep design assumptions, if I remember correctly
but coq_makefile actually uses the content of .mlpack
I believe?
Perhaps but I am not sure who this warning is helping
We need to somehow make a coq_makefile test that invokes the warning from coqdep and check that coq_makefile still works
if it indeed needs an .mlpack
https://github.com/coq/coq/commit/01fb4ae4f30b1f87eaff2a5ed19133bf8c6933de
So 11 years ago it was decided that mlpack will be handled, but I can't find any info why
the coqdep warning is because it doesn't see the mlpack
that should go away once we port for meta
I got a way but we need to allow findlib to shut up the "two meta files on the path" warning
It is a pity we are having pain with that, because I think the fix is easy
Right, but why were we looking for mlpack in the first place?
That's what coqdep does
because it has no information otherwise of when a cmxs file will be generated
it is if you want to see it that way
a -modules vs non -modules setup
but in this case, we can solve it more easily
as we can delegate to findlib
for .v files that's more of a pain as -modules can't work yet
Last updated: Oct 13 2024 at 01:02 UTC