Compiling for Linux under Windows

ยท 1244 words ยท 6 minute read

Docker recently updated their Windows client to natively use Windows Subsystem for Linux as its backend. For smaller projects, I use Docker as an easy way to cross-compile without the need to bog down my personal system, keep clients projects isolated from one another, and lots of automated ad hoc testing.

The software we’re compiling is Input-Leap, I’ve used it years on many systems at home. Input-Leap is software that mimics the functionality of a KVM switch over TCP/IP, allowing you to use a single keyboard and mouse to control many seperate computers.

First, compiling for Linux natively, and after how to compile using Docker on Windows.

Compiling on Linux / WSL natively ๐Ÿ”—

If you’re using Windows, start by installing Windows Subsystem for Linux, then Ubuntu.

Open up a terminal and let’s begin the build process.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
## Update your system.
sudo apt-get update
sudo apt-get upgrade

## Install packges required for compilation.
sudo apt-get install -y git \
        build-essential \
        cmake \
        libcurl4-openssl-dev \
        libxtst-dev \
        libavahi-compat-libdnssd-dev \
        qtbase5-dev \
        libssl-dev

## Make seperated directory for source code.
mkdir ~/src/

## Change directory to newly created directory
cd ~/src/

## Clone latest input-leap source.
git clone https://github.com/input-leap/input-leap.git

## Enter directory and run build script.
cd ./input-leap/

## Change build from Debug to Release
sed -i 's/Debug/Release/g' ./clean_build.sh
./clean_build.sh

## Change to build directory
cd ./build/

## Run installation.
make install

Compiling on Linux / WSL natively using Docker ๐Ÿ”—

If you’re using Windows, start by installing Windows Subsystem for Linux, then Ubuntu, followed by Docker.

What is Docker? ๐Ÿ”—

Docker lets you seperate applications from the underlying instructure. In this example, I’m pulling (downloading) a ubuntu image which contains the base operating system we’re going to build on top of.

We’re going to write a Dockerfile. A Dockerfile is essentially a script that allows you to define which base image you’re going to use as an operating system, and which commands you’d like to run afterwards, building a new image that is a filesystem layer of filesystem changes that sits on top of our base image.

Benefits of using Docker ๐Ÿ”—

Docker lets you quarantine the package bloat of compilation to Docker images, which you can easily remove to save space. The way Docker builds images in read-only layers allows you to use a single, always clean base image for multiple projects while maintaining isolation between them. Changes you make are contained in layers built on top of these base images. Using a Dockerfile also allows you to transparently document all the dependancies and steps needed.

Docker allows a modular approach to development that can help with security and scalability.

1. Create Directory Structure ๐Ÿ”—

Let’s create the directories that we want to contain our installation files.

1
2
3
4
5
## Create directory for installation files.
mkdir -p ~/src/

## Move to directory
cd ~/src/

2. Writing our Dockerfile ๐Ÿ”—

The commands that we’re adding to our Dockerfile are very similar to the ones we would run when compiling this in a native Linux environment, with a few additions. We’ll go over the differences as well as the reasons for them.

Open up your primary file editor, point it at the new Dockerfile (by default, they’re just named “Dockerfile”)

1
nano Dockerfile

Write the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## Specify the base image.
FROM ubuntu:20.04

## Create and set working directory.
WORKDIR /tmp

## Set this mode when you need zero interaction while installing or upgrading the system via apt. It accepts the default answer for all questions.
RUN export DEBIAN_FRONTEND=noninteractive

## Set timezone information required for CMake.
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

## Update the base system.
RUN apt-get update && \
        apt-get upgrade -y

## Install packges required for compilation.
RUN apt-get install -y \
        git \
        build-essential \
        cmake \
        libcurl4-openssl-dev \
        libxtst-dev \
        libavahi-compat-libdnssd-dev \
        qtbase5-dev \
        libssl-dev

## Clone latest input-leap source.
RUN git clone \
        https://github.com/input-leap/input-leap.git


