ocaml / dune

A composable build system for OCaml.
https://dune.build/
MIT License
1.6k stars 397 forks source link

dune --version returns n/a #5554

Closed olafhering closed 2 years ago

olafhering commented 2 years ago

For me dune --version returns n/a. It is not obvious why this happens.

The boostrap procedure in boot/duneboot.ml does read dune-release, looking for the (version N) line. This is working correctly in my builds, the dune binary correctly reports the injected version:

[   49s] + sed -i~ '
[   49s]        /^([[:blank:]]*version[[:blank:]]\+/d
[   49s]        /^([[:blank:]]*lang[[:blank:]]\+dune[[:blank:]]/a (version 3.0.3)
[   49s]        ' dune-project
[   49s] + diff -u dune-project~ dune-project
[   49s] --- dune-project~  2022-03-01 18:14:02.000000000 +0000
[   49s] +++ dune-project   2022-04-07 12:33:31.737431896 +0000
[   49s] @@ -1,4 +1,5 @@
[   49s]  (lang dune 3.0)
[   49s] +(version 3.0.3)
[   49s]  ;          ^^^
[   49s]  ; When changing the version, don't forget to regenerate *.opam files
[   49s]  ; by running [dune build].
...
[   49s] + dune --version
[   49s] 3.0.3

However, building the "full" dune in a fresh, clean source, prepared with the sed call above, a dune build --verbose --for-release-of-packages=dune,dune-action-plugin,dune-build-info,dune-configurator,dune-glob,dune-private-libs,dune-rpc,dune-site,dyn,fiber,ordering,stdune,xdg -j16 @install results in a dune binary that returns n/a as version.

The question is: how is Build_info.V1.version supposed to be populated? I assume bin/main.ml is the place which processes --version.

emillon commented 2 years ago

Hi!

The question is: how is Build_info.V1.version supposed to be populated?

This mechanism is related to dune-build-info. In most cases, this piece of info is sourced from the (version) field in dune-project.

olafhering commented 2 years ago

Thanks. I add it with sed. So why is it not used? Which part is reading dune-project, which code should I instrument to see why it misses the version entry?

emillon commented 2 years ago

Can you explain how you get dune sources, when do you run sed and which dune binary are you talking about? If you want a 3.0.3 binary, you can start from the 3.0.3 tarball

From a git clone, does the following work (make clean is important):

 $ make clean
 $ echo '(version blabla)' >> dune-project
 $ make release
 $ ./_build/install/default/bin/dune --version
blabla
olafhering commented 2 years ago

Well, that gets me back to my question about the differences between the result of make dune.exe vs. make release.

In devel:languages:ocaml git hashes are exported verbatim with git archive into something like ocaml-dune-3.0.3.tar.xz.

It is my understanding that a full dune needs csexp, pp and result as dependencies. All three are built with dune, so that initial dune.exe is copied away into a separate ocaml-dune-bootstrap.rpm, which is then used to build csexp, pp and result. The full dune is built with --for-release-of-packages= as stated above.

But now that I tried to build without having dune in the list of --for-release-of-packages= I noticed it will build just the libs. For some reason it failed for me in the past with 3.0.0 (I do not have notes what the failure was).

I will look into this again next week. Perhaps I can undo the split of ocaml-dune-bootstrap again.

emillon commented 2 years ago

Well, that gets me back to my question about the differences between the result of make dune.exe vs. make release.

I'm not familiar enough with the bootstrap process to comment on this, sorry :/

In devel:languages:ocaml git hashes are exported verbatim with git archive into something like ocaml-dune-3.0.3.tar.xz.

OK, this is more or less a git clone. So you'll need to set (version) in dune-project.

It is my understanding that a full dune needs csexp, pp and result as dependencies.

Not quite, the dune sources that you obtain by cloning are self-contained because they contain convenience copies of these libraries. You will get a "full dune" by running the command listed in dune.opam (which correspond to make release) and getting the binary at _build/install/default/bin/dune.

Is it an issue to use these convenience copies?

olafhering commented 2 years ago

But now that I tried to build without having dune in the list of --for-release-of-packages= I noticed it will build just the libs. For some reason it failed for me in the past with 3.0.0 (I do not have notes what the failure was).

The actual error was: ocaml-dune.rpm contains just /usr/bin/dune + man pages + documentation as expected, but in addition it installs a META file which claims to be dune-configurator and it requires dune-configurator. This is translated into a rpm Provides + Requires, as a result ocaml-dune.rpm requires another package which provides dune-configurator, which can not exist at this point in the bootstrap process of the entire OCaml. I may open another bug about this, unless this META file is supposed to be that way.

In the meantime I adjusted the build process as you have suggested. Essentially it does what dune.opam does. There is a ./dune.exe and a _build/_default/dune.exe and even a dune.install and man pages. The resulting dune binaries provide the expected --version output.

olafhering commented 2 years ago

Reproducer, it prints n/a in the end, instead of the expected 3.0.3. dune5554.sh.txt

emillon commented 2 years ago

I removed the part that builds ocaml and tested the following:

#!/bin/bash
set -ex
read td < <(mktemp --directory --tmpdir=/dev/shm .XXX)
trap "rm -rf '${td}'" EXIT
pushd "${td}"
unset LANG
unset ${!LC_*}
cpus="$(getconf _NPROCESSORS_ONLN)"
ver_dune='3.0.3'
url_dune="https://github.com/ocaml/dune/archive/refs/tags/${ver_dune}.tar.gz"
tgz_dune='dune.tar.gz'
out_dune1='dune1'
prefix="${td}/prefix"
where="${td}/where"
curl -Lso "${tgz_dune}" "${url_dune}"
export PATH="${prefix}/bin:${PATH}"
mkdir "${out_dune1}"
pushd "${out_dune1}"
tar --extract --file="../${tgz_dune}" --auto-compress --strip-components=1
sed -i~ "
/^([[:blank:]]*version[[:blank:]]\+/d
/^([[:blank:]]*lang[[:blank:]]\+dune[[:blank:]]/a (version ${ver_dune})
" dune-project
(
ocaml configure.ml --libdir="${where}"
ocaml bootstrap.ml -j ${cpus}
./dune.exe --version
./dune.exe build dune.install --release --profile dune-bootstrap -j ${cpus}
./dune.exe install dune --release --profile dune-bootstrap -j ${cpus} --prefix="${prefix}" --libdir="${where}"
) &> log.txt
popd
rm -rf "${out_dune1}"
dune --version

This prints 3.0.3. Does it work for you too?

olafhering commented 2 years ago

Yes, of course. This is the code path everyone is using.

emillon commented 2 years ago

OK, sorry I was confused about the build plan. This is clear now.

I found the issue, it can be summarized as: when a prebuilt dune is used to build dune, the version is not found. The reason is that the dune binary is not attached to the dune package, so it does not inherit from the version in dune-project (which applies to all the packages).

I'll open a PR with that fix. Thanks!