Skip to content

Commit fa3e20f

Browse files
committed
Bundle libz3 within scalaz3.jar
The loading of the libz3 is now deterministic, no more LD_LIBRARY_PATH needed. libscalaz3/libz3 are always expected to be extracted to <tmp>/SCALAZ3_<checksum>. Works on linux and mac, compiles on windows but errors when running.
1 parent 20f2251 commit fa3e20f

File tree

4 files changed

+168
-126
lines changed

4 files changed

+168
-126
lines changed

README.md

Lines changed: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,82 +4,53 @@ ScalaZ3 for Scala 2.10
44
This is ScalaZ3 for Scala 2.10 and Z3 4.3. Switch to the branch '2.9.x' for
55
Scala 2.9 support.
66

7-
8-
Downloading Z3
9-
=================
10-
11-
Z3 can be downloaded from the [Z3 download site](http://z3.codeplex.com/)
12-
13-
147
Compiling ScalaZ3
158
=================
169

17-
Setup steps, for Linux
10+
Prerequisites
1811
----------------------
12+
You should have Java and SBT 0.13.x installed.
1913

20-
1) Download Z3, and copy the include and lib files to z3/[z3version]/include and
21-
z3/[z3version]/lib respectively. (eg: z3/4.3-unix-64b/include/z3.h and
22-
z3/4.3-unix-64b/lib/libz3.so).
23-
24-
2) Download sbt 0.12.x.
25-
26-
3) Run 'sbt package' to create the jar file. It will be in
27-
target/[scalaversion]/scalaz3....jar and will contain the shared
28-
library required by the bindings.
29-
30-
4) For testing, run
31-
32-
LD_LIBRARY_PATH=z3/[z3version]/lib sbt test
33-
34-
Alternatively, start a console by running
35-
36-
LD_LIBRARY_PATH=z3/[z3version]/lib scala -cp target/[scalaversion]scalaz3.jar
37-
38-
then try, e.g.,
39-
40-
println(z3.scala.version).
41-
42-
Setup steps, for Mac
14+
Linux
4315
----------------------
4416

45-
1) Download Z3, and copy the include and lib files to z3/[z3version]/include and
46-
z3/[z3version]/lib respectively. (eg: z3/4.3-osx-64b/include/z3.h and
47-
z3/4.3-osx-64b/lib/libz3.so).
48-
49-
2) Download sbt 0.12.x.
50-
51-
3) Run 'sbt package' to create the jar file. It will be in
52-
target/[scalaversion]/scalaz3....jar and will contain the shared
53-
library required by the bindings.
54-
55-
4) For testing, run
17+
1) Download Z3 source code from http://z3.codeplex.com/, compile it, and copy
18+
the headers and built library to z3/[z3version]/include and z3/[z3version]/lib
19+
respectively. (eg: z3/4.3-unix-64b/include/z3.h and
20+
z3/4.3-unix-64b/lib/libz3.so).
5621

57-
DYLD_LIBRARY_PATH=z3/[z3version]/lib sbt test
22+
2) Run 'sbt package' to create the jar file. It will be in
23+
'target/scala-2.10/scalaz3\_2.10-2.0.jar' and will contain the shared library
24+
dependencies.
5825

59-
Alternatively, start a console by running
26+
3) For testing, run
6027

61-
DYLD_LIBRARY_PATH=z3/[z3version]/lib scala -cp target/[scalaversion]scalaz3.jar
28+
sbt test
6229

63-
then try, e.g.,
30+
Mac
31+
----------------------
6432

65-
println(z3.scala.version).
33+
1) Download Z3 source code from http://z3.codeplex.com/, compile it, and copy
34+
the headers and built library to z3/[z3version]/include and z3/[z3version]/lib
35+
respectively. (eg: z3/4.3-unix-64b/include/z3.h and
36+
z3/4.3-unix-64b/lib/libz3.dnylib).
6637

67-
Setup steps, for Windows
68-
------------------------
38+
2) Run 'sbt package' to create the jar file. It will be in
39+
'target/scala-2.10/scalaz3\_2.10-2.0.jar' and will contain the shared library
40+
dependencies.
6941

70-
A) Download and install Z3 using the .msi installer
42+
3) For testing, run
7143

72-
B) Download sbt (see 2 above).
44+
sbt test
7345

