ocsigen / eliom

Multi-tier framework for programming web and mobile applications in OCaml.
http://eliom.org
Other
306 stars 54 forks source link

Missing primitives when building project #525

Open shonfeder opened 7 years ago

shonfeder commented 7 years ago

I think this is an eliom issue, since it seems to follow after a call to js_of_eliom (but please tell me if I should file elsewhere).

js_of_eliom -ppx -o local/var/www/amazons/eliom/amazons.js  -package lwt.ppx -package js_of_ocaml.ppx -package js_of_ocaml.deriving.ppx -package ocsigen-toolkit.client -package batteries  \
          _client/aux.cmo _client/game.cmo _client/state.cmo _client/render.cmo _client/amazons.cmo
There are some missing primitives
Dummy implementations (raising 'Failure' exception) will be used if they are not available at runtime.
You can prevent the generation of dummy implementations with the commandline option '--disable genprim'
Missing primitives provided by +nat.js:
  create_nat
  incr_nat
  initialize_nat
  set_digit_nat
  set_to_zero_nat
Missing primitives:
  re_search_forward

I've found some discussion of There are some missing primitives in #464, ocsigen/js_of_ocaml#587, and in js_of_ocaml manual:

Here's what I'm hoping to come out of my ticket:

  1. I'd like to know what kind of problems I can expect as a result of these "missing primitives".
  2. I'd like to figure out whether this is a problem with Eliom, with my use of it, or with some other part of the Ocsigen stack.
  3. I'd like to help motivate and/or create the documentation (and hopefully better inline help) to identify the causes and solutions of these kinds of problems, so others won't end up in my shoes.

In case it is helpful, I have supplied my system and version info in this gist. I am encountering the problem in this learning project.

shonfeder commented 7 years ago

I've made some progress in diagnosing this problem:

Reproducing the problem

Adding batteries as a dependency, even if I don't use anything from the library, will produce the missing primitives associated with +nat.js. To reproduce:

  1. Create a project with eliom-distillery following the instructions in the Client/server application tutorial:

    $ eliom-distillery -name study -template basic.ppx -target-directory study
  2. Add batteries as a dependency for the client side by editing the list of CLIENT_PACKAGES in Makefile.options:

    # OCamlfind packages for the client
    CLIENT_PACKAGES := lwt.ppx js_of_ocaml.ppx js_of_ocaml.deriving.ppx batteries
  3. Build the project using make test.byte, which will then produce the missing primitives error:

    js_of_eliom -ppx -o local/var/www/study/eliom/study.js  -package lwt.ppx -package js_of_ocaml.ppx -package js_of_ocaml.deriving.ppx -package batteries  \
              _client/study.cmo
    There are some missing primitives
    Dummy implementations (raising 'Failure' exception) will be used if they are not available at runtime.
    You can prevent the generation of dummy implementations with the commandline option '--disable genprim'
    Missing primitives provided by +nat.js:
      create_nat
      incr_nat
      initialize_nat
      set_digit_nat
      set_to_zero_nat

Impact of the problem

I have also confirmed that this problem is responsible for breaking my client-side code: once these missing primitives are in play, client-side code, such as this snippet from the tutorial, simply fails to run when the site is loaded:

let%client _ = Eliom_lib.alert "Hello!"

This sucks :(

Locating nat.js

Finally, I think I have located the nat.js file that is being sought: it seems to be the nat.js file included in the js_of_ocaml runtime.

Implications

It seems that the root of the problem has to do with how js_of_ocaml handles dependecies and (fails) to instruct the user on the source or solution to the problem.

However, this also seems to indicate problems with the Ocsigen/Eliom ecosystem, at least in regards to documentation and user experience. I have now spent numerous hours studying documentation and tutorials, and I don't recall reading anything that warned against using well-established and commonly used OCaml libraries. Nor have I yet found anything that explains how to make such usage work.

Ways forwards

I see three ways forward for this issue:

  1. My immediate aim is to find a quick solutions so I can advance my project. In my particular case, the easiest fix may just be to get rid of the batteries dependency by implementing the functionality I need myself. (Obviously, this is not a desirable or sustainable long-term fix.)
  2. In the middle-term, better documentation on how to anticipate and correct these kinds of problems will help new users in the future.
  3. For the long term, how can we avoid these kinds of problems all together? What mechanisms can be employed to make the usage of common libraries available without getting derailed in this way?
vasilisp commented 7 years ago

You have to pass +nat.js to the invocations of js_of_ocaml (and its Eliom wrapper, js_of_eliom). I guess the easiest way would be to add it to the JS_OF_ELIOM and JS_OF_OCAML lines in Makefile.

To automate this, I guess we would need to adapt ocamlfind/findlib to keep track of the primitives that libraries need.

shonfeder commented 7 years ago

@vasilisp Thanks for the tip!

I finally resolved the +nat.js missing primitives thanks to your pointer: I passed +nat.js through js_of_eliom to js_of_ocaml with the following change to JS_OF_ELIOM in the Makefile:

JS_OF_ELIOM       := js_of_eliom -jsopt +nat.js -ppx

Regarding automation: If I get a chance, I will dig in to ocamlfind/findlib to see if I can find hints for a way forward on that front. However, I would guess that changes in this direction should go in the js_of_ocaml repo rather than the Eliom repo — is that correct? Should I open an issue there?

On the Eliom front, what do you think about the following ideas for relatively easy usability improvements for these kinds of cases?

I would be happy to pursue one or both of these, if you think they would be useful additions.