Skip to content

Commit 632dcab

Browse files
committed
feature: use diff rather (mode promote) for generating opam files
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
1 parent 251c36b commit 632dcab

File tree

6 files changed

+157
-80
lines changed

6 files changed

+157
-80
lines changed

src/dune_rules/install_rules.ml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ let need_odoc_config (pkg : Package.t) =
1717
module Package_paths = struct
1818
let opam_file (ctx : Build_context.t) (pkg : Package.t) =
1919
let opam_file = Package.opam_file pkg in
20-
let exists =
21-
match Package.has_opam_file pkg with
22-
| Exists b -> b
23-
| Generated -> true
24-
in
25-
if exists then Some (Path.Build.append_source ctx.build_dir opam_file) else None
20+
match Package.has_opam_file pkg with
21+
| Exists false -> Memo.return None
22+
| Exists true -> Memo.return (Some (Path.Build.append_source ctx.build_dir opam_file))
23+
| Generated ->
24+
let dir = Path.Build.append_source ctx.build_dir (Package.dir pkg) in
25+
let+ project = Dune_load.find_project ~dir in
26+
Some (Opam_create.build_path ~build_dir:ctx.build_dir ~project pkg)
2627
;;
2728

2829
let meta_fn pkg = "META." ^ Package.Name.to_string pkg
@@ -579,7 +580,7 @@ end = struct
579580
let* packages = Dune_load.packages () in
580581
let+ init =
581582
Package_map_traversals.parallel_map packages ~f:(fun _name (pkg : Package.t) ->
582-
let opam_file = Package_paths.opam_file ctx pkg in
583+
let* opam_file = Package_paths.opam_file ctx pkg in
583584
let init =
584585
let file section local_file dst =
585586
Install.Entry.Unexpanded.make

src/dune_rules/opam_create.ml

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,13 @@ let opam_fields project (package : Package.t) =
337337

338338
let template_file = Path.extend_basename ~suffix:".template"
339339

340+
let build_path ~build_dir ~project pkg =
341+
let opam_path = Path.Build.append_source build_dir (Package.opam_file pkg) in
342+
if Dune_project.dune_version project < (3, 23)
343+
then opam_path
344+
else Path.Build.extend_basename opam_path ~suffix:".generated"
345+
;;
346+
340347
let opam_template ~opam_path =
341348
let open Action_builder.O in
342349
let opam_template_path = template_file opam_path in
@@ -377,32 +384,60 @@ let generate project pkg ~template =
377384
let add_alias_rule (ctx : Build_context.t) ~project ~pkg =
378385
let build_dir = ctx.build_dir in
379386
let dir = Path.Build.append_source build_dir (Dune_project.root project) in
387+
let source_opam_path = Package.opam_file pkg |> Path.source in
380388
let opam_path = Path.Build.append_source build_dir (Package.opam_file pkg) in
389+
let generated_opam_path = build_path ~build_dir ~project pkg in
381390
let aliases =
382391
[ Alias.make Alias0.install ~dir
383392
; Alias.make Alias0.runtest ~dir
384393
; Alias.make Alias0.check ~dir (* check doesn't pick up the promote target? *)
385394
]
386395
in
387-
let deps = Path.Set.singleton (Path.build opam_path) in
396+
let deps = Path.Set.singleton (Path.build generated_opam_path) in
388397
Memo.parallel_iter aliases ~f:(fun alias ->
389-
(* TODO slow. we should be calling these functions only once, rather than
390-
once per package *)
391-
Rules.Produce.Alias.add_deps alias (Action_builder.path_set deps))
398+
let* () =
399+
(* TODO slow. we should be calling these functions only once, rather than
400+
once per package *)
401+
Rules.Produce.Alias.add_deps alias (Action_builder.path_set deps)
402+
in
403+
if Dune_project.dune_version project < (3, 23)
404+
then Memo.return ()
405+
else
406+
Rules.Produce.Alias.add_action
407+
alias
408+
~loc:(Loc.in_file source_opam_path)
409+
(let open Action_builder.O in
410+
let+ () = Action_builder.path (Path.build generated_opam_path)
411+
and+ () =
412+
Action_builder.if_file_exists
413+
source_opam_path
414+
~then_:(Action_builder.path (Path.build opam_path))
415+
~else_:(Action_builder.return ())
416+
in
417+
Action.Full.make (Action.diff (Path.build opam_path) generated_opam_path)))
392418
;;
393419

394420
let add_opam_file_rule sctx ~project ~pkg =
395-
let open Action_builder.O in
396421
let build_dir = Super_context.context sctx |> Context.build_dir in
397422
let opam_path = Path.Build.append_source build_dir (Package.opam_file pkg) in
423+
let generated_opam_path = build_path ~build_dir ~project pkg in
398424
let opam_rule =
425+
let open Action_builder.O in
399426
(let+ template = opam_template ~opam_path:(Path.build opam_path) in
400427
generate project pkg ~template)
401-
|> Action_builder.write_file_dyn opam_path
428+
|> Action_builder.write_file_dyn generated_opam_path
402429
in
403430
let dir = Path.Build.append_source build_dir (Dune_project.root project) in
404-
let mode = Rule.Mode.Promote { lifetime = Unlimited; into = None; only = None } in
405-
Super_context.add_rule sctx ~mode ~dir opam_rule
431+
if Dune_project.dune_version project < (3, 23)
432+
then (
433+
let mode = Rule.Mode.Promote { lifetime = Unlimited; into = None; only = None } in
434+
Super_context.add_rule sctx ~mode ~dir opam_rule)
435+
else
436+
let* () = Super_context.add_rule sctx ~dir opam_rule in
437+
let visible_opam_rule =
438+
Action_builder.copy ~src:(Path.build generated_opam_path) ~dst:opam_path
439+
in
440+
Super_context.add_rule sctx ~mode:Fallback ~dir visible_opam_rule
406441
;;
407442

408443
let add_opam_file_rules sctx project =

src/dune_rules/opam_create.mli

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ open Import
55
(** Given an opam filename, returns the filename of the template file *)
66
val template_file : Path.t -> Path.t
77

8+
(** Path to the generated opam file in the build directory. *)
9+
val build_path
10+
: build_dir:Path.Build.t
11+
-> project:Dune_project.t
12+
-> Package.t
13+
-> Path.Build.t
14+
815
(** Generate the contents of an opam file. [template] is the filename and
916
contents of the template file. *)
1017
val generate : Dune_project.t -> Package.t -> template:(Path.t * string) option -> string

test/blackbox-tests/test-cases/dune-init/dune-init.t/run.t

Lines changed: 74 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -376,38 +376,6 @@ We can build the project:
376376
And the opam file will be generated as expected
377377

378378
$ cat new_exec_proj/new_exec_proj.opam | sed 's/"dune"/$dune/' | sed -E 's/3.[0-9]+/3.XX/g'
379-
# This file is generated by dune, edit dune-project instead
380-
opam-version: "2.0"
381-
synopsis: "A short synopsis"
382-
description: "A longer description"
383-
maintainer: ["Maintainer Name <maintainer@example.com>"]
384-
authors: ["Author Name <author@example.com>"]
385-
license: "LICENSE"
386-
tags: ["add topics" "to describe" "your" "project"]
387-
homepage: "https://github.com/username/reponame"
388-
doc: "https://url/to/documentation"
389-
bug-reports: "https://github.com/username/reponame/issues"
390-
depends: [
391-
$dune {>= "3.XX"}
392-
"ocaml"
393-
"odoc" {with-doc}
394-
]
395-
build: [
396-
[$dune "subst"] {dev}
397-
[
398-
$dune
399-
"build"
400-
"-p"
401-
name
402-
"-j"
403-
jobs
404-
"@install"
405-
"@runtest" {with-test}
406-
"@doc" {with-doc}
407-
]
408-
]
409-
dev-repo: "git+https://github.com/username/reponame.git"
410-
x-maintenance-intent: ["(latest)"]
411379

412380
We can build and run the resulting executable:
413381

@@ -486,49 +454,91 @@ We can build and install the project:
486454

487455
$ dune build --root new_lib_proj @install
488456
Entering directory 'new_lib_proj'
457+
File "new_lib_proj.opam", line 1, characters 0-0:
458+
--- new_lib_proj.opam
459+
+++ new_lib_proj.opam.generated
460+
@@ -0,0 +1,32 @@
461+
+# This file is generated by dune, edit dune-project instead
462+
+opam-version: "2.0"
463+
+synopsis: "A short synopsis"
464+
+description: "A longer description"
465+
+maintainer: ["Maintainer Name <maintainer@example.com>"]
466+
+authors: ["Author Name <author@example.com>"]
467+
+license: "LICENSE"
468+
+tags: ["add topics" "to describe" "your" "project"]
469+
+homepage: "https://github.com/username/reponame"
470+
+doc: "https://url/to/documentation"
471+
+bug-reports: "https://github.com/username/reponame/issues"
472+
+depends: [
473+
+ "dune" {>= "3.23"}
474+
+ "ocaml"
475+
+ "odoc" {with-doc}
476+
+]
477+
+build: [
478+
+ ["dune" "subst"] {dev}
479+
+ [
480+
+ "dune"
481+
+ "build"
482+
+ "-p"
483+
+ name
484+
+ "-j"
485+
+ jobs
486+
+ "@install"
487+
+ "@runtest" {with-test}
488+
+ "@doc" {with-doc}
489+
+ ]
490+
+]
491+
+dev-repo: "git+https://github.com/username/reponame.git"
492+
+x-maintenance-intent: ["(latest)"]
489493
Leaving directory 'new_lib_proj'
494+
[1]
490495

491496
And the opam file will be generated as expected
492497

493498
$ cat new_lib_proj/new_lib_proj.opam | sed -E 's/3.[0-9]+/3.XX/g'
494-
# This file is generated by dune, edit dune-project instead
495-
opam-version: "2.0"
496-
synopsis: "A short synopsis"
497-
description: "A longer description"
498-
maintainer: ["Maintainer Name <maintainer@example.com>"]
499-
authors: ["Author Name <author@example.com>"]
500-
license: "LICENSE"
501-
tags: ["add topics" "to describe" "your" "project"]
502-
homepage: "https://github.com/username/reponame"
503-
doc: "https://url/to/documentation"
504-
bug-reports: "https://github.com/username/reponame/issues"
505-
depends: [
506-
"dune" {>= "3.XX"}
507-
"ocaml"
508-
"odoc" {with-doc}
509-
]
510-
build: [
511-
["dune" "subst"] {dev}
512-
[
513-
"dune"
514-
"build"
515-
"-p"
516-
name
517-
"-j"
518-
jobs
519-
"@install"
520-
"@runtest" {with-test}
521-
"@doc" {with-doc}
522-
]
523-
]
524-
dev-repo: "git+https://github.com/username/reponame.git"
525-
x-maintenance-intent: ["(latest)"]
526499

527500
And we we can run the tests:
528501

529502
$ dune runtest --root new_lib_proj
530503
Entering directory 'new_lib_proj'
504+
File "new_lib_proj.opam", line 1, characters 0-0:
505+
--- new_lib_proj.opam
506+
+++ new_lib_proj.opam.generated
507+
@@ -0,0 +1,32 @@
508+
+# This file is generated by dune, edit dune-project instead
509+
+opam-version: "2.0"
510+
+synopsis: "A short synopsis"
511+
+description: "A longer description"
512+
+maintainer: ["Maintainer Name <maintainer@example.com>"]
513+
+authors: ["Author Name <author@example.com>"]
514+
+license: "LICENSE"
515+
+tags: ["add topics" "to describe" "your" "project"]
516+
+homepage: "https://github.com/username/reponame"
517+
+doc: "https://url/to/documentation"
518+
+bug-reports: "https://github.com/username/reponame/issues"
519+
+depends: [
520+
+ "dune" {>= "3.23"}
521+
+ "ocaml"
522+
+ "odoc" {with-doc}
523+
+]
524+
+build: [
525+
+ ["dune" "subst"] {dev}
526+
+ [
527+
+ "dune"
528+
+ "build"
529+
+ "-p"
530+
+ name
531+
+ "-j"
532+
+ jobs
533+
+ "@install"
534+
+ "@runtest" {with-test}
535+
+ "@doc" {with-doc}
536+
+ ]
537+
+]
538+
+dev-repo: "git+https://github.com/username/reponame.git"
539+
+x-maintenance-intent: ["(latest)"]
531540
Leaving directory 'new_lib_proj'
541+
[1]
532542

533543

534544
Initializing Projects Using the PATH Argument

test/blackbox-tests/test-cases/dune-project-meta/fresh-build.t

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,19 @@ source tree if (generate_opam_files true) is enabled.
2222
$ dune build foo.install
2323
$ grep opam _build/default/foo.install
2424
"_build/install/default/lib/foo/opam"
25+
26+
The same should hold once opam generation switches to diff actions.
27+
28+
$ rm -f foo.opam
29+
$ cat >dune-project <<EOF
30+
> (lang dune 3.23)
31+
> (package
32+
> (name foo))
33+
> (generate_opam_files true)
34+
> EOF
35+
36+
$ dune build foo.install
37+
$ grep opam _build/default/foo.install
38+
"_build/install/default/lib/foo/opam"
39+
$ if test -e foo.opam; then echo present; else echo absent; fi
40+
absent

test/blackbox-tests/test-cases/package-runtest-alias.t

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ a package:
99
> (dir foo))
1010
> EOF
1111

12-
$ dune build @check
12+
$ dune build @check 2>&1 | sed -n '1,3p'
13+
File "foo.opam", line 1, characters 0-0:
14+
--- foo.opam
15+
+++ foo.opam.generated
16+
[1]
17+
$ dune promotion list
18+
foo.opam
19+
$ dune promote
20+
Promoting _build/default/foo.opam.generated to foo.opam.
1321
$ cat foo.opam | grep -o '"@runtest/foo" {with-test}'
1422
"@runtest/foo" {with-test}

0 commit comments

Comments
 (0)