This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,48 @@
Test that the target directory exists
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (alias mel)
> (emit_stdlib false)
> (target output))
> EOF
Create the target dir
$ mkdir ./output
$ cat > output/dune <<EOF
> (rule
> (with-stdout-to index.txt (echo "hello")))
> (alias (name mel) (deps index.txt))
> EOF
$ cat > hello.ml <<EOF
> let () = Js.log "hello"
> EOF
$ dune build @mel
$ ls _build/default/output
hello.js
index.txt
Target promotion works
$ dune clean
$ cat > dune <<EOF
> (melange.emit
> (alias mel)
> (target output)
> (emit_stdlib false)
> (promote (until-clean)))
> EOF
$ dune build @mel
$ ls _build/default/output
hello.js
index.txt

View file

@ -0,0 +1,114 @@
Test alias field on melange.emit stanzas
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (alias app))
> EOF
$ cat > main.ml <<EOF
> let () =
> Js.log "hello"
> EOF
$ dune build @app
$ node _build/default/output/main.js
hello
Default alias melange works
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main))
> (melange.emit
> (target output2)
> (emit_stdlib false)
> (modules main2))
> EOF
$ cat > main2.ml <<EOF
> let () =
> Js.log "hello"
> EOF
$ dune clean
$ dune build @melange
$ node _build/default/output/main.js
hello
$ node _build/default/output2/main2.js
hello
Dune default alias works
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (modules main)
> (emit_stdlib false))
> (melange.emit
> (target output2)
> (modules main2)
> (emit_stdlib false))
> EOF
$ cat > main2.ml <<EOF
> let () =
> Js.log "hello"
> EOF
$ dune clean
$ dune build
$ node _build/default/output/main.js
hello
$ node _build/default/output2/main2.js
hello
Users can override melange alias (even if useless)
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (alias melange))
> EOF
$ dune clean
$ dune build @melange
If user defines an alias, the default alias is not used for that stanza
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (alias foo))
> EOF
$ dune clean
$ dune build @melange
Error: Alias "melange" specified on the command line is empty.
It is not defined in . or any of its descendants.
[1]
Even if user defines an alias, dune default alias should still work
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (modules main)
> (emit_stdlib false)
> (alias foo))
> EOF
$ dune clean
$ dune build
$ node _build/default/output/main.js
hello

View file

@ -0,0 +1,54 @@
Test that we can install melange mode libraries
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ cat >dune <<EOF
> (library
> (modes melange)
> (public_name foo))
> EOF
$ cat >foo.ml <<EOF
> let x = "foo"
> EOF
$ dune build @install
$ cat ./_build/default/foo.install
lib: [
"_build/install/default/lib/foo/META"
"_build/install/default/lib/foo/dune-package"
"_build/install/default/lib/foo/foo.ml"
"_build/install/default/lib/foo/melange/foo.cmi" {"melange/foo.cmi"}
"_build/install/default/lib/foo/melange/foo.cmj" {"melange/foo.cmj"}
"_build/install/default/lib/foo/melange/foo.cmt" {"melange/foo.cmt"}
]
$ sed -E 's/lang dune [0-9.]+/lang dune XXX/' _build/install/default/lib/foo/dune-package
(lang dune XXX)
(name foo)
(sections (lib .))
(files
(lib
(META dune-package foo.ml melange/foo.cmi melange/foo.cmj melange/foo.cmt)))
(library
(name foo)
(kind normal)
(main_module_name Foo)
(modes melange)
(modules
(singleton
(obj_name foo)
(visibility public)
(source (path Foo) (impl (path foo.ml))))))
$ dune install --prefix prefix --display short
Installing prefix/lib/foo/META
Installing prefix/lib/foo/dune-package
Installing prefix/lib/foo/foo.ml
Installing prefix/lib/foo/melange/foo.cmi
Installing prefix/lib/foo/melange/foo.cmj
Installing prefix/lib/foo/melange/foo.cmt

View file

@ -0,0 +1,55 @@
Example using melange.emit, copy_files and include_subdirs
$ mkdir assets
$ cat > assets/file.txt <<EOF
> hello from file
> EOF
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ mkdir src
$ cat > src/dune <<EOF
> (melange.emit
> (target app)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (alias mel))
>
> (subdir
> app
> (copy_files
> (files %{project_root}/assets/file.txt))
> (alias
> (name mel)
> (deps file.txt)))
> EOF
$ cat > src/main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "../file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
$ output_dir=_build/default/src/app
$ src=$output_dir/src/main.js
$ asset=$output_dir/file.txt
$ dune build @mel
$ dune build $asset
$ node $src
hello from file
Works with `(include_subdirs unqualified)` too
$ echo "(include_subdirs unqualified)" >> src/dune
$ dune build @mel
$ dune build $asset
$ node $src
hello from file

View file

@ -0,0 +1,50 @@
Example showing melange.emit and copy_files, where the files are copied
into the melange.emit target folder
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ mkdir src public
$ cat > src/dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (alias mel))
> EOF
$ touch public/img.png
Builds normally
$ dune build @mel
Now try copying a file
$ cat > src/dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (alias mel))
>
> (subdir
> output
> (subdir
> src
> (copy_files
> (files %{project_root}/public/img.png))))
> EOF
It works:
$ dune build @mel
We add a module and it stays working:
$ cat > src/a.ml <<EOF
> let () = Js.log "foo"
> EOF
$ dune build @mel

View file

@ -0,0 +1,64 @@
Test simple interactions between melange.emit and copy_files
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (alias mel))
>
> (copy_files
> (alias mel)
> (files assets/file.txt))
> EOF
$ mkdir assets
$ cat > assets/file.txt <<EOF
> hello from file
> EOF
$ cat > main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "../assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
$ dune build @mel
$ node _build/default/output/main.js
hello from file
Copy the file into the output folder, so we can use same path as in-source
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (alias mel))
>
> (subdir output
> (subdir assets
> (copy_files (alias mel) (files %{project_root}/assets/file.txt))))
> EOF
$ cat > main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
$ dune build @mel
$ node _build/default/output/main.js
hello from file

View file

@ -0,0 +1,103 @@
Test dependency on installed package
$ mkdir a b prefix app
$ cat > a/dune-project <<EOF
> (lang dune 3.8)
> (package (name a))
> (using melange 0.1)
> EOF
$ cat > a/dune <<EOF
> (library
> (modes melange)
> (public_name a))
> EOF
$ cat > a/foo.ml <<EOF
> let x = "foo"
> EOF
$ dune build --root a
Entering directory 'a'
Leaving directory 'a'
$ dune install --root a --prefix $PWD/prefix --display short
Installing $TESTCASE_ROOT/prefix/lib/a/META
Installing $TESTCASE_ROOT/prefix/lib/a/a.ml
Installing $TESTCASE_ROOT/prefix/lib/a/dune-package
Installing $TESTCASE_ROOT/prefix/lib/a/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmt
$ cat >b/dune-project <<EOF
> (lang dune 3.8)
> (package (name b))
> (using melange 0.1)
> EOF
$ cat > b/dune <<EOF
> (library
> (modes melange)
> (public_name b)
> (libraries a))
> EOF
$ cat > b/bar.ml <<EOF
> let x = A.Foo.x
> EOF
$ cat > b/foo.ml <<EOF
> let x = Bar.x
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root b @install --display=short
Entering directory 'b'
ocamldep .b.objs/b__Bar.impl.d
ocamldep .b.objs/b__Foo.impl.d
melc .b.objs/melange/b.{cmi,cmj,cmt}
melc .b.objs/melange/b__Bar.{cmi,cmj,cmt}
melc .b.objs/melange/b__Foo.{cmi,cmj,cmt}
Leaving directory 'b'
$ dune install --root b --prefix $PWD/prefix --display=short
Installing $TESTCASE_ROOT/prefix/lib/b/META
Installing $TESTCASE_ROOT/prefix/lib/b/b.ml
Installing $TESTCASE_ROOT/prefix/lib/b/bar.ml
Installing $TESTCASE_ROOT/prefix/lib/b/dune-package
Installing $TESTCASE_ROOT/prefix/lib/b/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b.cmi
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b.cmj
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b.cmt
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b__Bar.cmi
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b__Bar.cmj
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b__Bar.cmt
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b__Foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/b/melange/b__Foo.cmt
$ cat >app/dune-project <<EOF
> (lang dune 3.8)
> (package (name app))
> (using melange 0.1)
> EOF
$ cat > app/dune <<EOF
> (melange.emit
> (target dist)
> (alias melange-dist)
> (emit_stdlib false)
> (libraries b))
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root app @melange-dist --display=short
Entering directory 'app'
melc dist/node_modules/a/a.js
melc dist/node_modules/a/foo.js
melc dist/node_modules/b/b.js
melc dist/node_modules/b/bar.js
melc dist/node_modules/b/foo.js
Leaving directory 'app'

View file

@ -0,0 +1,11 @@
(melange.emit
(target output)
(emit_stdlib false)
(libraries bar impl2)
(modules foo))
(library
(name bar)
(libraries impl1)
(modes melange)
(modules))

View file

@ -0,0 +1,3 @@
(lang dune 3.8)
(using melange 0.1)

View file

@ -0,0 +1 @@
let () = print_endline "should not run"

