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,9 @@
;; This test erroneously modify one of its dependencies
(alias
(name x)
(deps data (universe))
(action (system "\| echo hello >> data
"\| # To force the mtime to change:
"\| # https://github.com/ocaml/dune/pull/1359
"\| touch -t 01010000 data
)))

View file

@ -0,0 +1,20 @@
In this test the "x" alias depends on the file "data" but the action
associated to "x" appends a line to "data". The expected behavior is
an error from Dune telling the user that this is not allowed, however
Dune currently silently ignores this.
$ echo hello > data
$ dune build @x
$ cat _build/default/data
hello
hello
$ dune build @x
$ cat _build/default/data
hello
hello
$ dune build @x
$ cat _build/default/data
hello
hello

View file

@ -0,0 +1,231 @@
Test for --action-stdxxx-on-success
====================================
$ export BUILD_PATH_PREFIX_MAP="sh=$(command -v sh):$BUILD_PATH_PREFIX_MAP"
$ echo '(lang dune 3.0)' > dune-project
$ cat > dune <<EOF
> (rule
> (alias default)
> (action (system "echo 'Hello, world!'")))
>
> (rule
> (alias default)
> (action (system "echo 'Something went wrong!' >&2")))
>
> (rule
> (alias both-stdout-and-stderr-output)
> (action (system "echo stdout; echo stderr >&2")))
> EOF
By default, stdout and stderr are always printed:
$ dune build
Hello, world!
Something went wrong!
swallow tests
-------------
$ dune clean
$ dune build --action-stdout-on-success=swallow --action-stderr-on-success=swallow
must-be-empty tests
----------------------
In the two above tests, we ask Dune to enforce that the the stdout
(resp. stderr) of actions is empty via the must-be-empty setting.
Since the first rule has a non-empty stdout and the second has a
non-empty stderr, we observe that in each case the build fails
printing the output of the action that had a non-empty output.
$ dune clean
$ dune build --action-stdout-on-success=must-be-empty
Something went wrong!
File "dune", lines 1-3, characters 0-65:
1 | (rule
2 | (alias default)
3 | (action (system "echo 'Hello, world!'")))
Hello, world!
[1]
$ dune clean
$ dune build --action-stderr-on-success=must-be-empty
Hello, world!
File "dune", lines 5-7, characters 0-77:
5 | (rule
6 | (alias default)
7 | (action (system "echo 'Something went wrong!' >&2")))
Something went wrong!
[1]
Same but with output on both stdout and stderr:
$ dune clean
$ dune build @both-stdout-and-stderr-output \
> --action-stdout-on-success=must-be-empty \
> --action-stderr-on-success=must-be-empty
File "dune", lines 9-11, characters 0-95:
9 | (rule
10 | (alias both-stdout-and-stderr-output)
11 | (action (system "echo stdout; echo stderr >&2")))
stdout
stderr
[1]
Incremental builds
------------------
Dune handles --action-stdxxx-on-success in such a way that if
changing the status of one of the two option changes what is printed
to the terminal, then the action is re-executed.
$ dune clean
$ dune build \
> --action-stdout-on-success=swallow \
> --action-stderr-on-success=swallow
For instance, if we previously swallowed stdout/stderr and stop doing
it, actions that printed something to stdout or stderr are
re-executed:
$ dune build
Hello, world!
Something went wrong!
However, we currently re-execute too much. In particular, we
re-execute actions whose outcome is not affected by the change:
$ cat > dune <<EOF
> (rule
> (alias default)
> (action (system "echo a.stdout; echo a.stderr >&2")))
>
> (rule
> (alias default)
> (action (system "echo b.stderr >&2")))
> EOF
$ dune clean
$ dune build --action-stdout-on-success=swallow
a.stderr
b.stderr
You can observe in the below call that both actions are being
re-executed:
$ dune build
a.stdout
a.stderr
b.stderr
However, re-executing the second action was not necessary given that
its stdout was empty. Dune could have recorded the fact that the
second action had an empty stdout and so was unaffected by the status
of --action-stdout-on-success. Dune could also cache the
stdout/stderr of actions across builds and only re-print them rather
than re-execute actions entirely.
In case of errors
-----------------
In case of errors, we print everything no matter what.
$ cat > dune <<EOF
> (rule
> (alias default)
> (action (system "echo 'Hello, world!'; exit 1")))
> EOF
$ dune build
File "dune", lines 1-3, characters 0-73:
1 | (rule
2 | (alias default)
3 | (action (system "echo 'Hello, world!'; exit 1")))
Hello, world!
[1]
$ dune clean
$ dune build --action-stdout=swallow
File "dune", lines 1-3, characters 0-73:
1 | (rule
2 | (alias default)
3 | (action (system "echo 'Hello, world!'; exit 1")))
Hello, world!
[1]
$ dune clean
$ dune build --action-stdout=must-be-empty
File "dune", lines 1-3, characters 0-73:
1 | (rule
2 | (alias default)
3 | (action (system "echo 'Hello, world!'; exit 1")))
Hello, world!
[1]
With compound actions
---------------------
At the moment, the behavior is a bit odd. We swallow the stdout of the
first command but not the second:
$ cat > dune <<EOF
> (rule
> (alias default)
> (action
> (progn
> (system "echo 1")
> (system "echo 2; exit 1"))))
> EOF
$ dune build --action-stdout-on-success=swallow
File "dune", lines 1-6, characters 0-93:
1 | (rule
2 | (alias default)
3 | (action
4 | (progn
5 | (system "echo 1")
6 | (system "echo 2; exit 1"))))
2
[1]
For must-be-empty, if two programs print something without failing we
stop at the first program. That's not terrible, but it would seem
better if we stop at the end of the whole action.
$ cat > dune <<EOF
> (rule
> (alias default)
> (action
> (progn
> (system "echo 1")
> (system "echo 2"))))
> EOF
$ dune build --action-stdout-on-success=must-be-empty
File "dune", lines 1-6, characters 0-85:
1 | (rule
2 | (alias default)
3 | (action
4 | (progn
5 | (system "echo 1")
6 | (system "echo 2"))))
1
[1]
With builtin actions
--------------------
We currently never swallow the output of builtin actions such as
`echo`, which is odd:
$ cat > dune <<EOF
> (rule
> (alias default)
> (action (echo "Hello, world!\n")))
> EOF
$ dune build --action-stdout-on-success=swallow
Hello, world!

