Skip to content

GAP buildsystem use cases

Max Horn edited this page Apr 1, 2016 · 4 revisions

Use cases for the GAP build system

Preface

The out-of-tree builds below all use a hierarchy of the form $GAPROOT/build/configName

but in fact this is not necessary, nor enforced. You could just as well use $GAPROOT/configName or $GAPROOT/foo/bar or even a directory outside the $GAPROOT.

The use cases

Plain in-tree (single user)

  • Summary: a single GAP source tree, with packages, is compiled and used.

  • Audience: Average user

  • This is the most common setup, and also targets novice users, so it should be as easy and smooth as possible

  • Filesystem layout:

    GAPROOT/
       pkg/
    
  • Steps:

    1. Build GAP:

      cd $GAPROOT && ./configure && make
    2. Build bundled packages: We could provide a script to conveniently compile "known" packages:

      cd $GAPROOT/pkg && ./BuildPackages.sh

      How the script exactly builds the packages would need to be determined, but the easiest for now would be to do it just as before, i.e.:

      cd $GAPROOT/pkg/PKGNAME && ./configure & make

      i.e. no special installation or anything.

In-tree, with multiple build variants

  • This is useful to have builds for different architectures in a network directory shared across multiple hosts. It might also be used by GAP developers who want to use the same GAP source tree to build multiple GAP configs, e.g. with debug dis-/enabled; with HPC dis-/enabled, etc.

  • Audience: Power users, such as system administrators, long-year GAP users, and GAP developers. This means that it is OK to require these people to follow slightly more complicated instructions than in the average case. But of course we should still be as simple as possible.

  • Filesystem layout:

    GAPROOT/
      pkg/
        PKGNAME/
      build/
        configA/
        configB/
        ...
    
  • Steps:

    1. Build GAP:

      cd $GAPROOT
      mkdir -p build/configA
      cd build/configA
      ../../configure CONFIGFLAGS  # e.g.: --with-debug CFLAGS="-O0 -g"
    2. Build bundled packages: There are multiple options here:

      • we could provide a script to conveniently compile "known" packages (note the argument to the script, which is not there in use case 1):

        cd $GAPROOT/pkg && ./BuildPackages.sh ../build/configA
      • one could compile the packages manually, which might do roughly this (the script suggested above would do basically the same)

        cd $GAPROOT/build/configA
        mkdir -p pkg/PKGNAME && cd pkg/PKGNAME
        $GAPROOT/pkg/PKGNAME/configure
        make

        Note: On a technical level, GAP would consider the package to be located in $GAPROOT/pkg/PKGNAME as this is were the PackageInfo.g file is. But it would also know that it should look for the package's kernel extensions and binaries inside of $GAPROOT/build/configA/pkg/PKGNAME (depending on which variant of the build steps we take)

    3. Build external (e.g. under development) packages:

      cd /PATH/TO/SOMEPKG
      ./configure --with-gaproot=$GAPROOT/build/configA
      make
  • Issues:

    • The above scheme for handling packages has one major drawback: It doesn't work well if there are multiple versions of the same package around.

      This is not uncommon for package developers: There is a (compiled) version of their package bundled with GAP; but they also have a development version. When doing regular research with GAP, they might disable their development version, in order to use the stable bundled version. OTOH, when working on the dev version of their package, of course they want to use that...

      Of course one might argue that in such a case, the developer should simply have two GAP configs: one with the stable package, one with the dev version of the package.

      But what if one does not accept this as a solution?

      In the old system, the compiled kernel extensions were placed in a bin/ARCH/ subdirectory of the package source directory, which solved this problem. We could do something similar, too, as in the following snippet (which is in a sense "dual" to what I propose above):

      cd $GAPROOT/pkg/PKGNAME
      mkdir -p build/configA && cd build/configA
      ../configure --with-gaproot=$GAPROOT/build/configA
      make

      Problem is: different GAP configs now would not easily know which subdirectory of the package directory contains the correct kernel extension! Remember: The use of "build/configA" above is purely convention, nothing enforces this. So, one could also this:

      cd $GAPROOT/pkg/PKGNAME
      mkdir -p foo && cd foo
      ../configure --with-gaproot=$GAPROOT/build/configA
      make

      One solution then would be to force the user to use matching subdirectory names: If one $GAPROOT/build/configA/gap, then it will determine that its path relative to the GAPROOT is build/configA. It then uses this path relative to the package directory, i.e. it would look for kernel extensions in PATH/TO/PACKAGE/build/configA.

      One drawback of this is that it is somewhat fragile. E.g. what if the user makes a typo when configuring the package? (The package could of course perform a sanity check and refuse to run in this case, but that cures the symptoms, not the problem.) Also, it is slightly more tedious compared to the above. (And it wouldn't work well if the user builds a config of GAP outside the GAPROOT; but we could just declare that this is not supported; it isn't possible right now either, after all.)