View file

@ -0,0 +1,4 @@
(library
(name impl1)
(modes melange)
(implements vlib))

View file

@ -0,0 +1 @@
let run () = print_endline "impl1"

View file

@ -0,0 +1,4 @@
(library
(name impl2)
(modes melange)
(implements vlib))

View file

@ -0,0 +1 @@
let run () = print_endline "impl1"

View file

@ -0,0 +1,21 @@
`melange.emit` that tries to use two implementations for the same virtual lib
$ dune build @melange
Error: Conflicting implementations for virtual library "vlib" in
_build/default/vlib:
- "impl1" in _build/default/impl1
-> required by library "bar" in _build/default
- "impl2" in _build/default/impl2
This cannot work.
-> required by melange target output
-> required by alias melange
Error: Conflicting implementations for virtual library "vlib" in
_build/default/vlib:
- "impl1" in _build/default/impl1
-> required by library "bar" in _build/default
- "impl2" in _build/default/impl2
This cannot work.
-> required by melange target output
-> required by _build/default/output/foo.js
-> required by alias melange
[1]

View file

@ -0,0 +1,4 @@
(library
(name vlib)
(modes melange)
(virtual_modules vlib))

View file

@ -0,0 +1,20 @@
(env
(_
(env-vars
(DUNE_SANDBOX symlink))))
(cram
(applies_to :whole_subtree)
(deps %{bin:node} %{bin:melc})
(alias runtest-melange))
(cram
(deps %{bin:melc_stdlib_prefix})
(enabled_if
(not %{env:INSIDE_NIX=false}))
(applies_to merlin))
(cram
(deps
(package odoc))
(applies_to odoc))

View file

@ -0,0 +1,6 @@
(melange.emit
(target dist)
(alias mel)
(modules entry_module)
(emit_stdlib false)
(libraries parent))

View file

@ -0,0 +1,3 @@
(lang dune 3.8)
(using melange 0.1)

View file

@ -0,0 +1 @@
let () = Js.log (Parent.M_a.t)

View file

@ -0,0 +1,3 @@
(library
(modes melange)
(name leaf))

View file

@ -0,0 +1,4 @@
module Other = Other
let x = Other.t
let t = 1

View file

@ -0,0 +1,4 @@
(library
(modes melange)
(name parent)
(libraries leaf))

View file

@ -0,0 +1,5 @@
Test file unmangling with melange.emit that depends on a library, that depends on another library
$ dune build @mel
$ node _build/default/dist/entry_module.js
1

View file

@ -0,0 +1,68 @@
Test that paths in `node_modules` are correct for sub-libraries of the
form `foo.bar.baz`
$ mkdir a app
$ cat > a/dune-project <<EOF
> (lang dune 3.8)
> (package (name a))
> (using melange 0.1)
> EOF
$ cat > a/dune <<EOF
> (library
> (modes melange)
> (name a)
> (public_name a.sub))
> EOF
$ cat > a/foo.ml <<EOF
> let x = "foo"
> EOF
$ dune build --root a
Entering directory 'a'
Leaving directory 'a'
$ dune install --root a --prefix $PWD/prefix --display short
Installing $TESTCASE_ROOT/prefix/lib/a/META
Installing $TESTCASE_ROOT/prefix/lib/a/dune-package
Installing $TESTCASE_ROOT/prefix/lib/a/sub/a.ml
Installing $TESTCASE_ROOT/prefix/lib/a/sub/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/a/sub/melange/a.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/sub/melange/a.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/sub/melange/a.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/sub/melange/a__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/sub/melange/a__Foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/sub/melange/a__Foo.cmt
$ cat prefix/lib/a/dune-package | grep path
(source (path A) (impl (path sub/a.ml-gen))))
(source (path Foo) (impl (path sub/foo.ml))))))
$ cat >app/dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > app/dune <<EOF
> (melange.emit
> (target dist)
> (alias dist)
> (emit_stdlib false)
> (libraries a.sub))
> EOF
$ cat > app/bar.ml <<EOF
> let x = Js.log A.Foo.x
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root app @dist --display short 2>&1 | grep -v melange
Entering directory 'app'
melc dist/node_modules/a.sub/a.js
melc dist/node_modules/a.sub/foo.js
melc dist/bar.js
Leaving directory 'app'
$ ls app/_build/default/dist/node_modules/a.sub
a.js
foo.js

View file

@ -0,0 +1,41 @@
Test dune rules
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main))
> EOF
$ cat > main.ml <<EOF
> Js.log "hello"
> EOF
Calling dune rules with the 'all' alias works fine
$ dune rules @all | grep In_build_dir
(In_build_dir _build/default/.output.mobjs/melange/melange__Main.cmj))))
Calling dune rules with the alias works fine
$ dune rules @melange | grep In_build_dir
(In_build_dir _build/default/.output.mobjs/melange/melange__Main.cmj))))
Using output folder fails
$ dune rules output
Error: Don't know how to build output
[1]
Creating dir fixes the problem
$ mkdir output
$ dune rules output | grep "\.cmj"
(In_build_dir _build/default/.output.mobjs/melange/melange__Main.cmj))))
.output.mobjs/melange/melange__Main.cmj))))

View file

@ -0,0 +1,5 @@
(melange.emit
(target dist)
(alias dist)
(emit_stdlib false)
(libraries lib))

View file

@ -0,0 +1,6 @@
(lang dune 3.8)
(package
(name pkg2))
(using melange 0.1)

View file

@ -0,0 +1,6 @@
(lang dune 3.8)
(package
(name pkg1))
(using melange 0.1)

View file

@ -0,0 +1,5 @@
(library
(modes melange)
(name lib1)
(libraries pkg2.npm)
(public_name pkg1.lib1))

View file

@ -0,0 +1,5 @@
(library
(modes melange)
(name lib2)
(libraries lib1)
(public_name pkg1.lib2))

View file

@ -0,0 +1,5 @@
(library
(modes melange)
(name lib)
(libraries pkg1.lib1 pkg1.lib2)
(public_name pkg2.lib))

View file

@ -0,0 +1 @@
let x = Lib1.x ^ Lib2.x ^ "baz"

View file

@ -0,0 +1,4 @@
(library
(modes melange)
(name npm)
(public_name pkg2.npm))

View file

@ -0,0 +1,6 @@
Test that libs are correctly installed in a complex setup
Build js files
$ dune build @dist
$ node _build/default/dist/app.js
foonpm

View file

@ -0,0 +1,93 @@
Test dependency on installed package
$ mkdir a b c prefix
$ cat > a/dune-project <<EOF
> (lang dune 3.8)
> (package (name a))
> (using melange 0.1)
> EOF
$ cat > a/dune <<EOF
> (library
> (modes byte melange)
> (public_name a))
> EOF
$ cat > a/foo.ml <<EOF
> let x = "foo"
> EOF
$ dune build --root a
Entering directory 'a'
Leaving directory 'a'
$ dune install --root a --prefix $PWD/prefix --display short
Installing $TESTCASE_ROOT/prefix/lib/a/META
Installing $TESTCASE_ROOT/prefix/lib/a/a.cma
Installing $TESTCASE_ROOT/prefix/lib/a/a.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/a.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/a.ml
Installing $TESTCASE_ROOT/prefix/lib/a/a__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/a__Foo.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/dune-package
Installing $TESTCASE_ROOT/prefix/lib/a/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmt
$ cat >b/dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > b/dune <<EOF
> (melange.emit
> (target dist)
> (alias dist)
> (emit_stdlib false)
> (libraries a))
> EOF
$ cat > b/bar.ml <<EOF
> let x = Js.log A.Foo.x
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root b @dist --display=short 2>&1 | grep -v melange
Entering directory 'b'
melc dist/node_modules/a/a.js
melc dist/node_modules/a/foo.js
melc dist/bar.js
Leaving directory 'b'
$ node b/_build/default/dist/bar.js
foo
$ cat >c/dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > c/dune <<EOF
> (melange.emit
> (target dist)
> (alias dist)
> (emit_stdlib false)
> (libraries a))
> EOF
$ cat > c/dune <<EOF
> (executable
> (name bar)
> (modes byte)
> (libraries a))
> EOF
$ cat > c/bar.ml <<EOF
> let () = print_endline A.Foo.x
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune exec ./c/bar.exe
foo

View file

