rescript-compiler icon indicating copy to clipboard operation
rescript-compiler copied to clipboard

Make BuckleScript a drop in replacement for `ocamlc`.

Open jordwalke opened this issue 7 years ago • 12 comments

I'm aware that bsc can be used for the most part exactly like ocamlc, but I am not clear if there are some differences. Could you please enumerate how bsc is not quite a drop in replacement for ocamlc, and what needs to be done to make it a drop in replacement?

Suppose we have our custom jenga rules that builds using ocamlc and produces libraries using -a for example. It would be awesome if you could simply change all of the references to ocamlc with bsc. What will it take to do this, and should it be a goal? It would tremendously help with the goal of being able to compile a library to either JavaScript or native.

jordwalke avatar Aug 13 '16 07:08 jordwalke

Apologies if this is covered somewhere, but I did check the docs.

jordwalke avatar Aug 13 '16 07:08 jordwalke

note bsc will be more like ocamlopt , cmj is like cmx. (OCaml bytecode compiler get real separate compilation, only interface needed, not any cross module optimization)

The missing part as you said, is the -a flag which does not make sense currently in Buckle(we have plan to add it, but needs more time for design #288), but since you are going to implement a build system in jengaboot, it should be not too hard to ignore such rule, no?

The other part is -bs-package-name $npm_package_name and -bs-package-output path/to/store/js/files.

Note that you can customize cmi, cmj output for support namespace like ocamlopt. The JS files are fixed (relative path to package.json) is due to JS files are really not relocatable, you can not install JS files after build (this only works for google module system but not commonjs).

bobzhang avatar Aug 13 '16 12:08 bobzhang

Bob, about relocating output files. With npm, it is very common to do npm link which creates symlinks so MyPackage might be compiled by many other things that depend on MyPackage, each of them having different compilation rules. Therefore it is important that our build system be able to support outputing the build artifacts to another directory somewhere (where we might mirror the node modules directory if needed).

jordwalke avatar Aug 15 '16 07:08 jordwalke

Also, it seems that the most compelling feature is being able to take any of the OCaml libraries and trivially turn them into bs libraries. If bs supported the exact compiler interface as ocamlopt, then it would be very easy to convert any existing library by simply changing one or two things in the Makefile.

jordwalke avatar Aug 15 '16 07:08 jordwalke

It is fine to do npm link, since, for JS files, the recorded path is relative to package.json. It also supports outputting the build artifact to different directory (for cm* files, it behaves exactly like ocamlopt, for js files, user can specify the output path by -bs-package-output)

To make it work with Makefile, probably user need do two things:

#.

OCAMLOPT=bsc -bs-package-name $npm_package_name -bs-package-output lib/js

#. replace cmx with cmj

We can provide a dummy option support for -a if that helps, what do you think

bobzhang avatar Aug 15 '16 13:08 bobzhang

myProject/
├── node_modules/
│   └── myDependency/
│       ├── package.json
│       └── myDependencySource.re
├── package.json
├── _build/
└── mySourceFile.re

That is a typical npm setup. We need to build everything into _build. Even the source files for node_modules/myDependency. There are many good reasons:

  1. You can delete _build and it removes all build artifacts for all packages.
  2. myDependency might be symlinked to another installation location, and we can't dump artifacts in there because it might be symlinked by many dependers, and they would all be stepping on eachother's artifacts.

If BuckleScript's CLI API matched ocamlc then the -o flag would be sufficient to output compilation artifacts for dependencies into _build.

Is -bs-package-output the same thing as -o? If so, why not just call it -o to make it even easier to get it to work with a build system.

I think a dummy -a would also be a good idea, but -a also remembers link flags and then the final linking stage will use them - which might actually be useful for BS one day too.

I think I'm just not seeing the benefits of deviating at all from the ocaml compiler flag API, but I'm sure you've thought of good reasons.

jordwalke avatar Aug 15 '16 23:08 jordwalke

The problem of -o is that its location depends on where you run the command, for JS output, we need fix its location(relative to package.json) no matter where user runs the command. bsc accept multiple -bs-package-output so user can spit out goog module, commonjs and amd all at the same time If user follows some convention, always generate js files in package.json/lib/js then it is pretty easy to adapt

bobzhang avatar Aug 16 '16 12:08 bobzhang

The problem of -o is that its location depends on where you run the command, for JS output, we need fix its location(relative to package.json) no matter where user runs the command.

You could put that burden on the person who supplies the -o flag. In our case, we might have a very different convention for where it goes anyways. We will make sure that people who depend on that output, will supply the right -I flag to pick it up correctly. That style of cli interface is a pain, and BS does much better, but the main value is that tons of existing build systems went through that pain, and it would be good to support them (maybe this is a good community task to pick up, if it's lower priority for you).

jordwalke avatar Sep 08 '16 08:09 jordwalke

You could put that burden on the person who supplies the -o flag.

That would be too restrictive to normal users.

I am a little worried that if the author of the package does not have interest or minimal commitment to support buckle, this would not be a sustainable effort, since there are a number of ways to break it, introducing c stubs without providing JS polyfills (via deps or using Str etc). And there are bunch of optimizations can be applied to vanilla OCaml libraries to make it faster in JS backend, if the author does not have interest in supporting JS backend, then we could not get optimal JS code generated.

The scala community does have some special build rules to make it work in scalajs, tweaking the build system with some extra flags is the minimal effort compared with other more subtle stuff, just my opinions.

Btw, if other people are interested in contributing, we can discuss how to make it work better

bobzhang avatar Sep 08 '16 13:09 bobzhang

My company is considering moving some of our existing OCaml code to run on Node.js to leverage existing JS libraries. Not being able to use opam deps is a major blocker for existing code with transitive requirements. We would be willing to lend some effort to make this easier.

Currently, it seems like a viable path for us might be to use JS-of-ocaml and Bucklescript in the same Node.js process, with some codegen to simplify talking between them.

gtrak avatar Nov 08 '17 22:11 gtrak

Yeah not being able to use PPX's easily via opam has stalled a lot of what I've been doing... ^.^;

OvermindDL1 avatar Nov 08 '17 23:11 OvermindDL1

Looks like this issue is no longer relevant?

yawaramin avatar Nov 06 '21 20:11 yawaramin

Yes, this does not seem relevant anymore, closing.

cknitt avatar May 27 '23 19:05 cknitt