Giter Site home page Giter Site logo

ocaml / dune Goto Github PK

View Code? Open in Web Editor NEW
1.6K 39.0 396.0 56.55 MB

A composable build system for OCaml.

Home Page: https://dune.build/

License: MIT License

OCaml 94.88% Makefile 0.13% JavaScript 0.01% C 0.95% Shell 0.27% Pascal 0.01% C++ 0.02% Emacs Lisp 0.58% Coq 0.11% Roff 0.03% Reason 0.01% NASL 0.01% Nix 0.16% Dockerfile 0.10% PowerShell 2.76%
build ocaml opam dune jbuilder

dune's Introduction

Dune

A Composable Build System for OCaml

Main Workflow Release Coverage License Contributors

Dune is a build system for OCaml. It provides a consistent experience and takes care of the low-level details of OCaml compilation. You need only to provide a description of your project, and Dune will do the rest.

Dune implements a scheme that's inspired from the one used inside Jane Street and adapted to the open source world. It has matured over a long time and is used daily by hundreds of developers, meaning it's highly tested and productive.

Dune comes with a manual. If you want to get started without reading too much, look at the quick start guide or watch this introduction video.

The example directory contains examples of projects using Dune.

How does it work?

Dune reads project metadata from dune files, which are static files with a simple S-expression syntax. It uses this information to setup build rules, generate configuration files for development tools such as Merlin, handle installation, etc.

Dune itself is fast, has very little overhead, and supports parallel builds on all platforms. It has no system dependencies. OCaml is all you need to build Dune and packages using Dune.

In particular, one can install OCaml on Windows with a binary installer and then use only the Windows Console to build Dune and packages using Dune.

Strengths

Composable

Dune is composable, meaning that multiple Dune projects can be arranged together, leading to a single build that Dune knows how to execute. This allows for monorepos of projects.

Dune makes simultaneous development on multiple packages a trivial task.

Gracefully Handles Multi-Package Repositories

Dune knows how to handle repositories containing several packages. When building via opam, it is able to correctly use libraries that were previously installed, even if they are already present in the source tree.

The magic invocation is:

$ dune build --only-packages <package-name> @install

Build Against Several Configurations at Once

Dune can build a given source code repository against several configurations simultaneously. This helps maintaining packages across several versions of OCaml, as you can test them all at once without hassle.

In particular, this makes it easy to handle cross-compilation. This feature requires opam.

Installation

Requirements

Dune requires OCaml version 4.08.0 to build itself and can build OCaml projects using OCaml 4.02.3 or greater.

Installation

We recommended installing Dune via the opam package manager:

$ opam install dune

If you are new to opam, make sure to run eval $(opam config env) to make dune available in your PATH. The dune binary is self-contained and relocatable, so you can safely copy it somewhere else to make it permanently available.

You can also build it manually with:

$ make release
$ make install

If you do not have make, you can do the following:

$ ocaml boot/bootstrap.ml
$ ./dune.exe build -p dune --profile dune-bootstrap
$ ./dune.exe install dune

The first command builds the dune.exe binary. The second builds the additional files installed by Dune, such as the man pages, and the last simply installs all of that on the system.

Please note: unless you ran the optional ./configure script, you can simply copy dune.exe anywhere and it will just work. dune is fully relocatable and discovers its environment at runtime rather than hard-coding it at compilation time.

Support

Issues Discussions Discuss OCaml Discord

If you have questions or issues about Dune, you can ask in our GitHub discussions page or open a ticket on GitHub.

dune's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dune's Issues

bugfix

diff --git a/src/future.ml b/src/future.ml
index 58174ca..9153c35 100644
--- a/src/future.ml
+++ b/src/future.ml
@@ -387,7 +387,7 @@ module Scheduler = struct
        | [s] -> Format.fprintf ppf "%s" s
        | (x :: _) as group ->
           Format.fprintf ppf "%s.{%a}"
-            (Filename.chop_extension x)
+            (Filename.remove_extension x)
             (Format.pp_print_list ~pp_sep:pp_comma pp_ext)
             group in
      let pp_contexts ppf = function

Error while trying to compile an executable.

[vb@parvati ~/code/bitsouk/bitmex]% make
jbuilder build src/poloniex_data.exe
Workspace root: /home/vb/code/bitsouk/bitmex
Running[0]: /home/vb/.opam/valet/bin/ocamlc.opt -config > /tmp/jbuildd1ddd3.output
Running[1]: /home/vb/.opam/valet/bin/ocamlfind printconf path > /tmp/jbuild71d06b.output
Running[2]: /usr/bin/opam config var lib > /tmp/jbuild3482ab.output
Actual targets:
- _build/default/src/poloniex_data.exe
Internal error, please report upstream.
Description: Path.Local.parent called on the root
Backtrace:
make: *** [Makefile:2: all] Error 1

Additional info:

[vb@parvati ~/code/bitsouk/bitmex]% cat src/jbuild
(executables
 ((names (bfx_data bfx bitmex_data bitmex poloniex_data poloniex))
  (preprocess (pps (ppx_sexp_conv)))
  (libraries (uuidm bs-api))
  ))
[vb@parvati ~/code/bitsouk/bitmex]% ls -l src
total 220
-rw-rw-r-- 1 vb users 15115  6 mars  16:06 bfx_data.ml
-rw-rw-r-- 1 vb users 42455  9 mars  18:01 bfx.ml
-rw-rw-r-- 1 vb users 15299  6 mars  16:06 bitmex_data.ml
-rw-rw-r-- 1 vb users 72521  9 mars  18:01 bitmex.ml
-rw-rw-r-- 1 vb users   151  9 mars  18:02 jbuild
-rw-rw-r-- 1 vb users  6212  6 mars  16:06 leak.ml
-rw-rw-r-- 1 vb users 14585  9 mars  11:03 poloniex_data.ml
-rw-rw-r-- 1 vb users 44775  9 mars  18:01 poloniex.ml

docs syntax

This section of the docs gives as an example:

(action "./${<} blah")

I think this is old syntax? I get an error using it, but either (bash ...) or (run ...) works fine.

Latest version of ppx_deriving not working with jbuilder

Hi,
I have pinned the latest version of https://github.com/whitequark/ppx_deriving which implements migrate_parsetree based ppx. However, using (preprocess (pps (ppx_deriving.std))) doesn't seem to apply any ppx_deriving based transformations. Is my usage not correct? If so could you please provide guidance of how we can use ppx_deriving with jbuilder.

I opened an issue is ppx_deriving but I got directed here instead.
ocaml-ppx/ppx_deriving#134 (comment)

other file extensions with preprocessor

I'm trying to build a project written in Reason with jbuilder.
Basically all my project files have a .re or .rei extension. .re/.rei are the equivalent of .ml/.mli. Compilation happens with a refmt as preprocessor, e.g. ocamlopt -pp "refmt --print binary" -impl hello_world.re -o hello_world.exe". I tried to build some rules for this, but didn't manage to get them working. I'm not entirely sure, after reading the manual, if this is possible. Is it possible?

Example: a project with hello.ml which depends on a function exposed by someReasonFile.re.

(executable
  ((name hello)))
 (rule
     ((targets (someReasonFile.re))
      (action  (system "refmt --print binary ${<}"))))   

