[education/rkward] rkward/rbackend: Confine all qt-related stuff to its own library
Thomas Friedrichsmeier
null at kde.org
Fri May 10 17:04:24 BST 2024
Git commit f06f2904cae6104601f3f5a3ca980ad968fc9d68 by Thomas Friedrichsmeier.
Committed on 06/05/2024 at 14:54.
Pushed by tfry into branch 'master'.
Confine all qt-related stuff to its own library
M +16 -12 rkward/rbackend/CMakeLists.txt
M +4 -23 rkward/rbackend/rkrapi.cpp
M +1 -1 rkward/rbackend/rkrapi.h
A +35 -0 rkward/rbackend/rkrbackend_dlopen.cpp [License: GPL(v2.0+)]
M +13 -5 rkward/rbackend/rkrbackendprotocol_backend.cpp
M +9 -0 rkward/rbackend/rkrbackendprotocol_backend.h
M +1 -0 rkward/rbackend/rkwarddevice/CMakeLists.txt
https://invent.kde.org/education/rkward/-/commit/f06f2904cae6104601f3f5a3ca980ad968fc9d68
diff --git a/rkward/rbackend/CMakeLists.txt b/rkward/rbackend/CMakeLists.txt
index ad55b8bbe..1c68cf33a 100644
--- a/rkward/rbackend/CMakeLists.txt
+++ b/rkward/rbackend/CMakeLists.txt
@@ -45,23 +45,27 @@ SET (
ADD_LIBRARY(rbackend STATIC ${rbackend_frontend_SRCS} ${rbackend_shared_SRCS})
TARGET_LINK_LIBRARIES(rbackend rkgraphicsdevice.frontend Qt6::Widgets KF6::TextEditor KF6::WindowSystem)
-IF(${DLOPEN_RLIB})
-TARGET_COMPILE_DEFINITIONS(rbackend PUBLIC RK_DLOPEN_LIBRSO)
-ENDIF()
ADD_DEFINITIONS (-DRKWARD_BACKEND_PATH="${KDE_INSTALL_FULL_LIBEXECDIR}")
LINK_DIRECTORIES(${R_SHAREDLIBDIR})
-ADD_EXECUTABLE(rkward.rbackend ${rbackend_backend_SRCS} ${rbackend_shared_SRCS})
-ECM_MARK_NONGUI_EXECUTABLE(rkward.rbackend)
-TARGET_LINK_LIBRARIES(rkward.rbackend rkgraphicsdevice.backend ${CMAKE_THREAD_LIBS_INIT} Qt6::Network Qt6::Core KF6::I18n)
+# See rkrapi.h for documentation and rationale of the linking strategy
IF(${DLOPEN_RLIB})
- IF(NOT WIN32)
- TARGET_LINK_LIBRARIES(rkward.rbackend dl)
- ENDIF()
-ELSE()
-TARGET_LINK_LIBRARIES(rkward.rbackend ${R_USED_LIBS})
-ENDIF()
+ ADD_LIBRARY(rkward.rbackend.lib SHARED ${rbackend_backend_SRCS} ${rbackend_shared_SRCS})
+ TARGET_LINK_LIBRARIES(rkward.rbackend.lib rkgraphicsdevice.backend ${CMAKE_THREAD_LIBS_INIT} Qt6::Network Qt6::Core KF6::I18n)
+ TARGET_COMPILE_DEFINITIONS(rkward.rbackend.lib PUBLIC RK_DLOPEN_LIBRSO)
+ INSTALL(TARGETS rkward.rbackend.lib DESTINATION ${KDE_INSTALL_LIBDIR})
+
+ ADD_EXECUTABLE(rkward.rbackend rkrbackend_dlopen.cpp)
+ TARGET_LINK_LIBRARIES(rkward.rbackend rkward.rbackend.lib)
+ IF(NOT WIN32)
+ TARGET_LINK_LIBRARIES(rkward.rbackend dl)
+ ENDIF()
+ELSE(${DLOPEN_RLIB})
+ ADD_EXECUTABLE(rkward.rbackend ${rbackend_backend_SRCS} ${rbackend_shared_SRCS})
+ TARGET_LINK_LIBRARIES(rkward.rbackend rkgraphicsdevice.backend ${R_USED_LIBS} ${CMAKE_THREAD_LIBS_INIT} Qt6::Network Qt6::Core KF6::I18n)
+ENDIF(${DLOPEN_RLIB})
+ECM_MARK_NONGUI_EXECUTABLE(rkward.rbackend)
IF(WIN32)
# 64MB stack size is what R itself is build with on Windows, while by default the stack size would be 1MB
diff --git a/rkward/rbackend/rkrapi.cpp b/rkward/rbackend/rkrapi.cpp
index 9918fe8a7..f2b84bc24 100644
--- a/rkward/rbackend/rkrapi.cpp
+++ b/rkward/rbackend/rkrapi.cpp
@@ -15,35 +15,16 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include "../debug.h"
-void RFn::init(const char* libname) {
+void RFn::init(void* libr_dll_handle, void* (*dlsym_fun)(void*, const char*)) {
#if defined RK_DLOPEN_LIBRSO
-//#if defined(RTLD_DEEPBIND) // causes hard fail on suse tumbleweed 05/2024
-// RK_DEBUG(RBACKEND, DL_DEBUG, "Now loading R lib, dynamically (deepbind)");
-// RFn::init(dlopen(RLIBNAME, RTLD_NOW | RTLD_DEEPBIND));
-//#else
- RK_DEBUG(RBACKEND, DL_DEBUG, "Now loading R lib, dynamically (local)");
-#if defined(Q_OS_WIN)
- auto dllinfo = LoadLibraryA(libname);
-#else
- auto dllinfo = dlopen(libname, RTLD_NOW | RTLD_LOCAL);
-#endif
- if (!dllinfo) {
- RK_DEBUG(RBACKEND, DL_ERROR, "Failure loading R lib from '%s'", libname);
- }
-//#endif
-
auto rfn = new RFn(); // we need a dummy object, even if we are only interested in the static members
auto meta = rfn->metaObject();
- RK_DEBUG(RBACKEND, DL_DEBUG, "Loading %d symbols from R lib %p", meta->propertyCount() - meta->propertyOffset(), dllinfo);
+ RK_DEBUG(RBACKEND, DL_DEBUG, "Loading %d symbols from R lib %p", meta->propertyCount() - meta->propertyOffset(), libr_dll_handle);
for (int i = meta->propertyOffset(); i < meta->propertyCount(); ++i) {
auto prop = meta->property(i);
auto name = prop.name();
-#if defined(Q_OS_WIN)
- auto symb = GetProcAddress(dllinfo, name);
-#else
- auto symb = dlsym(dllinfo, name);
-#endif
- RK_DEBUG(RBACKEND, DL_DEBUG, "Lookup of symbol %s in %p: %p", name, dllinfo, symb);
+ auto symb = dlsym_fun(libr_dll_handle, name);
+ RK_DEBUG(RBACKEND, DL_DEBUG, "Lookup of symbol %s in %p: %p", name, libr_dll_handle, symb);
prop.write(rfn, QVariant::fromValue((void*) symb)); // NOTE: Qt refuses to write nullptr as value, but that's already the initial value of each member
}
#else
diff --git a/rkward/rbackend/rkrapi.h b/rkward/rbackend/rkrapi.h
index bdb718ce1..0091f0cd4 100644
--- a/rkward/rbackend/rkrapi.h
+++ b/rkward/rbackend/rkrapi.h
@@ -326,7 +326,7 @@ IMPORT_R_API(R_GE_maskType);
#endif
public:
- static void init(const char* dllname);
+ static void init(void* libr_dll_handle, void* (*dlsym_fun)(void*, const char*));
};
#endif
diff --git a/rkward/rbackend/rkrbackend_dlopen.cpp b/rkward/rbackend/rkrbackend_dlopen.cpp
new file mode 100644
index 000000000..2e403677e
--- /dev/null
+++ b/rkward/rbackend/rkrbackend_dlopen.cpp
@@ -0,0 +1,35 @@
+/*
+rkrbackend_dlopen - This file is part of RKWard (https://rkward.kde.org). Created: Mon May 06 2024
+SPDX-FileCopyrightText: 2024 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+SPDX-FileContributor: The RKWard Team <rkward-devel at kde.org>
+SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+void *resolve_symb(void* dllinfo, const char* name) {
+#if defined(Q_OS_WIN)
+ retrun GetProcAddress(dllinfo, name);
+#else
+ return dlsym(dllinfo, name);
+#endif
+}
+
+int main(int argc, char *argv[]) {
+// TODO: Debugging!
+// TODO: Take lib name from CMake?
+#ifdef Q_OS_WIN
+ auto r_dllinfo = LoadLibraryA("R.dll");
+ auto rkb_dllinfo = LoadLibraryA("rkward.rbackend.lib.dll");
+#else
+ auto r_dllinfo = dlopen("libR.so", RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
+ auto rkb_dllinfo = dlopen("librkward.rbackend.lib.so", RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
+#endif
+ int (*do_main) (int, char**, void*, void* (*)(void*, const char*));
+ do_main = (decltype(do_main)) resolve_symb(rkb_dllinfo, "do_main");
+ return do_main(argc, argv, r_dllinfo, resolve_symb);
+}
diff --git a/rkward/rbackend/rkrbackendprotocol_backend.cpp b/rkward/rbackend/rkrbackendprotocol_backend.cpp
index 8f4a7d721..6f8dfebb8 100644
--- a/rkward/rbackend/rkrbackendprotocol_backend.cpp
+++ b/rkward/rbackend/rkrbackendprotocol_backend.cpp
@@ -58,7 +58,17 @@ SPDX-License-Identifier: GPL-2.0-or-later
RKDebugMessageOutput (QtDebugMsg, QMessageLogContext (), buffer);
}
+#ifdef RK_DLOPEN_LIBRSO
+ extern "C"
+# ifdef Q_OS_WIN
+ __declspec(dllexport)
+# else
+ __attribute__((__visibility__("default")))
+#endif
+ int do_main(int argc, char *argv[], void* libr_dll_handle, void* (*dlsym_fun)(void*, const char*)) {
+#else
int main(int argc, char *argv[]) {
+#endif
#ifdef Q_OS_MACOS
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
@@ -112,12 +122,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
// TODO: Should rather take the libname from CMake
// maybe we also want to accept an absolute path specified on command line from the frontend
-#ifdef Q_OS_WIN
-# define RLIBNAME "R.dll"
-#else
-# define RLIBNAME "libR.so"
+#ifdef RK_DLOPEN_LIBRSO
+ RFn::init(libr_dll_handle, dlsym_fun);
#endif
- RFn::init(RLIBNAME);
RKRBackendTransmitter transmitter (servername, token);
RKRBackendProtocolBackend::p_transmitter = &transmitter;
@@ -127,6 +134,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
// NOTE:: Since some unknown version of R (4.3.0 at the latest, but probably much earlier), run_Rmainloop() does not return, it will
// eventually exit, instead.
RKRBackendProtocolBackend::doExit();
+ return 0;
}
void RKRBackendProtocolBackend::doExit() {
diff --git a/rkward/rbackend/rkrbackendprotocol_backend.h b/rkward/rbackend/rkrbackendprotocol_backend.h
index 8ff354738..076ac6871 100644
--- a/rkward/rbackend/rkrbackendprotocol_backend.h
+++ b/rkward/rbackend/rkrbackendprotocol_backend.h
@@ -13,6 +13,14 @@ SPDX-License-Identifier: GPL-2.0-or-later
class QThread;
class RKRBackendTransmitter;
+extern "C"
+#ifdef Q_OS_WIN
+ __declspec(dllexport)
+#else
+ __attribute__((__visibility__("default")))
+#endif
+int do_main(int, char**, void*, void* (*)(void*, const char*));
+
class RKRBackendProtocolBackend {
public:
static bool inRThread ();
@@ -29,6 +37,7 @@ friend class RKRBackend;
friend class RKRBackendThread;
friend class RKRBackendTransmitter;
friend int main(int, char**);
+friend int do_main(int, char**, void*, void* (*)(void*, const char*));
void sendRequest (RBackendRequest *request);
static void msleep (int delay);
static RKRBackendProtocolBackend* instance () { return _instance; };
diff --git a/rkward/rbackend/rkwarddevice/CMakeLists.txt b/rkward/rbackend/rkwarddevice/CMakeLists.txt
index 90687e278..08d57b12a 100644
--- a/rkward/rbackend/rkwarddevice/CMakeLists.txt
+++ b/rkward/rbackend/rkwarddevice/CMakeLists.txt
@@ -24,4 +24,5 @@ ADD_LIBRARY(rkgraphicsdevice.backend STATIC ${rkgraphicsdevice_backend_SRCS})
TARGET_LINK_LIBRARIES(rkgraphicsdevice.backend Qt6::Core Qt6::Network)
IF(${DLOPEN_RLIB})
TARGET_COMPILE_DEFINITIONS(rkgraphicsdevice.backend PUBLIC RK_DLOPEN_LIBRSO)
+TARGET_COMPILE_OPTIONS(rkgraphicsdevice.backend PUBLIC -fPIC)
ENDIF()
More information about the rkward-tracker
mailing list