@ -0,0 +1,80 @@
Test dependency on installed package
$ mkdir -p lib-a lib-a/sub b prefix
$ cat > lib-a/dune-project <<EOF
> (lang dune 3.8)
> (package (name a))
> (using melange 0.1)
> EOF
$ cat > lib-a/dune <<EOF
> (include_subdirs unqualified)
> (library
> (modes melange)
> (public_name a))
> EOF
$ cat > lib-a/foo.ml <<EOF
> let x = "foo"
> EOF
$ cat > lib-a/sub/sub.ml <<EOF
> let y = "bar"
> EOF
$ dune build --root lib-a
Entering directory 'lib-a'
Leaving directory 'lib-a'
$ dune install --root lib-a --prefix $PWD/prefix --display short
Installing $TESTCASE_ROOT/prefix/lib/a/META
Installing $TESTCASE_ROOT/prefix/lib/a/a.ml
Installing $TESTCASE_ROOT/prefix/lib/a/dune-package
Installing $TESTCASE_ROOT/prefix/lib/a/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Foo.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Sub.cmi
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Sub.cmj
Installing $TESTCASE_ROOT/prefix/lib/a/melange/a__Sub.cmt
Installing $TESTCASE_ROOT/prefix/lib/a/sub/sub.ml
$ cat >b/dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > b/dune <<EOF
> (melange.emit
> (target dist)
> (alias dist)
> (emit_stdlib false)
> (libraries a))
> EOF
$ cat > b/bar.ml <<EOF
> let x = Js.log A.Foo.x
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root b @dist --display=short 2>&1 | grep -v melange
Entering directory 'b'
melc dist/node_modules/a/a.js
melc dist/node_modules/a/foo.js
melc dist/node_modules/a/sub/sub.js
melc dist/bar.js
Leaving directory 'b'
$ find b/_build/default/dist | grep -v melange | sort
b/_build/default/dist
b/_build/default/dist/bar.js
b/_build/default/dist/node_modules
b/_build/default/dist/node_modules/a
b/_build/default/dist/node_modules/a/a.js
b/_build/default/dist/node_modules/a/foo.js
b/_build/default/dist/node_modules/a/sub
b/_build/default/dist/node_modules/a/sub/sub.js
$ node b/_build/default/dist/bar.js
foo

View file

@ -0,0 +1,55 @@
Test dependency on a private library in the same package as melange.emit
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (package (name pkg))
> (using melange 0.1)
> EOF
$ mkdir a b prefix
$ cat > a/dune <<EOF
> (library
> (name a)
> (modes melange)
> (package pkg))
> EOF
$ cat > a/foo.ml <<EOF
> let x = "foo"
> EOF
$ dune build
$ dune install --prefix $PWD/prefix --display short
Installing $TESTCASE_ROOT/prefix/lib/pkg/META
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/a.ml
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/melange/.public_cmi_melange/a.cmi
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/melange/.public_cmi_melange/a.cmt
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/melange/.public_cmi_melange/a__Foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/melange/.public_cmi_melange/a__Foo.cmt
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/melange/a.cmj
Installing $TESTCASE_ROOT/prefix/lib/pkg/__private__/a/melange/a__Foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/pkg/dune-package
$ cat > b/dune <<EOF
> (melange.emit
> (target dist)
> (alias dist)
> (libraries a)
> (emit_stdlib false)
> (package pkg))
> EOF
$ cat > b/bar.ml <<EOF
> let x = Js.log A.Foo.x
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build @dist --display=short 2>&1 | grep -v melange
melc b/dist/node_modules/pkg.__private__.a/a.js
melc b/dist/node_modules/pkg.__private__.a/foo.js
melc b/dist/b/bar.js
$ node _build/default/b/dist/b/bar.js
foo

View file

@ -0,0 +1,41 @@
using `(select ...)` in melange.emit
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat >bar.melange.ml <<EOF
> let message = "hello from melange"
> EOF
$ cat >bar.native.ml <<EOF
> let message = print_endline "hello from native"
> EOF
$ cat >foo.fake.ml <<EOF
> let message = "foo has fake " ^^ Fakefoobar.fake
> EOF
$ cat >foo.no_fake.ml <<EOF
> let message = "foo has no fake"
> EOF
$ cat >main.ml <<EOF
> let () = Js.log Bar.message
> let () = Js.log Foo.message
> EOF
$ cat >dune <<EOF
> (melange.emit
> (target output)
> (alias mel)
> (emit_stdlib false)
> (libraries
> (select bar.ml from
> (melange -> bar.melange.ml)
> (!melange -> bar.native.ml))
> (select foo.ml from
> (fakefoobar -> foo.fake.ml)
> (!fakefoobar -> foo.no_fake.ml))))
> EOF
$ dune build @mel
$ node ./_build/default/output/main.js
hello from melange
foo has no fake

View file

@ -0,0 +1,86 @@
Test dependency on installed package
$ mkdir xyz
$ cat > xyz/dune-project <<EOF
> (lang dune 3.8)
> (package (name aa_fe))
> (using melange 0.1)
> EOF
$ cat > xyz/dune <<EOF
> (library
> (modes melange)
> (name aa_fe_melange)
> (public_name aa_fe.melange))
> EOF
$ cat > xyz/foo.ml <<EOF
> let x = "foo"
> EOF
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat >dune-workspace <<EOF
> (lang dune 3.8)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target dist)
> (alias dist)
> (emit_stdlib false)
> (libraries aa_fe.melange))
> EOF
$ cat > bar.ml <<EOF
> let x = Js.log Aa_fe_melange.Foo.x
> EOF
$ dune build @dist
$ node _build/default/dist/bar.js
foo
Move inner lib to a subfolder inside its dune-project
$ cd xyz
$ mkdir inner
$ mv dune-project inner
$ mv dune inner
$ mv foo.ml inner
$ cd -
$TESTCASE_ROOT
$ dune build @dist
$ node _build/default/dist/bar.js
foo
Move everything except the workspace to a subfolder
$ mkdir abc
$ mv dune-project abc
$ mv dune abc
$ mv bar.ml abc
$ dune build @dist
$ node _build/default/abc/dist/abc/bar.js
foo
Move back inner lib to main folder
$ cd xyz/inner
$ mv dune-project ..
$ mv dune ..
$ mv foo.ml ..
$ cd -
$TESTCASE_ROOT
$ dune build @dist
$ node _build/default/abc/dist/abc/bar.js
foo

View file

@ -0,0 +1,34 @@
Test simple interactions between melange.emit and copy_files
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> (using directory-targets 0.1)
> EOF
$ cat > dune <<EOF
> (rule (target (dir some_dir))
> (action
> (progn (system "mkdir %{target}")
> (system "echo hello from file inside dir target > %{target}/inside-dir-target.txt"))))
> (melange.emit
> (alias mel)
> (target output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps ./some_dir))
> EOF
$ cat > main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./some_dir/inside-dir-target.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
$ dune build @mel
Error: Is a directory
-> required by _build/default/output/some_dir
-> required by alias output/mel
[1]

View file

@ -0,0 +1,202 @@
Test simple interactions between melange.emit and copy_files
$ mkdir a
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> (using directory-targets 0.1)
> EOF
$ cat > a/dune <<EOF
> (melange.emit
> (alias mel)
> (target output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps assets/file.txt assets/file.txt))
> EOF
$ mkdir a/assets
$ cat > a/assets/file.txt <<EOF
> hello from file
> EOF
$ cat > a/main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
Rules created for the assets in the output directory
$ dune rules @mel | grep file.txt
((deps ((File (In_build_dir _build/default/a/assets/file.txt))))
((files (_build/default/a/output/a/assets/file.txt)) (directories ())))
(chdir _build/default (copy a/assets/file.txt a/output/a/assets/file.txt))))
$ dune build @mel
The runtime_dep index.txt was copied to the build folder
$ ls _build/default/a/output/a/assets
file.txt
$ dune build a/output/a/assets/file.txt --display=short
$ ls _build/default/a/output/a
assets
main.js
$ node _build/default/a/output/a/main.js
hello from file
Test depending on non-existing paths
$ mkdir another
$ dune clean
$ cat > another/dune <<EOF
> (melange.emit
> (alias non-existing-mel)
> (target another-output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps doesnt-exist.txt))
> EOF
$ dune build @non-existing-mel
File "another/dune", lines 1-7, characters 0-177:
1 | (melange.emit
2 | (alias non-existing-mel)
3 | (target another-output)
4 | (emit_stdlib false)
5 | (libraries melange.node)
6 | (preprocess (pps melange.ppx))
7 | (runtime_deps doesnt-exist.txt))
Error: No rule found for another/doesnt-exist.txt
[1]
Test depend on non-file dependencies
$ cat > another/dune <<EOF
> (melange.emit
> (alias non-existing-mel)
> (target another-output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps (sandbox none)))
> EOF
$ dune build @non-existing-mel
File "another/dune", line 7, characters 15-29:
7 | (runtime_deps (sandbox none)))
^^^^^^^^^^^^^^
Error: only files are allowed in this position
[1]
Test depending on paths that "escape" the melange.emit directory
$ dune clean
$ cat > another/dune <<EOF
> (melange.emit
> (alias mel)
> (target another-output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps ../a/assets/file.txt))
> EOF
$ cat > another/main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
Rules are created for the runtime deps
$ dune rules @mel | grep .txt
((deps ((File (In_build_dir _build/default/a/assets/file.txt))))
((files (_build/default/a/output/a/assets/file.txt)) (directories ())))
(chdir _build/default (copy a/assets/file.txt a/output/a/assets/file.txt))))
((deps ((File (In_build_dir _build/default/a/assets/file.txt))))
((files (_build/default/another/another-output/a/assets/file.txt))
(copy a/assets/file.txt another/another-output/a/assets/file.txt))))
$ dune build @mel
Path ends ups being emitted "correctly", but outside the target dir.
$ ls _build/default/another/another-output/another
main.js
$ ls _build/default/another/another-output/a/assets
file.txt
Test depending on external paths
$ mkdir external
$ cat > external/dune <<EOF
> (melange.emit
> (alias mel)
> (target external-output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps /etc/hosts))
> EOF
$ cat > external/main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
$ dune build @mel --display=short 2>&1 | grep -i main
ppx external/main.pp.ml
melc external/.external-output.mobjs/melange/melange__Main.{cmi,cmj,cmt}
melc external/external-output/external/main.js
External paths are not copied to the target directory
$ ls _build/default/external/external-output/external
main.js
Test depending on runtime assets inside `(include_subdirs ..)`
$ mkdir -p incl/sub
$ cat > incl/dune <<EOF
> (include_subdirs unqualified)
> (melange.emit
> (alias mel)
> (target incl-output)
> (emit_stdlib false)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps ./file.txt ./sub/file.txt))
> EOF
$ cat > incl/file.txt <<EOF
> hello from sub file
> EOF
$ cat > incl/sub/file.txt <<EOF
> hello from sub file
> EOF
$ cat > incl/sub/main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
$ dune build @mel --display=short 2>&1 | grep -i main
ppx incl/sub/main.pp.ml
melc incl/.incl-output.mobjs/melange/melange__Main.{cmi,cmj,cmt}
melc incl/incl-output/incl/sub/main.js
$ node _build/default/incl/incl-output/incl/sub/main.js
hello from sub file

