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

How to use dependencies like Core with Reason & rebuild? #556

Closed
davidpelaez opened this issue May 28, 2016 · 12 comments
Closed

How to use dependencies like Core with Reason & rebuild? #556

davidpelaez opened this issue May 28, 2016 · 12 comments

Comments

@davidpelaez
Copy link

I had never taken the time to learn OCaml but Reason does indeed feel more accessible to me. Thank you for contributing to make OCaml easier for people like me! I'm using the weekend to get started and trying to follow Real World OCaml examples with Reason syntax. I've been unable to open Core.Std. Here's the question I wrote in StackOverflow:

I'm new to OCaml and I'm trying to try (:P) Facebook Reason syntax. I cannot find a way to make this compile because if cannot find the Core module (already installed with opam).

I'm trying to compile a sample program from Real World OCaml

open Core.Std;

let rec read_and_accumulate accum => {
  let line = In_channel.input_line In_channel.stdin;
  switch line {
    | None => accum
    | Some x => read_and_accumulate (accum +. Float.of_string x)
  }
};

let () = printf "Total: %F\n" (read_and_accumulate 0.);

This is the command I'm using for compilation: rebuild accum.native.

When I have this in _tags (from the instructions in https://janestreet.github.io/installation.html)

true: package(core,ppx_jane)
true: thread,debug

My error changes but I still don't know what to do:

File "_tags", line 1, characters 6-28:
Warning: tag "package" does not expect a parameter, but is used with parameter "core,ppx_jane"
File "_tags", line 1, characters 6-28:
Warning: the tag "package(core,ppx_jane)" is not used in any flag or dependency declaration, so it will have no effect; it may be a typo. Otherwise you can use `mark_tag_used` in your myocamlbuild.ml to disable this warning.
+ /Users/David/.opam/4.02.3/bin/ocamldep.opt -modules -pp refmt -impl accum2.re | tee accum2.re.depends accum2.ml.depends
accum2.re: Core Float In_channel
+ /Users/David/.opam/4.02.3/bin/ocamlc.opt -c -g -thread -pp '-g -thread' -pp refmt -o accum2.cmo -intf-suffix .rei -impl accum2.re
File "accum2.re", line 1, characters 5-13:
Error: Unbound module Core
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.

What do I have to do to use Core with Reason?

Adopting the syntax is pretty easy and I have only been reading for a couple hours, but there's zero docs about how to use Reason for non OCaml users.

I posted this in http://stackoverflow.com/questions/37504534/how-to-use-jane-streets-core-with-reason so it would be helpful if you reply there, otherwise I'll copy any help received here :)

@jordwalke
Copy link
Member

Thank you for your patience with respect to using and forming dependencies on external packages at build time. This is something we want to make easier as a next step (keep an eye on jengaboot for a better long term solution).

@yunxing Likely knows the answer to your immediate question.

@jordwalke
Copy link
Member

Adopting the syntax is pretty easy and I have only been reading for a couple hours, but there's zero docs about how to use Reason for non OCaml users.

Yes! I totally agree. On the Reason landing page, you'll see that there are three main "pillars" of Reason: Syntax, Build, Share. The Build and Share items are faded out as a sort of acknowledgment of what you've observed, and conveying our intent to eventually "fill them in". I hope @yunxing knows the answer to your question to unblock you in the short term though.

We're hoping that eventually, you'll just be able to make a package.json with an entry for "Core": versionNumber and then everything will just magically work.

@davidpelaez
Copy link
Author

@jordwalke thanks for the reply. I'm not sure about the .json part, but sound good that you are thinking about it. Hopefully @yunxing can help met out, I didn't understand how to use jengaboot to solve the issue. :)

@chenglou
Copy link
Member

@davidpelaez I'm developing jengaboot a bit silently. If you want, jump on #reasonml in free node and ping me =)

@IwanKaramazow
Copy link
Contributor

In theory I thought you could do something like this:

/* Hello.re */
open! Core.Std;

 let rec read_and_accumulate accum => {
   let line = In_channel.input_line In_channel.stdin;
   switch line {
     | None => accum
     | Some x => read_and_accumulate (accum +. Float.of_string x)
   }
 };

 let () = printf "Total: %F\n" (read_and_accumulate 0.);

rebuild Hello.native -pkg core
This gives me:

Error: No implementations provided for the following modules:
         Thread referenced from /Users/me/.opam/4.02.3/lib/core/core.cmxa(Core)
         Mutex referenced from /Users/me/.opam/4.02.3/lib/core/core.cmxa(Core)
         Condition referenced from /Users/me/.opam/4.02.3/lib/core/core.cmxa(Core)
         Event referenced from /Users/me/.opam/4.02.3/lib/core/core.cmxa(Core)
Command exited with code 2.

I tried it the CommonML way, but this gives me
ocamlfind: Error from package 'threads': Missing -thread or -vmthread switch.
This apparently a known issue:
jordwalke/CommonML#10

I'll try Jenga later this evening, hopefully I'll have more success 😄

@davidpelaez
Copy link
Author

rebuild accum2.native -use-ocamlfind seem to bring it a little forward, but I don't have any experience with OCaml so I cannot find a way to see anything useful for debugging purposes in the following output:

