Git commit 8ecd26dcf2f42b748fcf2ca8259a8588e624e4d0 by Thomas Friedrichsmeier.
Committed on 30/12/2019 at 13:40.
Pushed by tfry into branch 'master'.

Somewhat experimental: Auto-lazy-install RKWard R package

This is so we can support switching to a different (compatible) R installation 
without re-installation of RKWard.
Needed on Mac, will be nice to have everywere.

Needs testing.

M  +1    -1    doc/rkward/man-rkward.1.docbook
M  +1    -0    rkward.kdev4
M  +18   -3    rkward/rbackend/rkrbackend.cpp
M  +12   -6    rkward/rbackend/rpackages/CMakeLists.txt
D  +0    -36   rkward/rbackend/rpackages/rpackage_install.cmake.in
M  +21   -1    rkward/rkward.cpp

https://commits.kde.org/rkward/8ecd26dcf2f42b748fcf2ca8259a8588e624e4d0

diff --git a/doc/rkward/man-rkward.1.docbook b/doc/rkward/man-rkward.1.docbook
index 8ff350ed..2b411c4a 100644
--- a/doc/rkward/man-rkward.1.docbook
+++ b/doc/rkward/man-rkward.1.docbook
@@ -80,7 +80,7 @@
 </varlistentry>
 <varlistentry>
 <term><option>--r-executable</option> <replaceable>command</replaceable></term>
-<listitem><para>In the case of several R installations, specify the 
installation to use, &eg; <filename>/usr/bin/R</filename>. Note that the 
&rkward; R library must have been installed to this installation of R, or 
startup will fail.</para></listitem>
+<listitem><para>In the case of several R installations, specify the 
installation to use, &eg; <filename>/usr/bin/R</filename>. You can also use the 
string <replaceable>"auto"</replaceable>, in  which case RKWard will try to 
find R at one of the known standard installation paths. 
<emphasis>NOTE</emphasis> that while RKWard will <emphasis>often</emphasis> 
work with newer versions of R, it will <emphasis>sometimes</emphasis> need to 
be re-compiled for that version, or it may be incompatible 
altogether.</para></listitem>
 </varlistentry>
 <varlistentry>
 <term><option>--reuse</option></term>
diff --git a/rkward.kdev4 b/rkward.kdev4
index e9cfb7f4..a2b625a0 100644
--- a/rkward.kdev4
+++ b/rkward.kdev4
@@ -1,3 +1,4 @@
 [Project]
+CreatedFrom=CMakeLists.txt
 Manager=KDevCMakeManager
 Name=rkward
diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index d255a9b6..a96439e7 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -2,7 +2,7 @@
                           rkrbackend  -  description
                              -------------------
     begin                : Sun Jul 25 2004
-    copyright            : (C) 2004 - 2013 by Thomas Friedrichsmeier
+    copyright            : (C) 2004 - 2019 by Thomas Friedrichsmeier
     email                : [email protected]
  ***************************************************************************/
 