View file

@ -0,0 +1,3 @@
(executable
(name sub_process)
(libraries unix))

View file

@ -0,0 +1,10 @@
let () =
match Sys.argv with
| [| _ |] -> exit (Sys.command (Filename.quote_command Sys.executable_name [ "sub" ]))
| [| _; "sub" |] ->
let oc = open_out (Sys.getenv "BEACON_FILE") in
Printf.fprintf oc "%d" (Unix.getpid ());
close_out oc;
Unix.sleep max_int
| _ -> assert false
;;

View file

@ -0,0 +1,60 @@
$ cat > dune-project << EOF
> (lang dune 3.4)
> EOF
It is an error to pass an empty list:
$ cat > dune << EOF
> (rule
> (alias runtest)
> (action
> (cat result)))
>
> (rule
> (with-stdout-to result
> (cat)))
> EOF
$ dune runtest
File "dune", line 8, characters 2-7:
8 | (cat)))
^^^^^
Error: Not enough arguments for "cat"
[1]
The cat action supports several files.
$ echo "file a" > a
$ echo "file b" > b
$ echo "file c" > c
$ cat > dune << EOF
> (rule
> (alias runtest)
> (action
> (cat result)))
>
> (rule
> (with-stdout-to result
> (cat a b c)))
> EOF
$ dune runtest
file a
file b
file c
This requires 3.4.
$ cat > dune-project << EOF
> (lang dune 3.3)
> EOF
$ dune runtest
File "dune", line 8, characters 2-13:
8 | (cat a b c)))
^^^^^^^^^^^
Error: Passing several arguments to 'cat' is only available since version 3.4
of the dune language. Please update your dune-project file to have (lang dune
3.4).
[1]

View file

@ -0,0 +1,84 @@
The use of (concurrent ) illustrated in the context of diffing multiple files.
Say we want to diff 3 files.
$ cat A
I am file A.
$ cat B
I am file B.
$ cat C
I am file C.
We set up a (progn ) rule to diff all of them against their generated versions.
$ cat > dune << EOF
> (rule
> (action
> (progn
> (with-outputs-to A.diff (echo "I am file A.\n"))
> (with-outputs-to B.diff (echo "I am certainly file B.\n"))
> (with-outputs-to C.diff (echo "I am most certainly file C.\n")))))
>
> (rule
> (action
> (progn
> (with-outputs-to some-target (echo a))
> (diff A A.diff)
> (diff B B.diff)
> (diff C C.diff))))
> EOF
We can now run the rule and see that we fail before diffing C.
$ dune build
File "B", line 1, characters 0-0:
Error: Files _build/default/B and _build/default/B.diff differ.
[1]
We can check which diffs were run by asking Dune to promote the files.
$ dune promotion apply
Promoting _build/default/B.diff to B.
Since we failed early, only B was promoted.
Let's reset B to its original state.
$ rm B
$ cat > B << EOF
> I am file B.
> EOF
If we implement the rule using (concurrent ) instead.
$ cat > dune << EOF
> (rule
> (action
> (progn
> (with-outputs-to A.diff (echo "I am file A.\n"))
> (with-outputs-to B.diff (echo "I am certainly file B.\n"))
> (with-outputs-to C.diff (echo "I am most certainly file C.\n")))))
>
> (rule
> (action
> (concurrent
> (with-outputs-to some-target (echo a))
> (diff A A.diff)
> (diff B B.diff)
> (diff C C.diff))))
> EOF
We see that all the files get diffed.
$ dune build
File "B", line 1, characters 0-0:
Error: Files _build/default/B and _build/default/B.diff differ.
File "C", line 1, characters 0-0:
Error: Files _build/default/C and _build/default/C.diff differ.
[1]
And we have promotions for the two that failed.
$ dune promote
Promoting _build/default/B.diff to B.
Promoting _build/default/C.diff to C.

View file

@ -0,0 +1,58 @@
Specification of the concurrency action:
$ cat > dune-project << EOF
> (lang dune 3.7)
> EOF
$ cat > dune << EOF
> (rule
> (action
> (concurrent )))
> EOF
$ dune build
File "dune", line 3, characters 2-15:
3 | (concurrent )))
^^^^^^^^^^^^^
Error: 'concurrent' is only available since version 3.8 of the dune language.
Please update your dune-project file to have (lang dune 3.8).
[1]
Requires Dune 3.8.
$ cat > dune-project << EOF
> (lang dune 3.8)
> EOF
(concurrent ...) runs actions concurrently. Here we mock up an example where two
subactions rely on eachother to also be running in order to terminate.
We write a shell script that will simultaneously read and write to two named
pipes. (This has to be similtaneious otherwise the read will block the write).
They will block on the read however, which means if called with the same two
pipes but swapped, they will only terminate when both scripts are running at the
same time.
$ cat > run.sh << EOF
> echo foo>\$1 & read line<\$2
> EOF
We create an action that will create named pipes a and b and then run our script
on both of them, but importantly inside the concurrent action. This will
demonstrate that subactions are indeed being run concurrently.
$ cat > dune << EOF
> (rule
> (deps run.sh)
> (alias my-rule)
> (action
> (progn
> (run mkfifo a b)
> (concurrent
> (run sh run.sh a b)
> (run sh run.sh b a)))))
> EOF
When we run the rule, we see that the two actions are indeed run concurrently.
$ dune build -j2 @my-rule --force
Notice the need for a -j2. If Dune was configured with -j1 then the action would
never terminate.

View file

@ -0,0 +1,6 @@
(cram
(deps ../watching/helpers.sh bin/sub_process.exe))
(cram
(applies_to concurrent)
(enabled_if false))

View file