74-
C) The 'package' command in the current build script does not work with
75-
Windows; there is no equivalent for the gcc command. Run 'javah' so that it
76-
compiles the Java/Scala sources and generates the JNI header files.
46+
Windows
47+
----------------------
7748

78-
D) Assuming you have copied the 'include' and 'bin' directories from the Z3
79-
distribution in z3/[z3version], the following command should compile the shared
80-
library, assuming you have installed MinGW:
49+
1) Download Cygwin, and install packages for gcc.
8150

82-
gcc -shared -o lib-bin\scalaz3.dll -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I "[jdkpath]\include" -I "[jdkpath]\include\win32" -I z3\[z3version]\include src\c\*.h src\c\*.c z3\[z3version]\bin\z3.lib
51+
2) Download Z3 4.3 release, and copy libz3.dll to z3/[z3version]/bin and
52+
include/\*.h to /z3/[z3version]/include/. (eg: z3/4.3-win-64b/bin/libz3.dll)
8353

84-
E) You can manually create a jar with the contents of target/[scalaversion] and
85-
lib-bin.
54+
3) Run 'sbt package' to create the jar file. It will end up in
55+
'target/scala2.10/scalaz3\_2.10-2.0.jar' and will contain the shared library
56+
dependencies.

project/Build.scala

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@ object ScalaZ3build extends Build {
55

66
val natives = List("z3.Z3Wrapper")
77

8+
lazy val PS = java.io.File.pathSeparator
9+
lazy val DS = java.io.File.separator
10+
811
lazy val cPath = file("src") / "c"
912
lazy val cFiles = file("src") / "c" * "*.c"
1013
lazy val soName = System.mapLibraryName("scalaz3")
14+
15+
lazy val z3Name = if (isMac) "libz3.dylib" else if(isWindows) "libz3.dll" else System.mapLibraryName("z3")
16+
1117
lazy val libBinPath = file("lib-bin")
18+
lazy val z3BinFilePath = z3LibPath / z3Name
1219
lazy val libBinFilePath = libBinPath / soName
1320
lazy val jdkIncludePath = file(System.getProperty("java.home")) / ".." / "include"
1421
lazy val jdkUnixIncludePath = jdkIncludePath / "linux"
@@ -54,7 +61,7 @@ object ScalaZ3build extends Build {
5461

5562
val javahKey = TaskKey[Unit]("javah", "Prepares the JNI headers")
5663
val gccKey = TaskKey[Unit]("gcc", "Compiles the C sources")
57-
val checksumKey = TaskKey[Unit]("checksum", "Generates checksum file.")
64+
val checksumKey = TaskKey[String]("checksum", "Generates checksum file.")
5865

5966
val checksumTask = (streams, sourceDirectory in Compile) map {
6067
case (s, sd) =>
@@ -97,25 +104,31 @@ object ScalaZ3build extends Build {
97104
fw.close
98105

99106
s.log.info("Wrote checksum " + md5String + " as part of " + checksumFilePath.asFile + ".")
107+
108+
md5String
100109
}
101110

102111

103112
val javahTask = (streams, dependencyClasspath in Compile, classDirectory in Compile) map {
104113
case (s, deps, cd) =>
105114

106-
deps.map(_.data.absolutePath).find(_.endsWith("lib/scala-library.jar")) match {
115+
deps.map(_.data.absolutePath).find(_.endsWith("lib" + DS + "scala-library.jar")) match {
107116
case Some(lib) =>
108117
s.log.info("Preparing JNI headers...")
109-
exec("javah -classpath " + cd.absolutePath + ":"+lib+" -d " + cPath.absolutePath + " " + natives.mkString(" "), s)
118+
exec("javah -classpath " + cd.absolutePath + PS + lib + " -d " + cPath.absolutePath + " " + natives.mkString(" "), s)
110119

111120
case None =>
112121
s.log.error("Scala library not found in dependencies ?!?")
113122

114123
}
115124
} dependsOn(compile.in(Compile))
116125

126+
def extractDir(checksum: String): String = {
127+
System.getProperty("java.io.tmpdir") + DS + "SCALAZ3_" + checksum + DS + "lib-bin" + DS
128+
}
129+
117130

118-
val gccTask = (streams) map { case (s) =>
131+
val gccTask = (streams, checksumKey) map { case (s, cs) =>
119132
s.log.info("Compiling C sources ...")
120133

121134
// First, we look for z3
@@ -131,17 +144,20 @@ object ScalaZ3build extends Build {
131144
"-I" + jdkUnixIncludePath.absolutePath + " " +
132145
"-I" + z3IncludePath.absolutePath + " " +
133146
"-L" + z3LibPath.absolutePath + " " +
134-
"-g -lc -Wl,--no-as-needed -Wl,--copy-dt-needed -lz3 -fPIC -O2 -fopenmp " +
147+
"-g -lc " +
148+
"-Wl,-rpath,"+extractDir(cs)+" -Wl,--no-as-needed -Wl,--copy-dt-needed " +
149+
"-lz3 -fPIC -O2 -fopenmp " +
135150
cFiles.getPaths.mkString(" "), s)
136151

137152
} else if (isWindows) {
138153
exec("gcc -shared -o " + libBinFilePath.absolutePath + " " +
139154
"-D_JNI_IMPLEMENTATION_ -Wl,--kill-at " +
140-
"-I " + "\"" + jdkIncludePath.absolutePath + "\"" + " " +
141-
"-I " + "\"" + jdkWinIncludePath.absolutePath + "\"" + " " +
142-
"-I " + z3IncludePath.absolutePath + " " +
143-
cFiles.getPaths.mkString(" ") + " " +
144-
z3LibPath.absolutePath, s)
155+
"-D__int64=\"long long\" " +
156+
"-I " + "\"" + jdkIncludePath.absolutePath + "\" " +
157+
"-I " + "\"" + jdkWinIncludePath.absolutePath + "\" " +
158+
"-I " + "\"" + z3IncludePath.absolutePath + "\" " +
159+
cFiles.getPaths.mkString(" ") +
160+
" " + z3BinFilePath.absolutePath + "\" ", s)
145161
} else if (isMac) {
146162
val frameworkPath = "/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers"
147163

@@ -151,7 +167,9 @@ object ScalaZ3build extends Build {
151167
"-I" + frameworkPath + " " +
152168
"-I" + z3IncludePath.absolutePath + " " +
153169
"-L" + z3LibPath.absolutePath + " " +
154-
"-g -lc -lz3 -fPIC -O2 -fopenmp " +
170+
"-g -lc " +
171+
"-Wl,-rpath,"+extractDir(cs)+" " +
172+
"-lz3 -fPIC -O2 -fopenmp " +
155173
cFiles.getPaths.mkString(" "), s)
156174
} else {
157175
s.log.error("Unknown arch: "+osInf+" - "+osArch)
@@ -161,9 +179,25 @@ object ScalaZ3build extends Build {
161179

162180
val packageTask = (Keys.`package` in Compile).dependsOn(javahKey, gccKey)
163181

164-
val newMappingsTask = mappings in (Compile, packageBin) <<= (mappings in (Compile, packageBin)) map {
165-
case maps =>
166-
(libBinFilePath.getAbsoluteFile -> ("lib-bin/"+soName)) +: maps
182+
val newMappingsTask = mappings in (Compile, packageBin) <<= (mappings in (Compile, packageBin), streams) map {
183+
case (normalFiles, s) =>
184+
val newFiles =
185+
(libBinFilePath.getAbsoluteFile -> ("lib-bin/"+libBinFilePath.getName)) ::
186+
(z3LibPath.listFiles.toList.map { f =>
187+
f.getAbsoluteFile -> ("lib-bin/"+f.getName)
188+
})
189+
190+
s.log.info("Bundling files:")
191+
for ((from, to) <- newFiles) {
192+
s.log.info(" - "+from+" -> "+to)
193+
}
194+
195+
newFiles ++ normalFiles
196+
}
197+
198+
val newTestClassPath = internalDependencyClasspath in (Test) <<= (artifactPath in (Compile, packageBin)) map {
199+
case jar =>
200+
List(Attributed.blank(jar))
167201
}
168202

169203
lazy val root = Project(id = "ScalaZ3",
@@ -174,6 +208,7 @@ object ScalaZ3build extends Build {
174208
javahKey <<= javahTask,
175209
compile.in(Compile) <<= compile.in(Compile).dependsOn(checksumTask),
176210
Keys.`package`.in(Compile) <<= packageTask,
211+
newTestClassPath,
177212
newMappingsTask
178213
)
179214
)

project/build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sbt.version=0.12.2
1+
sbt.version=0.13.0

0 commit comments

Comments
 (0)