[Libreoffice-commits] .: 2 commits - libexttextcat/android.patch libexttextcat/makefile.mk sal/inc sal/osl

Tor Lillqvist tml at kemper.freedesktop.org
Tue Nov 15 23:29:42 PST 2011


 libexttextcat/android.patch                                |   20 ++
 libexttextcat/makefile.mk                                  |    2 
 sal/inc/sal/main.h                                         |    4 
 sal/osl/android/Makefile                                   |   14 +
 sal/osl/android/jni/lo-bootstrap.c                         |  124 +++++--------
 sal/osl/android/jni/lo-bootstrap.h                         |   45 ++++
 sal/osl/android/src/org/libreoffice/android/Bootstrap.java |   12 -
 sal/osl/unx/module.c                                       |    8 
 sal/osl/unx/nlsupport.c                                    |    4 
 9 files changed, 150 insertions(+), 83 deletions(-)

New commits:
commit 69b04c22986b03c675cf4925f76721190aa5ba82
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Tue Nov 15 21:46:14 2011 +0200

    Fix libexttextcat build for Android

diff --git a/libexttextcat/android.patch b/libexttextcat/android.patch
new file mode 100644
index 0000000..e82851d
--- /dev/null
+++ b/libexttextcat/android.patch
@@ -0,0 +1,20 @@
+--- misc/libexttextcat-3.2.0/config.sub
++++ misc/build/libexttextcat-3.2.0/config.sub
+@@ -120,7 +120,7 @@
+ # Here we must recognize all the valid KERNEL-OS combinations.
+ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+ case $maybe_os in
+-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
++  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+   uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+   kopensolaris*-gnu* | \
+   storm-chaos* | os2-emx* | rtmk-nova*)
+@@ -1250,7 +1250,7 @@
+ 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ 	      | -chorusos* | -chorusrdb* | -cegcc* \
+ 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
++	      | -mingw32* | -linux-gnu* | -linux-androideabi* | -linux-newlib* | -linux-uclibc* \
+ 	      | -uxpv* | -beos* | -mpeix* | -udk* \
+ 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff --git a/libexttextcat/makefile.mk b/libexttextcat/makefile.mk
index b90a4d7..7633a0b 100644
--- a/libexttextcat/makefile.mk
+++ b/libexttextcat/makefile.mk
@@ -49,6 +49,8 @@ TARFILE_MD5=e1c178b18f130b40494561f02bc1a948
 TARFILE_ROOTDIR=libexttextcat-3.2.0
 PATCH_FILES=libexttextcat-3.2.0-visibility.patch
 
+PATCH_FILES = android.patch
+
 .IF "$(GUI)"=="UNX"
 .IF "$(HAVE_GCC_VISIBILITY_FEATURE)" == "TRUE"
 EXTRA_CFLAGS+=-fvisibility=hidden
commit 3c445370a920987433efc97013aef187b6d29737
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Tue Nov 15 21:09:48 2011 +0200

    Further Android work, now most sal cppunit tests seem to run
    
    Do the LD_LIBRARY_PATH splitting in Java, much easier, and pass the
    split up path to the native setup() method.
    
    Use lo_dlopen() in the osl_loadModuleAscii.
    
    Harcode en-US.UTF-8 as the locale for now.
    
    Cut down on verbose logging of stuff that already works.

diff --git a/sal/inc/sal/main.h b/sal/inc/sal/main.h
index d1d3fff..e5e8f3b 100644
--- a/sal/inc/sal/main.h
+++ b/sal/inc/sal/main.h
@@ -129,8 +129,6 @@ extern "C" void lo_main(int argc, char **argv);
 #endif
 
 #define SAL_MAIN_WITH_ARGS_IMPL \
-static int sal_main_with_args(int argc, char **argv); \
-\
 void lo_main(int argc, char **argv) \
 { \
     LOGI("in lo_main, argc=%d, argv[0]=%s, argv[1]=%s", argc, argv[0], argv[1]); \
@@ -140,8 +138,6 @@ void lo_main(int argc, char **argv) \
 }
 
 #define SAL_MAIN_IMPL \
