Skip to content

Commit 30d209d

Browse files
authored
fix(melange): disallow private implementations of public virtual libs (#11253)
* test(melange): show wrong require for private impl of public virtual lib Signed-off-by: Antonio Nuno Monteiro <[email protected]> * fix(melange): disallow private implementations of public virtual libs Signed-off-by: Antonio Nuno Monteiro <[email protected]> * changelog Signed-off-by: Antonio Nuno Monteiro <[email protected]> --------- Signed-off-by: Antonio Nuno Monteiro <[email protected]>
1 parent 30ee6ac commit 30d209d

File tree

3 files changed

+80
-32
lines changed

3 files changed

+80
-32
lines changed

doc/changes/11253.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Disallow private implementations of public virtual libs in melange mode.
2+
(@amonteiro, #11253)

src/dune_rules/melange/melange_rules.ml

+46-31
Original file line numberDiff line numberDiff line change
@@ -576,38 +576,53 @@ let setup_js_rules_libraries =
576576
| None -> Memo.return ()
577577
| Some vlib ->
578578
let* vlib = Resolve.Memo.read_memo vlib in
579-
let* includes =
580-
let+ requires_link =
581-
let+ requires_link =
582-
Lib.Compile.for_lib
583-
~allow_overlaps:mel.allow_overlapping_dependencies
584-
(Scope.libs scope)
585-
vlib
586-
|> Lib.Compile.requires_link
587-
|> Memo.Lazy.force
588-
in
589-
let open Resolve.O in
590-
let+ requires_link = requires_link in
591-
(* Whenever a `concrete_lib` implementation contains a field
592-
`(implements virt_lib)`, we also set up the JS targets for the
593-
modules defined in `virt_lib`.
579+
let vlib_output = output_of_lib ~target_dir vlib in
580+
(match vlib_output, output with
581+
| `Public_library _, `Private_library_or_emit _ ->
582+
let info = Lib.info lib in
583+
User_error.raise
584+
~loc:(Lib_info.loc info)
585+
[ Pp.text
586+
"Dune doesn't currently support building private implementations of \
587+
virtual public libaries for `(modes melange)`"
588+
]
589+
~hints:
590+
[ Pp.textf
591+
"Add a `public_name` to the library `%s'."
592+
(Lib_name.to_string (Lib_info.name info))
593+
]
594+
| `Public_library _, `Public_library _ | `Private_library_or_emit _, _ ->
595+
let* includes =
596+
let+ requires_link =
597+
let+ requires_link =
598+
Lib.Compile.for_lib
599+
~allow_overlaps:mel.allow_overlapping_dependencies
600+
(Scope.libs scope)
601+
vlib
602+
|> Lib.Compile.requires_link
603+
|> Memo.Lazy.force
604+
in
605+
let open Resolve.O in
606+
let+ requires_link = requires_link in
607+
(* Whenever a `concrete_lib` implementation contains a field
608+
`(implements virt_lib)`, we also set up the JS targets for the
609+
modules defined in `virt_lib`.
594610
595-
In the cases where `virt_lib` (concrete) modules depend on any
596-
virtual modules (i.e. programming against the interface), we
597-
need to make sure that the JS rules that dune emits for
598-
`virt_lib` depend on `concrete_lib`, such that Melange can find
599-
the correct `.cmj` file, which is needed to emit the correct
600-
path in `import` / `require`. *)
601-
lib :: requires_link
602-
in
603-
cmj_includes ~requires_link ~scope lib_config
604-
in
605-
let output = output_of_lib ~target_dir vlib in
606-
parallel_build_source_modules
607-
~sctx
608-
~scope
609-
vlib
610-
~f:(build_js ~dir ~output ~includes ~compile_flags)
611+
In the cases where `virt_lib` (concrete) modules depend on any
612+
virtual modules (i.e. programming against the interface), we
613+
need to make sure that the JS rules that dune emits for
614+
`virt_lib` depend on `concrete_lib`, such that Melange can find
615+
the correct `.cmj` file, which is needed to emit the correct
616+
path in `import` / `require`. *)
617+
lib :: requires_link
618+
in
619+
cmj_includes ~requires_link ~scope lib_config
620+
in
621+
parallel_build_source_modules
622+
~sctx
623+
~scope
624+
vlib
625+
~f:(build_js ~dir ~output:vlib_output ~includes ~compile_flags))
611626
and+ () =
612627
parallel_build_source_modules
613628
~sctx

test/blackbox-tests/test-cases/melange/virtual-lib-public.t renamed to test/blackbox-tests/test-cases/melange/virtual-lib-private-impl.t

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Test a case of virtual libraries where the virtual library is public
1+
Test virtual libraries where the virtual lib is public and the concrete impl is
2+
private
23

34
$ mkdir -p vlib js_impl test
45
$ cat > dune-project <<EOF
@@ -46,3 +47,33 @@ Test a case of virtual libraries where the virtual library is public
4647
> EOF
4748

4849
$ dune build @melange
50+
File "js_impl/dune", lines 1-5, characters 0-95:
51+
1 | (library
52+
2 | (name timeJs)
53+
3 | (implements the_lib)
54+
4 | (modes melange)
55+
5 | (preprocess (pps melange.ppx)))
56+
Error: Dune doesn't currently support building private implementations of
57+
virtual public libaries for `(modes melange)`
58+
Hint: Add a `public_name` to the library `timeJs'.
59+
[1]
60+
61+
Making timeJs a public library makes it work
62+
63+
$ cat > dune-project <<EOF
64+
> (lang dune 3.13)
65+
> (using melange 0.1)
66+
> (package (name the_lib))
67+
> (package (name concrete_lib))
68+
> EOF
69+
70+
$ cat > js_impl/dune <<EOF
71+
> (library
72+
> (name timeJs)
73+
> (public_name concrete_lib)
74+
> (implements the_lib)
75+
> (modes melange)
76+
> (preprocess (pps melange.ppx)))
77+
> EOF
78+
79+
$ dune build @melange

0 commit comments

Comments
 (0)