diff mbox series

[bug#46806] gnu: ocaml-4.07: Bootstrap.

Message ID 20210227001244.17cc3833@tachikoma.lepiller.eu
State Accepted
Headers show
Series [bug#46806] gnu: ocaml-4.07: Bootstrap. | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue

Commit Message

Julien Lepiller Feb. 26, 2021, 11:13 p.m. UTC
Hi Guix!

This small series adds camlboot, a project to reimplement a bootstrap
for OCaml, which lets us remove the pre-built boot/ocaml{c,lex} :)

The first patch builds the bootstraped ocamlc and ocamllex. This takes
around 4 hours to build. The second patch rebuilds them using the source
code for ocaml 4.07.1, instead of the modified sources used in
camlboot, and reuse them to run the main Makefile (make world.opt).

As a result, we have identical files for this bootstrap and the
unbootstrapped OCaml (up to output store paths and hash of some files
that get embedded in native files, which differ because of the
different output path).

Comments

Julien Lepiller Feb. 28, 2021, 2:09 a.m. UTC | #1
Le Sat, 27 Feb 2021 00:13:39 +0100,
Julien Lepiller <julien@lepiller.eu> a écrit :

> Hi Guix!
> 
> This small series adds camlboot, a project to reimplement a bootstrap
> for OCaml, which lets us remove the pre-built boot/ocaml{c,lex} :)
> 
> The first patch builds the bootstraped ocamlc and ocamllex. This takes
> around 4 hours to build. The second patch rebuilds them using the
> source code for ocaml 4.07.1, instead of the modified sources used in
> camlboot, and reuse them to run the main Makefile (make world.opt).
> 
> As a result, we have identical files for this bootstrap and the
> unbootstrapped OCaml (up to output store paths and hash of some files
> that get embedded in native files, which differ because of the
> different output path).

Here's the second version of the series: the first patch is unchanged,
the second patch is slightly better: the bootstrap ocaml 4.07 now run
"make alldepends" to generate all the .depend files, and installs them
to its output at share/depends. Then, ocaml-4.07 simply copies the
bootstrap data from this package (ocamlc, ocamllex, ocamlrun and all
the .depends) that were deleted from the archive, since they were
pre-generated. I feel much better about this patch than the previous
one. Thoughts?
pukkamustard Feb. 28, 2021, 9:19 a.m. UTC | #2
Fantastic! Thank you and thanks to the camlboot project! I will 
try and
build this tonight.

Julien Lepiller <julien@lepiller.eu> writes:

> Hi Guix!
>
> This small series adds camlboot, a project to reimplement a 
> bootstrap
> for OCaml, which lets us remove the pre-built boot/ocaml{c,lex} 
> :)
>
> The first patch builds the bootstraped ocamlc and ocamllex. This 
> takes
> around 4 hours to build. The second patch rebuilds them using 
> the source
> code for ocaml 4.07.1, instead of the modified sources used in
> camlboot, and reuse them to run the main Makefile (make 
> world.opt).
>
> As a result, we have identical files for this bootstrap and the
> unbootstrapped OCaml (up to output store paths and hash of some 
> files
> that get embedded in native files, which differ because of the
> different output path).
Julien Lepiller Feb. 28, 2021, 10:57 a.m. UTC | #3
Would be fantastic if you could report build time for camlboot too :). The result should be almost identical to our current ocaml-4.07, though there are some due to different output directory being embedded.