-static int sal_main(void); \
-\
 void lo_main(int argc, char **argv) \
 { \
     LOGI("in lo_main, argc=%d, argv[0]=%s, argv[1]=%s", argc, argv[0], argv[1]); \
diff --git a/sal/osl/android/Makefile b/sal/osl/android/Makefile
index 4e89f66..2a606c4 100644
--- a/sal/osl/android/Makefile
+++ b/sal/osl/android/Makefile
@@ -3,10 +3,19 @@ NDK_HOME:=$(shell dirname $(NDK_HOME))
 
 all:
 	ndk-build V=1
+# Copy shared libraries we need to libs/armeabi-v7a so that ant will
+# include them in the .apk
 	cp ../../unxandr.pro/bin/cppunittester libs/armeabi-v7a/libcppunittester.so
 	cp ../../../solver/unxandr.pro/lib/libcppunit-1.12.so libs/armeabi-v7a
 	cp ../../unxandr.pro/lib/*.so libs/armeabi-v7a
 	cp $(NDK_HOME)/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_shared.so libs/armeabi-v7a
+# Copy them to obj/local/armeabi-v7a, too, where gdb will look for
+# them.  Not sure if this is useful or not; I have great problems with
+# ndk-gdb.
+	cp ../../unxandr.pro/bin/cppunittester obj/local/armeabi-v7a/libcppunittester.so
+	cp ../../../solver/unxandr.pro/lib/libcppunit-1.12.so obj/local/armeabi-v7a
+	cp ../../unxandr.pro/lib/*.so obj/local/armeabi-v7a
+	cp $(NDK_HOME)/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_shared.so obj/local/armeabi-v7a
 	unset JAVA_HOME && ant debug
 	@echo 'Install it on the device with ant debug install'
 	@echo 'Then run it with something like what "make run" does (see Makefile)'
@@ -14,5 +23,8 @@ all:
 run: all
 	unset JAVA_HOME && ant debug install
 #
-# Note: this is of course just an example
+# Note: this is of course just an example. The full path the the test
+# .so needs to be supplied, unfortunately, I guess cppunittester
+# checks its existance using the pathname instead of just
+# osl_loadModule'ing it.
 	adb shell am start -n org.libreoffice.android/.Bootstrap -e lo-main-library libcppunittester -e lo-main-cmdline "cppunittester /data/data/org.libreoffice.android/lib/libqa_sal_types.so"
diff --git a/sal/osl/android/jni/lo-bootstrap.c b/sal/osl/android/jni/lo-bootstrap.c
index 327d868..ad35568 100644
--- a/sal/osl/android/jni/lo-bootstrap.c
+++ b/sal/osl/android/jni/lo-bootstrap.c
@@ -41,7 +41,7 @@
 
 #include <android/log.h>
 
-#include <../../../inc/osl/android-lo-bootstrap.h>
+#include "lo-bootstrap.h"
 
 #include "android_native_app_glue.c"
 
@@ -113,40 +113,6 @@ free_ptrarray(void **pa)
     free(pa);
 }
 
-static void
-setup_library_locations(const char *lib_dir)
-{
-    int n;
-    char *ld_library_path;
-    char *elem;
-
-    ld_library_path = getenv("LD_LIBRARY_PATH");
-    if (ld_library_path == NULL)
-        ld_library_path = "/vendor/lib:/system/lib";
-    ld_library_path = strdup(ld_library_path);
-
-    n = 1;
-    elem = ld_library_path;
-    while ((elem = strchr(elem, ':')) != NULL) {
-        n++;
-        elem++;
-    }
-    library_locations = malloc((n + 2) * sizeof(char *));
-    library_locations[0] = lib_dir;
-    elem = ld_library_path;
-    library_locations[1] = elem;
-    n = 2;
-    while ((elem = strchr(elem, ':')) != NULL) {
-        *elem = '\0';
-        elem++;
-        library_locations[n++] = elem;
-    }
-    library_locations[n] = NULL;
-
-    for (n = 0; library_locations[n] != NULL; n++)
-        LOGI("library_locations[%d] = %s", n, library_locations[n]);
-}
-
 jobjectArray
 Java_org_libreoffice_android_Bootstrap_dlneeds(JNIEnv* env,
                                                jobject clazz,
@@ -236,7 +202,6 @@ Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env,
     }
 
     if ((*env)->IsInstanceOf(env, argument, StringArray)) {
-        LOGI("Yes, a string array argument of length %d", (*env)->GetArrayLength(env, argument));
         int argc = (*env)->GetArrayLength(env, argument);
         const char **argv = malloc(sizeof(char *) * (argc+1));
         int i, result;
@@ -258,16 +223,22 @@ Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env,
     return 0;
 }
 
+// public native boolean setup(String dataDir,
+//                             String[] ld_library_path);
+
 jboolean
-Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2(JNIEnv* env,
-                                                                  jobject this,
-                                                                  jstring dataDir)
+Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2_3Ljava_lang_String_2(JNIEnv* env,
+                                                                                       jobject this,
+                                                                                       jstring dataDir,
+                                                                                       jobjectArray ld_library_path)
 {
-    int i;
+    int i, n;
     const jbyte *dataDirPath;
     char *lib_dir;
 
-    LOGI("in %s! this=%p", __FUNCTION__, this);
+    n = (*env)->GetArrayLength(env, ld_library_path);
+
+    library_locations = malloc((n+2) * sizeof(char *));
 
     dataDirPath = (*env)->GetStringUTFChars(env, dataDir, NULL);
 
@@ -277,11 +248,25 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2(JNIEnv* env,
 
     (*env)->ReleaseStringUTFChars(env, dataDir, dataDirPath);
 
-    setup_library_locations(lib_dir);
+    library_locations[0] = lib_dir;
+
+    for (i = 0; i < n; i++) {
+        const jbyte *s = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, ld_library_path, i), NULL);
+        library_locations[i+1] = strdup(s);
+        (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, ld_library_path, i), s);
+    }
+
+    library_locations[n+1] = NULL;
+
+    for (n = 0; library_locations[n] != NULL; n++)
+        LOGI("library_locations[%d] = %s", n, library_locations[n]);
 
     return JNI_TRUE;
 }
 
+// public native boolean setup(int lo_main_ptr,
+//                             Object lo_main_argument);
+
 jboolean
 Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2(JNIEnv* env,
                                                                    jobject this,
@@ -291,8 +276,6 @@ Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2(JNIEnv* env,
     jclass StringArray;
     int i;
 
-    LOGI("in %s! this=%p", __FUNCTION__, this);
-
     lo_main = lo_main_ptr;
 
     StringArray = (*env)->FindClass(env, "[Ljava/lang/String;");
@@ -333,16 +316,15 @@ lo_dlneeds(const char *library)
 
     /* Open library and read ELF header */
 
-    LOGI("lo_dlneeds(%s)\n", library);
     fd = open(library, O_RDONLY);
 
     if (fd == -1) {
-        LOGI("Could not open library");
+        LOGI("lo_dlneeds: Could not open library %s: %s", library, strerror(errno));
         return NULL;
     }
 
     if (read(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
-        LOGI("Could not read ELF header");
+        LOGI("lo_dlneeds: Could not read ELF header of %s", library);
         close(fd);
         return NULL;
     }
@@ -350,12 +332,12 @@ lo_dlneeds(const char *library)
     /* Read in .shstrtab */
 
     if (lseek(fd, hdr.e_shoff + hdr.e_shstrndx * sizeof(shdr), SEEK_SET) < 0) {
-        LOGI("Could not seek to .shstrtab section header");
+        LOGI("lo_dlneeds: Could not seek to .shstrtab section header of %s", library);
         close(fd);
         return NULL;
     }
     if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) {
-        LOGI("Could not read section header");
+        LOGI("lo_dlneeds: Could not read section header of %s", library);
         close(fd);
         return NULL;
     }
@@ -367,13 +349,13 @@ lo_dlneeds(const char *library)
     /* Read section headers, looking for .dynstr section */
 
     if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) {
-        LOGI("Could not seek to section headers");
+        LOGI("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)) < sizeof(shdr)) {
-            LOGI("Could not read section header");
+            LOGI("lo_dlneeds: Could not read section header of %s", library);
             close(fd);
             return NULL;
         }
@@ -389,7 +371,7 @@ lo_dlneeds(const char *library)
     }
 
     if (i == hdr.e_shnum) {
-        LOGI("No .dynstr section");
+        LOGI("lo_dlneeds: No .dynstr section in %s", library);
         close(fd);
         return NULL;
     }
