Kate + Building in Docker
Have I said nice things about Kate recently? Not enough, so let me gush a little about Kate as an “IDE” and using it, with the Build Plugin, as a tool for editing locally and building remotely.
I work on a codebase that has very specific platform requirements. These requirements are difficult to reproduce in a normal host – or, if you have some modern rolling distro like openSUSE, well-nigh-impossible. That’s the situation where Docker shows up, since a Docker container can be whatever specific platform is needed.
So I have a Docker, with the special compilation environment over here, and the host machine, running a recent version of Kate over there. How can I make them work together?
Sharing Directories with Docker
When starting a Docker container with docker run
, you can bind-mount
locations into the container. So for a builder-container, where you
want to have the source code available inside, a convenient way to
do it is to bind-mount the source directory in the host, to a
location – the same location – in the container.
Something like this:
docker run \
-v /home/me/src/myproject:/home/me/src/myproject:rw \
--name myproject \
myprojectimage \
/bin/sh
The --name
argument is slightly-important. Docker comes up with
a creative random name of the container if you don’t give one explicitly,
and that makes it harder to connect to the running container.
I should note that my approach is “leave the container running, and connect to it for compilation”, not “start a new container for every build”. Your mileage may vary, and it’s easy enough to bung some commands to start a container and run make in it, in a shell script and use that.
Configuring the Build-in-Docker
The codebase I’m on uses CMake as meta-buildsystem, which leads
to the usual (?) convention: there’s a build/
dir underneath the sources,
CMake is run there, and then the build proceeds there as well:
# Do this in the container
mkdir /home/me/src/myproject/build
cd /home/me/src/myproject/build
cmake ..
When doing a build like this, Qt’s moc will generate files in (subdirectories-of)
the build/
directory; other sources might be generated there as well. Compiler errors
might reference absolute paths (e.g. /home/me/src/myproject/main.cc
)
or might reference relative paths (e.g. ../main.cc
).
Depending on the exact way Docker is run from the host, the build directory
may or may not be visible. For me, it isn’t, and for various reasons I
can’t create the same build/
path in the host. So instead, I create
a similar path that leads to the same relative paths back to the
source directory:
# Do this in the host
mkdir /home/me/src/myproject/build_
Setting up Kate-in-Host
This is the main course: using Kate as an IDE, running the build inside the Docker container.
First, we need to enable the Build Plugin. Kate comes with a bunch of plugins that provide extra search functionality, IDE functionality, better LaTeX support, .. it’s quite extensive. Go to Settings → Configure Kate.. and choose the Plugins pane (module? I don’t really know what those icons-in-a-column should be called, each of which calls up its own set of tabs). Tick the box in front of the Build Plugin.
Unfortunately, the Build Plugin doesn’t initialize quite right when enabled the first time. Quit Kate, then start it again.
Once it’s back, there is a Build button at the bottom of the window. Click on it to open up the tool view for the plugin. There are target sets, and there’s a top-level “name of the target set” and “working directory” – since this is laid out in a two-column table it looks a bit strange.
The Kate Documentation for the Build Plugin is reasonably extensive.
- Optionally, click on the T: Target Set label to change the name of the set.
- Click on the Dir: label to change the directory where the build happens. This is needed because otherwise the build happens either where Kate was started, or the directory where the current file is. I haven’t got a clear answer on that.
- Tick the box in front of build to make it the default target to build.
- Click on the make command to edit it.
- Fill in the command to run the build in the container. I use Docker’s run
command, with the name of the container to attach to.
-a
is a flag to preserve stdin, out, and error. Themake
command changes directory to the actual build-directory, and-j
is tuned to the available CPU power.docker run -a myproject \ make -C /home/me/src/myproject/build -j4
There’s a little cog-like icon with tooltip Build selected target. Click on the build line to select it, then hit the cog and see what happens.
Personally I like the KDevelop key-binding of F8
for “build the thing”, so I open the Build menu (top of the Kate window),
right-mouse-click on the menu entry Build Default Target, pick Configure Shortcut..
and bind F8
to it. By default, that key is bound to “switch to next view”, but I don’t
use split views.
O noes, Ninja
The Build Plugin parses the output of the build command – e.g. make
.
The Build Plugin also knows how to deal with Ninja.
However – and thanks to Christoph Cullmann for helping figure this out –
Kate uses a trick to separate the Ninja output from compiler output (with
make, this is apparently not needed). The environment variable NINJA_STATUS
gets special treatment from Kate. The variable needs to be passed in
to the container, so for a ninja build this is the Docker command
(where -e NINJA_STATUS
means “pass the value of the environment variable in to the container”).
docker run -a myproject \
-e NINJA_STATUS \
make -C /home/me/src/myproject/build -j4
Takeaway
With just a few steps, building a weird-ass codebase in a container can be a lot more pleasant by editing it outside the container with modern tools, and “remote build” is supported by Kate quite well.
If you wonder why I’m not using KDevelop, well, two things: it actually has less documentation on custom and remote builds, and two, it crashes just trying to read the weird-ass codebase. I have yet to debug the latter.