diff --git a/.gitignore b/.gitignore
index a72b66b484..b52f87bc2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ realm_version_check.timestamp
# Build artifacts
*.so
+*.dylib
*.d
*.o
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21c54448b0..7269fc014b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
### Enhancements
* RealmObjectSchema.isPrimaryKey(String) (#2440)
+* Added support for Robolectric on Max OS X (#1867).
### Bug fixes
diff --git a/build.gradle b/build.gradle
index 654c3174c0..0b50e99aca 100644
--- a/build.gradle
+++ b/build.gradle
@@ -104,6 +104,20 @@ task installRealmJava(type:Task) {
description = 'Install the Realm library and Gradle plugin into mavenLocal()'
}
+task installRobolectric(type:GradleBuild) {
+ description = 'Install the Robolectric library into example'
+ group = 'Install'
+ buildFile = file('realm/build.gradle')
+ tasks = ['installRobolectric']
+}
+
+task assembleRobolectric(type:GradleBuild) {
+ description = 'Assemble the Robolectric support'
+ group = 'Build'
+ buildFile = file('realm/build.gradle')
+ tasks = ['assembleRobolectric']
+}
+
task assembleExamples(type:GradleBuild) {
dependsOn installGradlePlugin
dependsOn installRealm
@@ -174,6 +188,16 @@ task distributionPackage(type:Zip) {
}
}
+task createRobolectricDistributionPackages(type:Zip) {
+ description = 'Create the Robolectric distribution package'
+ dependsOn assembleRobolectric
+
+ archiveName = "realm-robolectric-darwin-${currentVersion}.zip"
+ destinationDir = file("${buildDir}/outputs/distribution")
+
+ from('realm/realm-jni/build/librealm-jni-darwin.dylib')
+}
+
task cleanRealm(type:GradleBuild) {
description = 'Clean the Realm project'
group = 'Clean'
@@ -220,6 +244,12 @@ task uploadDistributionPackage(type: Exec) {
commandLine 's3cmd', 'put', "${buildDir}/outputs/distribution/realm-java-${currentVersion}.zip", 's3://static.realm.io/downloads/java/'
}
+task uploadRobolectricDistributionPackage(type: Exec) {
+ description = 'Upload the Robolectric distribution package to S3'
+ dependsOn createRobolectricDistributionPackages
+ commandLine 's3cmd', 'put', "${buildDir}/outputs/distribution/realm-robolectric-darwin-${currentVersion}.zip", 's3://static.realm.io/downloads/java/'
+}
+
task createEmptyFile(type: Exec) {
group = 'Release'
description = 'Create an empty file that will serve as a link on S3'
diff --git a/examples/build.gradle b/examples/build.gradle
index c1c2682d7a..27dcc6d7f4 100644
--- a/examples/build.gradle
+++ b/examples/build.gradle
@@ -7,7 +7,7 @@ configurations.all {
}
allprojects {
- def currentVersion = file("${rootDir}/../version.txt").text.trim()
+ ext.currentVersion = file("${rootDir}/../version.txt").text.trim()
buildscript {
repositories {
diff --git a/examples/robolectricExample/.gitignore b/examples/robolectricExample/.gitignore
new file mode 100644
index 0000000000..c4c4ffc6aa
--- /dev/null
+++ b/examples/robolectricExample/.gitignore
@@ -0,0 +1 @@
+*.zip
diff --git a/examples/robolectricExample/build.gradle b/examples/robolectricExample/build.gradle
new file mode 100644
index 0000000000..29cb69873d
--- /dev/null
+++ b/examples/robolectricExample/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'android-sdk-manager'
+apply plugin: 'com.android.application'
+apply plugin: 'android-command'
+apply plugin: 'com.neenbedankt.android-apt'
+apply plugin: 'realm-android'
+apply plugin: 'realm-robolectric'
+
+android {
+ compileSdkVersion rootProject.sdkVersion
+ buildToolsVersion rootProject.buildTools
+
+ defaultConfig {
+ applicationId 'io.realm.examples.robolectric'
+ targetSdkVersion 21
+ minSdkVersion 15
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ }
+ }
+
+ command {
+ events 2000
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:23.1.0'
+ compile 'com.android.support:design:23.1.0'
+ testCompile 'io.reactivex:rxjava:1.1.0'
+ testCompile 'junit:junit:4.12'
+ testCompile "org.robolectric:robolectric:3.0"
+}
diff --git a/examples/robolectricExample/src/main/AndroidManifest.xml b/examples/robolectricExample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..f06b2ed6c3
--- /dev/null
+++ b/examples/robolectricExample/src/main/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/robolectricExample/src/main/java/io/realm/examples/robolectric/MainActivity.java b/examples/robolectricExample/src/main/java/io/realm/examples/robolectric/MainActivity.java
new file mode 100644
index 0000000000..89f60a37ca
--- /dev/null
+++ b/examples/robolectricExample/src/main/java/io/realm/examples/robolectric/MainActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 Realm Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.realm.examples.robolectric;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/examples/robolectricExample/src/main/res/drawable-xxhdpi/ic_launcher.png b/examples/robolectricExample/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..433021180b
Binary files /dev/null and b/examples/robolectricExample/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/examples/robolectricExample/src/main/res/layout/activity_main.xml b/examples/robolectricExample/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000000..6516002320
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/layout/activity_main.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/robolectricExample/src/main/res/layout/content_main.xml b/examples/robolectricExample/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000000..1fb534d892
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/layout/content_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/examples/robolectricExample/src/main/res/menu/menu_main.xml b/examples/robolectricExample/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000000..a459e0a540
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/menu/menu_main.xml
@@ -0,0 +1,9 @@
+
diff --git a/examples/robolectricExample/src/main/res/values-v21/styles.xml b/examples/robolectricExample/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000000..6b23c86e5e
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/values-v21/styles.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/examples/robolectricExample/src/main/res/values-w820dp/dimens.xml b/examples/robolectricExample/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000000..63fc816444
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/examples/robolectricExample/src/main/res/values/colors.xml b/examples/robolectricExample/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..3ab3e9cbce
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/examples/robolectricExample/src/main/res/values/dimens.xml b/examples/robolectricExample/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..812cb7be0a
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 16dp
+ 16dp
+ 16dp
+
diff --git a/examples/robolectricExample/src/main/res/values/strings.xml b/examples/robolectricExample/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..c4033be75f
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ RobolectricTest
+ Settings
+
diff --git a/examples/robolectricExample/src/main/res/values/styles.xml b/examples/robolectricExample/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..16dbab30f2
--- /dev/null
+++ b/examples/robolectricExample/src/main/res/values/styles.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/examples/robolectricExample/src/test/java/io/realm/examples/robolectric/RobolectricTest.java b/examples/robolectricExample/src/test/java/io/realm/examples/robolectric/RobolectricTest.java
new file mode 100644
index 0000000000..15093b5c63
--- /dev/null
+++ b/examples/robolectricExample/src/test/java/io/realm/examples/robolectric/RobolectricTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Realm Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.realm.examples.robolectric;
+
+import android.app.Activity;
+import android.content.Context;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.annotation.Config;
+
+import io.realm.examples.robolectric.entities.Person;
+import io.realm.test.RealmRobolectricRule;
+import io.realm.Realm;
+import io.realm.RealmConfiguration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(RobolectricGradleTestRunner.class)
+@Config(constants = BuildConfig.class)
+public class RobolectricTest {
+
+ private Realm realm;
+ private Activity context;
+ private RealmConfiguration config;
+
+ @Rule
+ public RealmRobolectricRule realmRobolectricRule = new RealmRobolectricRule();
+
+ private Context getContext() {
+ return context;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ context = Robolectric.setupActivity(MainActivity.class);
+ config = new RealmConfiguration.Builder(getContext()).build();
+ Realm.deleteRealm(config);
+ realm = Realm.getInstance(config);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (realm != null) {
+ realm.close();
+ }
+ }
+
+ @Test
+ public void testIsEmpty() {
+ assertTrue(realm.isEmpty());
+ Person person = new Person();
+ person.setName("Brad Pitt");
+ person.setAge(52);
+ realm.beginTransaction();
+ realm.copyToRealm(person);
+ realm.commitTransaction();
+ assertFalse(realm.isEmpty());
+ }
+}
diff --git a/examples/robolectricExample/src/test/java/io/realm/examples/robolectric/entities/Person.java b/examples/robolectricExample/src/test/java/io/realm/examples/robolectric/entities/Person.java
new file mode 100644
index 0000000000..579835473f
--- /dev/null
+++ b/examples/robolectricExample/src/test/java/io/realm/examples/robolectric/entities/Person.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 Realm Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.realm.examples.robolectric.entities;
+
+import io.realm.RealmObject;
+
+public class Person extends RealmObject {
+ private String name;
+ private int age;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
diff --git a/examples/settings.gradle b/examples/settings.gradle
index 529a4f486c..46ad6b551b 100644
--- a/examples/settings.gradle
+++ b/examples/settings.gradle
@@ -12,6 +12,7 @@ include 'threadExample'
include 'unitTestExample'
include 'newsreaderExample'
include 'rxJavaExample'
+include 'robolectricExample'
rootProject.name = 'realm-examples'
diff --git a/gradle-plugin/build.gradle b/gradle-plugin/build.gradle
index dec61401ca..04b0106c5a 100644
--- a/gradle-plugin/build.gradle
+++ b/gradle-plugin/build.gradle
@@ -47,6 +47,7 @@ dependencies {
compile localGroovy()
compile "io.realm:realm-transformer:${version}"
compile 'com.neenbedankt.gradle.plugins:android-apt:1.8'
+ compile 'de.undercouch:gradle-download-task:2.0.0'
provided 'com.android.tools.build:gradle:1.5.0'
testCompile gradleTestKit()
diff --git a/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy b/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy
index 0536847d77..f6b04bcb39 100644
--- a/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy
+++ b/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy
@@ -54,9 +54,11 @@ class Realm implements Plugin {
if (isKotlinProject) {
project.dependencies.add("kapt", "io.realm:realm-annotations:${Version.VERSION}")
project.dependencies.add("kapt", "io.realm:realm-annotations-processor:${Version.VERSION}")
+ project.dependencies.add("kaptTest", "io.realm:realm-annotations-processor:${Version.VERSION}")
} else {
project.dependencies.add("apt", "io.realm:realm-annotations:${Version.VERSION}")
project.dependencies.add("apt", "io.realm:realm-annotations-processor:${Version.VERSION}")
+ project.dependencies.add("testApt", "io.realm:realm-annotations-processor:${Version.VERSION}")
}
}
diff --git a/gradle-plugin/src/main/groovy/io/realm/gradle/RealmRobolectric.groovy b/gradle-plugin/src/main/groovy/io/realm/gradle/RealmRobolectric.groovy
new file mode 100644
index 0000000000..1d3a77d92a
--- /dev/null
+++ b/gradle-plugin/src/main/groovy/io/realm/gradle/RealmRobolectric.groovy
@@ -0,0 +1,36 @@
+package io.realm.gradle
+
+import de.undercouch.gradle.tasks.download.DownloadTaskPlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class RealmRobolectric implements Plugin {
+
+ @Override
+ void apply(Project project) {
+ project.plugins.apply(DownloadTaskPlugin)
+
+ project.task('downloadRealmRobolectric') {
+ def targetZip = "${project.projectDir}/realm-robolectric-darwin-${Version.VERSION}.zip"
+ def targetLib = "${project.projectDir}/src/test/libs/librealm-jni-darwin.dylib"
+
+ inputs.file project.file(targetZip)
+ outputs.file project.file(targetLib)
+
+ doLast {
+ project.download {
+ src "http://static.realm.io/downloads/java/realm-robolectric-darwin-${Version.VERSION}.zip"
+ dest "${project.projectDir}"
+ }
+
+ project.copy {
+ from project.zipTree(project.file(targetZip))
+ into "${project.projectDir}/src/test/libs"
+ }
+ }
+ }
+ project.afterEvaluate {
+ project.test.dependsOn project.tasks.downloadRealmRobolectric
+ }
+ }
+}
\ No newline at end of file
diff --git a/gradle-plugin/src/main/resources/META-INF/gradle-plugins/realm-robolectric.properties b/gradle-plugin/src/main/resources/META-INF/gradle-plugins/realm-robolectric.properties
new file mode 100644
index 0000000000..d80324d416
--- /dev/null
+++ b/gradle-plugin/src/main/resources/META-INF/gradle-plugins/realm-robolectric.properties
@@ -0,0 +1 @@
+implementation-class=io.realm.gradle.RealmRobolectric
diff --git a/realm/realm-jni/build.gradle b/realm/realm-jni/build.gradle
index 27bd172ac8..3ef2819857 100644
--- a/realm/realm-jni/build.gradle
+++ b/realm/realm-jni/build.gradle
@@ -133,7 +133,10 @@ ext.coreDir = file("${buildDir}/core-${project.coreVersion}")
def coreDownloaded = false
-task downloadCore(group: 'build setup', description: 'Download the latest version of realm core') {
+task downloadCore {
+ group = 'build setup'
+ description = 'Download the latest version of realm core'
+
def isHashCheckingEnabled = {
return project.hasProperty('coreSha256Hash') && !project.coreSha256Hash.empty
}
@@ -191,7 +194,10 @@ task downloadCore(group: 'build setup', description: 'Download the latest versio
}
}
-task compileCore(group: 'build setup', description: 'Compile the core library from source code') {
+task compileCore {
+ group = 'build setup'
+ description = 'Compile the core library from source code'
+
// Build the library from core source code
doFirst {
if (!coreSourcePath) {
@@ -217,7 +223,10 @@ task compileCore(group: 'build setup', description: 'Compile the core library fr
}
}
-task deployCore(group: 'build setup', description: 'Deploy the latest version of realm core') {
+task deployCore {
+ group = 'build setup'
+ description = 'Deploy the latest version of realm core'
+
dependsOn {
coreSourcePath ? compileCore : downloadCore
}
@@ -257,6 +266,112 @@ task deployCore(group: 'build setup', description: 'Deploy the latest version of
}
}
+task compileCoreLibForHost {
+ group = 'build setup'
+ description = 'Compile the core library for host from source code'
+
+ doLast {
+ if (!coreSourcePath) {
+ throw new GradleException("The Realm Core library is needed to build support for Robolectric. coreSourcePath, /usr/local/lib/librealm.a or the environment REALM_CORE_HOME is needed.")
+ }
+ exec {
+ workingDir = coreSourcePath
+ environment 'REALM_ENABLE_ENCRYPTION', 'yes'
+ commandLine = [
+ "bash",
+ "build.sh",
+ "clean",
+ "config",
+ "build"
+ ]
+ }
+ copy {
+ from "$coreSourcePath/src/realm/librealm.a"
+ into "${projectDir}/../realm-library/src"
+ }
+ }
+}
+
+task prepareCoreLibForHost {
+ group = 'build setup'
+ description = 'Prepare the core library for host'
+
+ def staticLibHome = System.env.REALM_CORE_HOME ? System.env.REALM_CORE_HOME : '/usr/local'
+
+ doFirst {
+ if (file("${staticLibHome}/lib/librealm.a").exists() == false) {
+ if (!coreSourcePath) {
+ throw new GradleException("The Realm Core library is needed to build support for Robolectric. coreSourcePath, /usr/local/lib/librealm.a or the environment REALM_CORE_HOME is needed.")
+ }
+ }
+ }
+
+ doLast {
+ copy {
+ from "$staticLibHome/lib/librealm.a"
+ into "${projectDir}/../realm-library/src"
+ }
+ }
+}
+
+task assembleRobolectric {
+ group = 'build'
+ description = "Build the Robolectric shared library for Darwin"
+ dependsOn coreSourcePath ? compileCoreLibForHost : prepareCoreLibForHost
+
+ def realmCoreHome = System.env.REALM_CORE_HOME ? System.env.REALM_CORE_HOME : '/usr/local'
+ def coreHeader = coreSourcePath ? "-I$coreSourcePath/src/" : "-I$realmCoreHome/include/realm/"
+
+ doLast {
+ exec {
+ environment CC: "${clang ? 'clang' : 'gcc'}"
+ environment STRIP: "/usr/bin/strip -o librealm-jni-darwin-stripped.dylib"
+ commandLine = [
+ 'make',
+ "-j${Runtime.getRuntime().availableProcessors() * 2}",
+ "-l${Runtime.getRuntime().availableProcessors()}",
+ '-C', "${projectDir}/src",
+ "CC_IS=${clang ? 'clang' : 'gcc'}",
+ "REALM_CFLAGS_COMMON=-Wno-variadic-macros -DREALM_HAVE_CONFIG -DPIC $coreHeader -I/usr/local/include/ -I/System/Library/Frameworks/JavaVM.framework/Headers/",
+ "CFLAGS_ARCH=${commonCflags.join(' ')}",
+ "BASE_DENOM=darwin",
+ "REALM_LDFLAGS_COMMON=-lrealm -lstdc++ -L${projectDir}/../realm-library/src -L/usr/local/lib/ -Wl,-dead_strip -flto -Wl,-search_paths_first -framework CoreServices",
+ 'LIB_SUFFIX_SHARED=.dylib',
+ "REALM_ROBOLECTRIC=true",
+ "librealm-jni-darwin${getDebugExt()}.dylib"
+ ]
+ }
+
+ copy {
+ from "${projectDir}/src/librealm-jni-darwin${getDebugExt()}${getStrippedExt()}.dylib"
+ into "${projectDir}/build"
+ rename "librealm-jni-darwin${getDebugExt()}${getStrippedExt()}.dylib", 'librealm-jni-darwin.dylib'
+ }
+
+ // Store the unstripped version
+ copy {
+ from "${projectDir}/src/librealm-jni-darwin${getDebugExt()}.dylib"
+ into "${projectDir}/../build/output/jniLibs-unstripped/robolectric"
+ rename "librealm-jni-darwin${getDebugExt()}.dylib", 'librealm-jni-darwin.dylib'
+ }
+
+ delete fileTree(dir: "${projectDir}/../realm-library/src", include: '**/librealm.a')
+ }
+}
+
+task installRobolectric {
+ group = 'Install'
+ description = "Install native library to support Robolectric."
+ dependsOn {
+ assembleRobolectric
+ }
+
+ copy {
+ from "${projectDir}/build/librealm-jni-darwin.dylib"
+ into "${projectDir}/../../examples/robolectricExample/src/test/libs"
+ }
+}
+
toolchains.each { toolchain ->
def ndkDir = getNdk()
task "generateNdkToolchain${toolchain.name.capitalize()}"(type: Exec) {
@@ -314,7 +429,10 @@ targets.each { target ->
}
}
-task buildAndroidJni(group: 'build', description: 'Build the Android JNI shared library for all the supported platforms') {
+task buildAndroidJni {
+ group = 'build'
+ description = 'Build the Android JNI shared library for all the supported platforms'
+
targets.each { target ->
dependsOn "copyAndroidJni${target.name.capitalize()}"
}
@@ -329,7 +447,11 @@ task clean(type: Delete) {
delete fileTree(dir: "${projectDir}/../realm-library/src/main/jniLibs/", include: '**/librealm-jni*.so')
delete fileTree(dir: "${projectDir}/../build/output/jniLibs-unstripped/", include: '**/librealm-jni*.so')
+ delete fileTree(dir: "${projectDir}/../build/output/jniLibs-unstripped/robolectric", include: '**/librealm-jni*.dylib')
delete fileTree(dir: "${projectDir}/src/", include: '**/librealm-jni*-stripped.so')
+ delete fileTree(dir: "${projectDir}/src/", include: '**/librealm-jni*-stripped.dylib')
+ delete fileTree(dir: "${projectDir}/src/", include: '**/librealm-jni*.dylib')
+ delete fileTree(dir: "${projectDir}/../realm-library/src", include: '**/librealm.a')
doLast {
targets.each { target ->
diff --git a/realm/realm-jni/generic.mk b/realm/realm-jni/generic.mk
index 9b0d6fdf55..810a169519 100644
--- a/realm/realm-jni/generic.mk
+++ b/realm/realm-jni/generic.mk
@@ -1824,8 +1824,14 @@ ifeq ($(OS),Darwin)
# See http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
+define SHARED_LIBRARY_RULE_DARWIN
+$(1): $(2)
+ $$(strip $(3)) -o $(1)
+ $(STRIP) -x $(1)
+endef
+
# ARGS: qual_lib_name, deps, cmd, version
-SHARED_LIBRARY_RULE = $(if $(4),$(call SHARED_LIBRARY_RULE_VER,$(1),$(2),$(3),$(call MAP_SHARED_LIB_VERSION,$(1),$(4))),$(SHARED_LIBRARY_RULE_DEFAULT))
+SHARED_LIBRARY_RULE = $(if $(4),$(call SHARED_LIBRARY_RULE_VER,$(1),$(2),$(3),$(call MAP_SHARED_LIB_VERSION,$(1),$(4))),$(SHARED_LIBRARY_RULE_DARWIN))
# ARGS: qual_lib_name, deps, cmd, mapped_version
SHARED_LIBRARY_RULE_VER = $(call SHARED_LIBRARY_RULE_VER_2,$(1),$(2),$(3),$(word 1,$(4)),$(word 2,$(4)),$(word 3,$(4)))
diff --git a/realm/realm-jni/project.mk b/realm/realm-jni/project.mk
index cf9b0e6b95..f563f2e38a 100644
--- a/realm/realm-jni/project.mk
+++ b/realm/realm-jni/project.mk
@@ -38,7 +38,9 @@ endif
#endif
ifeq ($(REALM_ANDROID),)
- REALM_LDFLAGS += -llog
+ ifneq ($(REALM_ROBOLECTRIC),true)
+ REALM_LDFLAGS += -llog
+ endif
CFLAGS_INCLUDE += $(JAVA_CFLAGS)
ifneq ($(REALM_ENABLE_MEM_USAGE),)
PROJECT_CFLAGS += -DREALM_ENABLE_MEM_USAGE
diff --git a/realm/realm-library/build.gradle b/realm/realm-library/build.gradle
index bb8f95265e..c0a9c29be8 100644
--- a/realm/realm-library/build.gradle
+++ b/realm/realm-library/build.gradle
@@ -46,6 +46,7 @@ repositories {
dependencies {
provided 'io.reactivex:rxjava:1.1.0'
+ provided 'junit:junit:4.12'
compile "io.realm:realm-annotations:${version}"
androidTestCompile 'io.reactivex:rxjava:1.1.0'
diff --git a/realm/realm-library/src/main/java/io/realm/internal/RealmCore.java b/realm/realm-library/src/main/java/io/realm/internal/RealmCore.java
index 670184b827..1404a5a044 100644
--- a/realm/realm-library/src/main/java/io/realm/internal/RealmCore.java
+++ b/realm/realm-library/src/main/java/io/realm/internal/RealmCore.java
@@ -21,6 +21,7 @@
import io.realm.internal.android.ReLinker;
import java.io.File;
+import java.lang.Throwable;
import java.lang.reflect.Field;
import java.util.Locale;
@@ -37,10 +38,15 @@ public class RealmCore {
private static volatile boolean libraryIsLoaded = false;
public static boolean osIsWindows() {
- String os = System.getProperty("os.name").toLowerCase(Locale.getDefault());
+ String os = System.getProperty("os.name").toLowerCase(Locale.US);
return (os.contains("win"));
}
+ public static boolean osIsDarwin() {
+ String os = System.getProperty("os.name").toLowerCase(Locale.US);
+ return (os.contains("mac"));
+ }
+
/**
* Loads the .so file. This method is useful for static blocks as it does not rely on access to a Context.
*
@@ -56,17 +62,11 @@ public static synchronized void loadLibrary() {
if (osIsWindows()) {
loadLibraryWindows();
- }
- else {
- String jnilib;
- String debug = System.getenv("REALM_JAVA_DEBUG");
- if (debug == null || debug.isEmpty()) {
- jnilib = "realm-jni";
- }
- else {
- jnilib = "realm-jni-dbg";
- }
- System.loadLibrary(jnilib);
+ } else if (osIsDarwin()) {
+ resetLibraryPath();
+ loadLibrary("realm-jni-darwin", "realm-jni-darwin-dbg");
+ } else {
+ loadLibrary("realm-jni", "realm-jni-dbg");
}
libraryIsLoaded = true;
@@ -86,7 +86,12 @@ public static synchronized void loadLibrary(Context context) {
if (libraryIsLoaded) {
return;
}
- ReLinker.loadLibrary(context, "realm-jni");
+ if (osIsDarwin()) {
+ resetLibraryPath();
+ loadLibrary("realm-jni-darwin", "realm-jni-darwin");
+ } else {
+ ReLinker.loadLibrary(context, "realm-jni");
+ }
libraryIsLoaded = true;
}
@@ -116,6 +121,26 @@ private static String loadLibraryWindows() {
return jnilib;
}
+ /**
+ * Loads the release / debug .so file depending on REALM_JAVA_DEBUG.
+ */
+ private static void loadLibrary(String releaseJniLib, String debugJniLib) {
+ String jnilib;
+ String debug = System.getenv("REALM_JAVA_DEBUG");
+ if (debug == null || debug.isEmpty()) {
+ jnilib = releaseJniLib;
+ } else {
+ jnilib = debugJniLib;
+ }
+ try {
+ System.loadLibrary(jnilib);
+ } catch (Throwable e) {
+ System.err.println("error: " + e.getMessage());
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
private static String loadCorrectLibrary(String... libraryCandidateNames) {
for (String libraryCandidateName : libraryCandidateNames) {
try {
diff --git a/realm/realm-library/src/main/java/io/realm/test/RealmRobolectricRule.java b/realm/realm-library/src/main/java/io/realm/test/RealmRobolectricRule.java
new file mode 100644
index 0000000000..1e1e58e124
--- /dev/null
+++ b/realm/realm-library/src/main/java/io/realm/test/RealmRobolectricRule.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 Realm Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.realm.test;
+
+import android.text.TextUtils;
+
+import org.junit.rules.ExternalResource;
+
+import java.io.File;
+import java.lang.StringBuilder;
+
+/**
+ * JUnit Rule to initialize support for Robolectric.
+ */
+public class RealmRobolectricRule extends ExternalResource {
+ @Override
+ protected void before() throws Throwable {
+ final String libraryPathKey = "java.library.path";
+ final String previousLibraryPath = System.getProperty(libraryPathKey);
+ final String robolectricLibPath = "." + File.separator + "src" + File.separator + "test" + File.separator + "libs";
+
+ if (previousLibraryPath.contains(robolectricLibPath)) {
+ return;
+ }
+
+ final String libraryPath;
+ if (TextUtils.isEmpty(previousLibraryPath)) {
+ libraryPath = robolectricLibPath;
+ } else {
+ libraryPath = robolectricLibPath + File.pathSeparator + previousLibraryPath;
+ }
+ System.setProperty(libraryPathKey, libraryPath);
+ }
+}
+