aboutsummaryrefslogtreecommitdiff
path: root/Documentation/building.md
blob: 24d14de2b2935317d193f5f9446e88de50bb5e26 (plain) (blame)
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# Building from Source
A complete build of flow involves two parts

1. Building Scala sources (the front-end), resulting in a platform independent artifact (i.e. a jar file).

2. Building C sources (the back-end), yielding a native library that may only be used on systems resembling the platform for which it was compiled.

Both steps are independent, their only interaction being a header file generated by the JDK utility `javah` (see `sbt javah` for details), and may therefore be built in any order.

## Building Scala Sources
Run `sbt flow-main/packageBin` in the base directory. This simply compiles Scala sources as with any standard SBT project and packages the resulting class-files in a jar.

## Building Native Sources
The back-end is managed by GNU Autotools and all relevant files are contained in `flow-native`.

---

### Aside: Autotools Introduction
Autotools is a suite of programs constituting a sort of "meta-build system". It is used to generate a platform-independent build script known as `./configure`, which, when run, will analyze the current system (search for a C compiler, required libraries etc) and produce a `Makefile`. The makefile in turn is system-specific and can be used to create the final binary. In summary the build process is as follows:

1. Autotools (specifically the program `autoreconf`) generates `./configure`, this happens on the developer's machine
2. `./configure` is run on the host computer
3. `make` is run to produce a binary, also on the host computer

In a typical, source-controlled repository, only a bootstrapping script that calls Autotools is checked into version control. However, source *releases* include the generated `./configure` script. An end-user then downloads a source release and only has to run `./configure && make`.

However, since flow does currently not provide source releases (not to be confused with source repository or Git tags), the developer's machine is the same as the host machine and so the bootstrapping process always needs to be performed.

---

### Build Process

Several steps are involved in producing the native library:

1. Bootstrap the build (run this once, if `./configure` does not exist).

    1. Check availability of dependencies: autotools and libtool (on Debian-based systems run `apt-get install build-essential autoconf automake libtool`)
    2. Run `./bootstrap`

2. Compile
   
   1. Check availability of dependencies: C compiler and JDK
   2. Run `./configure && make`

3. Install

    The native library is now ready and can be:

	- copied to a local directory: `DESTDIR=$(pwd)/<directory> make install`

    - installed system-wide: `make install`

    - put into a "fat" jar, useful for dependency management with SBT (see next section)

### Creating a Fat Jar
The native library produced in the previous step may be bundled into a "fat" jar so that it can be included in SBT projects through its regular dependency mechanisms. In this process, SBT basically acts as a wrapper script around Autotools, calling the native build process and packaging generated libraries. Running `sbt flow-native/packageBin` in the base directory produces the fat jar in `flow-native-sbt/target`.

Note: an important feature of fat jars is to include native libraries for several platforms. To copy binaries compiled on other platforms to the fat jar, place them in a subfolder of `flow-native-sbt/lib_native`. The subfolder should have the name `$(os.name)-$(os.arch)`, where `os.name` and `os.arch` are the Java system properties of the respective platforms.

### Note About Versioning
The project and package versions follow a [sematic](http://semver.org/) pattern: `M.m.p`, where

- `M` is the major version, representing backwards incompatible changes

- `m` is the minor version, indicating backwards compatible changes such as new feature additions

- `p` is the patch number, representing internal modifications such as bug-fixes
 
Usually (following most Linux distribution's conventions), shared libraries produced by a project `name` of version `M.m.p` are named `libname.so.M.m.p`. However, since when accessing shared libraries through the JVM, only the `name` can be specified and no particular version, the convention adopted by flow is to append `M` to the library name and always keep the major version at zero. E.g. `libflow.so.3.1.2` becomes `libflow3.so.0.1.2`.