Le 28 février 2021 04:19:09 GMT-05:00, pukkamustard <pukkamustard@posteo.net> a écrit :
>
>Fantastic! Thank you and thanks to the camlboot project! I will 
>try and
>build this tonight.
>
>Julien Lepiller <julien@lepiller.eu> writes:
>
>> Hi Guix!
>>
>> This small series adds camlboot, a project to reimplement a 
>> bootstrap
>> for OCaml, which lets us remove the pre-built boot/ocaml{c,lex} 
>> :)
>>
>> The first patch builds the bootstraped ocamlc and ocamllex. This 
>> takes
>> around 4 hours to build. The second patch rebuilds them using 
>> the source
>> code for ocaml 4.07.1, instead of the modified sources used in
>> camlboot, and reuse them to run the main Makefile (make 
>> world.opt).
>>
>> As a result, we have identical files for this bootstrap and the
>> unbootstrapped OCaml (up to output store paths and hash of some 
>> files
>> that get embedded in native files, which differ because of the
>> different output path).
pukkamustard March 1, 2021, 9:16 a.m. UTC | #4
I managed to build camlboot and ocaml@4.07 with your patches.

> Would be fantastic if you could report build time for camlboot 
> too :).

Build time (on a quad-core i7 laptop):

```
$ time ./pre-inst-env guix build camlboot --no-offload
.
.
.
successfully built 
/gnu/store/ddi5n28hsrgvb89r8vjs0rfvapxfbaj2-camlboot-0.0.0-0.506280c.drv
/gnu/store/79bqayhrc6qfr2k7pfk7fn6lim0f8cfx-camlboot-0.0.0-0.506280c

real	322m35.119s
user	0m1.523s
sys	0m0.140s
```

ocaml@4.07 with your patches applied:

```
$ time ./pre-inst-env guix build ocaml@4.07 --no-offload
successfully built 
/gnu/store/sdxybpxzjhib5ijn3fx3r29ycp5vvafd-ocaml-4.07.1.drv
/gnu/store/cniid9xi3dck7kdpfm77h56h1s0701fm-ocaml-4.07.1

real	17m52.923s
user	0m9.268s
sys	0m1.013s
```

ocaml@4.07 at master:

```
$ time ./pre-inst-env guix build ocaml@4.07 --no-offload --check
successfully built 
/gnu/store/v599h0bhpyh2rq4nrnqqf56lwbsf0f71-ocaml-4.07.1.drv
successfully built 
/gnu/store/v599h0bhpyh2rq4nrnqqf56lwbsf0f71-ocaml-4.07.1.drv
/gnu/store/s7j0vl88zakkdcyvw1jw8cypfzi6ljnd-ocaml-4.07.1

real	21m44.000s
user	0m14.546s
sys	0m1.217s
```

> The result should be almost identical to our current ocaml-4.07, 
> though there are some due to different output directory being 
> embedded.

Checked some random files in both ocaml's with diffoscope and can 
confirm that differences seem to be mostly different output 
directories.

Haven't run diffoscope on everything as that would take quite some 
time...

-pukkamustard


>>
>>Fantastic! Thank you and thanks to the camlboot project! I will
>>try and
>>build this tonight.
>>
>>Julien Lepiller <julien@lepiller.eu> writes:
>>
>>> Hi Guix!
>>>
>>> This small series adds camlboot, a project to reimplement a
>>> bootstrap
>>> for OCaml, which lets us remove the pre-built 
>>> boot/ocaml{c,lex}
>>> :)
>>>
>>> The first patch builds the bootstraped ocamlc and ocamllex. 
>>> This
>>> takes
>>> around 4 hours to build. The second patch rebuilds them using
>>> the source
>>> code for ocaml 4.07.1, instead of the modified sources used in
>>> camlboot, and reuse them to run the main Makefile (make
>>> world.opt).
>>>
>>> As a result, we have identical files for this bootstrap and 
>>> the
>>> unbootstrapped OCaml (up to output store paths and hash of 
>>> some
>>> files
>>> that get embedded in native files, which differ because of the
>>> different output path).
Julien Lepiller March 1, 2021, 11:44 a.m. UTC | #5
Thanks! OK to push?

