Commit 8ecd26dc authored by Thomas Friedrichsmeier's avatar Thomas Friedrichsmeier
Browse files

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.
parent e7234ed1
......@@ -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>
......
[Project]
CreatedFrom=CMakeLists.txt
Manager=KDevCMakeManager
Name=rkward
......@@ -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 : thomas.friedrichsmeier@kdemail.net
***************************************************************************/
......@@ -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
......
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)
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)
......@@ -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);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment