aboutsummaryrefslogtreecommitdiff
path: root/project/native.scala
blob: 342a8639c16b2215ae59cd394b399c9589c59fbb (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import sbt._
import Keys._
import java.io.File
import java.util.jar.Manifest

object NativeKeys {

    val nativeBuildDirectory = settingKey[File]("Directory containing native build scripts.")
    val nativeTargetDirectory = settingKey[File]("Base directory to store native products.")
    val nativeOutputDirectory = settingKey[File]("Actual directory where native products are stored.")
    val nativePackageUnmanagedDirectory = settingKey[File]("Directory containing external products that will be copied to the native jar.")

    val nativeClean = taskKey[Unit]("Clean native build.")
    val nativeBuild = taskKey[File]("Invoke native build.")
}

object NativeDefaults {
    import NativeKeys._

    val autoClean = Def.task {
        val log = streams.value.log
        val build = nativeBuildDirectory.value

        Process("make distclean", build) #|| Process("make clean", build) ! log
    }

    val autoLib = Def.task {
        val log = streams.value.log
        val build = nativeBuildDirectory.value
        val out = nativeOutputDirectory.value

        val configure = Process(
            "./configure " +
            "--prefix=" + out.getAbsolutePath + " " +
            "--libdir=" + out.getAbsolutePath + " " +
            "--disable-versioned-lib", //Disable producing versioned library files, not needed for fat jars.
            build)

        val make = Process("make", build)

        val makeInstall = Process("make install", build)

        val ev = configure #&& make #&& makeInstall ! log
        if (ev != 0)
            throw new RuntimeException(s"Building native library failed. Exit code: ${ev}")

        (out ** ("*.la")).get.foreach(_.delete())

        out
    }

    val nativePackageMappings = Def.task {
        val managedDir = nativeTargetDirectory.value
        val unmanagedDir = nativePackageUnmanagedDirectory.value

        val managed = (nativeBuild.value ** "*").get
        val unmanaged = (unmanagedDir ** "*").get

        val managedMappings: Seq[(File, String)] = for (file <- managed; if file.isFile) yield {
            file -> ("native/" + (file relativeTo managedDir).get.getPath)
        }

        val unmanagedMappings: Seq[(File, String)] = for (file <- unmanaged; if file.isFile) yield {
            file -> ("native/" + (file relativeTo unmanagedDir).get.getPath)
        }

        managedMappings ++ unmanagedMappings
    }

    def os = System.getProperty("os.name").toLowerCase.filter(c => !c.isWhitespace)
    def arch = System.getProperty("os.arch").toLowerCase

    val settings: Seq[Setting[_]] = Seq(
        nativeTargetDirectory := target.value / "native",
        nativeOutputDirectory := nativeTargetDirectory.value / (os + "-" + arch),
        nativeClean := autoClean.value,
        nativeBuild := autoLib.value,
        nativePackageUnmanagedDirectory := baseDirectory.value / "lib_native",
        mappings in (Compile, packageBin) ++= nativePackageMappings.value
    )

}