View file

@ -0,0 +1,78 @@
Test simple interactions between melange.emit and copy_files
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (alias mel)
> (emit_stdlib false)
> (target output)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (runtime_deps assets/file.txt (glob_files_rec ./globbed/*.txt)))
> EOF
$ mkdir assets
$ cat > assets/file.txt <<EOF
> hello from file
> EOF
$ mkdir globbed
$ echo a.txt > globbed/a.txt
$ echo b.txt > globbed/b.txt
$ cat > main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> EOF
Rules created for the assets in the output directory
$ dune build output/assets/file.txt --display=short
$ find _build/default/output
_build/default/output
_build/default/output/assets
_build/default/output/assets/file.txt
$ dune clean
Alias is found even if source dir "output" isn't present
$ dune rules @mel | grep file.txt
((deps ((File (In_build_dir _build/default/assets/file.txt))))
(targets ((files (_build/default/output/assets/file.txt)) (directories ())))
(action (chdir _build/default (copy assets/file.txt output/assets/file.txt))))
$ dune build @mel
The runtime_dep index.txt was copied to the build folder
$ ls _build/default/
assets
globbed
main.ml
main.pp.ml
output
$ ls _build/default/output
assets
globbed
main.js
node_modules
$ dune build output/assets/file.txt --display=short
$ ls _build/default/output
assets
globbed
main.js
node_modules
$ ls _build/default/output/globbed
a.txt
b.txt
$ node _build/default/output/main.js
hello from file

View file

@ -0,0 +1,22 @@
Test (modules) field can be left empty
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (alias mel))
> EOF
$ cat > hello.ml <<EOF
> let () =
> print_endline "hello"
> EOF
$ dune build @mel
$ node _build/default/output/hello.js
hello

View file

@ -0,0 +1,30 @@
Using same melange.emit target in two contexts, where the stanzas are defined
in the same dune file
$ cat > dune-project << EOF
> (lang dune 3.13)
> (using melange 0.1)
> EOF
$ cat > dune-workspace << EOF
> (lang dune 3.13)
>
> (context default)
>
> (context
> (default
> (name alt-context)))
> EOF
$ cat > dune << EOF
> (melange.emit
> (target foo)
> (enabled_if (= %{context_name} "default")))
> (melange.emit
> (target foo)
> (enabled_if (= %{context_name} "alt-context")))
> EOF
$ cat > foo.ml <<EOF
> let () = print_endline "foo"
> EOF
$ dune build

View file

@ -0,0 +1,36 @@
Using same melange.emit target in two contexts
$ mkdir -p a b
$ cat > dune-project << EOF
> (lang dune 3.13)
> (using melange 0.1)
> EOF
$ cat > dune-workspace << EOF
> (lang dune 3.13)
>
> (context default)
>
> (context
> (default
> (name alt-context)))
> EOF
$ cat > a/dune << EOF
> (melange.emit
> (target foo)
> (enabled_if (= %{context_name} "default")))
> EOF
$ cat > a/foo.ml <<EOF
> let () = print_endline "foo"
> EOF
$ cat > b/dune << EOF
> (melange.emit
> (target foo)
> (enabled_if (= %{context_name} "alt-context")))
> EOF
$ cat > b/foo.ml <<EOF
> let () = print_endline "foo"
> EOF
$ dune build

View file

@ -0,0 +1,48 @@
Test installation for melange libraries in multiple contexts.
The expectation is that libraries that don't collide (e.g. a melange and a
native library) can be installed in the same context.
Create a package named foo
$ mkdir -p a b
$ cat > dune-project << EOF
> (lang dune 3.13)
> (using melange 0.1)
> (package (name foo))
> EOF
Define libraries in multiple contexts
$ cat > dune-workspace << EOF
> (lang dune 3.13)
> (context default)
> (context
> (default
> (name melange)))
> EOF
$ cat > a/dune << EOF
> (library
> (name foo)
> (public_name foo.native)
> (enabled_if (= %{context_name} "default")))
> (library
> (name foo)
> (public_name foo.melange)
> (modes melange)
> (enabled_if (= %{context_name} "melange")))
> EOF
$ cat > a/foo.ml <<EOF
> let () = print_endline "foo"
> EOF
$ dune build
$ mkdir -p out/man
Try installing both
$ dune install foo --prefix out
Error: Cannot specify '--prefix' or '--libdir' when installing into multiple
contexts!
[1]

View file

@ -0,0 +1,44 @@
`enabled_if` in `melange.emit`
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target out)
> (emit_stdlib false)
> (enabled_if %{bin-available:melc}))
> EOF
$ cat > x.ml <<EOF
> let () = Js.log "hello"
> EOF
$ dune rules @melange | grep '\.cmj'
(File (In_build_dir _build/default/.out.mobjs/melange/melange__X.cmj))))
.out.mobjs/melange/melange__X.cmj))))
$ dune build @melange
$ dune clean
`(enabled_if false)` shouldn't build any JS
$ cat > dune <<EOF
> (melange.emit
> (target out)
> (emit_stdlib false)
> (enabled_if false))
> EOF
$ dune build @melange
Error: Alias "melange" specified on the command line is empty.
It is not defined in . or any of its descendants.
[1]
No rules attached to the alias
$ dune rules @melange
Error: Alias "melange" specified on the command line is empty.
It is not defined in . or any of its descendants.
[1]

View file

@ -0,0 +1,30 @@
Test compile_flags are passed to JS file emission
$ cat > dune-project <<EOF
> (lang dune 3.13)
> (using melange 0.1)
> EOF
$ cat > main.ml <<EOF
> let () = Js.log "hello"
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main)
> (compile_flags :standard --mel-no-version-header))
> EOF
$ dune build @melange
File is generated with the "Generated by Melange" header even though we
specified the opposite in flags
$ cat _build/default/output/main.js
'use strict';
console.log("hello");
/* Not a pure module */

View file

@ -0,0 +1,141 @@
Test flags and compile_flags fields on melange.emit stanza
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
Using flags field in melange.emit stanzas is not supported
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main)
> (flags -w -14-26))
> EOF
$ dune build @mel
File "dune", line 5, characters 2-7:
5 | (flags -w -14-26))
^^^^^
Error: Unknown field "flags"
[1]
Adds a module that contains unused var (warning 26) and illegal backlash (warning 14)
$ cat > main.ml <<EOF
> let t = "\e\n" in
> print_endline "hello"
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main)
> (alias mel))
> EOF
Trying to build triggers both warnings
$ dune build @mel
File "main.ml", line 1, characters 9-11:
1 | let t = "\e\n" in
^^
Error (warning 14 [illegal-backslash]): illegal backslash escape in string.
Hint: Single backslashes \ are reserved for escape sequences
(\n, \r, ...). Did you check the list of OCaml escape sequences?
To get a backslash character, escape it with a second backslash: \\.
File "main.ml", line 1, characters 4-5:
1 | let t = "\e\n" in
^
Error (warning 26 [unused-var]): unused variable t.
[1]
Let's ignore them using compile_flags
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (modules main)
> (emit_stdlib false)
> (alias mel)
> (compile_flags -w -14-26))
> EOF
$ dune build @mel
$ node _build/default/output/main.js
hello
Can also pass flags from the env stanza. Let's go back to failing state:
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main)
> (alias mel))
> EOF
$ dune build @mel
File "main.ml", line 1, characters 9-11:
1 | let t = "\e\n" in
^^
Error (warning 14 [illegal-backslash]): illegal backslash escape in string.
Hint: Single backslashes \ are reserved for escape sequences
(\n, \r, ...). Did you check the list of OCaml escape sequences?
To get a backslash character, escape it with a second backslash: \\.
File "main.ml", line 1, characters 4-5:
1 | let t = "\e\n" in
^
Error (warning 26 [unused-var]): unused variable t.
[1]
Adding env stanza with both warnings silenced allows the build to pass successfully
$ cat > dune <<EOF
> (env
> (_
> (melange.compile_flags -w -14-26)))
> (melange.emit
> (alias mel)
> (target output)
> (emit_stdlib false)
> (modules main))
> EOF
$ dune build @mel
$ node _build/default/output/main.js
hello
Warning 102 (Melange only) is available if explicitly set
$ cat > main.ml <<EOF
> let compare a b = compare a b
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (modules main)
> (emit_stdlib false)
> (compile_flags -w +a-70))
> EOF
$ dune build output/main.js
File "main.ml", line 1, characters 18-29:
1 | let compare a b = compare a b
^^^^^^^^^^^
Warning 102 [polymorphic-comparison-introduced]: Polymorphic comparison introduced (maybe unsafe)
But it is disabled by default
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main))
> EOF
$ dune build output/main.js

