[rkward-cvs] SF.net SVN: rkward-code:[4802] trunk/rkward/rkward

tfry at users.sf.net tfry at users.sf.net
Fri Sep 5 09:38:21 UTC 2014


Revision: 4802
          http://sourceforge.net/p/rkward/code/4802
Author:   tfry
Date:     2014-09-05 09:38:20 +0000 (Fri, 05 Sep 2014)
Log Message:
-----------
Bugfixing, cleanups, and some missing bits for r4801.

Revision Links:
--------------
    http://sourceforge.net/p/rkward/code/4801

Modified Paths:
--------------
    trunk/rkward/rkward/CMakeLists.txt

Added Paths:
-----------
    trunk/rkward/rkward/rkward_startup_wrapper.cpp
    trunk/rkward/rkward/rkward_windows_icon.rc

Removed Paths:
-------------
    trunk/rkward/rkward/rkward.bat.in
    trunk/rkward/rkward/rkward.sh.in
    trunk/rkward/rkward/wrapper/

Modified: trunk/rkward/rkward/CMakeLists.txt
===================================================================
--- trunk/rkward/rkward/CMakeLists.txt	2014-09-05 08:39:35 UTC (rev 4801)
+++ trunk/rkward/rkward/CMakeLists.txt	2014-09-05 09:38:20 UTC (rev 4802)
@@ -9,16 +9,6 @@
 	SET(CPACK_BUNDLE_ICON rkward.icns)
 	SET(CPACK_BUNDLE_NAME RKWard)
 	SET(CPACK_BUNDLE_STARTUP_COMMAND rkward)
-	SET(APPEND_LOCAL_PATH "# ensure that PATH is set to include what we deliver with the bundle
-if ! [ $(echo $PATH | grep ${CMAKE_INSTALL_PREFIX}) ] ; then
-  export PATH=\"${CMAKE_INSTALL_PREFIX}/bin\":\"${CMAKE_INSTALL_PREFIX}/sbin\":$PATH
-fi")
-	IF(DEFINED R_LIBDIR)
-		SET(APPEND_LOCAL_RLIBS "# ensure that RKWard finds its own packages
-export R_LIBS=\"${R_LIBDIR}\"")
-	ENDIF(R_LIBDIR)
-	SET(KDE_START_DBUS "launchctl load -w \"${CMAKE_INSTALL_PREFIX}/Library/LaunchAgents/org.freedesktop.dbus-session.plist\"")
-#	SET(CPACK_BUNDLE_PLIST ${CMAKE_SOURCE_DIR}/rkward/Info.plist)
 ELSE(Q_WS_MAC)
 	SET(RKWARD_FRONTEND_LOCATION ${LIBEXEC_INSTALL_DIR})
 ENDIF(Q_WS_MAC)
@@ -83,8 +73,13 @@
 ADD_CUSTOM_COMMAND (OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/rkward.ico"
 			COMMAND cmake -E copy "${CMAKE_CURRENT_SOURCE_DIR}/icons/app-icon/rkward.ico"
 			"${CMAKE_CURRENT_BINARY_DIR}/rkward.ico")
-ADD_EXECUTABLE (rkward wrapper/rkward_startup_wrapper.cpp wrapper/rkward_windows_icon.rc rkward.ico)
+ADD_EXECUTABLE (rkward rkward_startup_wrapper.cpp rkward_windows_icon.rc rkward.ico)
+# NOTE: These definitions are needed for the wrapper, only.
+# We should switch with to target_compile_definitions once we require CMAKE 2.6+
 add_definitions ("-DR_EXECUTABLE=\\\"${R_EXECUTABLE}\\\"")
+add_definitions ("-DINSTALL_PATH=\\\"${CMAKE_INSTALL_PREFIX}\\\"")
+add_definitions ("-DR_LIBS=\\\"${R_LIBDIR}\\\"")
+add_definitions ("-DRKWARD_FRONTEND_LOCATION=\\\"${RKWARD_FRONTEND_LOCATION}\\\"")
 TARGET_LINK_LIBRARIES(rkward ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY})
 
 ADD_DEPENDENCIES(rkward.frontend rkward)