## Change build script to build the Release version instead of the Debug version.
RUN sed -i 's/Debug/Release/g' /tmp/input-leap/clean_build.sh

## Run input-leap build script.
RUN /tmp/input-leap/clean_build.sh

## Change to the build directory for installation
WORKDIR /tmp/input-leap/build/

## Run make
RUN make

## Create empty directory to "install" into.
RUN mkdir -p /tmp/install/

## This is the script that is ran by default when running the new image, in our case we want it run "make install" in the directory we've attached to our "real" system.
ENTRYPOINT make DESTDIR=/tmp/install/ install

3. Building a new image using our Dockerfile ๐Ÿ”—

Next, we tell Docker to build our new image using the Dockerfile we have created. Note that in this example, the resulting Docker image will be name “input-leap:build”, but you can change this tag to anything you choose.

1
2
## You can rename input-leap:build to anything you choose.
docker build --tag=input-leap:build . < Dockerfile

3. Installation of Input Leap ๐Ÿ”—

We now have a Docker image that contains the compiled binaries we need for installation of input-leap. We’re going to create a local directory, link it to the Docker images internal filesystem, and tell the installation to install it there.

1
2
## Create your faux installation directory
mkdir -p /home/$USER/src/install/

When running the Docker image for installation, use the “volume” argument to bind our local faux install directory, to the installation directory created in our docker image.

1
2
3
4
5
## Your local directory must be hardcoded, it does not recognize "~/" as a shortcut to your home directory
docker run \
        --tty \
        --volume=/home/$USER/src/install/:/tmp/install/ \
        input-leap:build

With any luck, you should see a similar output.

 --tty input-leap:build
[  1%] Built target gmock
[  2%] Built target gtest
[ 10%] Built target arch
[ 11%] Built target common
[ 17%] Built target base
[ 18%] Built target mt
[ 20%] Built target io
[ 26%] Built target net
[ 41%] Built target synlib
[ 49%] Built target server
[ 55%] Built target platform
[ 59%] Built target ipc
[ 61%] Built target client
[ 62%] Built target barrierc
[ 63%] Built target barriers
[ 68%] Built target integtests
[ 76%] Built target unittests
[ 76%] Automatic MOC and UIC for target guiunittests
[ 76%] Built target guiunittests_autogen
[ 80%] Built target guiunittests
[ 81%] Automatic MOC and UIC for target barrier
[ 81%] Built target barrier_autogen
[100%] Built target barrier
Install the project...
-- Install configuration: "Release"
-- Installing: /tmp/install/usr/local/share/icons/hicolor/scalable/apps/barrier.svg
-- Installing: /tmp/install/usr/local/share/applications/barrier.desktop
-- Installing: /tmp/install/usr/local/bin/barrierc
-- Installing: /tmp/install/usr/local/bin/barriers
-- Installing: /tmp/install/usr/local/bin/barrier

Job complete. You can now go to your faux installation directory, and find input-leap. You can use it in the existing directory, or copy it to your local /usr directory for integration.

ed@ubuntu:~/src/install$ tree .
.
โ””โ”€โ”€ usr
    โ””โ”€โ”€ local
        โ”œโ”€โ”€ bin
        โ”‚ย ย  โ”œโ”€โ”€ barrier
        โ”‚ย ย  โ”œโ”€โ”€ barrierc
        โ”‚ย ย  โ””โ”€โ”€ barriers
        โ””โ”€โ”€ share
            โ”œโ”€โ”€ applications
            โ”‚ย ย  โ””โ”€โ”€ barrier.desktop
            โ””โ”€โ”€ icons
                โ””โ”€โ”€ hicolor
                    โ””โ”€โ”€ scalable
                        โ””โ”€โ”€ apps
                            โ””โ”€โ”€ barrier.svg

Changelog ๐Ÿ”—

Date Description
03/24/2022 Updated installation instructions to reflect updated fork
10/20/2021 Initial blog added.