View file

@ -0,0 +1,56 @@
Reproduce github #7020
$ dir=_to-install
$ mkdir $dir
$ cat >$dir/dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> (package
> (name dummyfoo))
> EOF
$ cat >$dir/dune <<EOF
> (library
> (modes melange)
> (public_name dummyfoo))
> EOF
$ cat >$dir/META.dummyfoo.template <<EOF
> # DUNE_GEN
> EOF
$ dune build @install --root $dir
Entering directory '_to-install'
Leaving directory '_to-install'
$ cd $dir
$ dune install --root . --prefix _install --display short
Installing _install/lib/dummyfoo/META
Installing _install/lib/dummyfoo/dummyfoo.ml
Installing _install/lib/dummyfoo/dune-package
Installing _install/lib/dummyfoo/melange/dummyfoo.cmi
Installing _install/lib/dummyfoo/melange/dummyfoo.cmj
Installing _install/lib/dummyfoo/melange/dummyfoo.cmt
$ cd ..
$ export OCAMLPATH=$PWD/$dir/_install/lib
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat >dune <<EOF
> (melange.emit
> (target es6)
> (alias mel)
> (libraries dummyfoo)
> (emit_stdlib false)
> (module_systems es6))
> EOF
$ dune build @mel
Error: The library dummyfoo was not compiled with Dune or it was compiled
with Dune but published with a META template. Such libraries are not
compatible with melange support
-> required by alias mel
[1]

View file

@ -0,0 +1,3 @@
(lang dune 3.8)
(using melange 0.1)

View file

@ -0,0 +1 @@
let buy_it = "buy " ^ A.it

View file

@ -0,0 +1,4 @@
(include_subdirs unqualified)
(library
(name lib)
(modes melange))

View file

@ -0,0 +1 @@
let () = Js.log Lib.B.buy_it

View file

@ -0,0 +1,6 @@
(melange.emit
(target output)
(alias mel)
(emit_stdlib false)
(modules c)
(libraries lib))

View file