I'm getting Unbounded Module SomeReasonFile. What's wrong with this rule?
Can I generalize this rule to all files with .re extensions?

If hello.ml would be written in Reason (needing a preprocessor step), how would the executable look like?

.mli only modules

When porting cohttp to jbuilder, I discovered that .mli only modules don't seem to work. Since ocamlbuild supports them, it would be great if jbuilder would as well.

jbuilder ppx preprocessing not working on simple exampe

I tried using jbuilder to build a simple hello-world app which makes use of ppx_sexp_conv, but couldn't get the ppx preprocessing to work.

hello_world.ml

    open Core.Std
    type t = Hey of int [@@deriving sexp_of]
    let () = printf "Hello, %s world!\n" (Sexp.to_string (sexp_of_t (Hey 99)))

jbuilder:

    (executables
     ((names (hello_world))
      (preprocess (pps (ppx_sexp_conv)))
      (libraries (core))))

command:

$ jbuilder build hello_world.exe --verbose

-> (full log below)

File "hello_world.ml", line 3, characters 54-63:
Error: Unbound value sexp_of_t
Hint: Did you mean sexp_of_int or sexp_of_mat?

Running the generated ppx.exe by hand

(cd _build/default && ../.ppx/default/ppx_sexp_conv/ppx.exe --impl hello_world.ml)

I can see that the [@@deriving sexp_of] is not expanded,

I tried various changes to the preprocess line, i.e adding ppx_driver.main, but this just results in:

$ (cd _build/default && ../.ppx/default/ppx_sexp_conv+ppx_driver.runner/ppx.exe --dump-ast -o hello_world.pp.ml --impl hello_world.ml)
../.ppx/default/ppx_sexp_conv+ppx_driver.runner/ppx.exe: unknown option '--dump-ast'.

Am I doing something wrong, or is this a bug?

Cheers,
Nick

# Workspace root: /home/nic/try-jbuild/hw
Running[0]: /home/nic/.opam/4.02.3/bin/ocamlfind printconf path > /tmp/jbuild2dbb9e.output
Running[1]: /home/nic/.opam/4.02.3/bin/ocamlc.opt -config > /tmp/jbuild2ddd2a.output
# Jbuilder context:
#  ((name default)
#   (kind default)
#   (merlin true)
#   (for_host ())
#   (build_dir _build/default)
#   (toplevel_path (/home/nic/.opam/4.02.3/lib/toplevel))
#   (ocaml_bin /home/nic/.opam/4.02.3/bin)
#   (ocaml /home/nic/.opam/4.02.3/bin/ocaml)
#   (ocamlc /home/nic/.opam/4.02.3/bin/ocamlc.opt)
#   (ocamlopt (/home/nic/.opam/4.02.3/bin/ocamlopt.opt))
#   (ocamldep /home/nic/.opam/4.02.3/bin/ocamldep.opt)
#   (ocamllex /home/nic/.opam/4.02.3/bin/ocamllex.opt)
#   (ocamlyacc /home/nic/.opam/4.02.3/bin/ocamlyacc)
#   (ocamlmklib /home/nic/.opam/4.02.3/bin/ocamlmklib)
#   (env ())
#   (findlib_path (/home/nic/.opam/4.02.3/lib))
#   (arch_sixtyfour true)
#   (natdynlink_supported true)
#   (opam_vars ())
#   (ocamlc_config
#    ((architecture amd64)
#     (asm as)
#     (asm_cfi_supported true)
#     (ast_impl_magic_number Caml1999M016)
#     (ast_intf_magic_number Caml1999N015)
#     (bytecomp_c_compiler
#      "gcc -O -fno-defer-pop -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -O -fPIC")
#     (bytecomp_c_libraries "-lm  -ldl -lcurses -lpthread")
#     (cc_profile -pg)
#     (ccomp_type cc)
#     (cma_magic_number Caml1999A011)
#     (cmi_magic_number Caml1999I017)
#     (cmo_magic_number Caml1999O010)
#     (cmt_magic_number Caml2012T004)
#     (cmx_magic_number Caml1999Y014)
#     (cmxa_magic_number Caml1999Z013)
#     (cmxs_magic_number Caml2007D002)
#     (default_executable_name a.out)
#     (exec_magic_number Caml1999X011)
#     (ext_asm .s)
#     (ext_dll .so)
#     (ext_lib .a)
#     (ext_obj .o)
#     (host x86_64-unknown-linux-gnu)
#     (model default)
#     (native_c_compiler "gcc -O -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT")
#     (native_c_libraries "-lm  -ldl")
#     (native_pack_linker "ld -r  -o ")
#     (os_type Unix)
#     (ranlib ranlib)
#     (standard_library /home/nic/.opam/4.02.3/lib/ocaml)
#     (standard_library_default /home/nic/.opam/4.02.3/lib/ocaml)
#     (standard_runtime /home/nic/.opam/4.02.3/bin/ocamlrun)
#     (system linux)
#     (systhread_supported true)
#     (target x86_64-unknown-linux-gnu)
#     (version 4.02.3)
#     (with_frame_pointers false)))
#   (which
#    ((ocamlc (/home/nic/.opam/4.02.3/bin/ocamlc.opt))
#     (ocamlfind (/home/nic/.opam/4.02.3/bin/ocamlfind)))))
# Actual targets:
# - _build/default/hello_world.exe
Running[2]: (cd _build/default && /home/nic/.opam/4.02.3/bin/ocamlopt.opt -o ../.ppx/default/ppx_sexp_conv/ppx.exe -I /home/nic/.opam/4.02.3/lib/ocaml-migrate-parsetree -I /home/nic/.opam/4.02.3/lib/ocaml-migrate-parsetree/driver-main -I /home/nic/.opam/4.02.3/lib/ocaml/compiler-libs -I /home/nic/.opam/4.02.3/lib/ppx_core -I /home/nic/.opam/4.02.3/lib/ppx_driver -I /home/nic/.opam/4.02.3/lib/ppx_optcomp -I /home/nic/.opam/4.02.3/lib/ppx_sexp_conv -I /home/nic/.opam/4.02.3/lib/ppx_type_conv -I /home/nic/.opam/4.02.3/lib/result ocamlcommon.cmxa ppx_core.cmxa ppx_optcomp.cmxa ppx_driver.cmxa ppx_sexp_conv_expander.cmxa ppx_type_conv.cmxa result.cmxa migrate_parsetree.cmxa ppx_sexp_conv.cmxa migrate_parsetree_driver_main.cmxa)
Running[3]: (cd _build/default && ../.ppx/default/ppx_sexp_conv/ppx.exe --dump-ast -o hello_world.pp.ml --impl hello_world.ml)
Running[4]: (cd _build/default && /home/nic/.opam/4.02.3/bin/ocamldep.opt -modules hello_world.pp.ml) > _build/default/hello_world.depends.ocamldep-output
Running[5]: (cd _build/default && /home/nic/.opam/4.02.3/bin/ocamlc.opt -w -40 -g -bin-annot -I /home/nic/.opam/4.02.3/lib/bin_prot -I /home/nic/.opam/4.02.3/lib/core -I /home/nic/.opam/4.02.3/lib/core_kernel -I /home/nic/.opam/4.02.3/lib/fieldslib -I /home/nic/.opam/4.02.3/lib/num -I /home/nic/.opam/4.02.3/lib/ocaml -I /home/nic/.opam/4.02.3/lib/ocaml/threads -I /home/nic/.opam/4.02.3/lib/ppx_assert -I /home/nic/.opam/4.02.3/lib/ppx_bench -I /home/nic/.opam/4.02.3/lib/ppx_expect -I /home/nic/.opam/4.02.3/lib/ppx_inline_test -I /home/nic/.opam/4.02.3/lib/result -I /home/nic/.opam/4.02.3/lib/sexplib -I /home/nic/.opam/4.02.3/lib/typerep -I /home/nic/.opam/4.02.3/lib/variantslib -no-alias-deps -I . -o hello_world.cmo -c -impl hello_world.pp.ml)