+ ocamlfind env OCAMLOPT="ocamlopt.opt" /Users/David/.opam/4.02.3/bin/reopt -c -g -thread -package core,ppx_jane -pp '-g -thread -package core,ppx_jane' -pp refmt -o accum2.cmx -intf-suffix .rei -impl accum2.re
Usage: ocamlfind query        [-help | other options] <package_name> ...
   or: ocamlfind ocamlc       [-help | other options] <file> ...
   or: ocamlfind ocamlcp      [-help | other options] <file> ...
   or: ocamlfind ocamlmklib   [-help | other options] <file> ...
   or: ocamlfind ocamlmktop   [-help | other options] <file> ...
   or: ocamlfind ocamlopt     [-help | other options] <file> ...
   or: ocamlfind ocamloptp    [-help | other options] <file> ...
   or: ocamlfind ocamldep     [-help | other options] <file> ...
   or: ocamlfind ocamlbrowser [-help | other options]
   or: ocamlfind ocamldoc     [-help | other options] <file> ...
   or: ocamlfind install      [-help | other options] <package_name> <file> ...
   or: ocamlfind remove       [-help | other options] <package_name>
   or: ocamlfind printconf    [-help] [variable]
   or: ocamlfind lint         [-help] <file>
   or: ocamlfind list
   or: ocamlfind pkg/cmd arg ...
Select toolchain with:
  ocamlfind -toolchain <t> <command>
Abbreviations:
  e.g. ocamlfind opt instead of ocamlfind ocamlopt
Command exited with code 2.
Compilation unsuccessful after building 3 targets (2 cached) in 00:00:00.

@davidpelaez
Copy link
Author

After a lot of help from @chenglou I could figure out how to do it. Basically the _tags indicated in https://janestreet.github.io/installation.html have to be added and three more flags and values: -linkpkg (I assume for static linking), -pp refmt indicating the ReasonML preprocessor and -impl file.re to tell what file to load. So if I have this file accum.re:

open Core.Std;

let rec read_and_accumulate accum => {
  let line = In_channel.input_line In_channel.stdin;
  switch line {
    | None => accum
    | Some x => read_and_accumulate (accum +. Float.of_string x)
  }
};

let () = printf "Total: %F\n" (read_and_accumulate 0.);

I can compile it to a native binary with:

ocamlfind ocamlc -g -thread -package ppx_jane -package core -pp refmt -linkpkg -o accum.native -impl accum.re

I would like to use ocamlbuild but I couldn't find a way to set the impl flag through an ocamlbuild command. I can leave this open until I figure it out with ocamlbuild and/or rebuild as well.

@jordwalke
Copy link
Member

@davidpelaez Thank you for sharing your solution so others can use it!

@yunxing
Copy link
Contributor

yunxing commented Jun 1, 2016

Hi @davidpelaez, just got back to town. Thanks for checking out Reason.

You actually helped us to discover a bug in rebuild -- rebuild doesn't work with -use-ocamlfind!

First of all, here are some contexts about how rebuild works:
rebuild is a wrapper of ocamlbuild. It changes ocamlbuild by replacing all the calls to ocamlopt with reopt. Now what is reopt? reopt is a wrapper of ocamlopt which passes in correct flags so it understands reason.
image

What's the problem here?

After a package is installed, one needs to call ocamlbuild with -use-ocamlfind so the build system can find out where the installed package is. The command that is called by ocamlbuild becomes something like ocamlfind ocamlopt -package core ... (Like what you've been using).

However, remember we just replaced all the calls to ocamlc with reopt? The command above then becomes ocamlfind reopt -package core ... -- and ocamlfind doesn't understand that!

The fix?

Instead of changing the subcommand from ocamlfind ocamlopt to ocamlfind reopt, we should use the recommend way in their manual: Change an environment variable env OCAMLFIND_COMMANDS=="ocamlc=$REOPT" to modify the behavior of ocamlfind.

I'm going to submit a fix about this soon.

@Jimexist
Copy link
Contributor

Jimexist commented Apr 21, 2017

maybe this is somehow related.

I am using https://github.com/reasonml/ReasonNativeProject to start a native reason project and i hit the same error when i try to add core to opam config file.

λ ~/GitHub/rejq/ master* make
cp pkg/META.in pkg/META
ocamlbuild -package topkg pkg/build.native
Finished, 4 targets (0 cached) in 00:00:00.
./build.native build
+ ocamlfind ocamlc -c -package menhirLib -package cmdliner -package core -package yojson -pp '-package menhirLib -package cmdliner -package core -package yojson' -I src -pp 'refmt --print binary' -o src/rejq.cmo -intf-suffix .rei -impl src/rejq.re
ocamlfind: Error from package `threads': Missing -thread or -vmthread switch
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.
build.native: [ERROR] cmd ['rebuild' '-use-ocamlfind' '-I' 'src' '-pkg' 'yojson' '-pkg' 'core'
     '-pkg' 'cmdliner' '-pkg' 'menhirLib' 'opam' 'pkg/META' 'pkg/META'
     'src/rejq.native']: exited with 10
make: *** [build] Error 1

this time I cannot easily pass in the -thread opt because the build process is somewhat tightly controlled by https://github.com/reasonml/ReasonNativeProject/blob/master/pkg/build.ml

@dyst5422
Copy link

dyst5422 commented Nov 2, 2017

The solution @Jimexist is looking for (and anyone else is looking for) is the -tag option for rebuild that passes tags to ocamlc. So the common one is -tag thread. For the makefile provided in the ReasonNativeProject, this looks like

.PHONY:	all clean byte native profile debug test

OCB_FLAGS = -use-ocamlfind -tag bin_annot -tag thread -pkg core
OCB = 		rebuild $(OCB_FLAGS)

all: byte # profile debug
...

@jaredly
Copy link
Contributor

jaredly commented Jun 14, 2018

This question will probably get more discussion in the reasonml forums -- https://reasonml.chat/

@jaredly jaredly closed this as completed Jun 14, 2018
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

8 participants