@ -0,0 +1,17 @@
Test that libs using `(include_subdirs unqualified) work well with
`melange.emit` stanza
Build js files
$ output=inside/output
$ dune build @mel
The directory structure of the .js should mimic the directory structure of the
source:
$ find _build/default/$output -iname "*.js" | grep -v melange | sort
_build/default/inside/output/inside/app/b.js
_build/default/inside/output/inside/app/lib.js
_build/default/inside/output/inside/app/lib/a.js
_build/default/inside/output/inside/c.js
$ node _build/default/$output/inside/c.js
buy it

View file

@ -0,0 +1,75 @@
Test `melange.runtime_deps` for installed libraries where the dune file is
nested more than the dune-project file
$ mkdir lib app prefix
$ cat > lib/dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ mkdir -p lib/packages/foo/src/runtime
$ echo "function foo() { return 42; }" > lib/packages/foo/src/runtime/runtime.js
$ cat > lib/packages/foo/src/dune <<EOF
> (include_subdirs unqualified)
> (library
> (public_name foo)
> (name foo)
> (modes melange)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (melange.runtime_deps ./runtime/runtime.js))
> EOF
$ cat > lib/packages/foo/src/foo.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let () = Js.log2 "dirname:" dirname
> let read_asset () = Node.Fs.readFileSync (dirname ^ "/runtime/runtime.js") \`utf8
> EOF
$ dune build --root lib
Entering directory 'lib'
Leaving directory 'lib'
$ cat lib/_build/default/foo.install
lib: [
"_build/install/default/lib/foo/META"
"_build/install/default/lib/foo/dune-package"
"_build/install/default/lib/foo/foo.ml"
"_build/install/default/lib/foo/melange/foo.cmi" {"melange/foo.cmi"}
"_build/install/default/lib/foo/melange/foo.cmj" {"melange/foo.cmj"}
"_build/install/default/lib/foo/melange/foo.cmt" {"melange/foo.cmt"}
"_build/install/default/lib/foo/runtime/runtime.js" {"runtime/runtime.js"}
]
$ grep melange_runtime_deps lib/_build/install/default/lib/foo/dune-package
(melange_runtime_deps runtime/runtime.js))
$ cat > lib/packages/foo/src/dune <<EOF
> (include_subdirs qualified)
> (library
> (public_name foo)
> (name foo)
> (modes melange)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (melange.runtime_deps ./runtime/runtime.js))
> EOF
$ dune build --root lib
Entering directory 'lib'
Leaving directory 'lib'
$ cat lib/_build/default/foo.install
lib: [
"_build/install/default/lib/foo/META"
"_build/install/default/lib/foo/dune-package"
"_build/install/default/lib/foo/foo.ml"
"_build/install/default/lib/foo/melange/foo.cmi" {"melange/foo.cmi"}
"_build/install/default/lib/foo/melange/foo.cmj" {"melange/foo.cmj"}
"_build/install/default/lib/foo/melange/foo.cmt" {"melange/foo.cmt"}
"_build/install/default/lib/foo/runtime/runtime.js" {"runtime/runtime.js"}
]
$ grep melange_runtime_deps lib/_build/install/default/lib/foo/dune-package
(melange_runtime_deps runtime/runtime.js))

View file

@ -0,0 +1,34 @@
Test errors when public library runtime dependencies escape the dune file dir
$ mkdir lib app prefix
$ cat > lib/dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ mkdir -p lib/packages/foo/src/
$ echo "function foo() { return 42; }" > lib/packages/runtime.js
$ cat > lib/packages/foo/src/dune <<EOF
> (library
> (public_name foo)
> (name foo)
> (modes melange)
> (preprocess (pps melange.ppx))
> (melange.runtime_deps ../../runtime.js))
> EOF
$ cat > lib/packages/foo/src/foo.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let () = Js.log2 "dirname:" dirname
> EOF
$ dune build --root lib
Entering directory 'lib'
File "packages/foo/src/dune", line 6, characters 23-39:
6 | (melange.runtime_deps ../../runtime.js))
^^^^^^^^^^^^^^^^
Error: Public library `foo' depends on assets outside its source tree. This
is not allowed.
Hint: Move the offending dependency somewhere inside `packages/foo/src'.
Leaving directory 'lib'
[1]

View file

@ -0,0 +1,73 @@
Test `melange.runtime_deps` for installed libraries where the dune file is
nested more than the dune-project file
$ mkdir lib app prefix
$ cat > lib/dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ mkdir -p lib/packages/foo/src/
$ echo "function foo() { return 42; }" > lib/packages/foo/src/runtime.js
$ cat > lib/packages/foo/src/dune <<EOF
> (library
> (public_name foo)
> (name foo)
> (modes melange)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (melange.runtime_deps ./runtime.js))
> EOF
$ cat > lib/packages/foo/src/foo.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let () = Js.log2 "dirname:" dirname
> let read_asset () = Node.Fs.readFileSync (dirname ^ "/runtime.js") \`utf8
> EOF
$ dune build --root lib
Entering directory 'lib'
Leaving directory 'lib'
$ cat lib/_build/default/foo.install
lib: [
"_build/install/default/lib/foo/META"
"_build/install/default/lib/foo/dune-package"
"_build/install/default/lib/foo/foo.ml"
"_build/install/default/lib/foo/melange/foo.cmi" {"melange/foo.cmi"}
"_build/install/default/lib/foo/melange/foo.cmj" {"melange/foo.cmj"}
"_build/install/default/lib/foo/melange/foo.cmt" {"melange/foo.cmt"}
"_build/install/default/lib/foo/runtime.js"
]
$ cat lib/_build/install/default/lib/foo/dune-package | grep melange_runtime_deps
(melange_runtime_deps runtime.js))
$ dune install --root lib --prefix $PWD/prefix
$ mkdir -p app
$ cat > app/dune-project <<EOF
> (lang dune 3.8)
> (package (name app))
> (using melange 0.1)
> EOF
$ cat > app/dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (libraries foo))
> EOF
$ cat > app/main.ml <<EOF
> let () = Js.log (Foo.read_asset ())
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root app @melange
Entering directory 'app'
Leaving directory 'app'
File exists in output dir
$ ls app/_build/default/output/node_modules/foo
foo.js
runtime.js

View file

@ -0,0 +1,83 @@
Test `melange.runtime_deps` in a library that has been installed
$ mkdir lib app prefix
$ cat > lib/dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ mkdir -p lib/nested
$ echo "Some text" > lib/index.txt
$ echo "Some nested text" > lib/nested/hello.txt
$ cat > lib/dune <<EOF
> (library
> (public_name foo)
> (modes melange)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (melange.runtime_deps index.txt nested/hello.txt))
> EOF
$ cat > lib/foo.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let () = Js.log2 "dirname:" dirname
> let file_path = "./index.txt"
> let read_asset () = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> EOF
$ dune build --root lib
Entering directory 'lib'
Leaving directory 'lib'
$ cat lib/_build/default/foo.install
lib: [
"_build/install/default/lib/foo/META"
"_build/install/default/lib/foo/dune-package"
"_build/install/default/lib/foo/foo.ml"
"_build/install/default/lib/foo/index.txt"
"_build/install/default/lib/foo/melange/foo.cmi" {"melange/foo.cmi"}
"_build/install/default/lib/foo/melange/foo.cmj" {"melange/foo.cmj"}
"_build/install/default/lib/foo/melange/foo.cmt" {"melange/foo.cmt"}
"_build/install/default/lib/foo/nested/hello.txt" {"nested/hello.txt"}
]
$ cat lib/_build/install/default/lib/foo/dune-package | grep melange_runtime_deps
(melange_runtime_deps index.txt nested/hello.txt))
$ dune install --root lib --prefix $PWD/prefix
$ mkdir -p app/assets
$ cat > app/assets/file.txt <<EOF
> hello from file
> EOF
$ cat > app/dune-project <<EOF
> (lang dune 3.8)
> (package (name app))
> (using melange 0.1)
> EOF
$ cat > app/dune <<EOF
> (melange.emit
> (target output)
> (alias mel)
> (emit_stdlib false)
> (libraries foo melange.node)
> (preprocess (pps melange.ppx)))
> EOF
$ cat > app/main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> let () = Js.log (Foo.read_asset ())
> EOF
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build --root app @mel
Entering directory 'app'
Leaving directory 'app'
$ ls app/_build/default/output/node_modules/foo
foo.js
index.txt
nested

View file

@ -0,0 +1,68 @@
Melange (installed) library depends on private library
$ mkdir -p lib/lib lib/priv
$ cat > lib/dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ cat > lib/priv/dune <<EOF
> (library
> (name priv)
> (package foo)
> (modes melange))
> EOF
$ cat > lib/priv/priv.ml <<EOF
> let x = "private"
> EOF
$ cat > lib/lib/dune <<EOF
> (library
> (public_name foo)
> (modes melange)
> (libraries priv))
> EOF
$ cat > lib/lib/foo.ml <<EOF
> let x = "public lib uses " ^ Priv.x
> EOF
$ dune build @install --root lib
Entering directory 'lib'
Leaving directory 'lib'
$ dune install --prefix $PWD/prefix --root lib --display short
Installing $TESTCASE_ROOT/prefix/lib/foo/META
Installing $TESTCASE_ROOT/prefix/lib/foo/__private__/priv/melange/.public_cmi_melange/priv.cmi
Installing $TESTCASE_ROOT/prefix/lib/foo/__private__/priv/melange/.public_cmi_melange/priv.cmt
Installing $TESTCASE_ROOT/prefix/lib/foo/__private__/priv/melange/priv.cmj
Installing $TESTCASE_ROOT/prefix/lib/foo/__private__/priv/priv.ml
Installing $TESTCASE_ROOT/prefix/lib/foo/dune-package
Installing $TESTCASE_ROOT/prefix/lib/foo/foo.ml
Installing $TESTCASE_ROOT/prefix/lib/foo/melange/foo.cmi
Installing $TESTCASE_ROOT/prefix/lib/foo/melange/foo.cmj
Installing $TESTCASE_ROOT/prefix/lib/foo/melange/foo.cmt
$ mkdir app
$ cat > app/dune-project <<EOF
> (lang dune 3.8)
> (package (name foo))
> (using melange 0.1)
> EOF
$ cat > app/dune <<EOF
> (melange.emit
> (target output)
> (libraries foo)
> (emit_stdlib false))
> EOF
$ cat > app/entry.ml <<EOF
> let () = Js.log Foo.x
> EOF
Build the app that depends on `foo`, which in turn depends on a private lib
$ OCAMLPATH=$PWD/prefix/lib/:$OCAMLPATH dune build @melange --root app
Entering directory 'app'
Leaving directory 'app'

View file

@ -0,0 +1,19 @@
Entry points should not allow mli only modules as entry points.
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat >dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules_without_implementation foo)
> (alias mel))
> EOF
$ touch foo.mli bar.ml
$ dune build @mel
$ ls _build/default/output/*.js | sort
_build/default/output/bar.js

View file

@ -0,0 +1,3 @@
let buy_it: Lib.A.t = "buy it"
let () = Js.log buy_it

View file

@ -0,0 +1,5 @@
(melange.emit
(target output)
(alias mel)
(emit_stdlib false)
(libraries lib))

View file

@ -0,0 +1,3 @@
(lang dune 3.8)
(using melange 0.1)

View file

@ -0,0 +1,4 @@
(library
(name lib)
(modules_without_implementation a)
(modes melange))

View file

@ -0,0 +1,6 @@
Test melange libs flow when using `modules_without_implementation` stanza
Build js files
$ dune build @mel
$ node _build/default/output/b.js
buy it

View file

@ -0,0 +1,85 @@
Test what happens when melange.emit stanza depends on non-Melange libraries
$ cat > dune-project <<EOF
> (lang dune 3.14)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main_melange)
> (libraries foo))
> (executable
> (name main_native)
> (modules main_native)
> (libraries foo))
> EOF
$ cat > main_melange.ml <<EOF
> let _ = Foo.t
> EOF
$ cat > main_native.ml <<EOF
> let _ = Foo.t
> EOF
$ mkdir lib
$ cat > lib/dune <<EOF
> (library
> (name foo))
> EOF
$ cat > lib/Foo.ml <<EOF
> let t = "Hello World"
> EOF
Building the native executable does not fail
$ dune build ./main_native.exe
But building melange does
$ dune build @melange
File "lib/dune", lines 1-2, characters 0-21:
1 | (library
2 | (name foo))
Error: The library `foo` was added as a dependency of a `melange.emit`
stanza, but this library is not compatible with Melange. To fix this, add
`melange` to the `modes` field of the library `foo`.
[1]
Check the transitive case
$ cat > lib/dune <<EOF
> (library
> (name foo)
> (modes :standard melange)
> (libraries bar))
> EOF
$ cat > lib/Foo.ml <<EOF
> let t = Bar.t
> EOF
$ mkdir lib2
$ cat > lib2/dune <<EOF
> (library
> (name bar))
> EOF
$ cat > lib/Bar.ml <<EOF
> let t = "Hello World"
> EOF
$ dune build @melange
File "lib2/dune", lines 1-2, characters 0-21:
1 | (library
2 | (name bar))
Error: The library `bar` was added as a dependency of a `melange.emit`
stanza, but this library is not compatible with Melange. To fix this, add
`melange` to the `modes` field of the library `bar`.
[1]

View file

@ -0,0 +1,99 @@
Test moving modules in a library with `(include_subdirs unqualified)`
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (alias mel)
> (libraries foo)
> (emit_stdlib false)
> (preprocess (pps melange.ppx)))
> EOF
$ mkdir lib
$ cat > lib/dune <<EOF
> (include_subdirs unqualified)
> (library
> (name foo)
> (modes melange))
> EOF
$ cat > lib/foo.ml <<EOF
> let name = Bar.name
> EOF
$ mkdir lib/init
$ cat > lib/init/bar.ml <<EOF
> let name = "Zoe"
> EOF
$ dune build @mel
Melange shows the proper path to `bar.js`
$ cat _build/default/output/lib/foo.js | grep bar.js
const Foo__Bar = require("./init/bar.js");
$ mv lib/init lib/end
$ dune build @mel
The import in `foo.js` has been updated to the new bar.js target
$ cat _build/default/output/lib/foo.js | grep bar.js
const Foo__Bar = require("./end/bar.js");
The initial file is not there anymore
$ test -f _build/default/output/lib/init/bar.js
[1]
But the new one is
$ test -f _build/default/output/lib/end/bar.js
Now try the same thing with `melange.emit`
$ rm -rf lib
$ cat > dune <<EOF
> (include_subdirs unqualified)
> (melange.emit
> (target output)
> (alias mel)
> (emit_stdlib false)
> (preprocess (pps melange.ppx)))
> EOF
$ mkdir init
$ cat > init/bar.ml <<EOF
> let name = "Zoe"
> EOF
$ cat > foo.ml <<EOF
> let name = Bar.name
> EOF
$ dune build @mel
Melange shows the proper path to `bar.js`
$ cat _build/default/output/foo.js | grep bar.js
const Melange__Bar = require("./init/bar.js");
$ mv init end
$ dune build @mel
The import in `foo.js` has been updated to the new bar.js target
$ cat _build/default/output/foo.js | grep bar.js
const Melange__Bar = require("./end/bar.js");
The initial file is not there anymore
$ test -f _build/default/output/init/bar.js
[1]
But the new one is
$ test -f _build/default/output/end/bar.js

View file

@ -0,0 +1,64 @@
Test library modes
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
Build a regular library and an executable
$ mkdir lib
$ cat > lib/dune <<EOF
> (library
> (name mylib))
> EOF
$ cat > lib/mylib.ml <<EOF
> let some_binding = "string"
> EOF
$ cat > dune <<EOF
> (executable
> (name main)
> (modes byte exe)
> (libraries mylib))
> EOF
$ cat > main.ml <<EOF
> let () =
> print_endline Mylib.some_binding
> EOF
$ dune build main.bc
Now let's make the library compatible with melange
$ cat > lib/dune <<EOF
> (library
> (name mylib)
> (modes :standard melange))
> EOF
$ cat > main_melange.ml <<EOF
> let () =
> print_endline Mylib.some_binding
> EOF
$ cat > dune <<EOF
> (executable
> (name main)
> (modes byte exe)
> (modules main)
> (libraries mylib))
> (melange.emit
> (alias dist)
> (modules main_melange)
> (emit_stdlib false)
> (target dist)
> (libraries mylib))
> EOF
$ dune build @dist
$ dune build main.bc

View file

@ -0,0 +1,65 @@
Test `melange.runtime_deps` in a private library
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (alias mel)
> (libraries foo)
> (emit_stdlib false)
> (preprocess (pps melange.ppx))
> (runtime_deps assets/file.txt))
> EOF
$ mkdir lib
$ echo "Some text" > lib/index.txt
$ cat > lib/dune <<EOF
> (library
> (name foo)
> (modes melange)
> (libraries melange.node)
> (preprocess (pps melange.ppx))
> (melange.runtime_deps index.txt))
> EOF
$ cat > lib/foo.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./index.txt"
> let read_asset () = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> EOF
$ mkdir assets
$ cat > assets/file.txt <<EOF
> hello from file
> EOF
$ cat > main.ml <<EOF
> let dirname = [%mel.raw "__dirname"]
> let file_path = "./assets/file.txt"
> let file_content = Node.Fs.readFileSync (dirname ^ "/" ^ file_path) \`utf8
> let () = Js.log file_content
> let () = Js.log (Foo.read_asset ())
> EOF
$ dune build @mel
The runtime_dep index.txt was copied to the library build folder
$ ls _build/default/lib
foo.ml
foo.pp.ml
index.txt
The runtime_dep index.txt was copied to the build folder
$ ls _build/default/output/lib
foo.js
index.txt
$ node _build/default/output/main.js
hello from file
Some text

View file

@ -0,0 +1,4 @@
(melange.emit
(target out)
(lint
(pps correct_static_add)))

View file

@ -0,0 +1,28 @@
let detect_static_add = object
inherit Ppxlib.Ast_traverse.iter as super
method! expression e =
match e with
| { pexp_desc =
Pexp_apply
( {pexp_desc = Pexp_ident {txt = Lident "+"; _}; _}
, [ (Nolabel, {pexp_desc = Pexp_constant (Pconst_integer (a, None)); _})
; (Nolabel, {pexp_desc = Pexp_constant (Pconst_integer (b, None)); _})
]
)
; pexp_loc = loc
; _
} ->
let sum = int_of_string a + int_of_string b in
let repl = string_of_int sum in
Ppxlib.Driver.register_correction ~loc ~repl
| _ -> super#expression e
end
let impl s =
detect_static_add#structure s; s
let () =
Ppxlib.Driver.register_transformation
"detect_static_add"
~impl

View file

@ -0,0 +1,4 @@
(library
(name correct_static_add)
(kind ppx_rewriter)
(libraries ppxlib))

View file

@ -0,0 +1,3 @@
(lang dune 3.13)
(using melange 0.1)

View file

@ -0,0 +1,15 @@
The lint alias will run preprocessing actions listed under (lint). It also
defines corrections that may be promoted.
$ cat > correct/add.ml << EOF
> let () = Printf.printf "%d\n" @@ 1 + 2
> EOF
$ dune build @correct/lint
File "correct/add.ml", line 1, characters 0-0:
Error: Files _build/default/correct/add.ml and
_build/default/correct/add.ml.lint-corrected differ.
[1]
$ dune promote correct/add.ml
Promoting _build/default/correct/add.ml.lint-corrected to correct/add.ml.
$ cat correct/add.ml
let () = Printf.printf "%d\n" @@ 3

View file

@ -0,0 +1,93 @@
Test that melange.emit targets are not included in @install for packages they
don't belong to.
$ mkdir lib test ppx
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (package (name my-ppx))
> (package (name mel-foo))
> (using melange 0.1)
> EOF
$ cat > ppx/dune <<EOF
> (library
> (name my_ppx)
> (public_name my-ppx))
> EOF
$ touch ppx/my_ppx.ml
$ cat > lib/dune <<EOF
> (library
> (public_name mel-foo)
> (name mel_foo)
> (modes melange)
> (preprocess (pps melange.ppx)))
> EOF
$ cat > lib/mel_foo.ml <<EOF
> let x = "lib"
> EOF
$ cat > test/dune <<EOF
> (melange.emit
> (package mel-foo)
> (target js-out)
> (emit_stdlib false)
> (libraries mel-foo))
> EOF
$ cat > test/test_entry.ml <<EOF
> let () = Js.log Mel_foo.x
> EOF
`melange.emit` is attached to the package `mel-foo`, so it shouldn't be built
when building the other library
$ dune build -p my-ppx
It still builds everything normally with the alias
$ dune build @melange
$ ls _build/default/test/js-out/test/
test_entry.js
Now define a 3rd lib that we'll use to preprocess the melange.emit entries:
$ dune clean
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (package (name my-ppx))
> (package (name mel-foo))
> (package (name my-ppx2))
> (using melange 0.1)
> EOF
$ mkdir ppx2
$ cat > ppx2/dune <<EOF
> (library
> (name my_ppx2)
> (kind ppx_rewriter) (libraries ppxlib)
> (public_name my-ppx2))
> EOF
$ touch ppx2/my_ppx2.ml
$ cat > test/dune <<EOF
> (melange.emit
> (package mel-foo)
> (target js-out)
> (preprocess (pps my-ppx2))
> (emit_stdlib false)
> (libraries mel-foo))
> EOF
we can still build my-ppx independently
$ dune build -p my-ppx
and fails if it can't resolve libraries to build the alias
$ dune build @melange -p my-ppx
File "test/dune", line 6, characters 12-19:
6 | (libraries mel-foo))
^^^^^^^
Error: Library "mel-foo" not found.
-> required by _build/default/test/js-out/test/test_entry.js
-> required by alias test/melange
[1]

View file

@ -0,0 +1,33 @@
Show that Dune shouldn't emit a JS file for the `melange.emit` module group
wrapper
$ cat > dune-project <<EOF
> (lang dune 3.18)
> (using melange 0.1)
> EOF
$ cat > dune <<EOF
> (melange.emit
> (alias dist)
> (target dist)
> (emit_stdlib false))
> EOF
If there's more than 1 module, we currently emit the module group wrapper,
`.dist.mobjs/melange.js`
$ cat > x.ml <<EOF
> let () = print_endline "x"
> EOF
$ cat > y.ml <<EOF
> let () = print_endline "y"
> EOF
$ dune build @dist --display=short 2>&1 | grep 'melange\.js'
[1]
$ ls -a _build/default/dist
.
..
x.js
y.js

View file

@ -0,0 +1,44 @@
Show that the merlin config knows about melange.compile_flags
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ lib=foo
$ cat >dune <<EOF
> (library
> (name $lib)
> (private_modules bar)
> (melange.compile_flags :standard -w +42)
> (modes melange))
> EOF
$ touch bar.ml $lib.ml
$ dune build @check
$ dune ocaml merlin dump-config "$PWD" | grep -i "+42"
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
$ cat >dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (compile_flags :standard -w +42 ))
> EOF
$ dune build @check
$ dune ocaml merlin dump-config "$PWD" | grep -i "+42"
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w +42))

View file

@ -0,0 +1,183 @@
Temporary special merlin support for melange only libs
$ ocamlc_where="$(ocamlc -where)"
$ export BUILD_PATH_PREFIX_MAP="/OCAMLC_WHERE=$ocamlc_where:$BUILD_PATH_PREFIX_MAP"
$ melc_compiler="$(which melc)"
$ export BUILD_PATH_PREFIX_MAP="$(melc_stdlib_prefix)":$BUILD_PATH_PREFIX_MAP
$ export BUILD_PATH_PREFIX_MAP="/MELC_COMPILER=$melc_compiler:$BUILD_PATH_PREFIX_MAP"
$ export BUILD_PATH_PREFIX_MAP="/MELC_STDLIB=$(ocamlfind query melange):$BUILD_PATH_PREFIX_MAP"
$ cat >dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ lib=foo
$ cat >dune <<EOF
> (library
> (name $lib)
> (private_modules bar)
> (modes melange))
> EOF
$ touch bar.ml $lib.ml
$ dune build @check
$ dune ocaml merlin dump-config "$PWD" | grep -i "$lib"
((INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(B $TESTCASE_ROOT/_build/default/.foo.objs/melange)
(FLG (-open Foo__))
(UNIT_NAME foo__Bar))
((INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(B $TESTCASE_ROOT/_build/default/.foo.objs/melange)
(FLG (-open Foo__))
(UNIT_NAME foo__Bar))
Foo: _build/default/foo
((INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(B $TESTCASE_ROOT/_build/default/.foo.objs/melange)
(FLG (-open Foo__))
(UNIT_NAME foo))
Foo: _build/default/foo.ml
((INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(B $TESTCASE_ROOT/_build/default/.foo.objs/melange)
(FLG (-open Foo__))
(UNIT_NAME foo))
Foo__: _build/default/foo__
((INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(B $TESTCASE_ROOT/_build/default/.foo.objs/melange)
(UNIT_NAME foo__))
Foo__: _build/default/foo__.ml-gen
((INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(B $TESTCASE_ROOT/_build/default/.foo.objs/melange)
(UNIT_NAME foo__))
Paths to Melange stdlib appear in B and S entries without melange.emit stanza
$ dune ocaml dump-dot-merlin $PWD | grep -e "^B " -e "^S "
B /MELC_STDLIB/__private__/melange_mini_stdlib/melange/.public_cmi_melange
B /MELC_STDLIB/melange
B /MELC_STDLIB/melange
B $TESTCASE_ROOT/_build/default/.foo.objs/melange
S /MELC_STDLIB
S /MELC_STDLIB/__private__/melange_mini_stdlib
S /MELC_STDLIB
S $TESTCASE_ROOT
$ target=output
$ cat >dune <<EOF
> (melange.emit
> (target "$target")
> (compile_flags :standard --mel-noassertfalse)
> (emit_stdlib false)
> (modules main))
> EOF
$ touch main.ml
$ dune build @check
$ dune ocaml merlin dump-config $PWD | grep -i "$target"
(B $TESTCASE_ROOT/_build/default/.output.mobjs/melange)
(B $TESTCASE_ROOT/_build/default/.output.mobjs/melange)
Dump-dot-merlin includes the melange flags
$ dune ocaml dump-dot-merlin $PWD
EXCLUDE_QUERY_DIR
STDLIB /MELC_STDLIB/melange
SOURCE_ROOT $TESTCASE_ROOT
B /MELC_STDLIB/__private__/melange_mini_stdlib/melange/.public_cmi_melange
B /MELC_STDLIB/melange
B /MELC_STDLIB/melange
B $TESTCASE_ROOT/_build/default/.output.mobjs/melange
S /MELC_STDLIB
S /MELC_STDLIB/__private__/melange_mini_stdlib
S /MELC_STDLIB
S $TESTCASE_ROOT
# FLG -w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g --mel-noassertfalse
Check for flag directives ordering when another preprocessor is defined
$ cat >fooppx.ml <<EOF
> open Ppxlib
>
> let rules =
> let extension =
> Extension.declare "test" Expression Ast_pattern.__ (fun ~loc ~path:_ _ ->
> Ast_builder.Default.eint ~loc 42)
> in
> [ Context_free.Rule.extension extension ]
>
> let () = Ppxlib.Driver.register_transformation "rules" ~rules
> EOF
$ cat >dune <<EOF
> (library
> (name $lib)
> (private_modules bar)
> (modules bar)
> (preprocess (pps fooppx))
> (modes melange))
> (library
> (name fooppx)
> (modules fooppx)
> (libraries ppxlib)
> (kind ppx_rewriter))
> EOF
$ dune build @check
User ppx flags should appear in merlin config
$ dune ocaml merlin dump-config $PWD | grep -v "(B " | grep -v "(S "
Bar: _build/default/bar
((INDEX $TESTCASE_ROOT/_build/default/.fooppx.objs/cctx.ocaml-index)
(INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(STDLIB /MELC_STDLIB/melange)
(SOURCE_ROOT $TESTCASE_ROOT)
(EXCLUDE_QUERY_DIR)
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g))
(FLG (-ppx "$TESTCASE_ROOT/_build/default/.ppx/3a8685470d9b5edd99690707a29a2b1a/ppx.exe --as-ppx --cookie 'library-name="foo"'"))
(FLG (-open Foo))
(UNIT_NAME foo__Bar))
Bar: _build/default/bar.ml
((INDEX $TESTCASE_ROOT/_build/default/.fooppx.objs/cctx.ocaml-index)
(INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(STDLIB /MELC_STDLIB/melange)
(SOURCE_ROOT $TESTCASE_ROOT)
(EXCLUDE_QUERY_DIR)
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g))
(FLG (-ppx "$TESTCASE_ROOT/_build/default/.ppx/3a8685470d9b5edd99690707a29a2b1a/ppx.exe --as-ppx --cookie 'library-name="foo"'"))
(FLG (-open Foo))
(UNIT_NAME foo__Bar))
Foo: _build/default/foo
((INDEX $TESTCASE_ROOT/_build/default/.fooppx.objs/cctx.ocaml-index)
(INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(STDLIB /MELC_STDLIB/melange)
(SOURCE_ROOT $TESTCASE_ROOT)
(EXCLUDE_QUERY_DIR)
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g))
(FLG (-ppx "$TESTCASE_ROOT/_build/default/.ppx/3a8685470d9b5edd99690707a29a2b1a/ppx.exe --as-ppx --cookie 'library-name="foo"'"))
(UNIT_NAME foo))
Foo: _build/default/foo.ml-gen
((INDEX $TESTCASE_ROOT/_build/default/.fooppx.objs/cctx.ocaml-index)
(INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(STDLIB /MELC_STDLIB/melange)
(SOURCE_ROOT $TESTCASE_ROOT)
(EXCLUDE_QUERY_DIR)
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g))
(FLG (-ppx "$TESTCASE_ROOT/_build/default/.ppx/3a8685470d9b5edd99690707a29a2b1a/ppx.exe --as-ppx --cookie 'library-name="foo"'"))
(UNIT_NAME foo))
Fooppx: _build/default/fooppx
((INDEX $TESTCASE_ROOT/_build/default/.fooppx.objs/cctx.ocaml-index)
(INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(STDLIB /OCAMLC_WHERE)
(SOURCE_ROOT $TESTCASE_ROOT)
(EXCLUDE_QUERY_DIR)
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g))
(UNIT_NAME fooppx))
Fooppx: _build/default/fooppx.ml
((INDEX $TESTCASE_ROOT/_build/default/.fooppx.objs/cctx.ocaml-index)
(INDEX $TESTCASE_ROOT/_build/default/.foo.objs/cctx.ocaml-index)
(STDLIB /OCAMLC_WHERE)
(SOURCE_ROOT $TESTCASE_ROOT)
(EXCLUDE_QUERY_DIR)
(FLG (-w @1..3@5..28@30..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -g))
(UNIT_NAME fooppx))

View file

@ -0,0 +1,90 @@
Test cases when melc is not available
$ cat > dune-project <<EOF
> (lang dune 3.8)
> (using melange 0.1)
> EOF
$ cat > main_melange.ml <<EOF
> let () =
> print_endline "hello from melange"
> EOF
Set up some fake environment without melc
$ mkdir _path
$ ln -s $(command -v dune) _path/
$ ln -s $(command -v ocamlc) _path/
$ ln -s $(command -v ocamldep) _path/
For melange.emit stanzas, an error is shown
$ cat > dune <<EOF
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main_melange)
> (alias mel))
> EOF
$ (unset INSIDE_DUNE; PATH=_path dune build --always-show-command-line --root . @mel 2>&1 | grep Program)
Error: Program melc not found in the tree or in PATH
For libraries, if no melange.emit stanza is found, build does not fail
$ cat > dune <<EOF
> (library
> (name lib1)
> (modules :standard \ main_native)
> (modes byte melange))
> (executable
> (name main_native)
> (modules main_native)
> (modes exe byte)
> (libraries lib1))
> EOF
$ cat > main_native.ml <<EOF
> let () =
> print_endline Lib1.Lib.t
> EOF
$ cat > lib.ml <<EOF
> let t = "hello from native"
> EOF
$ (unset INSIDE_DUNE; PATH=_path dune build --always-show-command-line --root . main_native.bc)
$ dune exec ./main_native.bc
hello from native
If melange.emit stanza is found, but no rules are executed, build does not fail
$ cat > dune <<EOF
> (library
> (name lib1)
> (modules :standard \ main_native main_melange)
> (modes byte melange))
> (executable
> (name main_native)
> (modules main_native)
> (modes exe byte)
> (libraries lib1))
> (melange.emit
> (target output)
> (emit_stdlib false)
> (modules main_melange)
> (libraries lib1))
> EOF
$ (unset INSIDE_DUNE; PATH=_path dune build --always-show-command-line --root . main_native.bc)
$ dune exec ./main_native.bc
hello from native
But trying to build any melange artifacts will fail
$ (unset INSIDE_DUNE; PATH=_path dune build --always-show-command-line --root . output/main_melange.js)
File ".lib1.objs/melange/_unknown_", line 1, characters 0-0:
Error: Program melc not found in the tree or in PATH
(context: default)
Hint: opam install melange
[1]

View file

@ -0,0 +1,6 @@
(melange.emit
(target mli)
(modules x)
(libraries lib)
(emit_stdlib false)
(alias mel))

View file

@ -0,0 +1,6 @@
(lang dune 3.8)
(using melange 0.1)
(package
(name x))

View file

@ -0,0 +1,3 @@
(library
(name lib)
(modes melange))

View file

@ -0,0 +1 @@
let it = "it"

View file

@ -0,0 +1 @@
val it: string

Some files were not shown because too many files have changed in this diff Show more