@ -0,0 +1,35 @@
Shows what happens when Dune tries to kill an action that has sub-processes.
$ . ../watching/helpers.sh
$ export PATH=$PWD/bin:$PATH
$ echo '(lang dune 3.0)' > dune-project
$ cat >dune <<"EOF"
> (rule
> (action
> (progn
> (run sub_process.exe)
> (with-stdout-to x (echo "")))))
> EOF
$ export BEACON_FILE=$PWD/test-started
$ start_dune
$ build x >/dev/null 2>&1 &
sub_process.exe spawns a sub-process that creates $BEACON_FILE. We
wait for the beacon to be notified that the sub-process has started:
$ with_timeout dune_cmd wait-for-file-to-appear $BEACON_FILE
$ CHILD_PID=`cat $BEACON_FILE`
Now we stop Dune, which should normally kill all sub-processes:
$ stop_dune
$ if kill -s 0 $CHILD_PID 2> /dev/null; then
> echo "FAILURE: child is still running"
> else
> echo "SUCCESS: child has exited"
> fi
SUCCESS: child has exited

View file

@ -0,0 +1,71 @@
$ cat > dune-project << EOF
> (lang dune 2.0)
> (using action-plugin 0.1)
> EOF
$ cat > dune <<EOF
> (executable
> (name exit)
> (modules exit))
> (rule (with-stdout-to exit.ml (echo "let () = exit (int_of_string Sys.argv.(1))")))
> EOF
$ cat >> dune <<EOF
> (rule
> (alias a)
> (action (with-accepted-exit-codes 0 (run ./exit.exe 1))))
> EOF
$ dune build --display=short --root . @a
ocamlc .exit.eobjs/byte/dune__exe__Exit.{cmi,cmo,cmt}
ocamlopt .exit.eobjs/native/dune__exe__Exit.{cmx,o}
ocamlopt exit.exe
File "dune", lines 5-7, characters 0-75:
5 | (rule
6 | (alias a)
7 | (action (with-accepted-exit-codes 0 (run ./exit.exe 1))))
exit alias a (exit 1)
[1]
$ cat >> dune <<EOF
> (rule
> (alias b)
> (action (with-accepted-exit-codes (not 0) (run ./exit.exe 1))))
> EOF
$ dune build --display=short --root . @b
exit alias b
$ cat >> dune <<EOF
> (rule
> (alias c)
> (action (with-accepted-exit-codes (or 1 2 3) (run ./exit.exe 2))))
> (rule
> (alias d)
> (action (with-accepted-exit-codes (or 4 5 6) (run ./exit.exe 7))))
> EOF
$ dune build --display=short --root . @c
exit alias c
$ dune build --display=short --root . @d
File "dune", lines 14-16, characters 0-84:
14 | (rule
15 | (alias d)
16 | (action (with-accepted-exit-codes (or 4 5 6) (run ./exit.exe 7))))
exit alias d (exit 7)
[1]
$ cat >> dune <<EOF
> (rule
> (alias e)
> (action (with-accepted-exit-codes (not 0) (dynamic-run ./exit.exe 1))))
> EOF
$ dune build --display=short --root . @e
File "dune", line 19, characters 43-69:
19 | (action (with-accepted-exit-codes (not 0) (dynamic-run ./exit.exe 1))))
^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: with-accepted-exit-codes can only be used with "run", "bash" or
"system"
[1]

View file

@ -0,0 +1,116 @@
$ cat > dune-project << EOF
> (lang dune 2.2)
> (using action-plugin 0.1)
> EOF
$ cat > dune <<EOF
> (executable
> (name exit)
> (modules exit))
> (rule (with-stdout-to exit.ml (echo "let () = exit (int_of_string Sys.argv.(1))")))
> EOF
$ cat >> dune <<EOF
> (rule
> (alias f)
> (action (with-accepted-exit-codes
> 1
> (with-stdout-to out.txt
> (run ./exit.exe 1)))))
> EOF
$ dune build --display=short --root . @f
ocamlc .exit.eobjs/byte/dune__exe__Exit.{cmi,cmo,cmt}
ocamlopt .exit.eobjs/native/dune__exe__Exit.{cmx,o}
ocamlopt exit.exe
exit out.txt
$ cat >> dune <<EOF
> (rule
> (alias f2)
> (action (with-accepted-exit-codes
> 1
> (with-stdin-from input
> (chdir .
> (run ./exit.exe 1))))))
> EOF
$ echo "Hello, Dune!" > input
$ dune build --display=short --root . @f2
exit alias f2
$ cat >> dune <<EOF
> (rule
> (alias f3)
> (action (with-accepted-exit-codes
> 0
> (setenv VAR myvar
> (chdir .
> (system "echo \$VAR"))))))
> EOF
$ dune build --display=short --root . @f3
sh alias f3
myvar
$ cat >> dune <<EOF
> (rule
> (alias f4)
> (action (with-accepted-exit-codes
> 0
> (setenv VAR myvar
> (ignore-stdout
> (bash "echo \$VAR"))))))
> EOF
$ dune build --display=short --root . @f4
bash alias f4
$ cat >> dune <<EOF
> (rule
> (alias f5)
> (action (with-accepted-exit-codes
> 0
> (setenv VAR myvar
> (with-stdin-from input
> (chdir .
> (with-stdout-to out2.txt
> (run ./exit.exe 1))))))))
> EOF
$ echo "Hello, Dune!" > input
$ dune build --display=short --root . @f5
File "dune", lines 32-40, characters 0-225:
32 | (rule
33 | (alias f5)
34 | (action (with-accepted-exit-codes
35 | 0
36 | (setenv VAR myvar
37 | (with-stdin-from input
38 | (chdir .
39 | (with-stdout-to out2.txt
40 | (run ./exit.exe 1))))))))
exit out2.txt (exit 1)
[1]
$ cat >> dune <<EOF
> (rule
> (alias g)
> (action
> (with-accepted-exit-codes
> (not 0)
> (setenv VAR myvar
> (chdir .
> (with-stdout-to out.txt
> (dynamic-run ./exit.exe 1)))))))
> EOF
$ dune build --display=short --root . @g
File "dune", lines 46-49, characters 3-98:
46 | (setenv VAR myvar
47 | (chdir .
48 | (with-stdout-to out.txt
49 | (dynamic-run ./exit.exe 1)))))))
Error: Only "run", "bash", "system", "chdir", "setenv", "ignore-<outputs>",
"with-stdin-from", "with-<outputs>-to" and "no-infer" can be nested under
"with-accepted-exit-codes"
[1]