Command [5] exited with code 2:
$ (cd _build/default && /home/nic/.opam/4.02.3/bin/ocamlc.opt -w -40 -g -bin-annot -I /home/nic/.opam/4.02.3/lib/bin_prot -I /home/nic/.opam/4.02.3/lib/core -I /home/nic/.opam/4.02.3/lib/core_kernel -I /home/nic/.opam/4.02.3/lib/fieldslib -I /home/nic/.opam/4.02.3/lib/num -I /home/nic/.opam/4.02.3/lib/ocaml -I /home/nic/.opam/4.02.3/lib/ocaml/threads -I /home/nic/.opam/4.02.3/lib/ppx_assert -I /home/nic/.opam/4.02.3/lib/ppx_bench -I /home/nic/.opam/4.02.3/lib/ppx_expect -I /home/nic/.opam/4.02.3/lib/ppx_inline_test -I /home/nic/.opam/4.02.3/lib/result -I /home/nic/.opam/4.02.3/lib/sexplib -I /home/nic/.opam/4.02.3/lib/typerep -I /home/nic/.opam/4.02.3/lib/variantslib -no-alias-deps -I . -o hello_world.cmo -c -impl hello_world.pp.ml)
File "hello_world.ml", line 3, characters 54-63:
Error: Unbound value sexp_of_t
Hint: Did you mean sexp_of_int or sexp_of_mat?

Include subdirectories

I'm trying to convert to jbuilder an existing project that contains its sources spread in different sub-directories (~140 ml files). It seems that jbuilder looks only to sub-directories in order to find sub-libraries or just file to copy. Is it the case?

I'm trying to add a stanza (includes (sub_dirs (dirs)) that would tell to also look at these directories for .h, .ml, .mli, as if they where in the jbuild directory. It is not in the roadmap, but is it ok?

It seems to require to change quite a lot of types, such as in Module the ml_fname and mli_fname fields from string to Path.t.

clean subcommand

A command to delete _build and all targets by jbuilder would be nice to have

How to support bisect_ppx?

bisect_ppx is an odd ppx rewriter because you only want it active when you're measuring coverage. Usually when you're running your test suite. Dually, the tests only require the bisect ppx runtime when measuring the coverage. Ideally, this is something jbuilder would support on a global basis with minimum hassle. @diml any advice on might jbuilder accommodate bisect_ppx?

per_file support for flags

I would like to change the flags on a specific file (e.g. a generated file where I want to disable some warnings). Is this currently possible? If not, I think using something like this could be useful:

