gnucash unstable: Rework directory determination in CMake builds.

John Ralls jralls at code.gnucash.org
Tue Dec 5 20:26:46 EST 2017


Updated	 via  https://github.com/Gnucash/gnucash/commit/66817bb9 (commit)
	from  https://github.com/Gnucash/gnucash/commit/84929c8e (commit)



commit 66817bb997d601b74b25b7a465a318387fb81594
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Dec 5 14:48:45 2017 -0800

    Rework directory determination in CMake builds.
    
    Sets paths for finding componenents depending on the state of ENABLE_BINRELOC,
    GNC_UNINSTALLED, GNC_BUILDDIR and whether any install paths have been set
    outside of CMAKE_INSTALL_PREFIX.
    
    GNUInstallDirs changes the name of CMAKE_INSTALL_LIBDIR depending on the
    operating system and distro. When CMAKE_INSTALL_PREFIX is /usr,
    /usr/local, or any subdirectory of /opt it also changes
    CMAKE_INSTALL_FULL_SYSCONFDIR to /etc. An earlier commit by Aaron Laws
    mirrors the name of CMAKE_INSTALL_LIBDIR to the build library directory.
    
    It's possible for builders to set any of the install directories
    anywhere they please.
    
    Setting any directory outside of CMAKE_INSTALL_PREFIX breaks Binreloc so
    the toplevel CMakeLists.txt now detects that and disables Binreloc.
    
    If Binreloc is enabled then all path queries use it to find paths. This
    works in the build directory because the gnucash executable and all of
    the test programs are in build_directory/bin and LIBDIR, DATADIR, and
    SYSCONFDIR can be found in the same root path.
    
    If Binreloc is disabled then in order to build or run programs from the
    build directory one must set GNC_UNINSTALLED and set GNC_BUILDDIR to the
    absolute path of the build directory. When those are set GNC_BUILDDIR
    replaces CMAKE_INSTALL_PREFIX in all paths that are subdirectories of
    CMAKE_INSTALL_PREFIX; paths that are not in CMAKE_INSTALL_PREFIX are
    appended whole to GNC_BUILDDIR. This process is constent between CMake
    and gnc_path_get_foo. GnuCash is unlikely to run from a DESTDIR without
    Binreloc.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bf9732f..205fbcd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,23 @@ OPTION (AUTOTOOLS_IN_DIST "Add autotools support to distribution tarballs." ON)
 # These are also settable from the command line in a similar way.
 
 SET(GNUCASH_BUILD_ID "" CACHE STRING "Overrides the GnuCash build identification (Build ID) which defaults to a description of the vcs commit from which gnucash is built. Distributions may want to insert a package management based version number instead")
+
+# Check that all of the absolute install paths are inside
+# ${CMAKE_INSTALL_PREFIX}. If they're not, disable binreloc as it
+# won't be able to find paths that aren't relative to the location of
+# the executable.
+foreach(install_dir ${CMAKE_INSTALL_FULL_BINDIR}
+    ${CMAKE_INSTALL_FULL_SYSCONFDIR} ${CMAKE_INSTALL_FULL_DATAROOTDIR}
+    ${CMAKE_INSTALL_FULL_DATADIR} ${CMAKE_INSTALL_FULL_LIBDIR})
+  string(FIND ${install_dir} ${CMAKE_INSTALL_PREFIX} in_prefix)
+  if(in_prefix EQUAL -1)
+    set(ENABLE_BINRELOC OFF)
+    message(WARNING "${install_dir} is set outside of the intallation prefix ${CMAKE_INSTALL_PREFIX}. That will break relocation so ENABLE_BINRELOC is set to off. With relocation disabled GnuCash will run only in its configured install location. You must set GNC_UNINSTALLED=1 and GNC_BUILDDIR=/path/to/builddir to run from the build directory. GnuCash will not run from a DESTDIR.")
+    break()
+  endif()
+endforeach()
+
+# GnuCash installs two files in ${CMAKE_INSTALL_SYSCONFDIR}
 SET(BINDIR ${CMAKE_INSTALL_BINDIR} CACHE STRING "user executables")
 SET(SYSCONFDIR ${CMAKE_INSTALL_SYSCONFDIR} CACHE STRING "read-only single-machine data")
 SET(DATAROOTDIR ${CMAKE_INSTALL_DATAROOTDIR} CACHE STRING "read-only arch.-independent data root")