Le 1 mars 2021 04:16:14 GMT-05:00, pukkamustard <pukkamustard@posteo.net> a écrit :
>
>I managed to build camlboot and ocaml@4.07 with your patches.
>
>> Would be fantastic if you could report build time for camlboot 
>> too :).
>
>Build time (on a quad-core i7 laptop):
>
>```
>$ time ./pre-inst-env guix build camlboot --no-offload
>.
>.
>.
>successfully built 
>/gnu/store/ddi5n28hsrgvb89r8vjs0rfvapxfbaj2-camlboot-0.0.0-0.506280c.drv
>/gnu/store/79bqayhrc6qfr2k7pfk7fn6lim0f8cfx-camlboot-0.0.0-0.506280c
>
>real	322m35.119s
>user	0m1.523s
>sys	0m0.140s
>```
>
>ocaml@4.07 with your patches applied:
>
>```
>$ time ./pre-inst-env guix build ocaml@4.07 --no-offload
>successfully built 
>/gnu/store/sdxybpxzjhib5ijn3fx3r29ycp5vvafd-ocaml-4.07.1.drv
>/gnu/store/cniid9xi3dck7kdpfm77h56h1s0701fm-ocaml-4.07.1
>
>real	17m52.923s
>user	0m9.268s
>sys	0m1.013s
>```
>
>ocaml@4.07 at master:
>
>```
>$ time ./pre-inst-env guix build ocaml@4.07 --no-offload --check
>successfully built 
>/gnu/store/v599h0bhpyh2rq4nrnqqf56lwbsf0f71-ocaml-4.07.1.drv
>successfully built 
>/gnu/store/v599h0bhpyh2rq4nrnqqf56lwbsf0f71-ocaml-4.07.1.drv
>/gnu/store/s7j0vl88zakkdcyvw1jw8cypfzi6ljnd-ocaml-4.07.1
>
>real	21m44.000s
>user	0m14.546s
>sys	0m1.217s
>```
>
>> The result should be almost identical to our current ocaml-4.07, 
>> though there are some due to different output directory being 
>> embedded.
>
>Checked some random files in both ocaml's with diffoscope and can 
>confirm that differences seem to be mostly different output 
>directories.
>
>Haven't run diffoscope on everything as that would take quite some 
>time...
>
>-pukkamustard
>
>
>>>
>>>Fantastic! Thank you and thanks to the camlboot project! I will
>>>try and
>>>build this tonight.
>>>
>>>Julien Lepiller <julien@lepiller.eu> writes:
>>>
>>>> Hi Guix!
>>>>
>>>> This small series adds camlboot, a project to reimplement a
>>>> bootstrap
>>>> for OCaml, which lets us remove the pre-built 
>>>> boot/ocaml{c,lex}
>>>> :)
>>>>
>>>> The first patch builds the bootstraped ocamlc and ocamllex. 
>>>> This
>>>> takes
>>>> around 4 hours to build. The second patch rebuilds them using
>>>> the source
>>>> code for ocaml 4.07.1, instead of the modified sources used in
>>>> camlboot, and reuse them to run the main Makefile (make
>>>> world.opt).
>>>>
>>>> As a result, we have identical files for this bootstrap and 
>>>> the
>>>> unbootstrapped OCaml (up to output store paths and hash of 
>>>> some
>>>> files
>>>> that get embedded in native files, which differ because of the
>>>> different output path).
pukkamustard March 1, 2021, 12:04 p.m. UTC | #6
> Thanks! OK to push?

Ok for me!

