Commits

Ivan Vučica committed 89059b6

Objective-C test.

Comments (0)

Files changed (8)

+syntax: glob
+patchelf/*
+apk/*
+*.dex
+gen/*
+*.so
+*.o
+*.d
+*.jks
+*.apk
+*.class

AndroidManifest.xml

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.vucica.tv.ouya.sample.game" android:versionCode="1" android:versionName="1.0" >
 <!--   <uses-sdk android:minSdkVersion="10" />-->
    <uses-sdk android:minSdkVersion="14" />
-   <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >
+   <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:debuggable="true" >
       <!-- Our activity is the built-in NativeActivity framework class. This will take care of integrating with our NDK code. -->
-      <activity android:name="android.app.NativeActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
+	<!-- android:name="TGENativeActivity" --> <!-- needed for objc test -->
+	<!-- android:name="android.app.NativeActivity" --> <!-- use otherwise -->
+      <activity 
+	android:name="TGENativeActivity"
+	android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
          <!-- Tell NativeActivity the name of or .so -->
 	 <meta-data android:name="android.app.lib_name" android:value="TheGrandExperiment" />
          <intent-filter>
+package net.vucica.tv.ouya.sample.game;
 class DummyClass
 {
 }
 
 ANDROID_REV=android-18
 
+TEST_OBJC=true
+
 ##############################
 
 PLATFORM=linux
 JARSIGNER="$(JAVA_BIN)"/jarsigner
 KEYTOOL="$(JAVA_BIN)"/keytool
 JAVAC="$(JAVA_BIN)"/javac
+
 endif
 ifeq ("$(PLATFORM)","windows")
 COMPILER_BIN=$(shell cygpath -u `cygpath -w android-sdk`)/../compiler/bin/
 
 CFLAGS += -I $(COMPILER_BIN)/../include
 
+#CP_SO=cp
+CP_SO=$(COMPILER_BIN)/arm-linux-androideabi-objcopy -S 
+
+ifeq ($(TEST_OBJC),true)
+CFLAGS += -x objective-c $(shell gnustep-config --objc-flags) # testing objc
+LDFLAGS += $(shell gnustep-config --base-libs)
+FOUNDATION_COPY = $(CP_SO) $(shell gnustep-config --variable=GNUSTEP_LOCAL_LIBRARIES)/libgnustep-base.so.1.*.* apk/lib/armeabi/libgnustep-base.so
+OBJC_COPY = $(CP_SO) $(shell gnustep-config --variable=GNUSTEP_LOCAL_LIBRARIES)/libobjc.so.*.* apk/lib/armeabi/libobjc.so
+#DEP_PATCHELF = patchelf/src/patchelf
+#BUILD_PATCHELF = cd patchelf && ./bootstrap.sh && ./configure && make
+#FOUNDATION_PATCHELF = ./patchelf/src/patchelf --remove-needed libobjc.so.4.6 apk/lib/armeabi/libgnustep-base.so
+#TGE_PATCHELF = ./patchelf/src/patchelf --remove-needed libobjc.so.4.6 apk/lib/armeabi/lib$(APKNAME).so
+DEP_PATCHELF = patchelf_dummy
+BUILD_PATCHELF = @echo Not building patchelf
+TGE_PATCHELF = 
+
+# instead of rpl to replace .4.6 with null, we should do this: 
+# http://www.opengis.ch/2011/11/23/creating-non-versioned-shared-libraries-for-android/
+RPL = rpl -R -e libobjc.so.4.6 "libobjc.so\x00\x00\x00\x00" apk/lib/armeabi/
+
+JAVA_CLASS = TGENativeActivity
+
+else
+FOUNDATION_COPY = 
+OBJC_COPY =
+DEP_PATCHELF = patchelf_dummy
+BUILD_PATCHELF = @echo Not building patchelf
+FOUNDATION_PATCHELF = 
+TGE_PATCHELF = 
+RPL =
+
+JAVA_CLASS = DummyClass
+endif
+
 all: $(APKNAME).apk
 
 install: $(APKNAME).apk
 lib$(APKNAME).so: TheGrandExperiment.o android_native_app_glue.o
 	$(CC) $(LDFLAGS) TheGrandExperiment.o android_native_app_glue.o -o lib$(APKNAME).so
 
-$(APKNAME).unsigned.apk: lib$(APKNAME).so classes.dex AndroidManifest.xml
+$(DEP_PATCHELF):
+	$(BUILD_PATCHELF)
+
+$(APKNAME).unsigned.apk: lib$(APKNAME).so classes.dex AndroidManifest.xml $(DEP_PATCHELF)
 	rm -rf apk/
 	rm -rf gen
 	mkdir apk/
 	mkdir gen/
 	mkdir -p apk/lib/armeabi/
-	cp lib$(APKNAME).so apk/lib/armeabi
+
+	$(CP_SO) lib$(APKNAME).so apk/lib/armeabi/lib$(APKNAME).so
+	$(FOUNDATION_COPY)
+	$(OBJC_COPY)
+
+	$(FOUNDATION_PATCHELF)
+	$(TGE_PATCHELF)
+
+	$(RPL)
+
 	cp classes.dex apk/
 ifdef WITH_OUYA
 	mkdir -p `dirname "$(WITH_OUYA)"`
 $(KEYSTORE):
 	$(KEYTOOL) -genkey -v -keystore "$(KEYSTORE)" -alias "$(KEYNAME)" -keyalg RSA -keysize 2048 -validity 10000 -storepass "$(STOREPASS)" -keypass "$(KEYPASS)" -dname "$(DNAME)" -sigalg MD5withRSA
 
-classes.dex: classes/DummyClass.class
+classes.dex: classes/net/vucica/tv/ouya/sample/game/$(JAVA_CLASS).class
 	$(DX) --dex --output=$(PROJECT_PATH_WIN)/classes.dex --verbose $(PROJECT_PATH_WIN)/classes
 
-classes/DummyClass.class: DummyClass.java
-	mkdir -p classes/
-	$(JAVAC) -bootclasspath $(ANDROID_JAR) -d classes/ DummyClass.java -source 1.6 -target 1.6
+classes/net/vucica/tv/ouya/sample/game/$(JAVA_CLASS).class: $(JAVA_CLASS).java
+	mkdir -p classes/net/vucica/tv/ouya/sample/game/
+	$(JAVAC) -bootclasspath $(ANDROID_JAR) -d classes/ $(JAVA_CLASS).java -source 1.6 -target 1.6
 
 clean:
 	-rm *.o
 run:
 	$(ADB) shell am start -n $(IDENTIFIER)/android.app.NativeActivity
 
+nginx: /usr/share/nginx/www/$(APKNAME).apk
+/usr/share/nginx/www/$(APKNAME).apk: $(APKNAME).apk
+	cp $(APKNAME).apk /usr/share/nginx/www/
+	
 
 Build tools are presumed to be 19.0.1. `PLATFORM` needs to be set to
 `linux`. There may be other assumptions.
+
+Objective-C test
+----------------
+This code is also used to test Objective-C, and hence is no longer
+as minimal as it could be.
+
+`TGENativeActivity`, a subclass of `android.app.NativeActivity` is used.
+This is done so we can load additional libraries in correct order, instead
+of just the native activity code. Previously `DummyClass`, an empty class, 
+was used to produce `classes.dex`, required by Android; now
+`TGENativeActivity` is good enough for that.
+
+Also, when `TEST_OBJC=true` is set in `Makefile`, .c files are compiled
+as if they are Objective-C files. Using `#if __OBJC__`, extra code is used
+to test Objective-C functionality.
+
+Finally, when `TEST_OBJC=true`, additional libraries are copied into the
+apk (libobjc2 runtime, gnustep-base).
+
+hasCode
+-------
+Instead of DummyClass, we could use `android:hasCode="false"`.

TGENativeActivity.java

+package net.vucica.tv.ouya.sample.game;
+import android.app.NativeActivity;
+
+public class TGENativeActivity extends NativeActivity
+{
+  static
+  {
+    /*
+    AssetManager am = applicationContext.getAssets(); 
+    in = am.open(OPENSSL_SO_LIB_NAME); // source instream
+
+    File privateStorageDir = applicationContext.getFilesDir();
+    String libPath = privateStorageDir.getAbsolutePath();
+    */
+    System.loadLibrary("objc");
+    System.loadLibrary("gnustep-base");
+    System.loadLibrary("TheGrandExperiment");
+  }
+
+}

TheGrandExperiment.c

 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
 
+#if __OBJC__
+#include <Foundation/NSString.h>
+#endif
+
 /**
  * Our saved state data.
  */
 
     // loop waiting for stuff to do.
 
+    #if __OBJC__
+    NSString * aString = @"Hello NSString!";
+    LOGI([aString UTF8String]);
+    #endif
+
     while (1) {
         // Read all pending events.
         int ident;
+
+git clone https://github.com/NixOS/patchelf patchelf