View file

@ -0,0 +1,13 @@
$ cat > dune-project <<EOF
> (lang dune 2.0)
> EOF
$ cat > dune << EOF
> (rule (with-stdin-from input (with-stdout-to output (run cat))))
> EOF
$ echo "Hello, Dune!" > input
$ dune build --root . @all
$ cat _build/default/output
Hello, Dune!

View file

@ -0,0 +1,29 @@
$ cat > dune-project << EOF
> (lang dune 2.0)
> (using action-plugin 0.1)
> EOF
$ cat > dune <<EOF
> (executable
> (name exit)
> (modules exit))
> (rule (with-stdout-to exit.ml (echo "let () = exit (int_of_string Sys.argv.(1))")))
> EOF
$ cat >> dune <<EOF
> (rule
> (alias a)
> (action (with-accepted-exit-codes
> 1
> (with-stdout-to out.txt
> (run ./exit.exe 1)))))
> EOF
$ dune build --display=short --root . @a
File "dune", lines 9-10, characters 10-64:
9 | (with-stdout-to out.txt
10 | (run ./exit.exe 1)))))
Error: nesting modifiers under 'with-accepted-exit-codes' is only available
since version 2.2 of the dune language. Please update your dune-project file
to have (lang dune 2.2).
[1]

View file

@ -0,0 +1,39 @@
Some macros treat ':' as an argument delimiter but others do not. A consequence
of this is macro arguments which intentionally include a ':' character may look
like a sequence of multiple arguments but are treated as a single argument by
macros that don't split their argument on ':'. This tests that we maintain this
behaviour as we change the way that macros are implemented.
This test installs a binary whose name contains a ':' character and then checks
that we can look up the binary with the `bin` macro which does not split its
arguments on ':'.
$ cat > dune-project <<EOF
> (lang dune 3.0)
> (package (name foo))
> EOF
$ cat > foo.sh <<EOF
> #!/usr/bin/env sh
> echo foo
> EOF
$ chmod +x foo.sh
$ cat >dune <<EOF
> ; Use an install stanza to rename the script to "foo:bar"
> (install
> (section bin)
> (files (foo.sh as foo:bar)))
>
> ; Generate out.txt by running the script now named "foo:bar"
> (rule
> (target out.txt)
> (action
> (with-stdout-to %{target}
> (run %{bin:foo:bar}))))
> EOF
$ dune build out.txt
$ cat _build/default/out.txt
foo

View file

@ -0,0 +1,33 @@
Demonstrate the --alias argument to build aliases in the command
line without the @ syntax
$ cat >dune-project <<EOF
> (lang dune 3.19)
> EOF
$ cat >dune <<EOF
> (rule
> (alias foo)
> (action (echo "root: foo\n")))
> (rule
> (alias bar)
> (action (echo "root: bar\n")))
> EOF
$ mkdir x
$ cat >x/dune <<EOF
> (rule
> (alias bar)
> (action (echo "x: bar\n")))
> EOF
$ dune build --alias foo --alias x/bar
root: foo
x: bar
$ dune clean
$ dune build --alias-rec bar
root: bar
x: bar

View file

@ -0,0 +1,18 @@
Dune should suggest similar aliases when it cannot find one.
$ cat > dune-project << EOF
> (lang dune 3.7)
> EOF
$ cat > dune << EOF
> (rule
> (alias foo)
> (action
> (echo "Hello, world from \"foo\"!")))
> EOF
We have an alias "foo" but let's try to build something misspeled:
$ dune build @fou
Error: Alias "fou" specified on the command line is empty.
It is not defined in . or any of its descendants.
Hint: did you mean fmt or foo?
[1]

View file

@ -0,0 +1,67 @@
Testing the empty alias
$ cat > dune-project <<EOF
> (lang dune 3.17)
> EOF
Building the empty alias does nothing
$ dune build @empty
We should check that a user has not added anything to an empty alias:
$ cat > dune <<EOF
> (rule
> (alias empty)
> (action
> (echo "I should not be added!")))
> EOF
For versions prior to 3.20 this does not fail:
$ dune build @empty
I should not be added!
Also creating an alias called empty is allowed prior to 3.20:
$ cat > dune <<EOF
> (alias
> (name empty)
> (deps foo))
> EOF
$ cat > foo
$ dune build @empty
For versions 3.20 and after these should fail:
$ cat > dune-project <<EOF
> (lang dune 3.20)
> EOF
$ cat > dune <<EOF
> (rule
> (alias empty)
> (action
> (echo "I should not be added!")))
> EOF
$ dune build @empty
File "dune", lines 1-4, characters 0-65:
1 | (rule
2 | (alias empty)
3 | (action
4 | (echo "I should not be added!")))
Error: User-defined rules cannot be added to the 'empty' alias
[1]
$ cat > dune <<EOF
> (alias
> (name empty)
> (deps foo))
> EOF
$ dune build @empty
File "dune", lines 1-3, characters 0-33:
1 | (alias
2 | (name empty)
3 | (deps foo))
Error: User-defined rules cannot be added to the 'empty' alias
[1]

View file

@ -0,0 +1,22 @@
Test alias module for wrapped libraries that don't have a main module, i.e. the
wrap module is generated by dune.
$ cat >dune-project <<EOF
> (lang dune 3.5)
> EOF
$ cat >dune <<EOF
> (library
> (name foo))
> EOF
$ touch bar.ml
$ dune build
$ cat _build/default/foo.ml-gen
(* generated by dune *)
(** @canonical Foo.Bar *)
module Bar = Foo__Bar
The final `Foo` module should not be marked as deprecated/shadowed, since it
does not shadow any module.