Deleted: trunk/rkward/rkward/rkward.bat.in
===================================================================
--- trunk/rkward/rkward/rkward.bat.in	2014-09-05 08:39:35 UTC (rev 4801)
+++ trunk/rkward/rkward/rkward.bat.in	2014-09-05 09:38:20 UTC (rev 4802)
@@ -1,30 +0,0 @@
- at ECHO off
-REM Wrapper script to start RKWard.
-REM If the *first* parameter is "--debugger", run through the specified debugger
-
-REM ATTENTION: The SET R_BINARY=... line should remain on line number 10 of this script.
-REM This is where the NSIS installer assumes to find it.
-
-
-
-SET R_BINARY=@R_EXECUTABLE@
-
-
-REM Explicit initialization of KDE, in case Windows 7 asks for admin priviledges
-ECHO Initializing KDE
-%~dsp0\kdeinit4.exe
-
-ECHO Starting RKWard
-SET RKWARD.BIN=%~dsp0\rkward.frontend.exe
-SET RKWARD_ENSURE_PREFIX=%~dsp0\..
-SET PATH=%~dsp0;%PATH%
-SET DEBUGGER=
-
-IF NOT "%1" == "--debugger" GOTO run
-REM else:
-SHIFT
-SET DEBUGGER=%~s1
-SHIFT
-
-:run
-CALL "%R_BINARY%" CMD start %DEBUGGER% %RKWARD.BIN% %1 %2 %3 %4 %5 %6 %7 %8 %9

Deleted: trunk/rkward/rkward/rkward.sh.in
===================================================================
--- trunk/rkward/rkward/rkward.sh.in	2014-09-05 08:39:35 UTC (rev 4801)
+++ trunk/rkward/rkward/rkward.sh.in	2014-09-05 09:38:20 UTC (rev 4802)
@@ -1,58 +0,0 @@
-#!/bin/sh
-# Shell wrapper for rkward executable.
-error () {
-  echo "ERROR: $*" >&2
-  exit 1
-}
-
-export R_binary="@R_EXECUTABLE@"
-
-## Location of R may have moved, so check
-if test -x "${R_binary}"; then
-  :
-else
-  error "R binary ('${R_binary}') not found. Most likely your installation of R has moved to a new location. Please rebuild rkward."
-fi
-
-## Apparently on some systems an embedded R gets outsmarted somehow, and LC_NUMERIC is set to some dangerous value for the whole app (via SCIM)
-## To prevent this, set it here, explicitely. R does not work with wrong settings of LC_NUMERIC.
-
-## First, however, need to unset LC_ALL, if set. Instead we set LANG, so the default will be the same, where not overridden
-if [ -z "$LC_ALL" ]; then
-  :
-else
-  export LANG="$LC_ALL"
-  unset LC_ALL
-  echo "Warning: unsetting LC_ALL"
-fi
-
-# handle --debugger argument (if any)
-# the loop partially copied from the R wrapper script
-debugger=
-if [ "${1}" = "--debugger" ]; then
-  shift
-  if [ -z "${1}" ]; then
-    error  "option '--debugger' requires an argument"
-  else
-    debugger=${1}
-    shift
-  fi
-fi
-
-## set LC_NUMERIC to "C"
-export LC_NUMERIC="C"
-
- at APPEND_LOCAL_PATH@
- at APPEND_LOCAL_RLIBS@
- at KDE_START_DBUS@
-
-## Start rkward. Running through R CMD to set all the relevant R enviroment variables
-if test -x "`dirname $0`/rkward.frontend" ; then
-  # for running directly from a build directory. Don't use this, unless you are a developer!
-  rkward_binary="`dirname $0`/rkward.frontend"
-else
-  # for regular installations
-  export RKWARD_ENSURE_PREFIX="`dirname $0`/.."
-  rkward_binary="@RKWARD_FRONTEND_LOCATION@/rkward.frontend"
-fi
-exec $R_binary CMD $debugger ${rkward_binary} "$@"

