<html>
<head>
<title>
How to upgrade to a new version of Boehm Garbage Collector in Mercury.
</title>
</head>
<body
bgcolor="#ffffff"
text="#000000"
>
<H1>
How to upgrade to a new version of Boehm Garbage Collector in Mercury.
</H1>
<P>
<B>WARNING:</B> This process is difficult and should not be undertaken lightly.
Before attempting to upgrade one should definitely discuss it on the
mercury-reviews mailing list first.
</P>
<h2>
The setup
</h2>
<p>
I did this for version 7.4.2 of the collector and libatomic_ops.
The bdwgc and libatomic_ops repositories are here:
</p>
<table>
<tr><th></th><th>Web</th><th>git</th></tr>
<tr>
<td>
BDW GC
</td>
<td>
<a href="https://github.com/ivmai/bdwgc"> https://github.com/ivmai/bdwgc"</a>
</td>
<td>
<code>https://github.com/ivmai/bdwgc.git</code>
</td>
</tr>
<tr>
<td>
libatomic_ops
</td>
<td>
<a
href="https://github.com/ivmai/libatomic_ops">https://github.com/ivmai/libatomic_ops</a>
</td>
<td>
<code>https://github.com/ivmai/libatomic_ops.git</code>
</td>
</tr>
</table>
<p>
I've also separated out the various changes we've made to the GC into the
mercury7_4_2 branch of the following repository:
</p>
<table>
<tr><th></th><th>Web</th><th>git</th></tr>
<tr>
<td>
BDW GC with patches
</td>
<td>
<a href="https://github.com/PaulBone/bdwgc/tree/mercury7_4_2">
https://github.com/PaulBone/bdwgc/tree/mercury7_4_2</a>
</td>
<td>
<code>https://github.com/PaulBone/bdwgc.git</code>
</td>
</tr>
</table>
<p>
On a clean checkout I created a branch off of the master branch.
</p>
<code><pre>
$ git branch boehm7_4_2 master
$ git checkout boehm7_4_2
</pre></code>
<p>
Then, on this branch I deleted the existing boehm_gc directory. I have
already saved the various patches we've made to this directory elsewhere.
</p>
<code><pre>
$ rm -rf boehm_gc
$ git commit -a
</pre></code>
<p>
Here's the tricky bit. I've added line numbers here.
Line 1 adds the boehm_gc on github as a remote repository so that we can
refer to it in future commands. It is named "boehm_gc" and the URL is
given. The -f argument specifies that git should "fetch" this
repository's history.
Line 2 begins a merge, but won't commit it (--no-commit).
The merge strategy is "ours" and we use the tag from the Boehm GC repo
"gc7_4_2".
Note that the tag is not prefixed by the remote repository's name, but if we
used a branch it would be.
I think that the merge strategy tells the merge command how to
update the working tree.
I admit that line 3 is a bit of a magic incantation,
it causes the Boehm GC repository, at tag gc7_4_2 to be written into the
path boehm_gc, the slash on the end of the path is important but I don't
know why, that's what the man page told me.
Finally line 4 completes the merge, committing it with the given commit
message.
</p>
<code><pre>
1 $ git remote add -f boehm_gc https://github.com/ivmai/bdwgc.git
2 $ git merge -s ours --no-commit gc7_4_2
3 $ git read-tree --prefix=boehm_gc/ -u gc7_4_2
4 $ git commit -m "Imported Boehm GC 7.4.2 into boehm_gc"
</pre></code>
<p>
Next, we do the same thing for the libatomic_ops repository.
</p>
<code><pre>
$ git remote add -f libatomic_ops https://github.com/ivmai/libatomic_ops.git
$ git merge -s ours --no-commit libatomic_ops-7_4_2
$ git read-tree --prefix=boehm_gc/libatomic_ops/ -u libatomic_ops-7_4_2
$ git commit -m "Imported libatomic_ops 7.4.2 into boehm_gc/libatomic_ops"
</code></pre>
<p>
For now I will push this to a branch in my forked repository until I'm
finished testing.
</p>
<h2>Mercury's customisations to the Boehm GC</h2>
<p>
I experimented a lot before I accomplished this step. In the end I used a
really round-about method. First re-writting this history by cherry picking
it onto a fork of the bdwgc repository (named boehm_gc_local). Then by
rebasing that onto the boehm7_4_2 breach created above.
</p>
<code><pre>
$ git branch mer_custom boehm_gc_local/mercury7_4_2
$ git checkout mer_custom
$ git rebase -s subtree --onto boehm7_4_2 gc7_4_2
$ git checkout boehm7_4_2
$ git merge --ff mer_custom
$ git branch -D mer_custom
</code></pre>
<h2>Pulling changes from upstream</h2>
<p>
The final step is how to update Mercury's copy of the collector when there
are changes upstream. Lets pretend the team have released a new version,
but since they haven't we'll update to master.
Remember we need to update both the collector and libatomic_ops
</p>
<code><pre>
$ git merge -s recursive -X subtree=boehm_gc boehm_gc/master
</pre></code>
<p>
When I tried this either without specifing a merge stratergy (the default
"recursive" is selected) or the subtree stratergy it didn't work, git wasn't
smart enough to figure out what to do.
Specifying the recursive stratergy with the subtree option as above tells
git exactly what subtree the merge should occur in.
Subtree is an option <i>of</i> the recursive stratergy, not of the merge
command in general.
</p>
<p>
Now resolve any conflicts and finish the merge.
I found it useful to use vimdiff to help me merge changes, git can call
vimdiff for you. git can launch a number of different tools depending on
your tastes.
</p>
<code><pre>
$ git mergetool --tool=vimdiff
</pre></code>
<p>
Then do the same for the libatomic_ops directory.
</p>
<code><pre>
$ git merge -s recursive -X subtree=boehm_gc/libatomic_ops libatomic_ops/master
</pre></code>
<p>
Once more resolve any conflicts and complete the merge. Now it's time to
test Mercury.
Bootcheck the compiler in at least asm_fast.gc and hlc.gc.
Then use the new system to do an install (with non-empty LIBGRADES)
and test that the installed version can compile some test programs.
This is because the update may have added some new files which may not be
copied into the install directories.
Some build scripts may also need to be updated (in particular
tools/bootcheck and scripts/prepare_install_dir.in).
</p>
<p>
Finally update .README.in (in the root directory) and
bindist/bindist.README to reflect the current version of the collector
being used.
Then commit these changes and have the changes reviewed before pushing them
into the public repository.
</p>
</body>
</html>