View file

@ -0,0 +1,21 @@
Test alias module for wrapped libraries:
$ cat >dune-project <<EOF
> (lang dune 3.5)
> EOF
$ cat >dune <<EOF
> (library
> (name foo))
> EOF
$ touch foo.ml bar.ml
$ dune build
$ cat _build/default/foo__.ml-gen
(* generated by dune *)
(** @canonical Foo.Bar *)
module Bar = Foo__Bar
module Foo__ = struct end
[@@deprecated "this module is shadowed"]

View file

@ -0,0 +1,128 @@
Testing multiple aliases in rules stanza
First we start with a dune-project before alias was introduced:
$ cat > dune-project << EOF
> (lang dune 1.9)
> EOF
$ cat > dune << EOF
> (rule
> (alias a)
> (action (echo "I have run")))
> EOF
$ dune build @a
File "dune", line 2, characters 1-10:
2 | (alias a)
^^^^^^^^^
Error: 'alias' is only available since version 2.0 of the dune language.
Please update your dune-project file to have (lang dune 2.0).
[1]
Next we update the dune-project file to use dune 2.0:
$ cat > dune-project << EOF
> (lang dune 2.0)
> EOF
$ dune build @a
I have run
We now update the dune file to use multiple aliases
$ cat > dune << EOF
> (rule
> (alias a b)
> (action (echo "I have run")))
> EOF
$ dune build @a
File "dune", line 2, characters 10-11:
2 | (alias a b)
^
Error: Too many arguments for "alias"
[1]
That doesn't work so we use the aliases field
$ cat > dune << EOF
> (rule
> (aliases a b)
> (action (echo "I have run")))
> EOF
$ dune build @a @b
File "dune", line 2, characters 1-14:
2 | (aliases a b)
^^^^^^^^^^^^^
Error: 'aliases' is only available since version 3.5 of the dune language.
Please update your dune-project file to have (lang dune 3.5).
[1]
Updating the dune-project file to use dune 3.5 allows the build to succeed:
$ cat > dune-project << EOF
> (lang dune 3.5)
> EOF
$ dune build @a
I have run
$ dune build @b
Also note having both the alias and aliases fields in the same rule stanza is
not allowed
$ cat > dune << EOF
> (rule
> (alias a)
> (aliases b)
> (action (echo "I have run")))
> EOF
$ dune build @a
File "dune", lines 1-4, characters 0-60:
1 | (rule
2 | (alias a)
3 | (aliases b)
4 | (action (echo "I have run")))
Error: fields "alias" and "aliases" are mutually exclusive.
[1]
Even if the aliases list is empty
$ cat > dune << EOF
> (rule
> (alias a)
> (aliases)
> (action (echo "I have run")))
> EOF
$ dune build @a
File "dune", lines 1-4, characters 0-58:
1 | (rule
2 | (alias a)
3 | (aliases)
4 | (action (echo "I have run")))
Error: fields "alias" and "aliases" are mutually exclusive.
[1]
Building both aliases at the same time should only run the action once
$ cat > dune << EOF
> (rule
> (aliases a b)
> (action (echo "I have run\n")))
> EOF
$ dune clean
$ dune build @a @b
I have run
A similar test with a rule that produces a target
$ cat > dune << EOF
> (rule
> (targets a)
> (aliases b c)
> (action
> (progn
> (echo "I have run\n")
> (with-stdout-to a (echo "foo")))))
> EOF
$ dune clean
$ dune build @b @c
I have run

View file

@ -0,0 +1,11 @@
(alias
(name just-in-src)
(deps (alias src/x)))
(alias
(name everywhere)
(deps (alias_rec x)))
(alias
(name alias-depending-on-unknown-alias)
(deps (alias unknown-alias)))

View file

@ -0,0 +1 @@
(lang dune 1.0)

View file

@ -0,0 +1,32 @@
$ dune clean
$ dune build @just-in-src
running in .
$ dune clean
$ dune build @everywhere
running in .
running in bar
running in baz
$ dune clean
$ dune build @x
running in .
running in bar
running in baz
$ dune build @plop
Error: Alias "plop" specified on the command line is empty.
It is not defined in . or any of its descendants.
[1]
$ dune build @truc/x
Error: Don't know about directory truc specified on the command line!
[1]
Test error messages for unknown aliases
$ dune build @unknown-alias
Error: Alias "unknown-alias" specified on the command line is empty.
It is not defined in . or any of its descendants.
[1]
$ dune build @alias-depending-on-unknown-alias
Error: No rule found for alias unknown-alias
-> required by alias alias-depending-on-unknown-alias in dune:9
[1]

View file

@ -0,0 +1,3 @@
(alias
(name x)
(action (chdir %{workspace_root} (echo "running in .\n"))))

View file

@ -0,0 +1,3 @@
(alias
(name x)
(action (chdir %{workspace_root} (echo "running in bar\n"))))

View file

@ -0,0 +1,3 @@
(alias
(name x)
(action (chdir %{workspace_root} (echo "running in baz\n"))))

View file

@ -0,0 +1,5 @@
(rule (with-stdout-to foo (run echo foo)))
(alias
(name install)
(deps foo))

View file

@ -0,0 +1,4 @@
@all includes user defined install alias
$ dune build --display short @all
echo foo

View file

@ -0,0 +1,6 @@
@all builds custom install stanzas
$ dune build @subdir/all
Error: No rule found for subdir/foobar
-> required by alias subdir/all
[1]

View file

@ -0,0 +1,3 @@
(install
(section share)
(files foobar))

View file

@ -0,0 +1 @@
(executable (name foo))

View file

@ -0,0 +1,4 @@
@all builds private exe's
$ dune build @all --display short 2>&1 | grep -i exe
ocamlopt foo.exe

View file

@ -0,0 +1 @@
(library (name bar))

View file

@ -0,0 +1,4 @@
@all builds private libs
$ dune build --display short @all 2>&1 | grep bar.cma
ocamlc bar.cma