(flags (per_file (<flag> (module-list)))

jbuilder adding findlib path of local library

See my attempt at porting cohttp to jbuilder: mirage/ocaml-cohttp#533

The relevant jbuild files:

lwt/jbuild

(jbuild_version 1)

(library
 ((name cohttp_lwt_unix)
  (public_name cohttp-lwt-unix)
  (wrapped false)
  (libraries (conduit.lwt-unix magic-mime lwt.unix cohttp cohttp-lwt))))

lwt-core/jbuild

(jbuild_version 1)

(library
 ((name cohttp_lwt)
  (public_name cohttp-lwt)
  (preprocess (pps (ppx_sexp_conv)))
  (wrapped false)
  (libraries (lwt uri cohttp))))

And yet jbuilder is adding <switch>/lib/cohttp to the include path

Running[2]: (cd _build/default && /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/bin/ocamlopt.opt -w -40 -g -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/base -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/base/caml -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/base/shadow_stdlib -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/base64 -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/bytes -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/cohttp -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/fieldslib -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/lwt -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/ocaml -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/re -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/result -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/sexplib -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/sexplib/0 -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/stringext -I /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/lib/uri -no-alias-deps -I lwt-core -o lwt-core/cohttp_lwt.cmx -c -impl lwt-core/cohttp_lwt.pp.ml)
Running[3]: (cd _build/default && /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/bin/ocamlc.opt -w -40 -g -a -o lwt-core/cohttp_lwt.cma lwt-core/cohttp_lwt_body.cmo lwt-core/cohttp_lwt_s.cmo lwt-core/cohttp_lwt.cmo lwt-core/string_io_lwt.cmo)

Command [3] exited with code 2:
$ (cd _build/default && /home/rgrinberg/.opam/ocaml-base-compiler.4.04.0/bin/ocamlc.opt -w -40 -g -a -o lwt-core/cohttp_lwt.cma lwt-core/cohttp_lwt_body.cmo lwt-core/cohttp_lwt_s.cmo lwt-core/cohttp_lwt.cmo lwt-core/string_io_lwt.cmo)
File "_none_", line 1:
Error: Files lwt-core/cohttp_lwt.cmo and lwt-core/cohttp_lwt_s.cmo
       make inconsistent assumptions over interface Cohttp_lwt_s

Incorrect hint

# Error: Findlib package "irmin-mem" not found.
# -> required by "test/irmin-mem/jbuild (context default)"
# Hint: try: jbuilder external-lib-deps --missing -p irmin-mirage -j 4

But then:

$ jbuilder external-lib-deps --missing -p irmin-mirage
jbuilder: required argument TARGET is missing
Usage: jbuilder external-lib-deps [OPTION]... TARGET...
Try `jbuilder external-lib-deps --help' or `jbuilder --help' for more information.

support for watermarking source files

Topkg has the great feature to be able to watermark source files depending on the context: see http://erratique.ch/software/topkg/doc/Topkg.Pkg.html#VALwatermarks

VERSION has a special treatment: for releases, it is exactly the package version. When compiled in --dev mode (or the equivalent) it uses git describe. So if you get a binary built in dev mode, it's easy to set the output of <binary> --version to the right thing, just use let version = "%%VERSION%%" in your program.

no rule found for .merlin-exists

When I follow the instructions for building hello world in the quick start guide, I get

$ jbuilder build hello_world.exe
Workspace root: /home/nathan/pill/src/hello-world
Running[0]: /home/nathan/.opam/4.04.0/bin/ocamlc.opt -config > /tmp/jbuildcad7cf.output
Running[1]: /home/nathan/.opam/4.04.0/bin/ocamlfind printconf path > /tmp/jbuild71440f.output
Running[2]: /usr/local/bin/opam config var lib > /tmp/jbuildc7d285.output
Actual targets:
- _build/default/hello_world.exe
No rule found for _build/default/.merlin-exists

Use with opam-cross-windows

Is it possible to use jbuilder with https://github.com/whitequark/opam-cross-windows? I tried a hackish approach of putting the $SWITCH/windows-sysroot/bin at the front of my $PATH but that gives me an error stating that ocamlyacc isn't available at the same path.

I see that jbuilder is expecting all ocaml* executables to live in the same directort. I don't see a simple way to work around this. Any suggestions?

Thank you!

Jbuilder doesn't support 2 executables sharing a module

E.g. something like:

(executables
 ((modules (x1 helper))
  (names (x1))))

(executables
 ((modules (x2 helper))
  (names (x2))))

It will complain that helper has multiple rules defined for it. This isn't a big deal because you can always just make helper a library but it would be good to either document if this is intended or lift this small limitation.

compiling exe fails with "No rule found for _build/default/.merlin-exists"

[ben@euler .../toys/hello-jbuild/qs1]$ ls
hello_world.ml  jbuild

[ben@euler .../toys/hello-jbuild/qs1]$ cat hello_world.ml
print_endline "Hello, world!"

[ben@euler .../toys/hello-jbuild/qs1]$ cat jbuild
(executables (
  (names (hello_world))
  (libraries ())
))

[ben@euler .../toys/hello-jbuild/qs1]$ jbuilder build hello_world.exe
Workspace root: /home/ben/code/ocaml/toys/hello-jbuild/qs1
Running[0]: /usr/bin/ocamlc.opt -config > /tmp/jbuild1c997e.output
Running[1]: /usr/local/bin/opam config var lib > /tmp/jbuilde571d9.output
Actual targets:
- _build/default/hello_world.exe
No rule found for _build/default/.merlin-exists

[ben@euler .../toys/hello-jbuild/qs1]$ cat _build/log 
# jbuilder build hello_world.exe
$ /usr/bin/ocamlc.opt -config > /tmp/jbuild1c997e.output
$ /usr/local/bin/opam config var lib > /tmp/jbuilde571d9.output
# Jbuilder context:
#  ((name default)
#   (kind default)
#   (merlin true)
#   (for_host ())
#   (build_dir _build/default)
#   (toplevel_path (/home/ben/.opam/system/lib/toplevel))
#   (ocaml_bin /usr/bin)
#   (ocaml /usr/bin/ocaml)
#   (ocamlc /usr/bin/ocamlc.opt)
#   (ocamlopt (/usr/bin/ocamlopt.opt))
#   (ocamldep /usr/bin/ocamldep.opt)
#   (ocamllex /usr/bin/ocamllex.opt)
#   (ocamlyacc /usr/bin/ocamlyacc)
#   (ocamlmklib /usr/bin/ocamlmklib.opt)
#   (env ())
#   (findlib_path (/home/ben/.opam/system/lib))
#   (arch_sixtyfour false)
#   (natdynlink_supported true)
#   (opam_vars ((lib /home/ben/.opam/system/lib)))
#   (ocamlc_config
#    ((architecture i386)
#     (asm as)
#     (asm_cfi_supported true)
#     (ast_impl_magic_number Caml1999M020)
#     (ast_intf_magic_number Caml1999N018)
#     (bytecomp_c_compiler
#      "gcc -std=gnu99 -O2 -fno-strict-aliasing -fwrapv -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -fPIC")
#     (bytecomp_c_libraries "-lm  -ldl -lcurses -lpthread                  ")
#     (cc_profile -pg)
#     (ccomp_type cc)
#     (cma_magic_number Caml1999A012)
#     (cmi_magic_number Caml1999I021)
#     (cmo_magic_number Caml1999O011)
#     (cmt_magic_number Caml2012T008)
#     (cmx_magic_number Caml1999Y015)
#     (cmxa_magic_number Caml1999Z014)
#     (cmxs_magic_number Caml2007D002)
#     (default_executable_name a.out)
#     (exec_magic_number Caml1999X011)
#     (ext_asm .s)
#     (ext_dll .so)
#     (ext_lib .a)
#     (ext_obj .o)
#     (flambda false)
#     (host i686-pc-linux-gnu)
#     (model default)
#     (native_c_compiler
#      "gcc -std=gnu99 -O2 -fno-strict-aliasing -fwrapv -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT")
#     (native_c_libraries "-lm  -ldl")
#     (native_pack_linker "ld -r  -o ")
#     (os_type Unix)
#     (ranlib ranlib)
#     (safe_string false)
#     (spacetime false)
#     (standard_library /usr/lib/ocaml)
#     (standard_library_default /usr/lib/ocaml)
#     (standard_runtime /usr/bin/ocamlrun)
#     (system linux_elf)
#     (systhread_supported true)
#     (target i686-pc-linux-gnu)
#     (version 4.04.0)
#     (with_frame_pointers false)))
#   (which ((ocamlc (/usr/bin/ocamlc.opt)) (ocamlfind ()))))

Using jbuilder installed from an opam pin at revision 3e9b52a

How to use sedlex?

Hi,
I am trying to build a project that uses sedlex for lexing tokens. I have (preprocess (pps (sedlex))) in my jbuild file. However, I keep getting uninterpreted extension %sedlex.regexp?. Am I specifying the sedlex ppx incorrectly?

Error: no packages are defined here

I was trying to come up with some very little project that shows, hopefully, how to use jbuilder, because at least for me it's a bit mystical; that project is here: https://github.com/alinpopa/jbuilder_example01

Trying to build it using the bellow command, and I'm getting the following error, which doesn't really make too much sense to me:

jbuilder build --debug-actions --debug-dependency-path --debug-rules --debug-findlib @install

Workspace root: /Users/alin/work/ocaml/jbuilder_example01
File "bin/jbuild", line 1, characters 0-0:
Error: no packages are defined here

I believe that I'm trying to find out what's the magical incantation to build a proper project, with some minimalistic structure, only very few modules, etc. I'd think that having an example project, more than a very simple one liner hello world, would help a bit with starting working with jbuilder (at least this would help me, but I wasn't able to find a proper simple project, without using a mix of opam/make/merlin files, which confuses me a lot).
Sorry, I'd have raise this as a question on some mailinglist/slack channel/something, but turns out that there is no such communication channel? For example, a JaneStreet OCaml mailing list, or anything... is this mailing list something I could use for such a topic? https://groups.google.com/forum/#!forum/ocaml-core

Thanks.

Customize --dev options

I would like to be able to customize the options added by --dev (I personally dislike 6 and 9 in some code bases).

I think it would also be nice to have -keep-locs and -short-paths there too.

Build fails with "Path.Local.parent called on the root"

After I got the most basic hello world program running from the quick start guide, I then tried to build a program that depends on Core. It failed with the error message mentioned in the issue title.

More concretely, this bash snippet

set -x
cat hello_world.ml
cat jbuild
cat jbuild-workspace
jbuilder build hello_world.exe || echo FAILED
cat _build/log

yields

+ cat hello_world.ml
open Core.Std

let command =
  let open Command.Let_syntax in
  Command.basic' ~summary:"say hello to the world"
    [%map_open
     let () = return ()
     in
     fun () ->
       print_endline "Hello, world!"
    ]
+ cat jbuild
;; -*- mode: lisp -*-