> Le 1 mars 2021 04:16:14 GMT-05:00, pukkamustard 
> <pukkamustard@posteo.net> a écrit :
>>
>>I managed to build camlboot and ocaml@4.07 with your patches.
>>
>>> Would be fantastic if you could report build time for camlboot
>>> too :).
>>
>>Build time (on a quad-core i7 laptop):
>>
>>```
>>$ time ./pre-inst-env guix build camlboot --no-offload
>>.
>>.
>>.
>>successfully built
>>/gnu/store/ddi5n28hsrgvb89r8vjs0rfvapxfbaj2-camlboot-0.0.0-0.506280c.drv
>>/gnu/store/79bqayhrc6qfr2k7pfk7fn6lim0f8cfx-camlboot-0.0.0-0.506280c
>>
>>real	322m35.119s
>>user	0m1.523s
>>sys	0m0.140s
>>```
>>
>>ocaml@4.07 with your patches applied:
>>
>>```
>>$ time ./pre-inst-env guix build ocaml@4.07 --no-offload
>>successfully built
>>/gnu/store/sdxybpxzjhib5ijn3fx3r29ycp5vvafd-ocaml-4.07.1.drv
>>/gnu/store/cniid9xi3dck7kdpfm77h56h1s0701fm-ocaml-4.07.1
>>
>>real	17m52.923s
>>user	0m9.268s
>>sys	0m1.013s
>>```
>>
>>ocaml@4.07 at master:
>>
>>```
>>$ time ./pre-inst-env guix build ocaml@4.07 --no-offload --check
>>successfully built
>>/gnu/store/v599h0bhpyh2rq4nrnqqf56lwbsf0f71-ocaml-4.07.1.drv
>>successfully built
>>/gnu/store/v599h0bhpyh2rq4nrnqqf56lwbsf0f71-ocaml-4.07.1.drv
>>/gnu/store/s7j0vl88zakkdcyvw1jw8cypfzi6ljnd-ocaml-4.07.1
>>
>>real	21m44.000s
>>user	0m14.546s
>>sys	0m1.217s
>>```
>>
>>> The result should be almost identical to our current 
>>> ocaml-4.07,
>>> though there are some due to different output directory being
>>> embedded.
>>
>>Checked some random files in both ocaml's with diffoscope and 
>>can
>>confirm that differences seem to be mostly different output
>>directories.
>>
>>Haven't run diffoscope on everything as that would take quite 
>>some
>>time...
>>
>>-pukkamustard
>>
>>
>>>>
>>>>Fantastic! Thank you and thanks to the camlboot project! I 
>>>>will
>>>>try and
>>>>build this tonight.
>>>>
>>>>Julien Lepiller <julien@lepiller.eu> writes:
>>>>
>>>>> Hi Guix!
>>>>>
>>>>> This small series adds camlboot, a project to reimplement a
>>>>> bootstrap
>>>>> for OCaml, which lets us remove the pre-built
>>>>> boot/ocaml{c,lex}
>>>>> :)
>>>>>
>>>>> The first patch builds the bootstraped ocamlc and ocamllex.
>>>>> This
>>>>> takes
>>>>> around 4 hours to build. The second patch rebuilds them 
>>>>> using
>>>>> the source
>>>>> code for ocaml 4.07.1, instead of the modified sources used 
>>>>> in
>>>>> camlboot, and reuse them to run the main Makefile (make
>>>>> world.opt).
>>>>>
>>>>> As a result, we have identical files for this bootstrap and
>>>>> the
>>>>> unbootstrapped OCaml (up to output store paths and hash of
>>>>> some
>>>>> files
>>>>> that get embedded in native files, which differ because of 
>>>>> the
>>>>> different output path).
Simon Tournier March 3, 2021, 1:27 p.m. UTC | #7
Hi Julien,

On Sat, 27 Feb 2021 at 00:13, Julien Lepiller <julien@lepiller.eu> wrote:

> The first patch builds the bootstraped ocamlc and ocamllex. This takes
> around 4 hours to build. The second patch rebuilds them using the source
> code for ocaml 4.07.1, instead of the modified sources used in
> camlboot, and reuse them to run the main Makefile (make world.opt).

On my machine, camlboot takes ~3h to build.  Then ocaml-4.07-boot takes
~30s.  Last there is no meaningful difference between building
ocaml-4.07 using the embedded ocamlc and ocamlex binaries and using the
binaries from ocaml-4.04-boot; both ~6m.

I have check that camlboot, ocaml-4.07-boot and ocaml-4.07 build
reproducibly with ’--check’.  They do.


> As a result, we have identical files for this bootstrap and the
> unbootstrapped OCaml (up to output store paths and hash of some files
> that get embedded in native files, which differ because of the
> different output path).