View file

@ -0,0 +1,34 @@
@all does not depend directly on file copies from the source tree
$ cat > dune-project <<EOF
> (lang dune 3.0)
> EOF
Add two files
$ touch a.ml b.ml
An empty project, should not copy any file.
$ dune build
$ [ -d _build/default ] && find _build/default -name '*.ml'
[1]
A project that only uses a.ml, should not copy b.ml
$ cat > dune <<EOF
> (library (name a) (modules a))
> EOF
$ dune build
$ find _build/default -name '*.ml'
_build/default/a.ml
A project that uses both files, should copy both.
$ cat > dune <<EOF
> (library (name a))
> EOF
$ dune build
$ find _build/default -name '*.ml' | sort
_build/default/a.ml
_build/default/b.ml

View file

@ -0,0 +1 @@
(rule (with-stdout-to foo (run echo foobar)))

View file

@ -0,0 +1,4 @@
@all builds user defined rules
$ dune build --display short @all
echo foo

View file

@ -0,0 +1,9 @@
(alias
(name runtest)
(locks l)
(action (diff a.expected a)))
(alias
(name runtest)
(locks l)
(action (diff b.expected b)))

View file

@ -0,0 +1,2 @@
(lang dune 1.11)
(name promotion-stop-example)

View file

@ -0,0 +1,10 @@
All promotions should be run, whether they share locks or not:
The following should trigger two failures, one for a.expected and one for
b.expected but it is not because of a bug introduced in 2.0.
$ dune runtest
File "a.expected", line 1, characters 0-0:
Error: Files _build/default/a.expected and _build/default/a differ.
File "b.expected", line 1, characters 0-0:
Error: Files _build/default/b.expected and _build/default/b differ.
[1]

View file

@ -0,0 +1,43 @@
Check support for alternative dune file name "dune-file".
The feature is not supported in < 3.0.
$ cat >dune-project <<EOF
> (lang dune 2.8)
> (accept_alternative_dune_file_name)
> EOF
$ dune build
File "dune-project", line 2, characters 0-35:
2 | (accept_alternative_dune_file_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: 'accept_alternative_dune_file_name' is only available since version
3.0 of the dune language. Please update your dune-project file to have (lang
dune 3.0).
[1]
The feature *is* supported in 3.0 and later, but it is opt-in:
$ cat >dune-project <<EOF
> (lang dune 3.0)
> EOF
$ cat >dune <<EOF
> (rule (alias foo) (action (echo "In dune")))
> EOF
$ cat >dune-file <<EOF
> (rule (alias foo) (action (echo "In dune-file")))
> EOF
$ dune build @foo
In dune
Need to enable explicitly:
$ cat >dune-project <<EOF
> (lang dune 3.0)
> (accept_alternative_dune_file_name)
> EOF
$ dune build @foo
In dune-file

View file

@ -0,0 +1,4 @@
(alias
(name runtest)
(deps
(alias /foo/bar)))

View file

@ -0,0 +1,7 @@
$ dune runtest
File "dune", line 4, characters 9-17:
4 | (alias /foo/bar)))
^^^^^^^^
Error: Invalid alias!
Tried to reference path outside build dir: "/foo/bar"
[1]

View file

@ -0,0 +1,4 @@
(alias
(name runtest)
(deps
(alias %{workspace_root}/../../../foobar)))

View file

@ -0,0 +1,6 @@
$ dune runtest
File "dune", line 4, characters 9-42:
4 | (alias %{workspace_root}/../../../foobar)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: path outside the workspace: ./../../../foobar from default
[1]

View file

@ -0,0 +1,3 @@
let _c = Bigarray.C_layout_typ
let () = Printf.eprintf "Welcome to a\n%!"

View file

@ -0,0 +1,3 @@
(executable
(name a)
(libraries bigarray))

View file

@ -0,0 +1,5 @@
let _c1 = B_lib.v
let _c2 = Bigarray.C_layout_typ
let () = Printf.eprintf "Welcome to b\n%!"

View file

@ -0,0 +1 @@
let v = Bigarray.C_layout_typ

View file

@ -0,0 +1,10 @@
(library
(name b_lib)
(libraries
(re_export bigarray))
(modules b_lib))
(executable
(name b)
(libraries b_lib)
(modules b))

View file

@ -0,0 +1,3 @@
let _c = Bigarray.C_layout_typ
let () = Printf.eprintf "Welcome to c WITH bigarray support\n%!"

View file

@ -0,0 +1 @@
let () = Printf.eprintf "Welcome to c with nothing inferred\n%!"

View file

@ -0,0 +1 @@
let () = Printf.eprintf "Welcome to c WITHOUT bigarray support\n%!"

View file

@ -0,0 +1,9 @@
(executable
(name c)
(libraries
(select
c.ml
from
(!bigarray -> c.nobigarray.ml)
(bigarray -> c.bigarray.ml)
(-> c.dummy.ml))))

View file

@ -0,0 +1,3 @@
let _d = Bigarray.C_layout_typ
let () = Printf.eprintf "Welcome to d WITH bigarray support\n%!"

View file

@ -0,0 +1 @@
let () = Printf.eprintf "Welcome to d with nothing inferred\n%!"

View file

@ -0,0 +1 @@
let () = Printf.eprintf "Welcome to d WITHOUT bigarray support\n%!"

View file

@ -0,0 +1,9 @@
(executable
(name d)
(libraries
(select
d.ml
from
(bigarray -> d.bigarray.ml)
(!bigarray -> d.nobigarray.ml)
(-> d.dummy.ml))))

View file

@ -0,0 +1,3 @@
(lang dune 3.0)
(implicit_transitive_deps false)

View file