Copied: trunk/rkward/rkward/rkward_startup_wrapper.cpp (from rev 4801, trunk/rkward/rkward/wrapper/rkward_startup_wrapper.cpp)
===================================================================
--- trunk/rkward/rkward/rkward_startup_wrapper.cpp	                        (rev 0)
+++ trunk/rkward/rkward/rkward_startup_wrapper.cpp	2014-09-05 09:38:20 UTC (rev 4802)
@@ -0,0 +1,267 @@
+/***************************************************************************
+                          rkward_startup_wrapper  -  description
+                             -------------------
+    begin                : Sun Mar 10 2013
+    copyright            : (C) 2013, 2014 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+/** This simple helper executable is responsible for reading basic configuration
+ * settings, checking for some services and starting RKWard. These things used
+ * to be done using a script, and there was nothing wrong with that, in principle.
+ * However, the binary allows more flexibility, and more consistency across
+ * platforms. */
+
+#include <QApplication>
+#include <QMessageBox>
+#include <QDir>
+#include <QProcess>
+#include <QSettings>
+#include <QUrl>
+#include <QFile>
+
+#ifndef RKWARD_FRONTEND_LOCATION
+#	define RKWARD_FRONTEND_LOCATION ""
+#endif
+
+#ifndef R_EXECUTABLE
+#	define R_EXECUTABLE ""
+#endif
+
+QString findExeAtPath (const QString appname, const QString &path) {
+	QDir dir (path);
+	dir.makeAbsolute ();
+	if (QFileInfo (dir.filePath (appname)).isExecutable ()) return dir.filePath (appname);
+	if (QFileInfo (dir.filePath (appname + ".exe")).isExecutable ()) return dir.filePath (appname + ".exe");
+	if (QFileInfo (dir.filePath (appname + ".com")).isExecutable ()) return dir.filePath (appname + ".com");
+	if (QFileInfo (dir.filePath (appname + ".bat")).isExecutable ()) return dir.filePath (appname + ".bat");
+	return QString ();
+}
+
+QString findRKWardAtPath (const QString &path) {
+	return findExeAtPath ("rkward.frontend", path);
+}
+
+QString quoteCommand (const QString &orig) {
+#ifdef Q_WS_WIN
+	QString ret = "\"";
+	for (int i = 0; i < orig.size (); ++i) {
+		if (orig[i] == QLatin1Char ('"')) ret.append ("\"\"");
+		else if (orig[i] == QLatin1Char ('\\')) ret.append ("\\\\");
+		else ret.append (orig[i]);
+	}
+	ret.append (QLatin1Char ('"'));
+	return ret;
+#else
+	return orig;
+#endif
+}
+
+#ifndef Q_WS_WIN
+// see http://blog.qt.digia.com/blog/2006/03/16/starting-interactive-processes-with-qprocess/
+// Need an interactive process e.g. for running through gdb
+#	include <unistd.h>
+class InteractiveProcess : public QProcess {
+    static int stdinClone;
+public:
+    InteractiveProcess (QObject *parent = 0) : QProcess (parent) {
+        if (stdinClone == -1) stdinClone = ::dup (fileno(stdin));
+    }
+protected:
+    void setupChildProcess () {
+        ::dup2 (stdinClone, fileno(stdin));
+    }
+};
+int InteractiveProcess::stdinClone = -1;
+#else
+// no easy solution for Windows. But ain't Windows the world of graphical debuggers, anyway...
+#	define InteractiveProcess QProcess
+#endif
+
+int main (int argc, char *argv[]) {
+	QApplication app (argc, argv);
+	QStringList args = app.arguments ();
+	if (!args.isEmpty ()) args.pop_front ();	// The command itself
+
+	// Parse arguments that need handling in the wrapper
+	bool usage = false;
+	QString debugger_arg;
+	QString r_exe_arg;
+	int debug_level = 2;
+
+	for (int i=0; i < args.size (); ++i) {
+		if (args[i] == "--debugger") {
+			if ((i+1) < args.size ()) {
+				debugger_arg = args.takeAt (i + 1);
+			} else usage = true;
+			args.removeAt (i);
+			--i;
+		} else if (args[i] == "--r-executable") {
+			if ((i+1) < args.size ()) {
+				r_exe_arg = args.takeAt (i + 1);
+			} else usage = true;
+			args.removeAt (i);
+			--i;
+		} else if (args[i] == "--debug-level") {
+			if ((i+1) < args.size ()) {
+				debug_level = args[i+1].toInt ();
+			}
+		}
+	}
+
+	// Locate KDE and RKWard installations
+	QString kdeinit4_exe;
+	QString rkward_frontend_exe;
+	rkward_frontend_exe = findRKWardAtPath (app.applicationDirPath ());	// this is for running directly from a build tree
+	if (rkward_frontend_exe.isNull ()) {	// this is for the regular case: startup wrapper is not in the same dir as rkward.frontend
+		QString kde4_config_exe;
+		kde4_config_exe = findExeAtPath ("kde4-config", QDir::currentPath ());
+		if (kde4_config_exe.isNull ()) kde4_config_exe = findExeAtPath ("kde4-config", app.applicationDirPath ());
+		if (kde4_config_exe.isNull ()) kde4_config_exe = findExeAtPath ("kde4-config", QDir (app.applicationDirPath ()).filePath ("KDE/bin"));
+		if (kde4_config_exe.isNull ()) {
+#ifdef Q_WS_WIN
+			QStringList syspath = QString (qgetenv ("PATH")).split (";");
+#else
+			QStringList syspath = QString (qgetenv ("PATH")).split (":");
+#endif
+			for (int i = 0; i < syspath.size (); ++i) {
+				kde4_config_exe = findExeAtPath ("kde4-config", syspath[i]);
+				if (!kde4_config_exe.isNull ()) break;
+			}
+		}
+
+		if (kde4_config_exe.isNull ()) {
+			QMessageBox::critical (0, "Could not find KDE installation", "The KDE installation could not be found (kde4-config). When moving / copying RKWard, make sure to copy the whole application folder, or create a shorcut / link, instead.");
+			exit (1);
+		}
+
+		QDir kde_dir (QFileInfo (kde4_config_exe).absolutePath ());
+		kde_dir.makeAbsolute ();
+#ifdef Q_WS_WIN
+		kdeinit4_exe = findExeAtPath ("kdeinit4", kde_dir.path ());
+		qputenv ("PATH", QString (kde_dir.path () + ";" + qgetenv ("PATH")).toLocal8Bit ());
+		if (debug_level > 3) qDebug ("Adding %s to the system path", qPrintable (kde_dir.path ()));
+#endif
+		// important if RKWard is not in KDEPREFIX/bin but e.g. KDEPREFIX/lib/libexec
+		qputenv ("RKWARD_ENSURE_PREFIX", kde_dir.path().toLocal8Bit ());
+		if (debug_level > 3) qDebug ("Setting environment variable RKWARD_ENSURE_PREFIX=%s", qPrintable (kde_dir.path ()));
+qDebug ("%s", RKWARD_FRONTEND_LOCATION);
+		rkward_frontend_exe = findRKWardAtPath (RKWARD_FRONTEND_LOCATION);
+		if (rkward_frontend_exe.isNull ()) rkward_frontend_exe = findRKWardAtPath (kde_dir.absoluteFilePath ("bin"));
+		if (rkward_frontend_exe.isNull ()) rkward_frontend_exe = findRKWardAtPath (kde_dir.absoluteFilePath ("../lib/libexec"));
+
+		if (rkward_frontend_exe.isNull ()) {
+			QMessageBox::critical (0, "RKWard frontend binary missing", "RKWard frontend binary could not be found. When moving / copying RKWard, make sure to copy the whole application folder, or create a shorcut / link, instead.");
+			exit (1);
+		}
+	}
+
+	if (usage) {
+		QProcess::execute (rkward_frontend_exe, QStringList ("--help"));
+		exit (1);
+	}
+
+#ifdef Q_WS_WIN
+	// Explicit initialization of KDE, in case Windows 7 asks for admin priviledges
+	if (kdeinit4_exe.isNull ()) {
+		kdeinit4_exe = findExeAtPath ("kdeinit4", QFileInfo (rkward_frontend_exe).absolutePath ());
+	}
+	if (!kdeinit4_exe.isNull ()) QProcess::execute (kdeinit4_exe, QStringList ());
+#else
+// Apparently on some systems an embedded R gets outsmarted somehow, and LC_NUMERIC is set to some dangerous value for the whole app (via SCIM)
+// To prevent this, set it here, explicitely. R does not work with wrong settings of LC_NUMERIC.
+
+// First, however, need to unset LC_ALL, if set. Instead we set LANG, so the default will be the same, where not overridden
+	QString lcall = qgetenv ("LC_ALL");
+	if (!lcall.isEmpty ()) {
+		qputenv ("LANG", lcall.toLocal8Bit ());
+		qputenv ("LC_ALL", "");
+		qDebug ("Warning: Unsetting LC_ALL");
+	}
+
+	qputenv ("LC_NUMERIC", "C");
+#endif
+
+#ifdef Q_WS_MAC
+	QString oldpath = qgetenv ("PATH");
+	if (!oldpath.contains (INSTALL_PATH)) {
+		//ensure that PATH is set to include what we deliver with the bundle
+		qputenv ("PATH", QString ("\"%1/bin\":\"%1/sbin\":%2").arg (INSTALL_PATH).arg (oldpath).toLocal8Bit ());
+	}
+	// ensure that RKWard finds its own packages
+	qputenv ("R_LIBS"=R_LIBS);
+	QProcess::execute ("lanuchctl", QStringList () << "load" << "-w" << "\"" INSTALL_PATH "/Library/LaunchAgents/org.freedesktop.dbus-session.plist\"");
+#endif
+
+	// Look for R:
+	//- command line parameter
+	//- Specified in cfg file next to rkward executable
+	//- compile-time default
+	QString r_exe = r_exe_arg;
+	if (!r_exe.isNull ()) {
+		if (!QFileInfo (r_exe).isExecutable ()) {
+			QMessageBox::critical (0, "Specified R executable does not exist", QString ("The R executable specified on the command line (%1) does not exist or is not executable.").arg (r_exe));
+			exit (1);
+		}
+		if (debug_level > 3) qDebug ("Using R specified on command line");
+	} else {
+		QFileInfo frontend_info (rkward_frontend_exe);
+		QDir frontend_path = frontend_info.absoluteDir ();
+		QFileInfo rkward_ini_file (frontend_path.absoluteFilePath ("rkward.ini"));
+		if (rkward_ini_file.isReadable ()) {
+			QSettings rkward_ini (rkward_ini_file.absoluteFilePath (), QSettings::IniFormat);
+			r_exe = rkward_ini.value ("R executable").toString ();
+			if (!r_exe.isNull ()) {
+				if (QDir::isRelativePath (r_exe)) {
+					r_exe = frontend_path.absoluteFilePath (r_exe);
+				}
+				if (!QFileInfo (r_exe).isExecutable ()) {
+					QMessageBox::critical (0, "Specified R executable does not exist", QString ("The R executable specified in the rkward.ini file (%1) does not exist or is not executable.").arg (rkward_ini_file.absoluteFilePath ()));
+					exit (1);
+				}
+			}
+			if (debug_level > 3) qDebug ("Using R as configured in config file %s", qPrintable (rkward_ini_file.absoluteFilePath ()));
+		}
+		if (r_exe.isNull ()) {
+			r_exe = R_EXECUTABLE;
+			if (!QFileInfo (r_exe).isExecutable ()) {
+				QMessageBox::critical (0, "Specified R executable does not exist", QString ("The R executable specified at compile time (%1) does not exist or is not executable. Probably the installation of R has moved. You can use the command line parameter '--R', or supply an rkward.ini file to specify the new location.").arg (r_exe));
+				exit (1);
+			}
+			if (debug_level > 3) qDebug ("Using R as configured at compile time");
+		}
+	}
+
+	qputenv ("R_BINARY", r_exe.toLocal8Bit ());
+	QStringList call_args ("CMD");
+	if (!debugger_arg.isNull ()) call_args.append (debugger_arg.split (" "));
+	call_args.append (quoteCommand (rkward_frontend_exe));
+
+	if (!args.isEmpty ()) {
+		// NOTE: QProcess quotes its arguments, *but* properly passing all spaces and quotes through the R CMD wrapper, seems near(?) impossible on Windows. Instead, we use percent encoding, internally.
+		for (int i = 0; i < args.size (); ++i) {
+			call_args.append (QString::fromUtf8 (QUrl::toPercentEncoding (args[i], QByteArray (), " \"")));
+		}
+	}
+
+	if (debug_level > 2) qDebug ("Starting frontend: %s %s", qPrintable (r_exe), qPrintable (call_args.join (" ")));
+
+	InteractiveProcess proc;
+	proc.setProcessChannelMode (QProcess::ForwardedChannels);
+	proc.start (quoteCommand (r_exe), call_args);
+	bool ok = proc.waitForFinished (-1);
+	if (proc.exitCode () || !ok) {
+		QMessageBox::critical (0, "Error starting RKWard", QString ("Starting RKWard failed with error \"%1\"").arg (proc.errorString ()));
+	}
+
+	return (0);
+}

Copied: trunk/rkward/rkward/rkward_windows_icon.rc (from rev 4790, trunk/rkward/rkward/wrapper/rkward_windows_icon.rc)
===================================================================
--- trunk/rkward/rkward/rkward_windows_icon.rc	                        (rev 0)
+++ trunk/rkward/rkward/rkward_windows_icon.rc	2014-09-05 09:38:20 UTC (rev 4802)
@@ -0,0 +1,2 @@
+DI_ICON1               ICON    DISCARDABLE     "rkward.ico"
+





More information about the rkward-tracker mailing list