At first look, yes. :-)


Modulo the minor comments I made, patches LGTM!  Thanks.


Well, the next steps are to build ocaml-4.09 and ocaml-4.11 using the
previous ocamlc and ocamlex version, right?

Then, it implies rebuild all the OCaml packages, right?  It could be
done in this core-updates cycle, WDYT?

Cheers,
simon
Julien Lepiller March 3, 2021, 1:46 p.m. UTC | #8
We'd have to check we actually can build them. The plan was to build menhir with this ocaml4.07, since it's required to generate the parser for ocaml >= 4.08, and improve camlboot to support more recent versions. We would prevent the need for a chain of bootstraps that way.

Anyway, I'll push that after fixing your comments, and we'll see what we can do for the following ocaml versions. Thanks for the review!

I don't think ocaml has so many dependants that it requires core-updates. Not even sure it needs staging.

Le 3 mars 2021 08:27:54 GMT-05:00, zimoun <zimon.toutoune@gmail.com> a écrit :
>Hi Julien,
>
>On Sat, 27 Feb 2021 at 00:13, Julien Lepiller <julien@lepiller.eu>
>wrote:
>
>> The first patch builds the bootstraped ocamlc and ocamllex. This
>takes
>> around 4 hours to build. The second patch rebuilds them using the
>source
>> code for ocaml 4.07.1, instead of the modified sources used in
>> camlboot, and reuse them to run the main Makefile (make world.opt).
>
>On my machine, camlboot takes ~3h to build.  Then ocaml-4.07-boot takes
>~30s.  Last there is no meaningful difference between building
>ocaml-4.07 using the embedded ocamlc and ocamlex binaries and using the
>binaries from ocaml-4.04-boot; both ~6m.
>
>I have check that camlboot, ocaml-4.07-boot and ocaml-4.07 build
>reproducibly with ’--check’.  They do.
>
>
>> As a result, we have identical files for this bootstrap and the
>> unbootstrapped OCaml (up to output store paths and hash of some files
>> that get embedded in native files, which differ because of the
>> different output path).
>
>At first look, yes. :-)
>
>
>Modulo the minor comments I made, patches LGTM!  Thanks.
>
>
>Well, the next steps are to build ocaml-4.09 and ocaml-4.11 using the
>previous ocamlc and ocamlex version, right?
>
>Then, it implies rebuild all the OCaml packages, right?  It could be
>done in this core-updates cycle, WDYT?
>
>Cheers,
>simon
Simon Tournier March 3, 2021, 2:05 p.m. UTC | #9
On Wed, 3 Mar 2021 at 14:46, Julien Lepiller <julien@lepiller.eu> wrote:
>
> We'd have to check we actually can build them. The plan was to build menhir with this ocaml4.07, since it's required to generate the parser for ocaml >= 4.08, and improve camlboot to support more recent versions. We would prevent the need for a chain of bootstraps that way.

Thanks for the explanations.
I have tried to replace gcc by clang for camlboot but it fails.
And also tried other Scheme than Guile, obviously fails. :-)


> I don't think ocaml has so many dependants that it requires core-updates. Not even sure it needs staging.

Oh right, I thought that more OCaml packages were in Guix. :-)

Cheers,
simon
Julien Lepiller March 3, 2021, 4:14 p.m. UTC | #10
Le Wed, 3 Mar 2021 15:05:18 +0100,
zimoun <zimon.toutoune@gmail.com> a écrit :

> On Wed, 3 Mar 2021 at 14:46, Julien Lepiller <julien@lepiller.eu>
> wrote:
> >
> > We'd have to check we actually can build them. The plan was to
> > build menhir with this ocaml4.07, since it's required to generate
> > the parser for ocaml >= 4.08, and improve camlboot to support more
> > recent versions. We would prevent the need for a chain of
> > bootstraps that way.  
> 
> Thanks for the explanations.
> I have tried to replace gcc by clang for camlboot but it fails.
> And also tried other Scheme than Guile, obviously fails. :-)
> 
> 
> > I don't think ocaml has so many dependants that it requires
> > core-updates. Not even sure it needs staging.  
> 
> Oh right, I thought that more OCaml packages were in Guix. :-)
> 
> Cheers,
> simon