@@ -1646,9 +1646,24 @@ void RKRBackend::initialize (const char *locale_dir) {
 
        bool lib_load_fail = false;
        bool sink_fail = false;
-       if (!runDirectCommand ("library (\"rkward\")\n")) lib_load_fail = true;
+       // Try to load rkward package. If that fails, or is the wrong version, 
try to install
+       // rkward package, then load again.
+       QString libloc = RKRBackendProtocolBackend::dataDir () + 
"/.rkward_packages/" + QString::number (r_version / 10);
+       QString versioncheck = QString 
("stopifnot(.rk.app.version==\"%1\")\n").arg (RKWARD_VERSION);
+       QString command = "local({\n"
+                         "  libloc <- " + RKRSharedFunctionality::quote 
(libloc) + "\n"
+                         "  if (!dir.exists (libloc)) dir.create(libloc, 
recursive=TRUE)\n"
+                         "  ok <- FALSE\n"
+                         "  suppressWarnings (try ({library (\"rkward\", 
lib.loc=libloc); " + versioncheck + "; ok <- TRUE}))\n"
+                                         "  if (!ok) {\n"
+                                         "    suppressWarnings (try 
(detach(\"package:rkward\")))\n"
+                                         "    
install.packages(normalizePath(paste(libloc, \"..\", c (\"rkward.tgz\", 
\"rkwardtests.tgz\"), sep=\"/\")), lib=libloc, repos=NULL)\n"
+                                         "    library (\"rkward\",  
lib.loc=libloc)\n"
+                                         "  }\n"
+                                         "})\n";
+       if (!runDirectCommand (command)) lib_load_fail = true;
        RK_setupGettext (locale_dir);   // must happen *after* package loading, 
since R will re-set it
-       if (!runDirectCommand (QString 
("stopifnot(.rk.app.version==\"%1\")\n").arg (RKWARD_VERSION))) lib_load_fail = 
true;
+       if (!runDirectCommand (versioncheck)) lib_load_fail = true;
        if (!runDirectCommand (".rk.fix.assignments ()\n")) sink_fail = true;
 
 // error/output sink and help browser
diff --git a/rkward/rbackend/rpackages/CMakeLists.txt 
b/rkward/rbackend/rpackages/CMakeLists.txt
index a503965f..0a6bd309 100644
--- a/rkward/rbackend/rpackages/CMakeLists.txt
+++ b/rkward/rbackend/rpackages/CMakeLists.txt
@@ -1,8 +1,14 @@
-INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}   
 )
+MACRO(createRpackage name)
+       FILE(GLOB_RECURSE rkwardfiles${name} LIST_DIRECTORIES true 
CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*")
+       MESSAGE(STATUS ${rkwardfiles${name}})
+       ADD_CUSTOM_COMMAND(OUTPUT ${name}.tgz
+               COMMAND ${CMAKE_COMMAND} -E tar "cfz" 
"${CMAKE_CURRENT_BINARY_DIR}/${name}.tgz" "${name}"
+               WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+               DEPENDS ${rkwardfiles${name}})
+ENDMACRO()
 
-CONFIGURE_FILE(
-       "${CMAKE_CURRENT_SOURCE_DIR}/rpackage_install.cmake.in"
-       "${CMAKE_CURRENT_BINARY_DIR}/rpackage_install.cmake"
-       @ONLY)
+createRpackage(rkward)
+createRpackage(rkwardtests)
+ADD_CUSTOM_TARGET(rpackages ALL DEPENDS rkward.tgz rkwardtests.tgz)
 
-INSTALL(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/rpackage_install.cmake 
-DDESTDIR=${DESTDIR} -DBUILD_TIMESTAMP=${BUILD_TIMESTAMP})
+INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/rkward.tgz" 
"${CMAKE_CURRENT_BINARY_DIR}/rkwardtests.tgz" DESTINATION 
${DATA_INSTALL_DIR}/rkward/rpackages)
diff --git a/rkward/rbackend/rpackages/rpackage_install.cmake.in 
b/rkward/rbackend/rpackages/rpackage_install.cmake.in
deleted file mode 100644
index 476a45de..00000000
--- a/rkward/rbackend/rpackages/rpackage_install.cmake.in
+++ /dev/null
@@ -1,36 +0,0 @@
-SET(DESTDIR $ENV{DESTDIR})
-SET(BUILD_TIMESTAMP "@BUILD_TIMESTAMP@")
-
-MESSAGE(STATUS "Installing R support packages")
-
-IF(NOT ${BUILD_TIMESTAMP} EQUAL "")
-       SET (TIMESTAMPARG "--built-timestamp=${BUILD_TIMESTAMP}")
-ENDIF(NOT ${BUILD_TIMESTAMP} EQUAL "")
-
-IF(WIN32)
-       SET(R_LIBDIR @R_LIBDIR@)
-       IF(DESTDIR)
-               # strip drive letter
-               STRING(REGEX REPLACE "^.:." "" R_LIBDIR ${R_LIBDIR})
-               SET(R_LIBDIR "${DESTDIR}/${R_LIBDIR}")
-               FILE(MAKE_DIRECTORY "${R_LIBDIR}")
-       ENDIF(DESTDIR)
-       EXECUTE_PROCESS(
-               COMMAND @R_EXECUTABLE@ CMD INSTALL ${TIMESTAMPARG} -c -l 
${R_LIBDIR} "@CMAKE_CURRENT_SOURCE_DIR@/rkward" 
"@CMAKE_CURRENT_SOURCE_DIR@/rkwardtests"
-               WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@"
-               RESULT_VARIABLE R_LIB_INSTALL_EXIT_CODE
-       )
-ELSE(WIN32)
-       EXECUTE_PROCESS(
-               COMMAND mkdir -p "@CMAKE_CURRENT_BINARY_DIR@/tmp" 
${DESTDIR}/@R_LIBDIR@
-       )
-       EXECUTE_PROCESS(
-               COMMAND env TMPDIR="@CMAKE_CURRENT_BINARY_DIR@/tmp" 
@R_EXECUTABLE@ CMD INSTALL ${TIMESTAMPARG} -c -l ${DESTDIR}/@R_LIBDIR@ 
"@CMAKE_CURRENT_SOURCE_DIR@/rkward" "@CMAKE_CURRENT_SOURCE_DIR@/rkwardtests"
-               WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@"
-               RESULT_VARIABLE R_LIB_INSTALL_EXIT_CODE
-       )
-ENDIF(WIN32)
-
-IF(R_LIB_INSTALL_EXIT_CODE)
-       MESSAGE (SEND_ERROR "Failed to install R support libraries. Please make 
sure you have the required permissions.")
-ENDIF(R_LIB_INSTALL_EXIT_CODE)
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index bb2f69cd..d32db527 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -360,9 +360,28 @@ void RKWardMainWindow::startR () {
        RK_ASSERT (!RKGlobals::rInterface ());
 
        // make sure our general purpose files directory exists
-       bool ok = QDir ().mkpath (RKSettingsModuleGeneral::filesPath());
+       QString packages_path = RKSettingsModuleGeneral::filesPath() + 
"/.rkward_packages";
+       bool ok = QDir ().mkpath (packages_path);
        RK_ASSERT (ok);
 
+       // Copy RKWard R source packages to general  purpose files directory 
(if still needed).
+       // This may look redundant at first (since the package still needs to 
be installed from the
+       // backend. However, if frontend and backend are on different machines 
(eventually), only  the
+       // filesPath is shared between both.
+       QStringList packages;
+       packages << "rkward.tgz" << "rkwardtests.tgz";
+       for (int i = 0; i < packages.size (); ++i) {
+               QString package = QDir (packages_path).absoluteFilePath 
(packages[i]);
+               if (RKSettingsModuleGeneral::rkwardVersionChanged ()) {
+                       RK_DEBUG(APP, DL_INFO, "RKWard version changed. 
Discarding cached package at %s", qPrintable (package));
+                       QFile::remove (package);
+               }
+               if (!QFileInfo (package).exists()) {
+                       RK_DEBUG(APP, DL_INFO, "Copying rkward R source package 
to %s", qPrintable (package));
+                       RK_ASSERT(QFile::copy 
(RKCommonFunctions::getRKWardDataDir () + "/rpackages/" + packages[i], 
package));
+               }
+       }
+
        RKGlobals::rinter = new RInterface ();
        new RObjectList ();
 
@@ -947,3 +966,4 @@ void RKWardMainWindow::setCaption (const QString &) {
        KParts::MainWindow::setCaption (wcaption);
 }
 
+

Reply via email to