(jbuild_version 1)

(executables
 ((names (hello_world))
  (libraries (core))))
+ cat jbuild-workspace
;; -*- mode: lisp -*-
(context (
 (switch system)
 (merlin false)
))
+ jbuilder build hello_world.exe
Workspace root: /home/nathan/pill/src/hello-world
Running[0]: /usr/local/bin/opam config var root > /tmp/jbuild1cabf7.output
Running[1]: /usr/local/bin/opam config env --root /home/nathan/.opam --switch system --sexp > /tmp/jbuildb8308b.output
Running[2]: /usr/bin/ocamlc -config > /tmp/jbuild733b0a.output
Running[3]: /usr/bin/ocamlfind printconf path > /tmp/jbuildaf51b3.output
Running[4]: /usr/local/bin/opam config var lib > /tmp/jbuild796e42.output
Actual targets:
- _build/system/hello_world.exe
Internal error, please report upstream including the contents of _build/log.
Description: Path.Local.parent called on the root
Backtrace:
Raised at file "src/import.ml", line 20, characters 43-65
Called from file "src/lib_db.ml", line 19, characters 43-60
Called from file "src/lib_db.ml", line 19, characters 16-60
Called from file "src/lib_db.ml", line 19, characters 16-60
Called from file "src/lib_db.ml" (inlined), line 24, characters 14-45
Called from file "src/lib_db.ml", line 28, characters 8-42
Called from file "src/lib_db.ml", line 123, characters 43-68
Called from file "src/build_system.ml", line 201, characters 8-16
Called from file "src/build_system.ml", line 214, characters 16-24
Called from file "src/build_system.ml", line 201, characters 8-16
Called from file "src/build_system.ml", line 201, characters 8-16
Called from file "src/build_system.ml", line 231, characters 17-38
Called from file "src/build_system.ml", line 314, characters 27-53
Called from file "src/future.ml", line 93, characters 8-12
+ echo FAILED
FAILED
+ cat _build/log
# jbuilder build hello_world.exe
$ /usr/local/bin/opam config var root > /tmp/jbuild1cabf7.output
$ /usr/local/bin/opam config env --root /home/nathan/.opam --switch system --sexp > /tmp/jbuildb8308b.output
$ /usr/bin/ocamlfind printconf path > /tmp/jbuildaf51b3.output
$ /usr/local/bin/opam config var lib > /tmp/jbuild796e42.output
$ /usr/bin/ocamlc -config > /tmp/jbuild733b0a.output
# Jbuilder context:
#  ((name system)
#   (kind ((root /home/nathan/.opam) (switch system)))
#   (merlin false)
#   (for_host ())
#   (build_dir _build/system)
#   (toplevel_path (/home/nathan/.opam/system/lib/toplevel))
#   (ocaml_bin /usr/bin)
#   (ocaml /usr/bin/ocaml)
#   (ocamlc /usr/bin/ocamlc)
#   (ocamlopt (/usr/bin/ocamlopt))
#   (ocamldep /usr/bin/ocamldep)
#   (ocamllex /usr/bin/ocamllex)
#   (ocamlyacc /usr/bin/ocamlyacc)
#   (ocamlmklib /usr/bin/ocamlmklib)
#   (env
#    ((CAML_LD_LIBRARY_PATH
#      /home/nathan/.opam/system/lib/stublibs:/usr/lib/ocaml/stublibs)
#     (MANPATH :/home/nathan/.opam/system/man)
#     (OCAML_TOPLEVEL_PATH /home/nathan/.opam/system/lib/toplevel)
#     (OPAMSWITCH system)
#     (PATH
#      /home/nathan/.opam/system/bin:/home/nathan/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin)
#     (PERL5LIB /home/nathan/.opam/system/lib/perl5)))
#   (findlib_path
#    (/usr/lib/ocaml/METAS
#     /usr/lib/ocaml
#     /usr/local/lib/ocaml/4.02.3
#     /home/nathan/.opam/system/lib))
#   (arch_sixtyfour true)
#   (natdynlink_supported true)
#   (opam_vars ((lib /home/nathan/.opam/system/lib) (root /home/nathan/.opam)))
#   (ocamlc_config
#    ((architecture amd64)
#     (asm as)
#     (asm_cfi_supported true)
#     (ast_impl_magic_number Caml1999M016)
#     (ast_intf_magic_number Caml1999N015)
#     (bytecomp_c_compiler
#      "gcc -O  -D_FILE_OFFSET_BITS=64 -D_REENTRANT -O -fPIC")
#     (bytecomp_c_libraries "-lm  -ldl -lcurses -lpthread")
#     (cc_profile -pg)
#     (ccomp_type cc)
#     (cma_magic_number Caml1999A011)
#     (cmi_magic_number Caml1999I017)
#     (cmo_magic_number Caml1999O010)
#     (cmt_magic_number Caml2012T004)
#     (cmx_magic_number Caml1999Y014)
#     (cmxa_magic_number Caml1999Z013)
#     (cmxs_magic_number Caml2007D002)
#     (default_executable_name a.out)
#     (exec_magic_number Caml1999X011)
#     (ext_asm .s)
#     (ext_dll .so)
#     (ext_lib .a)
#     (ext_obj .o)
#     (host x86_64-pc-linux-gnu)
#     (model default)
#     (native_c_compiler "gcc -O  -D_FILE_OFFSET_BITS=64 -D_REENTRANT")
#     (native_c_libraries "-lm  -ldl")
#     (native_pack_linker "ld -r --hash-style=both --as-needed --build-id -o ")
#     (os_type Unix)
#     (ranlib ranlib)
#     (standard_library /usr/lib/ocaml)
#     (standard_library_default /usr/lib/ocaml)
#     (standard_runtime /usr/bin/ocamlrun)
#     (system linux)
#     (systhread_supported true)
#     (target x86_64-pc-linux-gnu)
#     (version 4.02.3)
#     (with_frame_pointers false)))
#   (which ((ocamlc (/usr/bin/ocamlc)) (ocamlfind (/usr/bin/ocamlfind)))))

How to add support for capnp code generation?

I wanted to tell jbuilder how to build OCaml files from capnp schema files. I tried:

 ((targets (%.ml %.mli))
  (deps (%.capnp))
  (action (run capnpc -o ocaml ${<}))))

But it seems that doesn't work. It would be good to say something about this in the manual (even if it's that it isn't possible).

Project broken with jbuilder HEAD

[vb@haramis ~/code/bitsouk/bs_devkit]% make
jbuilder build @install
Workspace root: /home/vb/code/bitsouk/bs_devkit
Running[0]: /home/vb/.opam/4.04.0/bin/ocamlfind printconf path > /tmp/jbuild592f1a.output
Running[1]: /home/vb/.opam/4.04.0/bin/ocamlc.opt -config > /tmp/jbuild78d33e.output
Actual targets:
- alias install
Running[2]: (cd _build/default && ../.ppx/default/ppx_bin_prot+ppx_sexp_conv/ppx.exe -dirname src --dump-ast -o src/bs_devkit.pp.ml --impl src/bs_devkit.ml)

Command [2] exited with code 2:
$ (cd _build/default && ../.ppx/default/ppx_bin_prot+ppx_sexp_conv/ppx.exe -dirname src --dump-ast -o src/bs_devkit.pp.ml --impl src/bs_devkit.ml)
../.ppx/default/ppx_bin_prot+ppx_sexp_conv/ppx.exe: unknown option '-dirname'.
ppx.exe [options] [<files>]
  --as-ppx                    Act as a -ppx rewriter
  --dump-ast                  Output a binary AST instead of source code
  -o FILE                     Output to this file instead of the standard output
  --intf FILE                 Treat FILE as a .mli file
  --impl FILE                 Treat FILE as a .ml file
  --cookie NAME=EXPR          Set the cookie NAME to EXPR
  -loc-filename <string>      File name to use in locations
  -reserve-namespace <string> Mark the given namespace as reserved
  -no-check                   Disable checks (unsafe)
  -apply <names>              Apply these transformations in order (comma-separated list)
  -dont-apply <names>         Exclude these transformations
  -no-merge                   Do not merge context free transformations (better for debugging rewriters)
  -help                       Display this list of options
  --help                      Display this list of options
make: *** [Makefile:2: all] Error 1

I'm getting this. It seems the compiled ppx executable is called with an option it does not support. Maybe you will understand something from this log…

How to use normal ppx rewriters?

I see the following passage in the manual:

You are however free to use ppx rewriters that are not based on ppx_driver in
this list, since ppx_driver is able to import rewriters that where not
designed for ppx_driver.

But I'm not sure how to enable things like js_of_ocaml.ppx for example. As the only preprocessors that seem to work are jane street's.

Would be nice to update the quickstart manual with an example for this as well by the way. Some non jane street preprocessors are quite common.

Feature request: `public_name` for executables

I'm really liking jbuilder - it's reduced the number of moving parts in a build quite significantly. One of the few things that still irks me is that there's a bit too much boilerplate to define an executable.

I'd like to be able to write (by analogy with the library stanza):

(executables
 ((name foo)
  (public_name bar)))

and have it work the same as what I currently write:

(executables
 ((names (foo))))
(install
 ((section bin)
  (files ((foo.exe as bar)))))

(It's also unclear to me why jbuilder uses single for library but plural for executables, and why a library has one name but an executable has several names. Is this a historical accident or a use-case I haven't run into yet?)

jbuild plugins

It is currently impossible for users to extend the jbuild syntax. The ml syntax offers an escape hatch but you have to switch the whole file. One possible way to allow this would be:

(plugin:foo <arg>)

where foo would be a command that would take the S-expression <arg> on stdin and output some jbuild syntax on stdout, which would be more or less inlined in the file. Possibly it could use a different version of the spec.

For that to work well with the jenga integration, the command would have to output what files it reads and globs it evaluates.

double quote in .merlin is not right

this line in .merlin:
FLG -ppx "_build/.ppx/4.04.0/ppx_type_conv+ppx_fields_conv/ppx.exe --as-ppx"

cause error when open .ml file.

"main.ml" 48L, 1028Csh: 1: Syntax error: Unterminated quoted string

(merlin) backtrace:
(merlin) project flags: unknown flag: --as-ppx"
Error detected while processing function merlin#Register..merlin#LoadProject:
line    2:
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/hwu/.opam/4.04.0/share/merlin/vim/autoload/merlin.py", line 740, in setup_merlin
    failures = command("project","get")
  File "/home/hwu/.opam/4.04.0/share/merlin/vim/autoload/merlin.py", line 201, in command
    return merlin_process().command(context(cmd))
  File "/home/hwu/.opam/4.04.0/share/merlin/vim/autoload/merlin.py", line 168, in command
    raise Error(value)
merlin.Error: {u'message': u'Error while running external preprocessor\nCommand line: "_build/.ppx/4.04.0/ppx_type_conv+ppx_fields_conv/ppx.exe \
'/tmp/camlppx8a78b1\' \'/tmp/camlppx16180d\' 1>/dev/null 2>/dev/null', u'valid': True, u'type': u'type', u'sub': []}

change double quote to single quote, the problem disappear.

FLG -ppx '_build/.ppx/4.04.0/ppx_type_conv+ppx_fields_conv/ppx.exe --as-ppx'

Rename _build to something else

_build is the same name that ocamlbuild uses for running builds. Since a lot of the potential users of jbuilder might be migrating from ocamlbuild, avoiding this possible conflict might be helpful.

Also, it's not unthinkable that some people might want to use jbuilder and ocamlbuild in the same project. Might as well make it as easy as possible for them.

Backtrace when dependencies are duplicated

If you write something like:

(library
  ...
  (libraries (foo foo)))

Then you get:

Error: exception Invalid_argument("Map.of_alist_exn")
Backtrace:
Raised at file "pervasives.ml", line 33, characters 20-45
Called from file "src/build.ml", line 61, characters 5-351
Called from file "src/gen_rules.ml", line 210, characters 9-59
Called from file "src/gen_rules.ml", line 827, characters 9-50
Called from file "src/gen_rules.ml", line 839, characters 6-77
Called from file "src/gen_rules.ml", line 1314, characters 6-171
Called from file "src/gen_rules.ml", line 1663, characters 13-117
Called from file "src/import.ml", line 43, characters 12-15
Called from file "src/gen_rules.ml", line 1659, characters 4-380
Called from file "list.ml", line 77, characters 12-15
Called from file "src/gen_rules.ml", line 1670, characters 11-39
Called from file "src/gen_rules.ml", line 1989, characters 6-110
Called from file "src/future.ml", line 88, characters 40-45
Called from file "list.ml", line 59, characters 20-23
Called from file "src/gen_rules.ml", line 1973, characters 2-732
Called from file "src/main.ml", line 48, characters 2-100
Called from file "src/future.ml", line 83, characters 65-70
Called from file "src/future.ml", line 37, characters 9-12
Re-raised at file "src/future.ml", line 17, characters 36-47
Called from file "src/future.ml", line 40, characters 9-23
Called from file "src/import.ml", line 385, characters 8-11
Re-raised at file "src/import.ml", line 387, characters 30-37
Called from file "src/future.ml", line 37, characters 9-12
Re-raised at file "src/future.ml", line 17, characters 36-47
Called from file "src/future.ml", line 40, characters 9-23
Called from file "src/import.ml", line 385, characters 8-11
Re-raised at file "src/import.ml", line 387, characters 30-37
Called from file "src/future.ml", line 37, characters 9-12
Re-raised at file "src/future.ml", line 17, characters 36-47
Called from file "src/future.ml", line 40, characters 9-23
Called from file "src/import.ml", line 385, characters 8-11
Re-raised at file "src/import.ml", line 387, characters 30-37
Called from file "src/future.ml", line 37, characters 9-12
Re-raised at file "src/future.ml", line 17, characters 36-47
Called from file "src/future.ml", line 40, characters 9-23
Called from file "src/import.ml", line 385, characters 8-11
Re-raised at file "src/import.ml", line 387, characters 30-37
Called from file "src/future.ml", line 37, characters 9-12
Re-raised at file "src/future.ml", line 17, characters 36-47
Called from file "src/future.ml", line 40, characters 9-23
Called from file "src/import.ml", line 385, characters 8-11
Re-raised at file "src/import.ml", line 387, characters 30-37
Called from file "src/future.ml", line 618, characters 8-31
Called from file "vendor/cmdliner/src/cmdliner_term.ml", line 27, characters 19-24
Called from file "vendor/cmdliner/src/cmdliner.ml", line 113, characters 32-39
Called from file "vendor/cmdliner/src/cmdliner.ml", line 143, characters 18-36
Called from file "vendor/cmdliner/src/cmdliner.ml", line 258, characters 22-48
Called from file "bin/main.ml", line 648, characters 10-51

