[WiP] Creating a snap package of LDC

Joseph Rushton Wakeling via digitalmars-d-ldc digitalmars-d-ldc at puremagic.com
Sun Aug 28 04:58:00 PDT 2016


Hello all,

I decided that it was time to try creating snap packages of 
various core D programs, and I thought I'd start with LDC since 
its very standard cmake-based build and install makes for 
super-easy integration with the snapcraft package-creation system.

The TL;DR is that creating the _package_ is super-easy, but there 
are a handful of interesting integration issues that it would be 
good to have your advice on.

For cross-reference, here's the discussion on the snapcraft 
mailing list where I raise the issues I encountered:
https://lists.ubuntu.com/archives/snapcraft/2016-August/000860.html

... and I'm writing the current email in the wake of feedback 
received there.  Anyway, first let me describe what I've done, 
before raising any questions.

The basics of how to create an LDC snap package are super easy.  
Simply create a file called `snapcraft.yaml` in an empty 
directory, containing the following contents:

-----------------------------------------
name: ldc2
version: "1.0.0"
summary: D compiler with LLVM backend
description: LDC is a compiler for the D programming Language.
              It is based on the latest DMD frontend and uses LLVM 
as backend.
confinement: strict

apps:
   ldc2:
     command: ldc2
     plugs: [home]
   ldmd2:
     command: ldmd2
     plugs: [home]

parts:
   ldc:
     plugin: cmake
     source: git://github.com/ldc-developers/ldc.git
     source-tag: v1.0.0
     build-packages:
     - ldc
     - llvm-dev
     - libconfig++-dev
     - libcurl4-gnutls-dev
     - libedit-dev
     - zlib1g-dev
-----------------------------------------

As you can see, this metadata describes the apps to be included 
in the snap package, together with the build plugin required 
(cmake is supported out of the box), and where to get the source 
(git is again out-of-the-box supported and you simply need to 
specify the version tag to check out).

Note the listing of `ldc` as a build dependency: this will use 
the Ubuntu-packaged ldc 0.17.1.  Note also the ["home"] plugs: 
this ensures that the applications in the containerized snap will 
still be able to access the user's home directory (pretty 
important if you want to build stuff).

Given all this, on any Ubuntu 16.04 system, from the same 
directory as the `snapcraft.yaml` file, just run:

     snapcraft

The snapcraft program will install any necessary build 
dependencies, check out the code, build it, and install the 
results into a `stage` directory.  This is then further processed 
to create a `prime` directory creating the actual contents that 
will be in the snap package; and finally, the snap package itself 
is generated.  Assuming you're running this on a 64-bit system, 
it will be named something like:

     ldc2_1.0.0_amd64.snap

This can then be installed (on Ubuntu 16.04) with:

     sudo snap install ldc2_1.0.0_amd64.snap

Snaps are installed (read-only) into the `/snap/` top-level 
folder; in this case, you can find the contents in 
`/snap/ldc2/current/` (`current` is a symlink to the particular 
snap that is currently in use).  Everything you'd expect to find 
in a normal LDC install will be in there: the `bin/` directory 
containing `ldc2` and `ldmd2`; the `etc/` directory containing 
`bash_completion.d` and `ldc2.conf`; the `include/` dir with the 
usual contents; the `lib/` dir containing static libraries of 
druntime and phobos (with and without debug symbols); and so on.

You should now be able to run `ldc2 --version` and see the 
appropriate info.

So far so good!  Unfortunately, now we have to start dealing with 
the integration issues.

One issue is to do with how the commands are exposed: the actual 
commands you can run will be called `ldc2` and `ldc2.ldmd2` (as 
snappy effectively 'namespaces' apps that do not share a name 
with the snap package).  This is solvable but will require some 
updates to `snapd` itself, so no need to discuss, just to be 
aware that this is the current situation.

Next, the `ldc2.conf` file's -I and -L path definitions are 
problematic, possibly because of the containerized way that 
snapcraft builds the snap:

     switches = [
         "-I/include/d/ldc",
         "-I/include/d",
         "-L-L/lib",
         "-defaultlib=phobos2-ldc,druntime-ldc",
         "-debuglib=phobos2-ldc-debug,druntime-ldc-debug"
     ];

This leads me to my first question: is it possible to specify the 
paths here relative to the location of the directory where the 
`ldc2` binary resides?  I tried using the dmd-style:

     -I%@P%/../include/d/ldc

... etc., but that didn't seem to work (I don't know if is %@P% 
in any way standard, or whether it's something dmd-specific...?).

Manually specifying the exact path on the command line (or 
manually editing the generated files before finalizing the snap 
package) can be used to work around this.

Finally, the snap-packaged LDC will currently fail at the linker 
stage, because (as I understand it) the snap package can't access 
regular system resources, only stuff that is in other snaps, and 
the core system snap doesn't include stuff like gcc.  So, 
building falls over with an error:

     Error: failed to locate gcc

There are a few long-term potential fixes here, including 
creating a snap that exposes GCC or a linker, but in the short 
term, I've been advised that probably the easiest way to create a 
reliable standalone LDC package is to bundle the linker into the 
snap.

So, my question is, what would be the minimum requirements for a 
linker to accompany ldc2, and how would I ensure that the built 
ldc2 tries to use _that_ linker rather than some other one?

Thanks & best wishes,

      -- Joe


More information about the digitalmars-d-ldc mailing list