aboutsummaryrefslogtreecommitdiff
path: root/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackaging.scala
blob: 22c42a154129689cc41716b8e10c58f70961c035 (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package ch.jodersky.sbt.jni
package plugins

import ch.jodersky.jni._
import sbt._
import sbt.Keys._

/** Packages libraries built with JniNative. */
object JniPackaging extends AutoPlugin {

  //JvmPlugin is required or else resource generators will be overriden
  override def requires = JniNative && plugins.JvmPlugin
  override def trigger = allRequirements

  object autoImport {

    val nativeLibraryPath = settingKey[String](
      "String that is prepended to the path of a native library when packaged. This value should be " +
        "passed to `NativeLoader.load()`"
    )

    val enableNativeCompilation = settingKey[Boolean](
      "Determines if native compilation is enabled. If disabled, only pre-compiled libraries in " +
        "`unmanagedNativeDirectories` will be packaged."
    )

    val unmanagedNativeDirectories = settingKey[Seq[File]](
      "Unmanaged directories containing native libraries. The libraries must be regular files " +
        "contained in a subdirectory corresponding to a platform. For example " +
        "`<unamagedNativeDirectory>/x86_64-linux/libfoo.so` is an unmanaged library for machines having " +
        "the x86_64 architecture and running the Linux kernel."
    )

    val unmanagedNativeLibraries = taskKey[Map[Platform, File]](
      "Reads `unmanagedNativeDirectories` and maps platforms to library files specified theirin."
    )

    val managedNativeLibraries = taskKey[Map[Platform, File]](
      "Maps locally built, platform-dependant libraries."
    )

    val nativeLibraries = taskKey[Map[Platform, File]](
      "All native libraries, managed and unmanaged."
    )

  }
  import autoImport._
  import JniNative.autoImport._

  lazy val settings: Seq[Setting[_]] = Seq(

    nativeLibraryPath := {
      val orgPath = organization.value.replaceAll("\\.", "/")
      s"/${orgPath}/${name.value}/native"
    },

    enableNativeCompilation := true,

    unmanagedNativeDirectories := Seq(baseDirectory.value / "lib_native"),

    unmanagedNativeLibraries := {
      val dirs: Seq[File] = unmanagedNativeDirectories.value
      val seq: Seq[(Platform, File)] = for (
        dir <- dirs;
        if (dir.exists && dir.isDirectory);
        platformDir <- dir.listFiles();
        if platformDir.isDirectory;
        platform = Platform.fromId(platformDir.name);
        library <- platformDir.listFiles();
        if library.isFile
      ) yield {
        platform -> library.getCanonicalFile()
      }

      seq.toMap
    },

    managedNativeLibraries := Def.taskDyn[Map[Platform, File]] {
      val enableManaged = (enableNativeCompilation).value
      if (enableManaged) Def.task {
        val library: File = nativeCompile.value
        val platform = nativePlatform.value
        Map(platform -> library)
      }
      else Def.task {
        Map()
      }
    }.value,

    // managed native libraries take precedence
    nativeLibraries := unmanagedNativeLibraries.value ++ unmanagedNativeLibraries.value,

    resourceGenerators += Def.task {

      val libraries: Seq[(Platform, File)] = nativeLibraries.value.toSeq

      val resources: Seq[File] = for ((plat, file) <- libraries) yield {

        //native library as a managed resource file
        val resource = resourceManaged.value /
          NativeLoader.fullLibraryPath(
            (nativeLibraryPath).value,
            plat
          )

        //copy native library to a managed resource (so it can also be loaded when not packaged as a jar)
        IO.copyFile(file, resource)
        resource
      }
      resources
    }.taskValue

  )

  override lazy val projectSettings = inConfig(Compile)(settings) ++
    Seq(crossPaths := false) //don't add scala version to native jars


}