@@ -397,13 +379,13 @@ lo_dlneeds(const char *library)
     /* Read section headers, looking for .dynamic section */
 
     if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) {
-        LOGI("Could not seek to section headers");
+        LOGI("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)) < sizeof(shdr)) {
-            LOGI("Could not read section header");
+            LOGI("lo_dlneeds: Could not read section header of %s", library);
             close(fd);
             return NULL;
         }
@@ -414,13 +396,13 @@ lo_dlneeds(const char *library)
             /* Count number of DT_NEEDED entries */
             n_needed = 0;
             if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) {
-                LOGI("Could not seek to .dynamic section");
+                LOGI("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)) < sizeof(dyn)) {
-                    LOGI("Could not read .dynamic entry");
+                    LOGI("lo_dlneeds: Could not read .dynamic entry of %s", library);
                     close(fd);
                     return NULL;
                 }
@@ -428,26 +410,26 @@ lo_dlneeds(const char *library)
                     n_needed++;
             }
 
-            LOGI("Found %d DT_NEEDED libs", 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) {
-                LOGI("Could not seek to .dynamic section");
+                LOGI("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)) < sizeof(dyn)) {
-                    LOGI("Could not read .dynamic entry");
+                    LOGI("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);
+                    /* LOGI("needs: %s\n", dynstr + dyn.d_un.d_val); */
                     result[n_needed] = strdup(dynstr + dyn.d_un.d_val);
                     n_needed++;
                 }
@@ -461,6 +443,8 @@ lo_dlneeds(const char *library)
         }
     }
 