@@ -82,7 +99,7 @@ SET(LOCALEDIR ${DATAROOTDIR}/locale CACHE STRING "locale-dependent data")
 SET(GNC_HELPDIR ${DATADIR} CACHE STRING "where to store help files")
 SET(DATADIRNAME share)
 SET(GNC_SYSTEM_XDG_DATA_DIRS /usr/local/share /usr/share)
-SET(GNC_DBD_DIR ${CMAKE_PREFIX_PATH}/lib/dbd CACHE PATH "specify location of libdbi drivers")
+SET(GNC_DBD_DIR ${CMAKE_PREFIX_LIBDIR}/dbd CACHE PATH "specify location of libdbi drivers")
 SET(PKGLIBDIR ${CMAKE_INSTALL_LIBDIR}/gnucash)
 SET(TEST_MYSQL_URL "" CACHE STRING "MySQL database URL for testing")
 SET(TEST_PGSQL_URL "" CACHE STRING "PgSQL database URL for testing")
diff --git a/libgnucash/core-utils/CMakeLists.txt b/libgnucash/core-utils/CMakeLists.txt
index 52e1251..a6f1c7b 100644
--- a/libgnucash/core-utils/CMakeLists.txt
+++ b/libgnucash/core-utils/CMakeLists.txt
@@ -43,10 +43,19 @@ ADD_CUSTOM_TARGET(swig-runtime-h DEPENDS ${SWIG_RUNTIME_H})
 SET_SOURCE_FILES_PROPERTIES (gnc-guile-utils.c PROPERTIES OBJECT_DEPENDS ${SWIG_RUNTIME_H})
 
 SET(prefix ${CMAKE_INSTALL_PREFIX})