Variation of previous use cases, but using compatibility mode:

  • Everything should work as it does right now. TODO: document what that means, exactly?
  • Filesystem layout: TODO
  • Steps: TODO
  • Issues: TODO

System installation using "make install"

  • The initial prep for this is as in use case 1.

  • This mode should make life much easier for people who package GAP for Linux distributions and other package managers (e.g. also for Fink, MacPorts and Homebrew on Mac OS X; or for systems like Guix, Nix; etc.)

  • As such, we should make sure to get feedback on the proposed file layout below from

  • Filesystem layout:

    GAPROOT/
      pkg/
        PKGNAME/
      build/
        configA/
        configB/
        ...
    PREFIX/
      bin/
        gap*              # this could be the actual GAP binary; or a shell script wrapping it
        gap.real          # the real GAP binary, in case bin/gap is a shell wrapper
        gac*
        gap-config*       # at least potentially....
      include/
        gap/              # GAP headers, needed to compile kernel extensions
          ariths.h
          blister.h
          bool.h
          ...
          weakptr.h
          gap-config.h    # new
      share/              # architecture independent files go in here
        gap/
          doc/
          lib/            # contains copy of $GAPROOT/lib
          prim/
          small/
          trans/
          tst/
          ...
          pkg/            # packages are installed in here
            PKGNAME/
              PackageInfo.g
              read.g
              init.g
              doc/
              lib/
              tst/
              ...
      lib/                # architecture ependent files go in here
        libgap.so         # hypothetical future libGAP
        gap/
          pkg/   # compiled kernel extensions go in here
            PKGNAME/
              libPKGNAME.so
              someExecutable*
    
  • In this setup, the installed GAP would always search in two "GAP root directories":

    PREFIX/share/gap
    PREFIX/lib/gap
    

    These would either be compiled into the executable (problem: we don't want to use them before install, in case there already is an installed GAP...); or else determine the paths based on the location of the GAP binary/

  • Steps:

    1. Build GAP (optionally with a custom PREFIX; the default PREFIX is /usr):
    cd $GAPROOT
    mkdir -p build/configA
    cd build/configA
    ../configure --with-prefix=PREFIX   # custom prefix is optional
    1. Install GAP

      make install

      To test the installed GAP, we can't use "make check" or "make test"; but we could have a special "make test-installed-gap" target (better name pending :-P) which does this, e.g. by running

      PREFIX/bin/gap run_installed_test_suite.g
    2. Build and install bundled packages Again, we could bundle scripts which automates this:

      cd $GAPROOT/pkg
      ./BuildPackages.sh
      ./InstallPackages.sh
    3. For external packages, the following could be done:

      cd /PATH/TO/SOMEPACKAGE
      ./configure
      make
      make install

      For this to work, the configure script must find the globally installed GAP, as described below.

  • Note: Of course, also with an installed GAP, one should be able to build a package against it. To this end, when running a packages ./configure, it would perform the following checks:

    1. if --with-gaproot=GAPROOT was given, use that to locate GAP (and error out if the dir contains no working GAP)
    2. Next, check if ../.. contains a working GAPROOT, and if yes, use it.
    3. Next, check if gap-config is in the PATH, and if yes, use what it says to figure out which GAP to use
    4. Give up with an error

    This leaves the problem of how GAP should find the package; but that is exactly the same as right now (so one would have to point GAP at a suitable additional GAP root directory; or perhaps in the future, directly at an additional pkg dir, or even the package directory itself).

    Of course, if one does make install in the package, it would be installed system wide, and so GAP would "find" it anyway.

Clone this wiki locally