diff options
-rw-r--r-- | android/Bootstrap/src/org/libreoffice/android/Bootstrap.java | 64 | ||||
-rw-r--r-- | android/experimental/DocumentLoader/Makefile | 241 | ||||
-rw-r--r-- | android/experimental/DocumentLoader/native-code.cxx | 48 | ||||
-rw-r--r-- | android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java | 8 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | distro-configs/LibreOfficeAndroid.conf | 1 | ||||
-rw-r--r-- | distro-configs/LibreOfficeAndroidX86.conf | 1 | ||||
-rw-r--r-- | sal/Package_inc.mk | 1 | ||||
-rw-r--r-- | sal/android/lo-bootstrap.c | 760 | ||||
-rw-r--r-- | sal/inc/osl/detail/android-bootstrap.h | 17 | ||||
-rw-r--r-- | sal/inc/osl/detail/component-mapping.h | 62 | ||||
-rw-r--r-- | sal/inc/osl/detail/ios-bootstrap.h | 14 | ||||
-rw-r--r-- | solenv/inc/unxand.mk | 2 |
13 files changed, 321 insertions, 902 deletions
diff --git a/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java b/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java index b97adfb6261a..2c8d2e7b31d1 100644 --- a/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java +++ b/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java @@ -62,21 +62,9 @@ public class Bootstrap extends NativeActivity String apkFile, String[] ld_library_path); - public static native boolean setup(int lo_main_ptr, - Object lo_main_argument, + public static native boolean setup(Object lo_main_argument, int lo_main_delay); - // This is not just a wrapper for the C library dlopen(), but also - // loads recursively dependent libraries. - public static native int dlopen(String library); - - // This is just a wrapper for the C library dlsym(). - public static native int dlsym(int handle, String symbol); - - // To be called after you are sure libgnustl_shared.so - // has been loaded - static native void patch_libgnustl_shared(); - // Extracts files in the .apk that need to be extraced into the app's tree static native void extract_files(); @@ -148,11 +136,6 @@ public class Bootstrap extends NativeActivity if (!setup(dataDir, activity.getApplication().getPackageResourcePath(), llpa)) return; - // We build LO code against the shared GNU C++ library - dlopen("libgnustl_shared.so"); - // and need to patch it. - patch_libgnustl_shared(); - // Extract files from the .apk that can't be used mmapped directly from it extract_files(); @@ -224,35 +207,8 @@ public class Bootstrap extends NativeActivity System.arraycopy(argv, 0, newargv, 1, argv.length); argv = newargv; - // Load the LO "program" here and look up lo_main - int loLib = dlopen(mainLibrary); - - if (loLib == 0) { - Log.i(TAG, String.format("Error: could not load %s", mainLibrary)); - mainLibrary = "libmergedlo.so"; - loLib = dlopen(mainLibrary); - if (loLib == 0) { - Log.i(TAG, String.format("Error: could not load fallback %s", mainLibrary)); - return; - } - } - - int lo_main = dlsym(loLib, "lo_main"); - if (lo_main == 0) { - Log.i(TAG, String.format("No lo_main in %s", mainLibrary)); - return; - } - - // Get extra libraries to load early, so that it's easier to debug - // them even with a buggy ndk-gdb that doesn't grok debugging - // information from libraries loaded after it has been attached to the - // process. - String extraLibs = getIntent().getStringExtra("lo-extra-libs"); - if (extraLibs != null) { - for (String lib : extraLibs.split(":")) { - dlopen(lib); - } - } + // Load the LO "program" here + System.loadLibrary(mainLibrary); // Start a strace on ourself if requested. @@ -272,7 +228,7 @@ public class Bootstrap extends NativeActivity delay = Integer.parseInt(sdelay); // Tell lo-bootstrap.c the stuff it needs to know - if (!setup(lo_main, argv, delay)) + if (!setup(argv, delay)) return; // Finally, call our super-class, NativeActivity's onCreate(), @@ -286,14 +242,12 @@ public class Bootstrap extends NativeActivity super.onCreate(savedInstanceState); } - // This is used to load the 'lo-bootstrap' library on application - // startup. The library has already been unpacked into - // /data/data/<app name>/lib/liblo-bootstrap.so at installation - // time by the package manager. + // Now with static loading we always have all native code in one native + // library which we always call liblo-native-code.so, regardless of the + // app. The library has already been unpacked into /data/data/<app + // name>/lib at installation time by the package manager. static { - System.loadLibrary("lo-bootstrap"); - System.loadLibrary("gnustl_shared"); - System.loadLibrary("libotouchlo"); + System.loadLibrary("lo-native-code"); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/android/experimental/DocumentLoader/Makefile b/android/experimental/DocumentLoader/Makefile index d4504092830c..a357e6b0b022 100644 --- a/android/experimental/DocumentLoader/Makefile +++ b/android/experimental/DocumentLoader/Makefile @@ -19,15 +19,154 @@ APP_DATA_PATH=/data/data/$(APP_PACKAGE) SODEST=libs/$(ANDROID_APP_ABI) OBJLOCAL=obj/local/$(ANDROID_APP_ABI) -define COPYSO -cp $(1) $(SODEST)$(if $(2),/$(2)) && $(STRIP) --strip-debug $(SODEST)$(if $(2),/$(2),/$(notdir $(1))) && \ -cp $(1) $(OBJLOCAL)$(if $(2),/$(2)) -endef - define COPYJAR cp $(1) libs endef +LIBS = \ + -Wl,--start-group \ + $(addprefix -l,$(strip \ + ascii_expat_xmlparse \ + avmedialo \ + basebmp \ + basegfxlo \ + bootstrap.uno \ + canvastoolslo \ + collator_data \ + comphelpgcc3 \ + configmgr.uno \ + cppcanvaslo \ + crypto \ + dbaxmllo \ + dbtoolslo \ + deploymentmisclo \ + dict_ja \ + dict_zh \ + drawinglayerlo \ + editenglo \ + expat_xmlparse \ + expat_xmltok \ + expwrap.uno \ + fastsax.uno \ + filterconfiglo \ + fontconfig \ + forlo \ + foruilo \ + freetype \ + frmlo \ + fsstorage.uno \ + fwelo \ + fwilo \ + fwklo \ + gcc3_uno \ + hwplo \ + i18nisolang1gcc3 \ + i18npool.uno \ + i18nregexplo \ + i18nsearch.uno \ + i18nutilgcc3 \ + icudata \ + icui18n \ + icule \ + icutu \ + icuuc \ + index_data \ + introspection.uno \ + java_uno \ + jpeg \ + jvmaccessgcc3 \ + jvmfwk \ + lcms2 \ + libotouchlo \ + lnglo \ + lo-bootstrap \ + localedata_en \ + localedata_es \ + localedata_euro \ + localedata_others \ + loglo \ + log_uno_uno \ + lpsolve55 \ + lwpftlo \ + msfilterlo \ + mswordlo \ + ooxlo \ + orcus \ + package2 \ + reflection.uno \ + reg \ + saxlo \ + sax_shared \ + sblo \ + sclo \ + scdlo \ + scfiltlo \ + sddlo \ + sdfiltlo \ + sdlo \ + sfxlo \ + smdlo \ + smlo \ + sotlo \ + spllo \ + stocservices.uno \ + store \ + svgfilterlo \ + svllo \ + svtlo \ + svxcorelo \ + svxlo \ + swdlo \ + swlo \ + t602filterlo \ + textconv_dict \ + textconversiondlgslo \ + textfdlo \ + textinstream.uno \ + textoutstream.uno \ + tklo \ + tllo \ + ucb1 \ + ucbhelper4gcc3 \ + ucpfile1 \ + ucppkg1 \ + uno_cppu \ + uno_cppuhelpergcc3 \ + uno_sal \ + uno_salhelpergcc3 \ + uno_cppuhelpergcc3 \ + unordflo \ + unoxmllo \ + utllo \ + uuilo \ + vbahelperlo \ + vbaswobj.uno \ + vcllo \ + wpftdrawlo \ + wpftwriterlo \ + xml2 \ + xmlfalo \ + xmlfdlo \ + xmlreader \ + xmlscriptlo \ + xmlsecurity \ + xoflo \ + xolo \ + xsec_fw \ + xslt \ + xsltdlglo \ + xsltfilterlo \ + xstor \ + )) \ + -Wl,--end-group + +WHOLELIBS = \ + -Wl,--whole-archive \ + $(addprefix -l,$(strip \ + juh \ + )) \ + -Wl,--no-whole-archive + # The default target just builds. all: build-ant @@ -39,87 +178,16 @@ properties: echo "APP_ABI := $(ANDROID_APP_ABI)" >>jni/Application.mk echo "APP_PLATFORM := android-14" >>jni/Application.mk +link-so: +# Build the single .so for this app + mkdir -p $(OBJLOCAL) + $(CXX) -Wl,-Map,liblo-native-code.map -Wl,--no-undefined -DANDROID -DDISABLE_DYNLOADING -shared -o $(OBJLOCAL)/liblo-native-code.so -I$(OUTDIR)/inc native-code.cxx -L$(OUTDIR)/lib $(WHOLELIBS) $(LIBS) -lgnustl_static -landroid -llog -lz + mkdir -p $(SODEST) + cp $(OBJLOCAL)/liblo-native-code.so $(SODEST) + $(STRIP) --strip-debug $(SODEST)/liblo-native-code.so + copy-stuff: -# First always clean - rm -rf libs $(OBJLOCAL) - mkdir -p $(SODEST) $(OBJLOCAL) -# -# Copy shared libraries (including UNO components) we need to -# libs/$(ANDROID_APP_ABI) so that ant will include them in the .apk. -# -# Copy them to obj/local/$(ANDROID_APP_ABI), too, where gdb will look for -# them. -# - for F in $(strip \ - basegfxlo \ - bootstrap.uno \ - comphelpgcc3 \ - dbaxmllo \ - dbtoolslo \ - expwrap.uno \ - frmlo \ - gcc3_uno \ - i18nisolang1gcc3 \ - icudatalo \ - icui18nlo \ - iculelo \ - icuuclo \ - introspection.uno \ - java_uno \ - juh \ - juhx \ - jvmaccessgcc3 \ - jvmfwk \ - libotouchlo \ - lo-bootstrap \ - localedata_en \ - localedata_others \ - lwpftlo \ - mergedlo \ - msfilterlo \ - mswordlo \ - ooxlo \ - reflection.uno \ - reg \ - sclo \ - scdlo \ - scfiltlo \ - sddlo \ - smdlo \ - stocservices.uno \ - store \ - svgfilterlo \ - swdlo \ - swlo \ - t602filterlo \ - textinstream.uno \ - tllo \ - ucbhelper4gcc3 \ - ucppkg1 \ - uno_cppu \ - uno_cppuhelpergcc3 \ - uno_sal \ - uno_salhelpergcc3 \ - uno_cppuhelpergcc3 \ - unordflo \ - unoxmllo \ - vbahelperlo \ - vbaswobj.uno \ - wpftdrawlo \ - wpftwriterlo \ - xml2 \ - xmlfdlo \ - xmlreader \ - xmlsecurity \ - xslt \ - ); do \ - $(call COPYSO,$(OUTDIR)/lib/lib$${F}.so); \ - done -# -# Then the shared GNU C++ library - $(call COPYSO,$(ANDROID_NDK_HOME)/sources/cxx-stl/gnu-libstdc++/$(ANDROID_NDK_TOOLCHAIN_VERSION_SUBDIR)libs/$(ANDROID_APP_ABI)/libgnustl_shared.so) -# -# Then other "assets". Let the directory structure under assets mimic +# Then "assets". Let the directory structure under assets mimic # that under solver for now. # # Please note that I have no idea what all of this is really necessary and for @@ -216,10 +284,11 @@ copy-stuff: # # Then gdbserver and gdb.setup so that we can debug with ndk-gdb. # + mkdir -p $(SODEST) cp $(ANDROID_NDK_GDBSERVER) $(SODEST) echo set solib-search-path ./obj/local/$(ANDROID_APP_ABI) >$(SODEST)/gdb.setup -build-ant: copy-stuff properties +build-ant: copy-stuff link-so properties # # Copy jar files we need # diff --git a/android/experimental/DocumentLoader/native-code.cxx b/android/experimental/DocumentLoader/native-code.cxx new file mode 100644 index 000000000000..415c6737ff26 --- /dev/null +++ b/android/experimental/DocumentLoader/native-code.cxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "osl/detail/android-bootstrap.h" + +extern "C" +{ + extern void * hwp_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * sc_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * scd_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * scfilt_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * sw_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * swd_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * unoxml_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * xmlfd_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * xo_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); + extern void * xof_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey ); +} + +extern "C" +__attribute__ ((visibility("default"))) +const lib_to_component_mapping * +lo_get_libmap(void) +{ + static lib_to_component_mapping map[] = { + { "libhwplo.a", hwp_component_getFactory }, + { "libscdlo.a", scd_component_getFactory }, + { "libscfiltlo.a", scfilt_component_getFactory }, + { "libsclo.a", sc_component_getFactory }, + { "libswdlo.a", swd_component_getFactory }, + { "libswlo.a", sw_component_getFactory }, + { "libunoxmllo.a", unoxml_component_getFactory }, + { "libxmlfdlo.a", xmlfd_component_getFactory }, + { "libxoflo.a", xof_component_getFactory }, + { "libxolo.a", xo_component_getFactory }, + { NULL, NULL } + }; + + return map; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java b/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java index 638c9b950a05..894fdab502a5 100644 --- a/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java +++ b/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java @@ -929,13 +929,7 @@ public class DocumentLoader Bootstrap.setup(this); // Avoid all the old style OSL_TRACE calls especially in vcl - Bootstrap.putenv("SAL_LOG=+WARN+INFO-INFO.legacy.osl"); - - // Load a lot of shlibs here explicitly in advance because that - // makes debugging work better, sigh - Bootstrap.dlopen("libmergedlo.so"); - Bootstrap.dlopen("libswdlo.so"); - Bootstrap.dlopen("libswlo.so"); + Bootstrap.putenv("SAL_LOG=+WARN+INFO"); // Log.i(TAG, "Sleeping NOW"); // Thread.sleep(20000); diff --git a/configure.in b/configure.in index 29e4d92ec078..ce0b498b747e 100644 --- a/configure.in +++ b/configure.in @@ -2422,8 +2422,8 @@ else fi AC_SUBST(DISABLE_SCRIPTING) -if test $_os = iOS; then - # Disable dynamic_loading always for iOS +if test $_os = iOS -o $_os = Android; then + # Disable dynamic_loading always for iOS and Android enable_dynamic_loading=no elif test -z "$enable_dynamic_loading"; then # Otherwise enable it unless speficically disabled diff --git a/distro-configs/LibreOfficeAndroid.conf b/distro-configs/LibreOfficeAndroid.conf index 01f11ca5e47a..70ecdccf572a 100644 --- a/distro-configs/LibreOfficeAndroid.conf +++ b/distro-configs/LibreOfficeAndroid.conf @@ -17,7 +17,6 @@ --disable-randr --disable-randr-link --disable-systray ---enable-mergelibs --without-junit --without-ppds --without-stlport diff --git a/distro-configs/LibreOfficeAndroidX86.conf b/distro-configs/LibreOfficeAndroidX86.conf index a3662d6fc96a..f4ae1364ea2c 100644 --- a/distro-configs/LibreOfficeAndroidX86.conf +++ b/distro-configs/LibreOfficeAndroidX86.conf @@ -18,7 +18,6 @@ --disable-randr --disable-randr-link --disable-systray ---enable-mergelibs --without-junit --without-ppds --without-stlport diff --git a/sal/Package_inc.mk b/sal/Package_inc.mk index c253de78510c..7ed1a9b873cb 100644 --- a/sal/Package_inc.mk +++ b/sal/Package_inc.mk @@ -67,6 +67,7 @@ $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/file.h,osl/detail/file. $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/android_native_app_glue.h,osl/detail/android_native_app_glue.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/android-bootstrap.h,osl/detail/android-bootstrap.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/ios-bootstrap.h,osl/detail/ios-bootstrap.h)) +$(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/component-mapping.h,osl/detail/component-mapping.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/allocator.hxx,rtl/allocator.hxx)) $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/alloc.h,rtl/alloc.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/bootstrap.h,rtl/bootstrap.h)) diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c index f1498695395f..b29fb7d044b9 100644 --- a/sal/android/lo-bootstrap.c +++ b/sal/android/lo-bootstrap.c @@ -43,8 +43,6 @@ #include <jni.h> -#include <linux/elf.h> - #include <android/log.h> #include "uthash.h" @@ -299,40 +297,8 @@ engine_handle_cmd(struct android_app* state, } } -static char * -read_section(int fd, - Elf32_Shdr *shdr) -{ - char *result; - - result = malloc(shdr->sh_size); - if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) { - close(fd); - free(result); - return NULL; - } - if (read(fd, result, shdr->sh_size) < (int) shdr->sh_size) { - close(fd); - free(result); - return NULL; - } - - return result; -} - -static void -free_ptrarray(void **pa) -{ - void **rover = pa; - - while (*rover != NULL) - free(*rover++); - - free(pa); -} - -/* The lo-bootstrap shared library is always loaded from Java, so - * this is always called by JNI first. +/* The lo-native-code shared library is always loaded from Java, so this is + * always called by JNI first. */ __attribute__ ((visibility("default"))) jint @@ -345,133 +311,6 @@ JNI_OnLoad(JavaVM* vm, void* reserved) return JNI_VERSION_1_2; } -__attribute__ ((visibility("default"))) -jobjectArray -Java_org_libreoffice_android_Bootstrap_dlneeds(JNIEnv* env, - jobject clazz, - jstring library) -{ - char **needed; - int n_needed; - const char *libName; - jclass String; - jobjectArray result; - - (void) clazz; - - libName = (*env)->GetStringUTFChars(env, library, NULL); - - needed = lo_dlneeds(libName); - - (*env)->ReleaseStringUTFChars(env, library, libName); - - if (needed == NULL) - return NULL; - - n_needed = 0; - while (needed[n_needed] != NULL) - n_needed++; - - /* Allocate return value */ - - String = (*env)->FindClass(env, "java/lang/String"); - if (String == NULL) { - LOGE("Could not find the String class"); - free_ptrarray((void **) needed); - return NULL; - } - - result = (*env)->NewObjectArray(env, n_needed, String, NULL); - if (result == NULL) { - LOGE("Could not create the String array"); - free_ptrarray((void **) needed); - return NULL; - } - - for (n_needed = 0; needed[n_needed] != NULL; n_needed++) - (*env)->SetObjectArrayElement(env, result, n_needed, (*env)->NewStringUTF(env, needed[n_needed])); - - free_ptrarray((void **) needed); - - return result; -} - -__attribute__ ((visibility("default"))) -jint -Java_org_libreoffice_android_Bootstrap_dlopen(JNIEnv* env, - jobject clazz, - jstring library) -{ - const char *libName; - void *p; - - (void) clazz; - - libName = (*env)->GetStringUTFChars(env, library, NULL); - p = lo_dlopen (libName); - (*env)->ReleaseStringUTFChars(env, library, libName); - - return (jint) p; -} - -__attribute__ ((visibility("default"))) -jint -Java_org_libreoffice_android_Bootstrap_dlsym(JNIEnv* env, - jobject clazz, - jint handle, - jstring symbol) -{ - const char *symName; - void *p; - - (void) clazz; - - symName = (*env)->GetStringUTFChars(env, symbol, NULL); - p = lo_dlsym ((void *) handle, symName); - (*env)->ReleaseStringUTFChars(env, symbol, symName); - - return (jint) p; -} - -__attribute__ ((visibility("default"))) -jint -Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env, - jobject clazz, - jint function, - jobject argument) -{ - jclass StringArray; - - (void) clazz; - - StringArray = (*env)->FindClass(env, "[Ljava/lang/String;"); - if (StringArray == NULL) { - LOGE("Could not find String[] class"); - return 0; - } - - if ((*env)->IsInstanceOf(env, argument, StringArray)) { - int argc = (*env)->GetArrayLength(env, argument); - const char **argv = malloc(sizeof(char *) * (argc+1)); - int i, result; - for (i = 0; i < argc; i++) { - argv[i] = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, argument, i), NULL); - /* LOGI("argv[%d] = %s", i, argv[i]); */ - } - argv[argc] = NULL; - - result = lo_dlcall_argc_argv((void *) function, argc, argv); - - for (i = 0; i < argc; i++) - (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, argument, i), argv[i]); - - free(argv); - return result; - } - - return 0; -} - // public static native boolean setup(String dataDir, // String apkFile, // String[] ld_library_path); @@ -591,22 +430,18 @@ get_jni_string_array(JNIEnv *env, } -// public static native boolean setup(int lo_main_ptr, -// Object lo_main_argument, +// public static native boolean setup(Object lo_main_argument, // int lo_main_delay); __attribute__ ((visibility("default"))) jboolean -Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env, +Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_Object_2I(JNIEnv* env, jobject clazz, - void *lo_main_ptr, jobject lo_main_argument, jint lo_main_delay) { (void) clazz; - lo_main = lo_main_ptr; - if (!get_jni_string_array(env, "setup: lo_main_argument", lo_main_argument, &lo_main_argc, &lo_main_argv)) return JNI_FALSE; @@ -668,344 +503,16 @@ Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, putenv(s); - (*env)->ReleaseStringUTFChars(env, string, s); -} - -__attribute__ ((visibility("default"))) -char ** -lo_dlneeds(const char *library) -{ - int i, fd; - int n_needed; - char **result; - char *shstrtab; - char *dynstr = NULL; - Elf32_Ehdr hdr; - Elf32_Shdr shdr; - Elf32_Dyn dyn; - - /* Open library and read ELF header */ - - fd = open(library, O_RDONLY); - - if (fd == -1) { - LOGE("lo_dlneeds: Could not open library %s: %s", library, strerror(errno)); - return NULL; - } - - if (read(fd, &hdr, sizeof(hdr)) < (int) sizeof(hdr)) { - LOGE("lo_dlneeds: Could not read ELF header of %s", library); - close(fd); - return NULL; - } - - /* Read in .shstrtab */ - - if (lseek(fd, hdr.e_shoff + hdr.e_shstrndx * sizeof(shdr), SEEK_SET) < 0) { - LOGE("lo_dlneeds: Could not seek to .shstrtab section header of %s", library); - close(fd); - return NULL; - } - if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) { - LOGE("lo_dlneeds: Could not read section header of %s", library); - close(fd); - return NULL; - } - - shstrtab = read_section(fd, &shdr); - if (shstrtab == NULL) - return NULL; - - /* Read section headers, looking for .dynstr section */ - - if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) { - LOGE("lo_dlneeds: Could not seek to section headers of %s", library); - close(fd); - return NULL; - } - for (i = 0; i < hdr.e_shnum; i++) { - if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) { - LOGE("lo_dlneeds: Could not read section header of %s", library); - close(fd); - return NULL; - } - if (shdr.sh_type == SHT_STRTAB && - strcmp(shstrtab + shdr.sh_name, ".dynstr") == 0) { - dynstr = read_section(fd, &shdr); - if (dynstr == NULL) { - free(shstrtab); - return NULL; - } - break; - } - } - - if (i == hdr.e_shnum) { - LOGE("lo_dlneeds: No .dynstr section in %s", library); - close(fd); - return NULL; - } - - /* Read section headers, looking for .dynamic section */ - - if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) { - LOGE("lo_dlneeds: Could not seek to section headers of %s", library); - close(fd); - return NULL; - } - for (i = 0; i < hdr.e_shnum; i++) { - if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) { - LOGE("lo_dlneeds: Could not read section header of %s", library); - close(fd); - return NULL; - } - if (shdr.sh_type == SHT_DYNAMIC) { - size_t dynoff; - - /* Count number of DT_NEEDED entries */ - n_needed = 0; - if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) { - LOGE("lo_dlneeds: Could not seek to .dynamic section of %s", library); - close(fd); - return NULL; - } - for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) { - if (read(fd, &dyn, sizeof(dyn)) < (int) sizeof(dyn)) { - LOGE("lo_dlneeds: Could not read .dynamic entry of %s", library); - close(fd); - return NULL; - } - if (dyn.d_tag == DT_NEEDED) - n_needed++; - } - - /* LOGI("Found %d DT_NEEDED libs", n_needed); */ - - result = malloc((n_needed+1) * sizeof(char *)); - - n_needed = 0; - if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) { - LOGE("lo_dlneeds: Could not seek to .dynamic section of %s", library); - close(fd); - free(result); - return NULL; - } - for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) { - if (read(fd, &dyn, sizeof(dyn)) < (int) sizeof(dyn)) { - LOGE("lo_dlneeds: Could not read .dynamic entry in %s", library); - close(fd); - free(result); - return NULL; - } - if (dyn.d_tag == DT_NEEDED) { - /* LOGI("needs: %s\n", dynstr + dyn.d_un.d_val); */ - result[n_needed] = strdup(dynstr + dyn.d_un.d_val); - n_needed++; - } - } - - close(fd); - if (dynstr) - free(dynstr); - free(shstrtab); - result[n_needed] = NULL; - return result; - } - } - - LOGE("lo_dlneeds: Could not find .dynamic section in %s", library); - close(fd); - return NULL; -} - -__attribute__ ((visibility("default"))) -void * -lo_dlopen(const char *library) -{ - /* - * We should *not* try to just dlopen() the bare library name - * first, as the stupid dynamic linker remembers for each library - * basename if loading it has failed. Thus if you try loading it - * once, and it fails because of missing needed libraries, and - * your load those, and then try again, it fails with an - * infuriating message "failed to load previously" in the log. - * - * We *must* first dlopen() all needed libraries, recursively. It - * shouldn't matter if we dlopen() a library that already is - * loaded, dlopen() just returns the same value then. - */ - - typedef struct loadedLib { - const char *name; - void *handle; - struct loadedLib *next; - } *loadedLib; - static loadedLib loaded_libraries = NULL; - - loadedLib rover; - loadedLib new_loaded_lib; - - struct stat st; - void *p; - char *full_name; - char **needed; - int i; - int found; - - struct timeval tv0, tv1, tvdiff; - - rover = loaded_libraries; - while (rover != NULL && - strcmp(rover->name, library) != 0) - rover = rover->next; - - if (rover != NULL) - return rover->handle; - - /* LOGI("lo_dlopen(%s)", library); */ - - found = 0; - if (library[0] == '/') { - full_name = strdup(library); - - if (stat(full_name, &st) == 0 && - S_ISREG(st.st_mode)) - found = 1; - else - free(full_name); - } else { - for (i = 0; !found && library_locations[i] != NULL; i++) { - full_name = malloc(strlen(library_locations[i]) + 1 + strlen(library) + 1); - strcpy(full_name, library_locations[i]); - strcat(full_name, "/"); - strcat(full_name, library); - - if (stat(full_name, &st) == 0 && - S_ISREG(st.st_mode)) - found = 1; - else - free(full_name); - } - } - - if (!found) { - LOGE("lo_dlopen: Library %s not found", library); - return NULL; - } - - needed = lo_dlneeds(full_name); - if (needed == NULL) { - free(full_name); - return NULL; - } - - for (i = 0; needed[i] != NULL; i++) { - if (lo_dlopen(needed[i]) == NULL) { - free_ptrarray((void **) needed); - free(full_name); - return NULL; - } - } - free_ptrarray((void **) needed); - - gettimeofday(&tv0, NULL); - p = dlopen(full_name, RTLD_LOCAL); - gettimeofday(&tv1, NULL); - timersub(&tv1, &tv0, &tvdiff); - LOGI("dlopen(%s) = %p, %ld.%03lds", - full_name, p, - (long) tvdiff.tv_sec, (long) tvdiff.tv_usec / 1000); - free(full_name); - if (p == NULL) - LOGE("lo_dlopen: Error from dlopen(%s): %s", library, dlerror()); - - new_loaded_lib = malloc(sizeof(*new_loaded_lib)); - new_loaded_lib->name = strdup(library); - new_loaded_lib->handle = p; - - new_loaded_lib->next = loaded_libraries; - loaded_libraries = new_loaded_lib; - - return p; -} - -__attribute__ ((visibility("default"))) -void * -lo_dlsym(void *handle, - const char *symbol) -{ - void *p = dlsym(handle, symbol); - /* LOGI("dlsym(%p, %s) = %p", handle, symbol, p); */ - if (p == NULL) - LOGE("lo_dlsym: %s", dlerror()); - return p; -} - -__attribute__ ((visibility("default"))) -int -lo_dladdr(void *addr, - Dl_info *info) -{ - FILE *maps; - char line[200]; - int result; - int found; - - result = dladdr(addr, info); - if (result == 0) { - /* LOGI("dladdr(%p) = 0", addr); */ - return 0; - } - - maps = fopen("/proc/self/maps", "r"); - if (maps == NULL) { - LOGE("lo_dladdr: Could not open /proc/self/maps: %s", strerror(errno)); - return 0; - } - - found = 0; - while (fgets(line, sizeof(line), maps) != NULL && - line[strlen(line)-1] == '\n') { - void *lo, *hi; - char file[sizeof(line)]; - file[0] = '\0'; - if (sscanf(line, "%x-%x %*s %*x %*x:%*x %*d %[^\n]", (unsigned *) &lo, (unsigned *) &hi, file) == 3) { - /* LOGI("got %p-%p: %s", lo, hi, file); */ - if (addr >= lo && addr < hi) { - if (info->dli_fbase != lo) { - LOGE("lo_dladdr: Base for %s in /proc/self/maps %p doesn't match what dladdr() said", file, lo); - fclose(maps); - return 0; - } - /* LOGI("dladdr(%p) = { %s:%p, %s:%p }: %s", - addr, - info->dli_fname, info->dli_fbase, - info->dli_sname ? info->dli_sname : "(none)", info->dli_saddr, - file); */ - info->dli_fname = strdup(file); - found = 1; - break; - } + { + static int beenhere=0; + if (!beenhere) { + LOGI("lo-bootstrap: Sleeping for 20 seconds, start ndk-gdb NOW if that is your intention"); + sleep(20); + beenhere = 1; } } - if (!found) - LOGE("lo_dladdr: Did not find %p in /proc/self/maps", addr); - fclose(maps); - - return result; -} - -__attribute__ ((visibility("default"))) -int -lo_dlclose(void *handle) -{ - /* As we don't know when the reference count for a dlopened shared - * object drops to zero, we wouldn't know when to remove it from - * our list, so we can't call dlclose(). - */ - LOGI("lo_dlclose(%p)", handle); - return 0; + (*env)->ReleaseStringUTFChars(env, string, s); } __attribute__ ((visibility("default"))) @@ -1235,195 +742,6 @@ lo_dlcall_argc_argv(void *function, return result; } -#ifdef ARM - -/* There is a bug in std::type_info::operator== and - * std::type_info::before() in libgnustl_shared.so in NDK r7 at - * least. They compare the type name pointers instead of comparing the - * type name strings. See - * http://code.google.com/p/android/issues/detail?id=22165 . So patch - * that, poke in jumps to our own code snippets below instead. - */ - -/* Replacement std::type_info::operator== */ - -__asm(" .arm\n" - " .global replacement_operator_equals_arm\n" - "replacement_operator_equals_arm:\n" - " push {lr}\n" - - /* Load name pointers into r0 and r1 */ - " ldr r0, [r0, #4]\n" - " ldr r1, [r1, #4]\n" - - /* First compare pointers */ - " cmp r0, r1\n" - - /* If equal, return true */ - " beq .L.equals.1\n" - - /* Otherwise call strcmp */ - " bl strcmp\n" - - /* And return true or false */ - " cmp r0, #0\n" - " moveq r0, #1\n" - " movne r0, #0\n" - " b .L.equals.9\n" - - ".L.equals.1:\n" - " mov r0, #1\n" - - ".L.equals.9:\n" - " pop {pc}\n" - ); - -extern unsigned int replacement_operator_equals_arm; - -/* The ARM (not Thumb) code of the operator== in NDK r7 */ -static unsigned int expected_operator_equals_r7_code[] = { - 0xe5903004, /* ldr r3, [r0, #4] */ - 0xe5910004, /* ldr r0, [r1, #4] */ - 0xe1530000, /* cmp r3, r0 */ - 0x13a00000, /* movne, #0 */ - 0x03a00001, /* moveq r0, #1 */ - 0xe12fff1e /* bx lr */ -}; - -/* Ditto for std::type_info::before() */ - -__asm(" .arm\n" - " .global replacement_method_before_arm\n" - "replacement_method_before_arm:\n" - " push {lr}\n" - - /* Load name pointers into r0 and r1 */ - " ldr r0, [r0, #4]\n" - " ldr r1, [r1, #4]\n" - - /* First compare pointers */ - " cmp r0, r1\n" - - /* If equal, return false */ - " beq .L.before.1\n" - - /* Otherwise call strcmp */ - " bl strcmp\n" - - /* And return true or false */ - " cmp r0, #0\n" - " movlt r0, #1\n" - " movge r0, #0\n" - " b .L.before.9\n" - - ".L.before.1:\n" - " mov r0, #0\n" - - ".L.before.9:\n" - " pop {pc}\n" - ); - -extern unsigned int replacement_method_before_arm; - -static unsigned int expected_method_before_r7_code[] = { - 0xe5903004, /* ldr r3, [r0, #4] */ - 0xe5910004, /* ldr r0, [r1, #4] */ - 0xe1530000, /* cmp r3, r0 */ - 0x23a00000, /* movcs r0, #0 */ - 0x33a00001, /* movcc r0, #1 */ - 0xe12fff1e /* bx lr */ -}; - -static void -patch(const char *symbol, - const char *plaintext, - unsigned *expected_code, - size_t expected_code_size, - unsigned *replacement_code) -{ - - void *libgnustl_shared; - void *code; - - void *base; - size_t size; - - /* libgnustl_shared.so should be already loaded as we build - * all LO code against it, so as we have loaded the .so - * containing lo_main() already, libgnustl_shared.so will have - * been brought in, too. - */ - libgnustl_shared = dlopen("libgnustl_shared.so", RTLD_LOCAL); - if (libgnustl_shared == NULL) { - LOGF("android_main: libgnustl_shared.so not mapped??"); - exit(0); - } - - code = dlsym(libgnustl_shared, symbol); - if (code == NULL) { - LOGF("android_main: %s not found!?", plaintext); - exit(0); - } - /* LOGI("%s is at %p", plaintext, operator_equals); */ - - if ((((unsigned) code) & 0x03) != 0) { - LOGE("android_main: Address of %s is not at word boundary, huh?", plaintext); - return; - } - - if ((((unsigned) &replacement_code) & 0x03) != 0) { - LOGE("android_main: Address of replacement %s is not at word boundary, huh?", plaintext); - return; - } - - if (memcmp(code, expected_code, expected_code_size) != 0) { - LOGI("android_main: Code for %s does not match that in NDK r7; not patching it", plaintext); - return; - } - - base = ROUND_DOWN(code, getpagesize()); - size = code + sizeof(expected_code_size) - ROUND_DOWN(code, getpagesize()); - if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - LOGE("android_main: mprotect() failed: %s", strerror(errno)); - return; - } - - /* Poke in a jump to replacement_code instead */ - ((unsigned *) code)[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */ - ((unsigned *) code)[1] = (unsigned) replacement_code; -} - -static void -patch_libgnustl_shared(void) -{ - patch("_ZNKSt9type_infoeqERKS_", - "std::type_info::operator==", - expected_operator_equals_r7_code, - sizeof(expected_operator_equals_r7_code), - &replacement_operator_equals_arm); - - patch("_ZNKSt9type_info6beforeERKS_", - "std::type_info::before()", - expected_method_before_r7_code, - sizeof(expected_method_before_r7_code), - &replacement_method_before_arm); -} -#endif // ARM - -// static native void patch_libgnustl_shared(); -__attribute__ ((visibility("default"))) -void -Java_org_libreoffice_android_Bootstrap_patch_1libgnustl_1shared(JNIEnv* env, - jobject clazz) -{ - (void) env; - (void) clazz; - -#ifdef ARM - patch_libgnustl_shared(); -#endif -} - #define UNPACK_TREE "/assets/unpack" static int @@ -1551,34 +869,30 @@ Java_org_libreoffice_android_Bootstrap_extract_1files(JNIEnv* env, } /* Android's JNI works only to libraries loaded through Java's - * System.loadLibrary(), it seems. Not to functions loaded by a dlopen() call - * in native code. For instance, to call a function in libvcllo.so, we need to - * have its JNI wrapper here, and then call the VCL function from it. Oh well, - * one could say it's clean to have all the Android-specific JNI functions - * here in this file. + * System.loadLibrary(), it seems. But now with just one big app-specific .so + * on Android, that would not be a problem, but for historical reasons, we + * have JNI wrappers here, and then call the VCL etc function from them. Oh + * well, one could say it's clean to have all the Android-specific JNI + * functions here in this file. */ // public static native void initVCL(); +extern void InitVCLWrapper(void); + __attribute__ ((visibility("default"))) void Java_org_libreoffice_android_Bootstrap_initVCL(JNIEnv* env, jobject clazz) { - void (*InitVCLWrapper)(void); (void) env; (void) clazz; - /* This obviously should be called only after libvcllo.so has been loaded */ - - InitVCLWrapper = dlsym(RTLD_DEFAULT, "InitVCLWrapper"); - if (InitVCLWrapper == NULL) { - LOGE("InitVCL: InitVCLWrapper not found"); - return; - } - (*InitVCLWrapper)(); + InitVCLWrapper(); } +extern void osl_setCommandArgs(int, char **); + __attribute__ ((visibility("default"))) void Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, @@ -1588,14 +902,13 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, char **c_argv; int c_argc; Dl_info lo_bootstrap_info; - void (*osl_setCommandArgs)(int, char **); (void) clazz; if (!get_jni_string_array(env, "setCommandArgs :argv", argv, &c_argc, (const char ***) &c_argv)) return; - if (lo_dladdr(Java_org_libreoffice_android_Bootstrap_setCommandArgs, &lo_bootstrap_info) != 0) { + if (dladdr(Java_org_libreoffice_android_Bootstrap_setCommandArgs, &lo_bootstrap_info) != 0) { char *new_argv0 = malloc(strlen(lo_bootstrap_info.dli_fname) + strlen(c_argv[0])); char *slash; strcpy(new_argv0, lo_bootstrap_info.dli_fname); @@ -1611,30 +924,20 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, c_argv[0] = new_argv0; } - osl_setCommandArgs = dlsym(RTLD_DEFAULT, "osl_setCommandArgs"); - if (osl_setCommandArgs == NULL) { - LOGE("setCommandArgs: osl_setCommandArgs not found"); - return; - } - (*osl_setCommandArgs)(c_argc, c_argv); + osl_setCommandArgs(c_argc, c_argv); } +extern int createWindowFoo(void); + __attribute__ ((visibility("default"))) jint Java_org_libreoffice_android_Bootstrap_createWindowFoo(JNIEnv* env, jobject clazz) { - int (*createWindowFoo)(void); (void) env; (void) clazz; - lo_dlopen("libvcllo.so"); - createWindowFoo = dlsym(RTLD_DEFAULT, "createWindowFoo"); - if (createWindowFoo == NULL) { - LOGE("createWindowFoo: createWindowFoo not found"); - return 0; - } - return (*createWindowFoo)(); + return createWindowFoo(); } @@ -1956,6 +1259,10 @@ lo_get_app(void) return app; } +/* Note that android_main() is used only in NativeActivity-based apps. Only + * the android/qa/sc unit test app is such, and it is unclear whether there is + * any reason to continue maintaining that buildable. + */ __attribute__ ((visibility("default"))) void android_main(struct android_app* state) @@ -1986,7 +1293,12 @@ android_main(struct android_app* state) state->userData = &engine; state->onAppCmd = engine_handle_cmd; - if (lo_dladdr(lo_main, &lo_main_info) != 0) { + /* Look up lo_main() dynamically even if it is in the same .so as this code, + * but that is only in the case for code built to be used in a NativeActivity-based app. + */ + lo_main = dlsym(RTLD_DEFAULT, "lo_main"); + + if (dladdr(lo_main, &lo_main_info) != 0) { lo_main_argv[0] = lo_main_info.dli_fname; } diff --git a/sal/inc/osl/detail/android-bootstrap.h b/sal/inc/osl/detail/android-bootstrap.h index bd453b3475dd..333d14b12550 100644 --- a/sal/inc/osl/detail/android-bootstrap.h +++ b/sal/inc/osl/detail/android-bootstrap.h @@ -29,29 +29,19 @@ #ifndef ANDROID_BOOSTRAP_H #define ANDROID_BOOSTRAP_H + #if defined(ANDROID) #include <jni.h> -#include <dlfcn.h> #include <dirent.h> #ifdef __cplusplus extern "C" { #endif -typedef struct lo_apk_dir lo_apk_dir; - -char **lo_dlneeds(const char *library); - -void *lo_dlopen(const char *library); +#include <osl/detail/component-mapping.h> -void *lo_dlsym(void *handle, - const char *symbol); - -int lo_dladdr(void *addr, - Dl_info *info); - -int lo_dlclose(void *handle); +typedef struct lo_apk_dir lo_apk_dir; void *lo_apkentry(const char *filename, size_t *size); @@ -77,6 +67,7 @@ struct android_app *lo_get_app(void); #endif #endif // ANDROID + #endif // ANDROID_BOOTSTRAP_H /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/osl/detail/component-mapping.h b/sal/inc/osl/detail/component-mapping.h new file mode 100644 index 000000000000..e085fbd659f1 --- /dev/null +++ b/sal/inc/osl/detail/component-mapping.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http: *www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Tor Lillqvist <tml@iki.fi> (initial developer) + * Copyright (C) 2011 SUSE Linux http://suse.com (initial developer's employer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef COMPONENT_MAPPING_H +#define COMPONENT_MAPPING_H + +#ifdef DISABLE_DYNLOADING + +#ifdef __cplusplus +extern "C" { +#endif + +/* On iOS and perhaps Android static linking of the LO code into one + * executable (on Android, into one shared library) is used. In order to get + * the needed UNO coponent linked in, the "main" code for an app needs to + * implement the lo_get_libmap() function to map UNO component library names + * as produced in a build for iOS (like configmgr.uno.a or libsclo.a) to the + * corresponding component_getFactory functions. + */ + +typedef struct { + const char *lib; + void * (*component_getFactory_function)(const char *, void *, void *); +} lib_to_component_mapping; + +const lib_to_component_mapping *lo_get_libmap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* DISABLE_DYNLOADING */ + +#endif /* COMPONENT_MAPPING_H */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/inc/osl/detail/ios-bootstrap.h b/sal/inc/osl/detail/ios-bootstrap.h index ac8ccf6562ef..5e4ced7934a0 100644 --- a/sal/inc/osl/detail/ios-bootstrap.h +++ b/sal/inc/osl/detail/ios-bootstrap.h @@ -36,19 +36,7 @@ extern "C" { #endif -/* On iOS static linking is used. In order to get the needed UNO - * coponent linked in, the "main" code for an app needs to implement - * the lo_get_libmap() function to map UNO component library names as - * produced in a build for iOS (like configmgr.uno.a or libsclo.a) to - * the corresponding component_getFactory functions. - */ - -typedef struct { - const char *lib; - void * (*component_getFactory_function)(const char *, void *, void *); -} lib_to_component_mapping; - -const lib_to_component_mapping *lo_get_libmap(void); +#include <osl/detail/component-mapping.h> #ifdef __cplusplus } diff --git a/solenv/inc/unxand.mk b/solenv/inc/unxand.mk index 8025388a9f64..60f389b63bb6 100644 --- a/solenv/inc/unxand.mk +++ b/solenv/inc/unxand.mk @@ -76,3 +76,5 @@ LINKFLAGSRUNPATH_URELIB= LINKFLAGSRUNPATH_UREBIN= LINKFLAGSRUNPATH_OOO= LINKFLAGSRUNPATH_SDKBIN= + +DLLPOST=.a |