Which is probably not the best user-facing error ever.

Run tests command

I understand this isn't implemented yet, but it's a pre-requisite for me to actually use jbuilder in a couple of open source projects. What's the ETA on having this?

If this isn't a priority, then perhaps I can help on this?

Support for inline tests/benchmarks

Some thoughts on how to add automatic support for inline tests/benchmarks in jbuilder.

Currently Jane Street jenga rules support linking inline test and/or benchmark runners as soon as ones uses ppx_inline_test and/or ppx_bench. Additionally they automatically run the tests in parallel as part of the runtest alias.

This is a really useful feature for development and it would be great to add this to jbuilder. The rules are not very complicated to setup, however I'd like to support this without hardcoding the knowledge of the various libraries and their layout (ppx_bench, ppx_inline_tests, ppx_expect, ...) inside jbuilder. This is for two reason:

  • to avoid having to update jbuilder whenever the details of these subsystems change. They don't change very often but do change from now and then
  • to allow other people to reuse the same mechanism for their own test/benchmark systems

Proposal

The runners

For any given library Jbuilder systematically setups rules for building <lib>-test-runner.exe and <lib>-bench-runner.exe executables. These executables link all of library <lib> and are used for running tests and benchmarks respectively.

Additional runner libraries

The various runners require additional libraries, essentially to report the results at the end. We need two things: a way to specify these additional libraries and a way to specify the code to run at the end of the runner. Currently the jenga rules hardcode this information and know what .cmx/.cmo to link last fo each runner.

Specifying additional libraries

We can simply add them in the jbuild of the ppx:

(library
 ((name ppx_inline_test)
  ...
  (ppx_runner_library (test ppx_inline_test.runner))))

and Jbuilder will know to link ppx_inline_test.runner in the test runner of any libraries using this ppx.

Specifying the reporter

To make things simple, we provide a small libmain library allowing one to set the entry point:

(** Set the main entry point of the program *)
val set_main : (unit -> unit) -> unit

(** Execute the registered entry point. Never returns *)
val run_main : unit -> _

(** Are we linked as part of a library test/benchmark runner or a normal executable? *)
val is_library_runner : unit -> bool

and jbuilder will add a module that calls run_main as the last .cmx/.cmo on the command line to link the runner.

running tests in parallel

We formalise the convention of ppx_inline_test for running tests in parallel: foo-runner.exe --list-partitions returns a list of partitions and ... --partition blah selects tests from partition blah.

Runtime test dependencies

Sometime inline tests require extra dependencies when running. For instance when they read a file. The jenga rules support this by looking for an (inline_tests ...) field in (library ...) stanzas:

(library
 ((name foo)
  ...
  (inline_tests ((deps (blah))))))

We can do the same in jbuilder.

helper scripts

The jenga rules generate helper shell scripts allowing one to run the tests/benchmarks manually. Instead, ppx_inline_test can provide an executable to call the generated runner appropriately. Alternatively we could extend jbuilder exec so that one can do:

$ jbuilder exec ./foo-test-runner.exe ...

Invalid META files cause jbuilder to crash

If a sub-package of an installed META file jbuilder looks at contain a dependency to a library that is not installed, jbuilder crashes immediately. It should crash only if we try to use this sub-package

ppx_jane+ppx_driver.runner error: unknown option '-embed-errors'

I'm using jbuilder 1.0+beta3.
I'm trying to use ppx_jane, because I'm using [@@deriving sexp] for one of my type, but I can't really make jbuilder work with it.
jbuild file:

(jbuild_version 1)

(executables
 ((names (myparsing))
  (libraries (core))
  (preprocess (pps (ppx_jane ppx_driver.runner)))
))

jbuilder log:

# jbuilder build myparsing.exe
$ /home/stryker/.opam/system/bin/ocamlfind printconf path > /tmp/jbuild743bf3.output
$ /usr/bin/ocamlc.opt -config > /tmp/jbuild78e625.output
> Warning: discarding value of variable "color" in OCAMLPARAM
$ /usr/bin/opam config var lib > /tmp/jbuildbed18f.output
# Jbuilder context:
#  ((name default)
#   (kind default)
#   (merlin true)
#   (for_host ())
#   (build_dir _build/default)
#   (toplevel_path (/home/stryker/.opam/system/lib/toplevel))
#   (ocaml_bin /usr/bin)
#   (ocaml /usr/bin/ocaml)
#   (ocamlc /usr/bin/ocamlc.opt)
#   (ocamlopt (/usr/bin/ocamlopt.opt))
#   (ocamldep /usr/bin/ocamldep.opt)
#   (ocamllex /usr/bin/ocamllex.opt)
#   (ocamlyacc /usr/bin/ocamlyacc)
#   (ocamlmklib /usr/bin/ocamlmklib)
#   (env ())
#   (findlib_path (/home/stryker/.opam/system/lib))
#   (arch_sixtyfour true)
#   (natdynlink_supported true)
#   (opam_vars ((lib /home/stryker/.opam/system/lib)))
#   (ocamlc_config
#    ((architecture amd64)
#     (asm as)
#     (asm_cfi_supported true)
#     (ast_impl_magic_number Caml1999M016)
#     (ast_intf_magic_number Caml1999N015)
#     (bytecomp_c_compiler
#      "gcc -O  -D_FILE_OFFSET_BITS=64 -D_REENTRANT -O -fPIC")
#     (bytecomp_c_libraries "-lm  -ldl -lcurses -lpthread")
#     (cc_profile -pg)
#     (ccomp_type cc)
#     (cma_magic_number Caml1999A011)
#     (cmi_magic_number Caml1999I017)
#     (cmo_magic_number Caml1999O010)
#     (cmt_magic_number Caml2012T004)
#     (cmx_magic_number Caml1999Y014)
#     (cmxa_magic_number Caml1999Z013)
#     (cmxs_magic_number Caml2007D002)
#     (default_executable_name a.out)
#     (exec_magic_number Caml1999X011)
#     (ext_asm .s)
#     (ext_dll .so)
#     (ext_lib .a)
#     (ext_obj .o)
#     (host x86_64-pc-linux-gnu)
#     (model default)
#     (native_c_compiler "gcc -O  -D_FILE_OFFSET_BITS=64 -D_REENTRANT")
#     (native_c_libraries "-lm  -ldl")
#     (native_pack_linker "ld -r --hash-style=both --as-needed --build-id -o ")
#     (os_type Unix)
#     (ranlib ranlib)
#     (standard_library /usr/lib/ocaml)
#     (standard_library_default /usr/lib/ocaml)
#     (standard_runtime /usr/bin/ocamlrun)
#     (system linux)
#     (systhread_supported true)
#     (target x86_64-pc-linux-gnu)
#     (version 4.02.3)
#     (with_frame_pointers false)))
#   (which
#    ((ocamlc (/usr/bin/ocamlc.opt))
#     (ocamlfind (/home/stryker/.opam/system/bin/ocamlfind)))))
$ (cd _build/default && ../.ppx/default/ppx_jane+ppx_driver.runner/ppx.exe -dirname . -inline-test-drop-with-deadcode -bench-drop-with-deadcode -embed-errors false --dump-ast -o myparsing.pp.ml --impl myparsing.ml)
> ../.ppx/default/ppx_jane+ppx_driver.runner/ppx.exe: unknown option '-embed-errors'.
> ppx.exe [extra_args] [<files>]
>   -dirname <dir>                   Name of the current directory relative to the root of the project
>   -inline-test-lib                 A base name to use for generated identifiers (has to be globally unique in a program).ppx_inline_test (and ppx_bench) are disabled unless this flag is passed.
>   -inline-test-drop                Drop unit tests
>   -inline-test-drop-with-deadcode  Drop unit tests by wrapping them inside deadcode to prevent unused variable warnings.
>   -bench-drop                      Drop inline benchmarks
>   -bench-drop-with-deadcode        Drop inline benchmarks by wrapping them inside deadcode to prevent unused variable warnings.
>   -as-ppx                          Run as a -ppx rewriter (must be the first argument)
>   -o <filename>                    Output file (use '-' for stdout)
>   -reserve-namespace <string>      Mark the given namespace as reserved
>   -loc-filename <string>           File name to use in locations
>   -no-optcomp                      Do not use optcomp
>   -dump-ast                        Dump the marshaled ast to the output file instead of pretty-printing it
>   -dparsetree                      Print the parsetree (same as ocamlc -dparsetree)
>   -impl <file>                     Treat the input as a .ml file
>   -intf <file>                     Treat the input as a .mli file
>   -no-check                        Disable checks (unsafe)
>   -debug-attribute-drop            Debug attribute dropping
>   -print-transformations           Print linked-in code transformations, in the order they are applied
>   -apply <names>                   Apply these transformations in order (comma-separated list)
>   -help                            Display this list of options
>   --help                           Display this list of options
[2]