Pushed as 0bd58ae7ff0d5c3935b0d660819aca4a0493ef8a, thanks for the
review!

Yeah, we might need some work to support other schemes. There's no C in
camlboot, but we reuse some of OCaml's sources, for the bytecode
interpreter (camlrun) and parser generator (ocamlyacc). So that's a
problem with OCaml.
diff mbox series

Patch

From 8fa9e59c8d90339478d65e269b37cbb3b201232d Mon Sep 17 00:00:00 2001
From: Julien Lepiller <julien@lepiller.eu>
Date: Sat, 27 Feb 2021 00:07:30 +0100
Subject: [PATCH 2/2] gnu: ocaml-4.07: Bootstrap.

* gnu/packages/ocaml.scm (ocaml-4.07): Implement bootstrap via camlboot.
---
 gnu/packages/ocaml.scm | 179 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 176 insertions(+), 3 deletions(-)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 01c14a0ba0..272ed3a2d6 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -255,7 +255,7 @@  functional, imperative and object-oriented styles of programming.")
                (base32
                 "1v3z5ar326f3hzvpfljg4xj8b9lmbrl53fn57yih1bkbx3gr3yzj"))))))
 
-(define-public ocaml-4.07
+(define ocaml-4.07-boot
   (package
     (inherit ocaml-4.09)
     (version "4.07.1")
@@ -267,11 +267,102 @@  functional, imperative and object-oriented styles of programming.")
                     "/ocaml-" version ".tar.xz"))
               (sha256
                (base32
-                "1f07hgj5k45cylj1q3k5mk8yi02cwzx849b1fwnwia8xlcfqpr6z"))))
+                "1f07hgj5k45cylj1q3k5mk8yi02cwzx849b1fwnwia8xlcfqpr6z"))
+              (modules '((guix build utils)))
+              (snippet
+               `(begin
+                  ;; Remove bootstrap binaries and pre-generated source files,
+                  ;; to ensure we actually bootstrap properly.
+                  (for-each delete-file (find-files "." "^.depend$"))
+                  (delete-file "boot/ocamlc")
+                  (delete-file "boot/ocamllex")))))
+    (arguments
+     `(#:tests? #f
+       #:phases
+       (modify-phases %standard-phases
+         (add-before 'configure 'copy-bootstrap
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let ((camlboot (assoc-ref inputs "camlboot")))
+               (copy-file (string-append camlboot "/bin/ocamllex") "boot/ocamllex")
+               (copy-file (string-append camlboot "/bin/ocamlc") "boot/ocamlc")
+               (chmod "boot/ocamllex" #o755)
+               (chmod "boot/ocamlc" #o755))))
+         (replace 'configure
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (mandir (string-append out "/share/man")))
+               (invoke "./configure"
+                       "--prefix" out
+                       "--mandir" mandir))))
+         (replace 'build
+           (lambda* (#:key parallel-build? #:allow-other-keys)
+             (define* (make . args)
+               (apply invoke "make"
+                      (append (if parallel-build?
+                                  `("-j" ,(number->string (parallel-job-count)))
+                                  '())
+                              args)))
+             (define (touch file) (invoke "touch" file))
+             (touch "byterun/.depend")
+             (make "-C" "byterun" "depend")
+             (make "-C" "byterun" "all")
+             (copy-file "byterun/ocamlrun" "boot/ocamlrun")
+             (touch ".depend")
+             (make "ocamlyacc")
+             (copy-file "yacc/ocamlyacc" "boot/ocamlyacc")
+             (touch "stdlib/.depend")
+             (make "-C" "stdlib" "sys.ml")
+             (make "-C" "stdlib" "CAMLDEP=../boot/ocamlc -depend" "depend")
+             (make "-C" "stdlib" "COMPILER="
+                   "CAMLC=../boot/ocamlc -use-prims ../byterun/primitives"
+                   "all")
+             (for-each
+               (lambda (file)
+                 (copy-file file (string-append "boot/" (basename file))))
+               (cons* "stdlib/stdlib.cma" "stdlib/std_exit.cmo" "stdlib/camlheader"
+                      (find-files "stdlib" ".*.cmi$")))
+             (symlink "../byterun/libcamlrun.a" "boot/libcamlrun.a")
+             (touch "tools/.depend")
+             (make "-C" "tools"
+                   "CAMLC=../boot/ocamlc -nostdlib -I ../boot -use-prims ../byterun/primitives -I .."
+                   "make_opcodes" "cvt_emit")
+             (touch "lex/.depend")
+             (make "-C" "lex" "CAMLDEP=../boot/ocamlc -depend" "depend")
+             (make "CAMLDEP=boot/ocamlc -depend" "depend")
+             (make "CAMLC=boot/ocamlc -nostdlib -I boot -use-prims byterun/primitives"
+                   "ocamlc")
+             (make "-C" "lex"
+                   "CAMLC=../boot/ocamlc -strict-sequence -nostdlib -I ../boot -use-prims ../byterun/primitives"
+                   "all")))
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin")))
+               (mkdir-p bin)
+               (install-file "ocamlc" bin)
+               (install-file "lex/ocamllex" bin)
+               (install-file "byterun/ocamlrun" bin)))))))
+    (native-inputs
+     `(("camlboot" ,camlboot)
+       ("perl" ,perl)
+       ("pkg-config" ,pkg-config)))))
+
+(define-public ocaml-4.07
+  (package
+    (inherit ocaml-4.07-boot)
     (arguments
       (substitute-keyword-arguments (package-arguments ocaml-4.09)
         ((#:phases phases)
          `(modify-phases ,phases
+            (add-before 'configure 'copy-bootstrap
+              (lambda* (#:key inputs #:allow-other-keys)
+                (let ((ocaml (assoc-ref inputs "ocaml")))
+                  (copy-file (string-append ocaml "/bin/ocamllex") "boot/ocamllex")
+                  (copy-file (string-append ocaml "/bin/ocamlc") "boot/ocamlc")
+                  (copy-file (string-append ocaml "/bin/ocamlrun") "boot/ocamlrun")
+                  (chmod "boot/ocamlrun" #o755)
+                  (chmod "boot/ocamllex" #o755)
+                  (chmod "boot/ocamlc" #o755))))
             (replace 'configure
               (lambda* (#:key outputs #:allow-other-keys)
                 (let* ((out (assoc-ref outputs "out"))
@@ -280,7 +371,89 @@  functional, imperative and object-oriented styles of programming.")
                   ;; --prefix=<PREFIX> syntax (with equals sign).
                   (invoke "./configure"
                           "--prefix" out
-                          "--mandir" mandir))))))))))
+                          "--mandir" mandir))))
+            (add-before 'build 'generate-depend
+              (lambda* (#:key parallel-build? #:allow-other-keys)
+                (define* (make . args)
+                  (apply invoke "make"
+                         (append (if parallel-build?
+                                     `("-j" ,(number->string (parallel-job-count)))
+                                     '())
+                                 args)))
+                ;; These files were deleted in a snippet because they are
+                ;; pre-generated
+                (invoke "touch" ".depend" "stdlib/.depend" "byterun/.depend"
+                        "tools/.depend" "lex/.depend" "asmrun/.depend"
+                        "debugger/.depend" "ocamltest/.depend" "ocamldoc/.depend"
+                        "ocamldoc/stdlib_non_prefixed/.depend"
+                        "otherlibs/bigarray/.depend"
+                        "otherlibs/graph/.depend"
+                        "otherlibs/raw_spacetime_lib/.depend"
+                        "otherlibs/str/.depend"
+                        "otherlibs/systhreads/.depend"
+                        "otherlibs/threads/.depend"
+                        "otherlibs/unix/.depend"
+                        "otherlibs/win32unix/.depend")
+                (make "-C" "byterun" "depend")
+                (make "-C" "asmrun" "depend")
+                (make "-C" "byterun" "all")
+                (copy-file "byterun/ocamlrun" "boot/ocamlrun")
+                (make "ocamlyacc")
+                (copy-file "yacc/ocamlyacc" "boot/ocamlyacc")
+                (make "-C" "stdlib" "sys.ml")
+                (make "-C" "stdlib"
+                      "CAMLDEP=../boot/ocamlc -depend"
+                      "depend")
+                (make "-C" "stdlib" "COMPILER="
+                      "CAMLC=../boot/ocamlc -use-prims ../byterun/primitives"
+                      "all")
+                (for-each
+                  (lambda (file)
+                    (copy-file file (string-append "boot/" (basename file))))
+                  (cons* "stdlib/stdlib.cma" "stdlib/std_exit.cmo" "stdlib/camlheader"
+                         (find-files "stdlib" ".*.cmi$")))
+                (symlink "../byterun/libcamlrun.a" "boot/libcamlrun.a")
+                (make "-C" "lex" "CAMLDEP=../boot/ocamlc -depend" "depend")
+                (make "-C" "lex" "all")
+                (substitute* "tools/Makefile"
+                  (("\\$\\(CAMLRUN\\) ./ocamldep") "../boot/ocamlc -depend"))
+                (substitute* '("otherlibs/graph/Makefile"
+                               "otherlibs/systhreads/Makefile"
+                               "otherlibs/threads/Makefile"
+                               "otherlibs/unix/Makefile")
+                  (("\\$\\(CAMLRUN\\) ../../tools/ocamldep")
+                   "../../boot/ocamlc -depend"))
+                (substitute* '("otherlibs/bigarray/Makefile"
+                               "otherlibs/raw_spacetime_lib/Makefile"
+                               "otherlibs/str/Makefile"
+                               "otherlibs/win32unix/Makefile")
+                  (("\\$\\(CAMLRUN\\) \\$\\(ROOTDIR\\)/tools/ocamldep")
+                   "../../boot/ocamlc -depend"))
+                (make "-C" "tools" "depend")
+                (make "-C" "otherlibs/bigarray" "depend")
+                (make "-C" "otherlibs/graph" "depend")
+                (make "-C" "otherlibs/raw_spacetime_lib" "depend")
+                (make "-C" "otherlibs/str" "depend")
+                (make "-C" "otherlibs/systhreads" "depend")
+                (make "-C" "otherlibs/threads" "depend")
+                (make "-C" "otherlibs/unix" "depend")
+                (make "-C" "otherlibs/win32unix" "depend")
+                (make "-C" "debugger" "CAMLDEP=../boot/ocamlc -depend" "depend")
+                (make "-C" "ocamltest" "ocamldep=../boot/ocamlc -depend -slash" "depend")
+                (make "parsing/parser.mli")
+                (substitute* "ocamldoc/Makefile"
+                  (("include Makefile.unprefix")
+                   "include Makefile.unprefix
+depend: $(STDLIB_MLIS) $(STDLIB_DEPS)"))
+                (make "-C" "ocamldoc" "OCAMLDEP=../boot/ocamlc -depend -slash" "depend")
+                (make "-C" "ocamldoc/stdlib_non_prefixed"
+                      "OCAMLDEP=../../boot/ocamlc -depend -slash" "depend")
+                (make "CAMLDEP=boot/ocamlc -depend" "depend")
+                ))))))
+    (native-inputs
+     `(("ocaml" ,ocaml-4.07-boot)
+       ("perl" ,perl)
+       ("pkg-config" ,pkg-config)))))
 
 (define-public ocaml ocaml-4.11)
 
-- 
2.30.0