-SET(datadir ${DATADIR})
-SET(bindir ${BINDIR})
-SET(libdir ${LIBDIR})
-SET(sysconfdir ${SYSCONFDIR})
+if(ENABLE_BINRELOC)
+  SET(datadir ${DATADIR})
+  SET(bindir ${BINDIR})
+  SET(libdir ${LIBDIR})
+  SET(sysconfdir ${SYSCONFDIR})
+  SET(localedir ${LOCALEDIR})
+else()
+  SET(datadir ${CMAKE_INSTALL_FULL_DATADIR})
+  SET(bindir ${CMAKE_INSTALL_FULL_BINDIR})
+  SET(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
+  SET(sysconfdir ${CMAKE_INSTALL_FULL_SYSCONFDIR})
+  SET(localedir "${CMAKE_INSTALL_FULL_DATAROOTDIR}/locale")
+endif()
 GNC_CONFIGURE(gncla-dir.h.in gncla-dir.h)
 
 ### Create gnc-version.h ###
diff --git a/libgnucash/core-utils/binreloc.c b/libgnucash/core-utils/binreloc.c
index 55b7905..1b7b1b6 100644
--- a/libgnucash/core-utils/binreloc.c
+++ b/libgnucash/core-utils/binreloc.c
@@ -33,7 +33,6 @@
 #ifndef __BINRELOC_C__
 #define __BINRELOC_C__
 #include <config.h>
-#include "gncla-dir.h"
 
 #include <platform.h>
 #if PLATFORM(WINDOWS)
@@ -53,7 +52,9 @@
 #include <limits.h>
 #include <string.h>
 #include "binreloc.h"
+#include "gnc-filepath-utils.h"
 #include <glib.h>
+#include "gncla-dir.h"
 
 G_BEGIN_DECLS
 
@@ -84,7 +85,7 @@ _br_find_exe (Gnc_GbrInitError *error)
        the current process */
     prefix = g_win32_get_package_installation_directory_of_module (NULL);
     result = g_build_filename (prefix,
-                               "bin", "gnucash.exe",
+                               BINDIR, "gnucash.exe",
                                (char*)NULL);
     g_free (prefix);
     return result;
@@ -385,13 +386,14 @@ gnc_gbr_find_exe_dir (const gchar *default_dir)
  *         will be returned. If default_prefix is NULL, then NULL will be
  *         returned.
  */
-gchar *
-gnc_gbr_find_prefix (const gchar *default_prefix)
+
+static inline gchar *
+get_mac_bundle_prefix()
 {
 #if defined ENABLE_BINRELOC && defined MAC_INTEGRATION
     gchar *id = gtkosx_application_get_bundle_id ();
     gchar *path = gtkosx_application_get_resource_path ();
-    if (id == NULL)
+     if (id == NULL)
     {
         gchar *dirname = g_path_get_dirname (path);
         g_free (path);
@@ -400,9 +402,24 @@ gnc_gbr_find_prefix (const gchar *default_prefix)
     }
     g_free (id);
     return path;
-#else
-    gchar *dir1, *dir2;
+#endif
+    return NULL;
+}
+
+static inline gchar*
+get_builddir_prefix()
+{
+    if (g_getenv ("GNC_UNINSTALLED"))
+        return g_strdup (g_getenv ("GNC_BUILDDIR"));
+    return NULL;
+}
 
+gchar *
+gnc_gbr_find_prefix (const gchar *default_prefix)
+{
+    gchar *dir1, *dir2;
+    if ((dir2 = get_builddir_prefix()) || (dir2 = get_mac_bundle_prefix()))
+        return dir2;
     if (exe == NULL)
     {
         /* BinReloc not initialized. */
@@ -415,7 +432,6 @@ gnc_gbr_find_prefix (const gchar *default_prefix)
     dir2 = g_path_get_dirname (dir1);
     g_free (dir1);
     return dir2;
-#endif //ENABLE_BINRELOC && defined MAC_INTEGRATION
 }
 
 
@@ -435,7 +451,7 @@ gnc_gbr_find_prefix (const gchar *default_prefix)
 gchar *
 gnc_gbr_find_bin_dir (const gchar *default_bin_dir)
 {
-    gchar *prefix, *dir;
+    gchar *prefix, *dir, *bindir;
     prefix = gnc_gbr_find_prefix (NULL);
     if (prefix == NULL)
     {
@@ -445,47 +461,13 @@ gnc_gbr_find_bin_dir (const gchar *default_bin_dir)
         else
             return NULL;
     }
-
-    dir = g_build_filename (prefix, "bin", NULL);
+    bindir = gnc_file_path_relative_part(PREFIX, BINDIR);
+    dir = g_build_filename (prefix, bindir, NULL);
+    g_free (bindir);
     g_free (prefix);
     return dir;
 }
 
-
-/** Locate the application's superuser binary folder.
- *
- * The path is generated by the following pseudo-code evaluation:
- * \code
- * prefix + "/sbin"
- * \endcode
- *
- * @param default_sbin_dir  A default path which will used as fallback.
- * @return A string containing the sbin folder's path, which must be freed when
- *         no longer necessary. If BinReloc is not initialized, or if the
- *         initialization function failed, then a copy of default_sbin_dir will
- *         be returned. If default_bin_dir is NULL, then NULL will be returned.
- */
-gchar *
-gnc_gbr_find_sbin_dir (const gchar *default_sbin_dir)
-{
-    gchar *prefix, *dir;
-
-    prefix = gnc_gbr_find_prefix (NULL);
-    if (prefix == NULL)
-    {
-        /* BinReloc not initialized. */
-        if (default_sbin_dir != NULL)
-            return g_strdup (default_sbin_dir);
-        else
-            return NULL;
-    }
-
-    dir = g_build_filename (prefix, "sbin", NULL);
-    g_free (prefix);
-    return dir;
-}
-
-
 /** Locate the application's data folder.
  *
  * The path is generated by the following pseudo-code evaluation:
@@ -503,7 +485,7 @@ gnc_gbr_find_sbin_dir (const gchar *default_sbin_dir)
 gchar *
 gnc_gbr_find_data_dir (const gchar *default_data_dir)
 {
-    gchar *prefix, *dir;
+    gchar *prefix, *dir, *datadir;
 
     prefix = gnc_gbr_find_prefix (NULL);
     if (prefix == NULL)
@@ -515,12 +497,13 @@ gnc_gbr_find_data_dir (const gchar *default_data_dir)
             return NULL;
     }
 
-    dir = g_build_filename (prefix, "share", NULL);
+    datadir = gnc_file_path_relative_part(PREFIX, DATADIR);
+    dir = g_build_filename (prefix, datadir, NULL);
+    g_free (datadir);
     g_free (prefix);
     return dir;
 }
 
-
 /** Locate the application's library folder.
  *
  * The path is generated by the following pseudo-code evaluation:
@@ -537,7 +520,7 @@ gnc_gbr_find_data_dir (const gchar *default_data_dir)
 gchar *
 gnc_gbr_find_lib_dir (const gchar *default_lib_dir)
 {
-    gchar *prefix, *dir;
+    gchar *prefix, *dir, *libdir;
 
     prefix = gnc_gbr_find_prefix (NULL);
     if (prefix == NULL)
@@ -549,46 +532,13 @@ gnc_gbr_find_lib_dir (const gchar *default_lib_dir)
             return NULL;
     }
 
-    dir = g_build_filename (prefix, LIBDIR, NULL);
-    g_free (prefix);
-    return dir;
-}
-
-
-/** Locate the application's libexec folder.
- *
- * The path is generated by the following pseudo-code evaluation:
- * \code
- * prefix + "/libexec"
- * \endcode
- *
- * @param default_libexec_dir  A default path which will used as fallback.
- * @return A string containing the libexec folder's path, which must be freed when
- *         no longer necessary. If BinReloc is not initialized, or if the initialization
- *         function failed, then a copy of default_libexec_dir will be returned.
- *         If default_libexec_dir is NULL, then NULL will be returned.
- */
-gchar *
-gnc_gbr_find_libexec_dir (const gchar *default_libexec_dir)
-{
-    gchar *prefix, *dir;
-
-    prefix = gnc_gbr_find_prefix (NULL);
-    if (prefix == NULL)
-    {
-        /* BinReloc not initialized. */
-        if (default_libexec_dir != NULL)
-            return g_strdup (default_libexec_dir);
-        else
-            return NULL;
-    }
-
-    dir = g_build_filename (prefix, "libexec", NULL);
+    libdir = gnc_file_path_relative_part(PREFIX, LIBDIR);
+    dir = g_build_filename (prefix, libdir, NULL);
+    g_free (libdir);
     g_free (prefix);
     return dir;
 }
 
-
 /** Locate the application's configuration files folder.
  *
  * The path is generated by the following pseudo-code evaluation:
@@ -605,7 +555,7 @@ gnc_gbr_find_libexec_dir (const gchar *default_libexec_dir)
 gchar *
 gnc_gbr_find_etc_dir (const gchar *default_etc_dir)
 {
-    gchar *prefix, *dir;
+    gchar *prefix, *dir, *sysconfdir;
 
     prefix = gnc_gbr_find_prefix (NULL);
     if (prefix == NULL)
@@ -617,7 +567,9 @@ gnc_gbr_find_etc_dir (const gchar *default_etc_dir)
             return NULL;
     }
 
-    dir = g_build_filename (prefix, "etc", NULL);
+    sysconfdir = gnc_file_path_relative_part(PREFIX, SYSCONFDIR);
+    dir = g_build_filename (prefix, sysconfdir, NULL);
+    g_free (sysconfdir);
     g_free (prefix);
     return dir;
 }
diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index ab2c216..881bfcf 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -193,6 +193,14 @@ gnc_resolve_file_path (const gchar * filefrag)
 
 }
 
+gchar *gnc_file_path_relative_part (const gchar *prefix, const gchar *path)
+{
+    std::string p{path};
+    if (p.find(prefix) == 0)
+        return g_strdup(p.substr(strlen(prefix)).c_str());
+    return g_strdup(path);
+}
+
 /* Searches for a file fragment paths set via GNC_DOC_PATH environment
  * variable. If this variable is not set, fall back to search in
  * - a html directory in the local user's gnucash settings directory
diff --git a/libgnucash/core-utils/gnc-filepath-utils.h b/libgnucash/core-utils/gnc-filepath-utils.h
index 9c2a93a..d0e9ff4 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.h
+++ b/libgnucash/core-utils/gnc-filepath-utils.h
@@ -41,6 +41,14 @@
  */
 gchar *gnc_resolve_file_path (const gchar *filefrag);
 
+/** Given a prefix and a path return the relative portion of the path.
+ * @param prefix The prefix that might be the first part of the path
+ * @param path The path from which the prefix might be removed
+ * @return a char* that must be g_freed containing the path without
+ *        the prefix if path begins with prefix, otherwise a copy of path.
+ */
+gchar *gnc_file_path_relative_part (const gchar *prefix, const gchar *path);
+
 /** @brief Find an absolute path to a localized version of a given
  *  relative path to a html or html related file.
  *  If no localized version exists, an absolute path to the file
diff --git a/libgnucash/core-utils/gnc-path.c b/libgnucash/core-utils/gnc-path.c
index 4a0607d..c979c1f 100644
--- a/libgnucash/core-utils/gnc-path.c
+++ b/libgnucash/core-utils/gnc-path.c
@@ -138,11 +138,16 @@ gchar *gnc_path_get_gtkbuilderdir()
  * @returns A newly allocated string. */
 gchar *gnc_path_get_localedir()
 {
-    gchar *prefix = gnc_path_get_prefix();
-    gchar *result = g_build_filename (prefix, LOCALE_DATADIRNAME, "locale", (char*)NULL);
-    g_free (prefix);
-    //printf("Returning localedir %s\n", result);
-    return result;
+    if (g_path_is_absolute (LOCALEDIR))
+        return g_strdup(LOCALEDIR);
+    else
+    {
+        gchar *prefix = gnc_path_get_prefix();
+        gchar *result = g_build_filename (prefix, LOCALEDIR, (char*)NULL);
+        g_free (prefix);
+        //printf("Returning localedir %s\n", result);
+        return result;
+    }
 }
 
 /** Returns the accounts file path, usually
diff --git a/libgnucash/core-utils/gncla-dir.h.in b/libgnucash/core-utils/gncla-dir.h.in
index c692178..a55d90f 100644
--- a/libgnucash/core-utils/gncla-dir.h.in
+++ b/libgnucash/core-utils/gncla-dir.h.in
@@ -30,4 +30,4 @@
 #define BINDIR "@-bindir-@"
 #define LIBDIR "@-libdir-@"
 
-#define LOCALE_DATADIRNAME "@-DATADIRNAME-@"
+#define LOCALEDIR "@-localedir-@"
diff --git a/libgnucash/core-utils/test/CMakeLists.txt b/libgnucash/core-utils/test/CMakeLists.txt
index f1aa444..2d7f46b 100644
--- a/libgnucash/core-utils/test/CMakeLists.txt
+++ b/libgnucash/core-utils/test/CMakeLists.txt
@@ -1,8 +1,8 @@
-
+set(MODULEPATH ${CMAKE_SOURCE_DIR}/libgnucash/core-utils)
 
 SET(CORE_UTILS_TEST_INCLUDE_DIRS
   ${CMAKE_BINARY_DIR}/common # for config.h
-  ${CMAKE_SOURCE_DIR}/libgnucash/core-utils
+  ${MODULEPATH}
   ${CMAKE_SOURCE_DIR}/common/test-core
   ${GLIB2_INCLUDE_DIRS}
   ${GTK_MAC_INCLUDE_DIRS}
@@ -27,5 +27,31 @@ IF (MAC_INTEGRATION)
   TARGET_COMPILE_DEFINITIONS(test-userdata-dir PRIVATE ${GTK_MAC_CFLAGS_OTHER})
 ENDIF(MAC_INTEGRATION)
 
-SET_DIST_LIST(test_core_utils_DIST CMakeLists.txt Makefile.am test-gnc-glib-utils.c
-    test-resolve-file-path.c test-userdata-dir.c test-userdata-dir-invalid-home.c)
+set(gtest_core_utils_INCLUDES
+  ${MODULEPATH}
+  ${CMAKE_BINARY_DIR}/common # for config.h
+  ${CMAKE_SOURCE_DIR}/common # for platform.h
+  ${CMAKE_BINARY_DIR}/libgnucash/core-utils # for gncla-dir.h
+  ${GLIB2_INCLUDE_DIRS}
+  ${GTEST_INCLUDE_DIR}
+  )
+
+SET(gtest_core_utils_LIBS
+  ${GLIB2_LDFLAGS}
+  ${Boost_LIBRARIES}
+  ${GTHREAD_LDFLAGS}
+  ${GTEST_LIB})
+
+set(test_gnc_path_util_SOURCES
+  ${MODULEPATH}/gnc-path.c
+  ${MODULEPATH}/binreloc.c
+  ${MODULEPATH}/gnc-filepath-utils.cpp
+  gtest-path-utilities.cpp
+  ${GTEST_SRC})
+
+gnc_add_test(test-gnc-path-util "${test_gnc_path_util_SOURCES}"
+  gtest_core_utils_INCLUDES gtest_core_utils_LIBS "GNC_UNINSTALLED=yes")
+
+SET_DIST_LIST(test_core_utils_DIST CMakeLists.txt Makefile.am
+  test-gnc-glib-utils.c test-resolve-file-path.c test-userdata-dir.c
+  test-userdata-dir-invalid-home.c gtest-path-utilities.cpp)
diff --git a/libgnucash/core-utils/test/gtest-path-utilities.cpp b/libgnucash/core-utils/test/gtest-path-utilities.cpp
new file mode 100644
index 0000000..94e8356
--- /dev/null
+++ b/libgnucash/core-utils/test/gtest-path-utilities.cpp
@@ -0,0 +1,125 @@
+extern "C"
+{
+#include <config.h>
+#include <glib.h>
+#include <gncla-dir.h>
+#include <gnc-path.h>
+#include <binreloc.h>
+#include <gnc-filepath-utils.h>
+}
+
+#include <gtest/gtest.h>
+
+struct PathTest : public testing::Test
+{
+    PathTest() : m_prefix{nullptr} {}
+    void SetUp()
+    {
+#ifdef ENABLE_BINRELOC
+        gnc_gbr_init(nullptr);
+#endif
+        char *builddir = g_strdup(g_getenv("GNC_BUILDDIR"));
+        if (builddir)
+            m_prefix = builddir;
+        else
+            m_prefix = g_get_current_dir();
+    }
+    void TearDown()
+    {
+        if (m_prefix)
+            g_free(m_prefix);
+    }
+    char *m_prefix;
+};
+
+TEST_F(PathTest, gnc_path_get_prefix)
+{
+#ifdef ENABLE_BINRELOC
+    EXPECT_STREQ(gnc_path_get_prefix(), m_prefix);
+#else
+    g_setenv("GNC_UNINSTALLED", "1", TRUE);
+    g_setenv("GNC_BUILDDIR", m_prefix, 1);
+    EXPECT_STREQ(gnc_path_get_prefix(), m_prefix);
+    g_unsetenv("GNC_UNINSTALLED");
+    g_unsetenv("GNC_BUILDDIR");
+    EXPECT_STREQ(gnc_path_get_prefix(), PREFIX);
+#endif
+}
+
+TEST_F(PathTest, gnc_path_get_bindir)
+{
+    gchar *dirname = gnc_file_path_relative_part(PREFIX, BINDIR);
+    gchar *binpath = g_build_filename(m_prefix, dirname, NULL);
+    g_free(dirname);
+#ifdef ENABLE_BINRELOC
+    EXPECT_STREQ(gnc_path_get_bindir(), binpath);
+    g_free(binpath);
+#else
+    g_setenv("GNC_UNINSTALLED", "1", TRUE);
+    g_setenv("GNC_BUILDDIR", m_prefix, 1);
+    EXPECT_STREQ(gnc_path_get_bindir(), binpath);
+    g_free(binpath);
+    g_unsetenv("GNC_UNINSTALLED");
+    g_unsetenv("GNC_BUILDDIR");
+    EXPECT_STREQ(gnc_path_get_bindir(), BINDIR);
+#endif
+}
+
+TEST_F(PathTest, gnc_path_get_libdir)
+{
+    gchar *dirname = gnc_file_path_relative_part(PREFIX, LIBDIR);
+    gchar *libpath = g_build_filename(m_prefix, dirname, NULL);
+    g_free(dirname);
+#ifdef ENABLE_BINRELOC
+    EXPECT_STREQ(gnc_path_get_libdir(), libpath);
+    g_free(libpath);
+#else
+    g_setenv("GNC_UNINSTALLED", "1", TRUE);
+    g_setenv("GNC_BUILDDIR", m_prefix, 1);
+    EXPECT_STREQ(gnc_path_get_libdir(), libpath);
+    g_free(libpath);
+    g_unsetenv("GNC_UNINSTALLED");
+    g_unsetenv("GNC_BUILDDIR");
+    EXPECT_STREQ(gnc_path_get_libdir(), LIBDIR);
+#endif
+}
+
+TEST_F(PathTest, gnc_path_get_datadir)
+{
+    gchar *dirname = gnc_file_path_relative_part(PREFIX, DATADIR);
+    gchar *datapath = g_build_filename(m_prefix, dirname, NULL);
+    g_free(dirname);
+#ifdef ENABLE_BINRELOC
+    EXPECT_STREQ(gnc_path_get_datadir(), datapath);
+    g_free(datapath);
+#else
+    g_setenv("GNC_UNINSTALLED", "1", TRUE);
+    g_setenv("GNC_BUILDDIR", m_prefix, 1);
+    EXPECT_STREQ(gnc_path_get_datadir(), datapath);
+    g_free(datapath);
+    g_unsetenv("GNC_UNINSTALLED");
+    g_unsetenv("GNC_BUILDDIR");
+    EXPECT_STREQ(gnc_path_get_datadir(), DATADIR);
+#endif
+}
+
+TEST_F(PathTest, gnc_path_get_sysconfdir)
+{
+    gchar *dirname = gnc_file_path_relative_part(PREFIX, SYSCONFDIR);
+    gchar *sysconfpath = g_build_filename(m_prefix, dirname, "gnucash", NULL);
+    g_free(dirname);
+#ifdef ENABLE_BINRELOC
+    EXPECT_STREQ(gnc_path_get_pkgsysconfdir(), sysconfpath);
+    g_free(sysconfpath);
+#else
+    g_setenv("GNC_UNINSTALLED", "1", TRUE);
+    g_setenv("GNC_BUILDDIR", m_prefix, 1);
+    EXPECT_STREQ(gnc_path_get_pkgsysconfdir(), sysconfpath);
+    g_free(sysconfpath);
+    g_unsetenv("GNC_UNINSTALLED");
+    g_unsetenv("GNC_BUILDDIR");
+    sysconfpath = g_build_filename(SYSCONFDIR, "gnucash", NULL);
+    EXPECT_STREQ(gnc_path_get_pkgsysconfdir(), sysconfpath);
+    g_free(sysconfpath);
+#endif
+}
diff --git a/libgnucash/engine/qof-backend.cpp b/libgnucash/engine/qof-backend.cpp
index 06ee78c..b954ec8 100644
--- a/libgnucash/engine/qof-backend.cpp
+++ b/libgnucash/engine/qof-backend.cpp
@@ -105,12 +105,7 @@ static char* get_default_module_dir(const char* rel_path)
     if (uninstalled)
     {
 #ifdef CMAKE_BUILD
-    #ifdef WIN32
-        #define MODULE_LIBDIR "bin"
-    #else
-        #define MODULE_LIBDIR LIBDIR "/gnucash"
-    #endif
-        pkglibdir = g_build_path (G_DIR_SEPARATOR_S, builddir, MODULE_LIBDIR, NULL);
+        pkglibdir = gnc_path_get_pkglibdir ();
 #else
         if (rel_path)
             pkglibdir = g_build_path (G_DIR_SEPARATOR_S, builddir,



Summary of changes:
 CMakeLists.txt                                     |  19 ++-
 libgnucash/core-utils/CMakeLists.txt               |  17 ++-
 libgnucash/core-utils/binreloc.c                   | 128 +++++++--------------
 libgnucash/core-utils/gnc-filepath-utils.cpp       |   8 ++
 libgnucash/core-utils/gnc-filepath-utils.h         |   8 ++
 libgnucash/core-utils/gnc-path.c                   |  15 ++-
 libgnucash/core-utils/gncla-dir.h.in               |   2 +-
 libgnucash/core-utils/test/CMakeLists.txt          |  34 +++++-
 .../core-utils/test/gtest-path-utilities.cpp       | 125 ++++++++++++++++++++
 libgnucash/engine/qof-backend.cpp                  |   7 +-
 10 files changed, 254 insertions(+), 109 deletions(-)
 create mode 100644 libgnucash/core-utils/test/gtest-path-utilities.cpp



More information about the gnucash-changes mailing list