Two executables stanza

I tried to duplicate the hello_world example twice with the following jbuild file:

(executables
 ((names (hello_world))
))

(executables
 ((names (hello_world2))
))

But I obtained an error because of multiple rules generated:

{$HOME/.opam/4.02.3/bin/ocamlopt.opt, _build/default/.merlin-exists, _build/default/hello_world2.cmi, _build/default/hello_world2.depends.sexp, _build/default/hello_world2.ml, _build/default/hello_world2.requires.sexp} -> {_build/default/hello_world2.cmx, _build/default/hello_world2.o}
{$HOME/.opam/4.02.3/bin/ocamlopt.opt, _build/default/.merlin-exists, _build/default/hello_world.depends.sexp, _build/default/hello_world.requires.sexp, _build/default/hello_world2.cmi, _build/default/hello_world2.ml} -> {_build/default/hello_world2.cmx, _build/default/hello_world2.o}
Multiple rules generated for _build/default/hello_world2.o

Is it supported to have multiple executables rules?

"key "CAML_LD_LIBRARY_PATH" present multiple times"

Not sure if it's an opam 2 bug or a jbuilder one. cc @AltGr

When I use the workspace feature (after doing eval `opam config env --switch 4.03.0` ) I get:

Running[1]: /usr/bin/opam config env --root /home/gabriel/.opam --switch 4.04.0 --sexp > /tmp/jbuild5f4db6.output
File "", line 1, characters 0-796:
Error: key "CAML_LD_LIBRARY_PATH" present multiple times

And indeed, the relevant piece of the opam output is:

  ("CAML_LD_LIBRARY_PATH" "/home/gabriel/.opam/4.04.0/lib/stublibs")
  ("CAML_LD_LIBRARY_PATH" "/home/gabriel/.opam/4.04.0/lib/ocaml/stublibs:/home/gabriel/.opam/4.04.0/lib/ocaml")
  ("CAML_LD_LIBRARY_PATH" "/home/gabriel/.opam/4.04.0/lib/stublibs:/home/gabriel/.opam/4.04.0/lib/ocaml/stublibs:/home/gabriel/.opam/4.04.0/lib/ocaml")

I'm not sure which of opam or jbuilder should be made more resilient here. I would guess both. :p

Testing a ppx define in jbuilder

I would like to test a ppx that I build with jbuilder. I tried several approaches

  • The oldschool method :
    ocaml -noinit -noprompt -ppx my_ppx < test.ml 2>&1 | tail -n +19 > test.result
    diff test.expected test.result
    
    Problem: I can't figure out how to talk about my_ppx.
  • The compiler/jsoo method: inline expect_test in my project and use it on my test file
    Problem: Still can't figure out how to talk about the my_ppx executable, and not sure how to actually run expect_test with it.
  • The "new" method, with toplevel_expect_test
    Problem: Regardless of the fact that the packaging is so badly done that I can't even actually run it. I have no idea how to actually write the build rules for the toplevel that interact with my ppx.

So, what's the solution ? I would really like to be at least able to write the rules for the first (old school) method.

optional compilation

[vb@haramis ~/code/ocaml-websocket]% jbuilder external-lib-deps --missing @install
Error: The following required libraries are missing in the default context:
- cryptokit (optional)

I am using the following stanza:

(library
 ((name rng_cryptokit)
  (public_name websocket.rng_cryptokit)
  (modules (rng_cryptokit))
  (optional)
  (libraries (rng cryptokit))))

Why jbuilder insists on building this if it is flagged optional and that cryptokit is not installed?

Suggetion: Move vendored libs to own dir

Having a structure such as:

vendor/re
vendor/cmdliner

Would make this repo a little easier to work with. For example, it will grep a lot more useful.

I realize that this might complicate the bootstrapping but perhaps it's worth it.

Support for -output-obj

Jbuilder seems not yet able to create standalone shared library -output-obj. However it is not very different from linking executables (you just need a +PIC switch). What would be the right way to add it to jbuilder?

  • a new stanza?
  • an option to executables?

Can't build jbuilder

First off, I'd like to apologize in advance if this is not the proper location for this. I can not find any information on how to install jbuilder, nor can I find any information on a mailing list or some means to contact the project community regarding my problems trying to install this software.

I see there is a Makefile, so I type make:
ocaml bootstrap.ml
File "bootstrap.ml", line 11, characters 5-8:
Error: Syntax error
make: *** [boot.exe] Error 2

I can only assume that my version of ocaml is old. I'm trying to install jbuilder on CentOS 7 (as is necessary for some other software).

rpm -qa | grep ocaml
ocaml-4.01.0-22.7.el7_2.x86_64
ocaml-runtime-4.01.0-22.7.el7_2.x86_64
ocaml-findlib-1.3.3-6.el7.x86_64
ocaml-compiler-libs-4.01.0-22.7.el7_2.x86_64

doc generation

It would be great if we could generate docs using jbuilder + odoc. @diml and @trefis said that there are some Jenga rules somewhere for this, it would be really nice if these would be imported in jbuilder.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.