Thursday, May 31, 2018

Building Mercurial 4.6

On a world where the popular way is to adopt Linux and Git I still would select Solaris and Mercurial as more specific and powerful alternatives.

Solaris 11.3 GA offers Mercurial 3.4 (still straight through from Selenic Consulting) while Solaris 11 Express offered the even older ancient version 1.3.1. Of course, that's crazy for the present time as they both can be considered relics! So I set to instate an upgraded version all by myself instead of waiting or relying on the official distribution of Solaris, which understandably is not strongly focused on this particular matter.

My goal is to achieve the following even under a legacy Solaris 11 Express 32-bits!

$ hg --version
Mercurial Distributed SCM (version 4.6)
(see https://mercurial-scm.org for more information)

Copyright (C) 2005-2018 Matt Mackall and others
This is free software; see the source for copying conditions. 

There is NO warranty; not even for ... A PARTICULAR PURPOSE. (Wow!)

As usual, I begin by downloading the source-code tarball from the official web site and, once more, I perform the basic building strategy and general assumptions already detailed on one of my previous posts: Staged Building.

$ pwd
/stage/build

$ ./gnu-build-preparation ../source/.../mercurial-4.6.tar.gz
...

$ cd mercurial/mercurial-4.6-32

$ source ../setenv-4.6 32
...

NOTE
Once more as it's usually the case with Python-related builds that deviates from GNU builds, it's necessary to perform the whole workflow as root as sudoing gmake won't do with respect to shell environment variables settings.
# su
# source ../setenv-4.6 32

Make sure the right Python version is selected:

# python --version
Python 2.7.15

 
But don't launch the build & install operation yet:

# gmake PREFIX=/opt/usr install

Before issuing the above command, it's absolutely necessary to fix a few (silly) bugs in the original distribution as depicted below:

  1. Because unfortunately GCC 3.4.3 on Solaris 11 Express doesn't yet support the visibility optimization flag (with reported gains of up 20% in speed), comment-out (#) the following of ./contrib/python-zstandard/setup_zstd.py:

    137 #     if compiler_type == 'unix':
    138 #         extra_args.append('-fvisibility=hidden')
     
  2. There is a bug on a contribution borrowed from the open-source Facebook Folly library, more specifically on file ./contrib/python-zstandard/zstd/common/cpu.h. Line 76 will trigger the following error: syntax error before ')'. The cause is an extraneous ':' just before the ')' on line 76 which must be removed as follows:
     
    70       __asm__(
    71           "pushl %%ebx\n\t"

    72           "cpuid\n\t"

    73           "popl %%ebx\n\t"

    74           : "=a"(f1a), "=c"(f1c), "=d"(f1d)

    75           : "a"(1)

    76           );
      
        
  3. The Docutils Python module must be installed beforehand, otherwise the build will be aborted with the following error message:
     
    abort: couldn't generate documentation: docutils module is missing
    ... install python-docutils or see http://docutils.sourceforge.net/

        
  4. The Makefile on the ./doc subdirectory has the following bug:
      
    As seen gmake was used, but again, somehow, Python invoked install instead of the expected ginstall which accepts the weird syntax of the Makefile, which strict Solaris install doesn't:
     
    cd doc && gmake install

    gmake[1]: Entering directory `./doc'


    for i in hg-ssh.8 hg.1 hgignore.5 hgrc.5 ; do \

      subdir=`echo $i | sed -n 's/^.*\.\([0-9]\)$/man\1/p'` ; \

      mkdir -p "/opt/usr/share/man"/$subdir ; \

      install -c -m 644 $i "/opt/usr/share/man"/$subdir ; \

    done
     
     

    install: The -c, -f, -n options each require a directory following!

    install: The -c, -f, -n options each require a directory following!

    install: The -c, -f, -n options each require a directory following!

    install: The -c, -f, -n options each require a directory following!

      
    gmake[1]: *** [install] Error 2
    gmake[1]: Leaving directory `.../mercurial-4.6-32/doc'

    gmake: *** [install-doc] Error 2

     
    As per install(1M) the correct syntax is:
       
      install -c dir [-m mode] [-u user] [-g group] [-o] [-s] file


    Hence, to fix the Makefile the following changes on lines 8 and 43 are required:
     
      ...

        8 INSTALL=install -m 644 -c

      ...

       43 $(INSTALL) "$(DESTDIR)$(MANDIR)"/$$subdir $$i ; \

      ...

Now the build & install should proceed smoothly and hassle-free!

# zfs snapshot -r .../opt/usr@mercurial-4.6