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

Dune utop runs js_of_ocaml bycodes #11231

Closed
Halbaroth opened this issue Dec 19, 2024 · 6 comments
Closed

Dune utop runs js_of_ocaml bycodes #11231

Halbaroth opened this issue Dec 19, 2024 · 6 comments

Comments

@Halbaroth
Copy link

I am working on a project that includes an executable compiled in js mode. This executable is the only artefact in the project that is compiled in this mode. I can no longer use dune utop because it throws the error:

Fatal error: Unimplemented Javascript primitive caml_js_expr!

I suspect that dune utop is attempting to execute bytecodes generated by js_of_ocaml, which fails as there is no appropriate Javascript runtime.

I wrote a MRE. Starting from a fresh project, use the following dune-project file:

(lang dune 3.16)

(name mre)

(package
 (name mre)
 (depends ocaml dune js_of_ocaml)
 (allow_empty))

And replace bin/dune by:

(executable
 (name main)
 (modes js)
 (libraries 
   mre 
   js_of_ocaml))

dune utop should output the same error.

I expect dune utop to ignore executables, or at least those compiled in JavaScript mode. Am I missing something?

@nojb
Copy link
Collaborator

nojb commented Dec 19, 2024

I expect dune utop to ignore executables, or at least those compiled in JavaScript mode. Am I missing something?

dune utop does not do anything with executables, but it tries to load all libraries used by your project. Probably the js_of_ocaml library cannot be loaded into the toplevel because it depends on primitives which are not present in the native runtime.

You can try to work around this issue by segregating the code that can run using the native runtime in a separate directory and running dune utop there.

@Halbaroth
Copy link
Author

Actually, I already have a workaround: I use the -p flag to exclude the executable but it also excludes a library.
It would be nice to load only the libraries that are dependencies of project's libraries but it could be complicate to implement in Dune.

@Halbaroth
Copy link
Author

Halbaroth commented Dec 19, 2024

It could be doable because dune top lib/ outputs only library's dependencies.

@Halbaroth
Copy link
Author

A very naive patch:

diff --git a/src/dune_rules/utop.ml b/src/dune_rules/utop.ml
index 85c53b2b1..e8e7e0584 100644
--- a/src/dune_rules/utop.ml
+++ b/src/dune_rules/utop.ml
@@ -61,44 +61,6 @@ let add_stanza db ~dir (acc, pps) stanza =
            ( Appendable_list.cons lib acc
            , Appendable_list.cons (Lib_info.loc info, Lib_info.name info) pps ))
        else acc, pps)
-  | Executables.T exes ->
-    let+ libs =
-      let* compile_info =
-        let* scope = Scope.DB.find_by_dir dir in
-        let dune_version =
-          let project = Scope.project scope in
-          Dune_project.dune_version project
-        in
-        let+ pps =
-          Resolve.Memo.read_memo
-            (Preprocess.Per_module.with_instrumentation
-               exes.buildable.preprocess
-               ~instrumentation_backend:
-                 (Lib.DB.instrumentation_backend (Scope.libs scope)))
-          >>| Preprocess.Per_module.pps
-        in
-        Lib.DB.resolve_user_written_deps
-          db
-          (`Exe exes.names)
-          exes.buildable.libraries
-          ~pps
-          ~dune_version
-          ~allow_overlaps:exes.buildable.allow_overlapping_dependencies
-          ~forbidden_libraries:exes.forbidden_libraries
-      in
-      let+ available = Lib.Compile.direct_requires compile_info in
-      Resolve.peek available
-    in
-    (match libs with
-     | Error () -> acc, pps
-     | Ok libs ->
-       List.fold_left libs ~init:(acc, pps) ~f:(fun (acc, pps) lib ->
-         let info = Lib.info lib in
-         match Lib_info.kind info with
-         | Normal -> Appendable_list.cons lib acc, pps
-         | Ppx_rewriter _ | Ppx_deriver _ ->
-           ( Appendable_list.cons lib acc
-           , Appendable_list.cons (Lib_info.loc info, Lib_info.name info) pps )))
   | _ -> Memo.return (acc, pps)
 ;;

The utop rule appears to recursively traverse all subdirectories, searching for both library and executable stanzas and to collect
all library and ppx dependencies. Is it intentional to include executable stanzas here?

@Halbaroth
Copy link
Author

After discussing with colleagues, it appears that loading all the dependencies is a desired feature. I will implement a workaround for my use case and I close this issue.

@nojb
Copy link
Collaborator

nojb commented Jan 6, 2025

I will implement a workaround for my use case and I close this issue.

Thanks for helping keep the bugtracker tidy! Cheers.

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

No branches or pull requests

2 participants