+    LOGI("lo_dlneeds: Could not find .dynamic section in %s", library);
+    close(fd);
     return NULL;
 }
 
@@ -505,7 +489,7 @@ lo_dlopen(const char *library)
     if (rover != NULL)
         return rover->handle;
 
-    LOGI("lo_dlopen(%s)", library);
+    /* LOGI("lo_dlopen(%s)", library); */
 
     if (library[0] == '/') {
         full_name = strdup(library);
@@ -531,7 +515,7 @@ lo_dlopen(const char *library)
     }
 
     if (!found) {
-        LOGI("Library %s not found", library);
+        LOGI("lo_dlopen: Library %s not found", library);
         return NULL;
     }
 
@@ -553,7 +537,7 @@ lo_dlopen(const char *library)
     LOGI("dlopen(%s) = %p", full_name, p);
     free(full_name);
     if (p == NULL)
-        LOGI(dlerror());
+        LOGI("lo_dlopen: %s", dlerror());
 
     new_loaded_lib = malloc(sizeof(*new_loaded_lib));
     new_loaded_lib->name = strdup(library);
@@ -570,9 +554,9 @@ lo_dlsym(void *handle,
          const char *symbol)
 {
     void *p = dlsym(handle, symbol);
-    LOGI("dlsym(%p, %s) = %p", handle, symbol, p);
+    /* LOGI("dlsym(%p, %s) = %p", handle, symbol, p); */
     if (p == NULL)
-        LOGI(dlerror());
+        LOGI("lo_dlsym: %s", dlerror());
     return p;
 }
 