@ -0,0 +1,27 @@
This tests the support for the bigarray atom in the dune libraries stanza.
History:
- OCaml 4.08 ([ocaml/ocaml#2263](https://github.com/ocaml/ocaml/pull/2263))
deletes the `map_file` functions completely, requiring _all_ code to be
updated to use `Unix.map_file`, if appropriate. From this release, it is
unnecessary to link with the separate Bigarray library.
- OCaml 5.00 ([ocaml/ocaml#10896](https://github.com/ocaml/ocaml/pull/10896)
removes the separate Bigarray library.
Code may be written which is designed to support both OCaml 4.06 and earlier and
also OCaml 5.0+. In such cases, it is appropriate to have `(libraries bigarray)`
even though there is no Bigarray library in OCaml 5.
This test uses `(libraries bigarray)` (the program uses `Bigarray`)
$ dune exec a/a.exe
Welcome to a
This test uses `(libraries (re_export bigarray))` similarly
$ dune exec b/b.exe
Welcome to b
This test uses a `(select )` construct and should always select bigarray support
$ dune exec c/c.exe
Welcome to c WITH bigarray support
This test uses a `(select )` construct and should always select bigarray
support (the evaluation of `select` order differs from the previous test)
$ dune exec d/d.exe
Welcome to d WITH bigarray support

View file

@ -0,0 +1,41 @@
Test for %{bin-available:...}
$ cat >dune-project <<EOF
> (lang dune 3.0)
> (package (name foo))
> EOF
$ cat >dune<<"EOF"
> (install
> (section bin)
> (enabled_if false)
> (files disabled))
> (rule
> (alias available)
> (action
> (progn
> (echo "dune: %{bin-available:dune}\n")
> (echo "local program foo: %{bin-available:foo}\n")
> (echo "non existent program: %{bin-available:*}\n")
> (echo "local path foo: %{bin-available:./foo}\n")
> (echo "local path bar: %{bin-available:./bar}\n")
> (echo "disabled binary is available: %{bin-available:disabled}\n")
> (echo "disabled by enabled_if: %{bin-available:bar}\n"))))
>
> (executable
> (public_name foo)
> (modules foo))
> (executable
> (public_name bar)
> (modules bar)
> (enabled_if false))
> EOF
$ touch foo.ml bar.ml
$ dune build @available
dune: true
local program foo: true
non existent program: false
local path foo: false
local path bar: false
disabled binary is available: false
disabled by enabled_if: false

View file

@ -0,0 +1,18 @@
Reproduces issue #3252
https://github.com/ocaml/dune/issues/3252
If a rule requires an expansion that introduces a failure, we should fail only
when the rule needs to be used to build a target.
$ cat >dune-project <<EOF
> (lang dune 2.0)
> (package (name randompackage))
> EOF
$ cat >dune <<EOF
> (rule
> (targets testfile)
> (deps %{bin:doesnotexistbinary})
> (action (echo "test")))
> EOF
$ dune build @install

View file

@ -0,0 +1,48 @@
; Example script taken from re2
; With normal strings
(alias
(name old)
(action (echo "\
ARFLAGS=rsc
CXX=g++
CXXFLAGS=\"-Wall -O3 -g -pthread\"
if ! ${.ARCH_SIXTYFOUR}; then
CXX=\"$CXX -m32\"
fi
${.MAKE} -s -C libre2 clean
${.MAKE} -s -C libre2 \\
ARFLAGS=\"$ARFLAGS\" \\
CXX=\"$CXX\" \\
CXXFLAGS=\"$CXXFLAGS\" \\
obj/libre2.a obj/so/libre2.so
cp libre2/obj/libre2.a libre2_c_stubs.a
cp libre2/obj/so/libre2.so dllre2_c_stubs.so
${.MAKE} -s -C libre2 clean
")))
; With block strings
(alias
(name new)
(action (echo "\> ARFLAGS=rsc
"\> CXX=g++
"\> CXXFLAGS="-Wall -O3 -g -pthread"
"\> if ! ${.ARCH_SIXTYFOUR}; then
"\> CXX="$CXX -m32"
"\> fi
"\> ${.MAKE} -s -C libre2 clean
"\> ${.MAKE} -s -C libre2 \
"\> ARFLAGS="$ARFLAGS" \
"\> CXX="$CXX" \
"\> CXXFLAGS="$CXXFLAGS" \
"\> obj/libre2.a obj/so/libre2.so
"\> cp libre2/obj/libre2.a libre2_c_stubs.a
"\> cp libre2/obj/so/libre2.so dllre2_c_stubs.so
"\> ${.MAKE} -s -C libre2 clean
)))
(alias
(name quoting-test)
(action (echo "\| normal: \065
"\> raw: \065
)))

View file

@ -0,0 +1,37 @@
$ dune build @old
ARFLAGS=rsc
CXX=g++
CXXFLAGS="-Wall -O3 -g -pthread"
if ! ${.ARCH_SIXTYFOUR}; then
CXX="$CXX -m32"
fi
${.MAKE} -s -C libre2 clean
${.MAKE} -s -C libre2 \
ARFLAGS="$ARFLAGS" \
CXX="$CXX" \
CXXFLAGS="$CXXFLAGS" \
obj/libre2.a obj/so/libre2.so
cp libre2/obj/libre2.a libre2_c_stubs.a
cp libre2/obj/so/libre2.so dllre2_c_stubs.so
${.MAKE} -s -C libre2 clean
$ dune build @new
ARFLAGS=rsc
CXX=g++
CXXFLAGS="-Wall -O3 -g -pthread"
if ! ${.ARCH_SIXTYFOUR}; then
CXX="$CXX -m32"
fi
${.MAKE} -s -C libre2 clean
${.MAKE} -s -C libre2 \
ARFLAGS="$ARFLAGS" \
CXX="$CXX" \
CXXFLAGS="$CXXFLAGS" \
obj/libre2.a obj/so/libre2.so
cp libre2/obj/libre2.a libre2_c_stubs.a
cp libre2/obj/so/libre2.so dllre2_c_stubs.so
${.MAKE} -s -C libre2 clean
$ dune build @quoting-test
normal: A
raw: \065

View file

@ -0,0 +1,72 @@
Pform expansion should work in `exec` but also in `build`:
$ cat > dune-project << EOF
> (lang dune 3.10)
> (package (name public))
> EOF
$ cat > dune << EOF
> (executable (public_name public) (modules Public))
> (executable (name private) (modules Private))
> (env
> (_ (binaries (private.exe as priv))))
> EOF
The executables in question just display what they are:
$ cat > public.ml << EOF
> let () = print_endline "Public"
> EOF
$ cat > private.ml << EOF
> let () = print_endline "Private"
> EOF
We also have a subfolder `foo`
$ mkdir foo
$ cat > foo/dune << EOF
> (executable (public_name blah))
> (env
> (_ (binaries (blah.exe as foo))))
> EOF
$ cat > foo/blah.ml << EOF
> let () = print_endline "Blah"
> EOF
Making Dune build the executables should work without error messages:
$ dune build %{bin:public}
Error: File unavailable:
$TESTCASE_ROOT/../install/default/bin/public
[1]
$ ls _build/default/public.exe
_build/default/public.exe
Building the private executable should also work.
$ dune build %{bin:private}
File "command line", line 1, characters 0-14:
Error: Program private not found in the tree or in PATH
(context: default)
[1]
$ ls _build/default/private.exe > /dev/null 2>&1 || return 1
[1]
Building the private executable via the env alias should work too:
$ dune build %{bin:priv}
$ (cd foo && dune build --root .. %{bin:priv}) # should work
Entering directory '..'
Leaving directory '..'
$ dune build %{bin:foo} # doesn't work because foo is underneath us
File "command line", line 1, characters 0-10:
Error: Program foo not found in the tree or in PATH
(context: default)
[1]
$ (cd foo && dune build --root .. %{bin:foo}) # should work
Entering directory '..'
File "command line", line 1, characters 0-10:
Error: Program foo not found in the tree or in PATH
(context: default)
Leaving directory '..'
[1]

View file

@ -0,0 +1,19 @@
Build a binary using a %{bin:..}` form
$ cat >dune-project <<EOF
> (lang dune 3.7)
> (package
> (name randompkg))
> EOF
$ mkdir bin
$ touch bin/bar.ml
$ cat >bin/dune <<EOF
> (executable
> (public_name bar))
> EOF
$ dune build '%{bin:bar}'
Error: File unavailable:
$TESTCASE_ROOT/../install/default/bin/bar
[1]

View file

@ -0,0 +1,70 @@
Generate empty interfaces when using (empty_module_interface_if_absent)
$ cat >dune-project <<EOF
> (lang dune 3.0)
> EOF
Executables
$ cat >main.ml <<EOF
> module D = Dep
> EOF
$ touch dep.ml
$ cat >dune <<EOF
> (executable (name main) (empty_module_interface_if_absent))
> EOF
$ dune build ./main.exe
$ cat _build/default/dep.mli
(* Auto-generated by Dune *)
Libraries
$ cat >dune <<EOF
> (library (name l) (modules a b) (empty_module_interface_if_absent))
> EOF
$ touch a.ml b.ml
$ dune build
$ cat _build/default/a.mli
(* Auto-generated by Dune *)
$ cat _build/default/b.mli
(* Auto-generated by Dune *)
Version check
$ cat >dune-project <<EOF
> (lang dune 2.9)
> EOF
$ dune build
File "dune", line 1, characters 32-66:
1 | (library (name l) (modules a b) (empty_module_interface_if_absent))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: 'empty_module_interface_if_absent' is only available since version 3.0
of the dune language. Please update your dune-project file to have (lang dune
3.0).
[1]
Check that interfaces are *not* generated if field is not used
$ cat >dune <<EOF
> (lang dune 3.0)
> EOF
$ cat >dune <<EOF
> (library (name l) (modules a b))
> EOF
$ touch a.mli
$ dune build
$ test -f _build/default/a.mli
$ test ! -f _build/default/b.mli

View file

@ -0,0 +1,47 @@
Create a library called `findlib.dynload`
$ mkdir findlib
$ cat > findlib/dune-project <<EOF
> (lang dune 3.7)
> (package (name findlib))
> EOF
$ cat > findlib/dune <<EOF
> (library
> (name findlib_dynload)
> (public_name findlib.dynload)
> (wrapped false)
> (libraries findlib dynlink)
> (modules fl_dynload)
> (special_builtin_support findlib_dynload))
> (library
> (public_name findlib)
> (modules findlib))
> EOF
$ cat >findlib/findlib.ml <<EOF
> type x = Record_core
> let record_package _ _ = assert false
> let record_package_predicates _ _ = assert false
> EOF
$ touch findlib/fl_dynload.ml
$ cat > dune-project <<EOF
> (lang dune 3.7)
> EOF
$ mkdir lib
$ cat > lib/dune <<EOF
> (library
> (name foo_dynload)
> (libraries findlib.dynload))
> EOF
$ touch lib/foo_dynload.ml
$ mkdir exe
$ cat > exe/dune <<EOF
> (executable
> (name the_exe)
> (libraries foo_dynload))
> EOF
$ touch exe/the_exe.ml
$ dune build

View file

@ -0,0 +1,4 @@
(executable
(name print_version)
(modes exe byte)
(libraries build_info))

View file

@ -0,0 +1,4 @@
let () =
(match Build_info.Build_info_data.version with
| None -> print_endline "<version missing>"
| Some version -> print_endline version)

View file

@ -0,0 +1,4 @@
(executable
(name toto)
(modes exe byte)
(public_name toto))

View file

@ -0,0 +1 @@
print_endline "Hello, world!"

View file

@ -0,0 +1,5 @@
(* The implementation of this module is generated by dune when linking an
executable *)
val version : string option
val statically_linked_libraries : (string * string option) list

View file

@ -0,0 +1,7 @@
(library
(name build_info)
(modules_without_implementation build_info_data)
(special_builtin_support
(build_info
(data_module build_info_data)
(api_version 1))))

View file

@ -0,0 +1,3 @@
(executable
(name foo)
(modes native))

View file

@ -0,0 +1,3 @@
#!/bin/sh
export PATH="$ORIG_PATH"
exec ocamlc "$@"

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