@@ -591,21 +575,13 @@ void android_main(struct android_app* state)
 {
     struct engine engine;
 
-    LOGI("here we are %s:%d", __FUNCTION__, __LINE__);
-
     app = state;
 
     memset(&engine, 0, sizeof(engine));
     state->userData = &engine;
     state->onAppCmd = engine_handle_cmd;
 
-    char cwd[1000];
-    getcwd(cwd, sizeof(cwd));
-    LOGI("cwd=%s", cwd);
-
-    // lo_main(lo_main_argc, lo_main_argv);
-
-    // loop waiting for stuff to do.
+    lo_main(lo_main_argc, lo_main_argv);
 
     while (1) {
         // Read all pending events.
diff --git a/sal/osl/android/jni/lo-bootstrap.h b/sal/osl/android/jni/lo-bootstrap.h
new file mode 100644
index 0000000..a46094c
--- /dev/null
+++ b/sal/osl/android/jni/lo-bootstrap.h
@@ -0,0 +1,45 @@
+/* -*- 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 at 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.
+ */
+
+#if defined(ANDROID)
+
+char **lo_dlneeds(const char *library);
+
+void *lo_dlopen(const char *library);
+
+
+void *lo_dlsym(void *handle,
+               const char *symbol);
+
+int lo_dlcall_argc_argv(void *function,
+                        int argc,
+                        const char **argv);
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/osl/android/src/org/libreoffice/android/Bootstrap.java b/sal/osl/android/src/org/libreoffice/android/Bootstrap.java
index fe65e0a..5e70543 100644
--- a/sal/osl/android/src/org/libreoffice/android/Bootstrap.java
+++ b/sal/osl/android/src/org/libreoffice/android/Bootstrap.java
@@ -44,7 +44,8 @@ public class Bootstrap extends NativeActivity
 {
     private static String TAG = "lo-bootstrap";
 
-    public native boolean setup(String dataDir);
+    public native boolean setup(String dataDir,
+                                String[] ld_library_path);
 
     public native boolean setup(int lo_main_ptr,
                                 Object lo_main_argument);
@@ -72,8 +73,13 @@ public class Bootstrap extends NativeActivity
             return;
         }
 
-        // This inspects LD_LIBRARY_PATH and dataDir
-        if (!setup(dataDir))
+        String llp = System.getenv("LD_LIBRARY_PATH");
+        if (llp == null)
+            llp = "/vendor/lib:/system/lib";
+
+        String[] llpa = llp.split(":");
+
+        if (!setup(dataDir, llpa))
             return;
 
         String mainLibrary = getIntent().getStringExtra("lo-main-library");
diff --git a/sal/osl/unx/module.c b/sal/osl/unx/module.c
index 7db8011..c0ee837 100644
--- a/sal/osl/unx/module.c
+++ b/sal/osl/unx/module.c
@@ -148,11 +148,17 @@ oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nR
     if (pModuleName)
     {
 #ifndef NO_DL_FUNCTIONS
+#ifdef ANDROID
+        void *(*lo_dlopen)(const char *) = dlsym(RTLD_DEFAULT, "lo_dlopen");
+        void *pLib;
+        OSL_ASSERT(lo_dlopen != NULL);
+        pLib = (*lo_dlopen)(pModuleName);
+#else
         int rtld_mode =
             ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
             ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
         void* pLib = dlopen(pModuleName, rtld_mode);
-
+#endif
 #if OSL_DEBUG_LEVEL > 1
         if (pLib == 0)
             OSL_TRACE("Error osl_loadModule: %s", dlerror());
diff --git a/sal/osl/unx/nlsupport.c b/sal/osl/unx/nlsupport.c
index fcfb050..efd68dd 100644
--- a/sal/osl/unx/nlsupport.c
+++ b/sal/osl/unx/nlsupport.c
@@ -932,7 +932,11 @@ void _imp_getProcessLocale( rtl_Locale ** ppLocale )
         locale = getenv( "LANG" );
 
     if( NULL == locale )
+#ifdef ANDROID
+        locale = "en-US.UTF-8";
+#else
         locale = "C";
+#endif
 
     *ppLocale = _parse_locale( locale );
 }


More information about the Libreoffice-commits mailing list