Patchwork gnu: Add phantomjs.

login
register
mail settings
Submitter Jan Nieuwenhuizen
Date Nov. 22, 2016, 10:17 p.m.
Message ID <87twazkvlb.fsf@gnu.org>
Download mbox | patch
Permalink /patch/17715/
State New
Headers show

Comments

Jan Nieuwenhuizen - Nov. 22, 2016, 10:17 p.m.
Hi,

I need phantomjs for a client and finally managed to built it from
source.

I tried to build it with our current qt-5.6/qtwebkit-5.7 but gave up;
apparently phantomjs needs patches to even build with qt-5.5.

While I think it's a waste not to share this patch, I don't intend to
spend much effort on these (I have very little respect, patience or love
for qt), please don't put too much effort in reviewing if this needs
much work.

Greetings,
Jan.
ng0 - Dec. 14, 2016, 3:58 p.m.
Jan Nieuwenhuizen <janneke@gnu.org> writes:

> Hi,
>
> I need phantomjs for a client and finally managed to built it from
> source.
>
> I tried to build it with our current qt-5.6/qtwebkit-5.7 but gave up;
> apparently phantomjs needs patches to even build with qt-5.5.
>
> While I think it's a waste not to share this patch, I don't intend to
> spend much effort on these (I have very little respect, patience or love
> for qt), please don't put too much effort in reviewing if this needs
> much work.
>
> Greetings,
> Jan.
>
> From 25f9e007ee2c7f641e7761d990c61bc142440430 Mon Sep 17 00:00:00 2001
> From: Jan Nieuwenhuizen <janneke@gnu.org>
> Date: Thu, 17 Nov 2016 11:39:00 +0100
> Subject: [PATCH] gnu: Add phantomjs.

I think it will be easier to review when you split it. This is
all somewhat related, but those are 6 new public(?) packages and
one very long patch.
I don't know much about Qt, skipping through this I just saw one
http which could be changed to https, that's all so far.

> * gnu/packages/patches/phantomjs-qt55.patch: New file.
> * gnu/local.mk (dist_patch_DATA): Add it.
> * gnu/packages/qt.scm (qtbase55, qtsvg55, qtxmlpatterns55, qtdeclarative55,
> qtwebkit55, phantomjs): New variable.
> ---
>  gnu/local.mk                              |   1 +
>  gnu/packages/patches/phantomjs-qt55.patch | 277 ++++++++++++++++++++++++++++++
>  gnu/packages/qt.scm                       | 256 +++++++++++++++++++++++++++
>  3 files changed, 534 insertions(+)
>  create mode 100644 gnu/packages/patches/phantomjs-qt55.patch
>
> diff --git a/gnu/local.mk b/gnu/local.mk
> index f780b24..96fde14 100644
> --- a/gnu/local.mk
> +++ b/gnu/local.mk
> @@ -787,6 +787,7 @@ dist_patch_DATA =						\
>    %D%/packages/patches/perl-module-pluggable-search.patch	\
>    %D%/packages/patches/perl-reproducible-build-date.patch	\
>    %D%/packages/patches/perl-www-curl-remove-symbol.patch	\
> +  %D%/packages/patches/phantomjs-qt55.patch			\
>    %D%/packages/patches/pidgin-add-search-path.patch		\
>    %D%/packages/patches/pinball-const-fix.patch			\
>    %D%/packages/patches/pinball-cstddef.patch			\
> diff --git a/gnu/packages/patches/phantomjs-qt55.patch b/gnu/packages/patches/phantomjs-qt55.patch
> new file mode 100644
> index 0000000..2a306f0
> --- /dev/null
> +++ b/gnu/packages/patches/phantomjs-qt55.patch
> @@ -0,0 +1,277 @@
> +Taken from Debian phantomjs/debian/patches/
> +
> +Last-Update: 2016-02-15
> +Forwarded: no
> +Author: Dmitry Smirnov <onlyjob@debian.org>
> +Description: fix FTBFS.
> +
> +--- a/src/phantomjs.pro
> ++++ b/src/phantomjs.pro
> +@@ -8,9 +8,9 @@
> + }
> + 
> + TEMPLATE = app
> + TARGET = phantomjs
> +-QT += network webkitwidgets
> ++QT += network webkitwidgets printsupport
> + CONFIG += console
> + 
> + DESTDIR = ../bin
> + 
> +Last-Update: 2016-02-15
> +Forwarded: no
> +Bug-Upstream: https://github.com/ariya/phantomjs/issues/13727
> +Author: Ximin Luo <infinity0@debian.org>
> +Reviewed-By: Dmitry Smirnov <onlyjob@debian.org>
> +Description: Port to Qt 5.5
> + - Remove second argument to evaluateJavascript(), which was not really used
> +   for anything, anyways
> +
> +--- a/src/utils.cpp
> ++++ b/src/utils.cpp
> +@@ -37,8 +37,9 @@
> + #include <QDateTime>
> + #include <QDir>
> + #include <QtWebKitWidggets/QWebFrame>
> + 
> ++
> + static QString findScript(const QString& jsFilePath, const QString& libraryPath)
> + {
> +     if (!jsFilePath.isEmpty()) {
> +         QFile jsFile;
> +@@ -131,9 +132,9 @@
> +         }
> +         return false;
> +     }
> +     // Execute JS code in the context of the document
> +-    targetFrame->evaluateJavaScript(scriptBody, QString(JAVASCRIPT_SOURCE_CODE_URL).arg(QFileInfo(scriptPath).fileName()));
> ++    targetFrame->evaluateJavaScript(scriptBody);
> +     return true;
> + }
> + 
> + bool loadJSForDebug(const QString& jsFilePath, const QString& libraryPath, QWebFrame* targetFrame, const bool autorun)
> +@@ -146,12 +147,12 @@
> +     QString scriptPath = findScript(jsFilePath, libraryPath);
> +     QString scriptBody = jsFromScriptFile(scriptPath, jsFileLanguage, jsFileEnc);
> + 
> +     scriptBody = QString("function __run() {\n%1\n}").arg(scriptBody);
> +-    targetFrame->evaluateJavaScript(scriptBody, QString(JAVASCRIPT_SOURCE_CODE_URL).arg(QFileInfo(scriptPath).fileName()));
> ++    targetFrame->evaluateJavaScript(scriptBody);
> + 
> +     if (autorun) {
> +-        targetFrame->evaluateJavaScript("__run()", QString());
> ++        targetFrame->evaluateJavaScript("__run()");
> +     }
> + 
> +     return true;
> + }
> +--- a/src/repl.cpp
> ++++ b/src/repl.cpp
> +@@ -146,9 +146,9 @@
> +     // Set the static callback to offer Completions to the User
> +     linenoiseSetCompletionCallback(REPL::offerCompletion);
> + 
> +     // Inject REPL utility functions
> +-    m_webframe->evaluateJavaScript(Utils::readResourceFileUtf8(":/repl.js"), QString(JAVASCRIPT_SOURCE_PLATFORM_URL).arg("repl.js"));
> ++    m_webframe->evaluateJavaScript(Utils::readResourceFileUtf8(":/repl.js"));
> + 
> +     // Add self to JavaScript world
> +     m_webframe->addToJavaScriptWindowObject("_repl", this);
> + 
> +@@ -183,10 +183,9 @@
> +     // This will return an array of String with the possible completions
> +     QStringList completions = REPL::getInstance()->m_webframe->evaluateJavaScript(
> +                                   QString(JS_RETURN_POSSIBLE_COMPLETIONS).arg(
> +                                       toInspect,
> +-                                      toComplete),
> +-                                  QString()
> ++                                      toComplete)
> +                               ).toStringList();
> + 
> +     foreach(QString c, completions) {
> +         if (lastIndexOfDot > -1) {
> +@@ -209,9 +208,9 @@
> +         if (userInput[0] != '\0') {
> +             // Send the user input to the main Phantom frame for evaluation
> +             m_webframe->evaluateJavaScript(
> +                 QString(JS_EVAL_USER_INPUT).arg(
> +-                    QString(userInput).replace('"', "\\\"")), QString("phantomjs://repl-input"));
> ++                    QString(userInput).replace('"', "\\\"")));
> + 
> +             // Save command in the REPL history
> +             linenoiseHistoryAdd(userInput);
> +             linenoiseHistorySave(m_historyFilepath.data()); //< requires "char *"
> +--- a/src/phantom.cpp
> ++++ b/src/phantom.cpp
> +@@ -380,9 +380,9 @@
> +         "require.cache['" + filename + "']._getRequire()," +
> +         "require.cache['" + filename + "'].exports," +
> +         "require.cache['" + filename + "']" +
> +         "));";
> +-    m_page->mainFrame()->evaluateJavaScript(scriptSource, QString(JAVASCRIPT_SOURCE_PLATFORM_URL).arg(QFileInfo(filename).fileName()));
> ++    m_page->mainFrame()->evaluateJavaScript(scriptSource);
> + }
> + 
> + bool Phantom::injectJs(const QString& jsFilePath)
> + {
> +@@ -477,10 +477,9 @@
> +     m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this);
> + 
> +     // Bootstrap the PhantomJS scope
> +     m_page->mainFrame()->evaluateJavaScript(
> +-        Utils::readResourceFileUtf8(":/bootstrap.js"),
> +-        QString(JAVASCRIPT_SOURCE_PLATFORM_URL).arg("bootstrap.js")
> ++        Utils::readResourceFileUtf8(":/bootstrap.js")
> +     );
> + }
> + 
> + bool Phantom::setCookies(const QVariantList& cookies)
> +--- a/src/config.cpp
> ++++ b/src/config.cpp
> +@@ -176,9 +176,9 @@
> +     QWebPage webPage;
> +     // Add this object to the global scope
> +     webPage.mainFrame()->addToJavaScriptWindowObject("config", this);
> +     // Apply the JSON config settings to this very object
> +-    webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig), QString());
> ++    webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig));
> + }
> + 
> + QString Config::helpText() const
> + {
> +--- a/src/webpage.cpp
> ++++ b/src/webpage.cpp
> +@@ -752,10 +752,10 @@
> + 
> +     qDebug() << "WebPage - evaluateJavaScript" << function;
> + 
> +     evalResult = m_currentFrame->evaluateJavaScript(
> +-                     function,                                   //< function evaluated
> +-                     QString("phantomjs://webpage.evaluate()")); //< reference source file
> ++                     function                                   //< function evaluated
> ++                     );
> + 
> +     qDebug() << "WebPage - evaluateJavaScript result" << evalResult;
> + 
> +     return evalResult;
> +@@ -925,9 +925,9 @@
> +         networkOp = QNetworkAccessManager::DeleteOperation;
> +     }
> + 
> +     if (networkOp == QNetworkAccessManager::UnknownOperation) {
> +-        m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');", QString());
> ++        m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');");
> +         return;
> +     }
> + 
> +     if (address == "about:blank") {
> +@@ -1314,9 +1314,9 @@
> +                 return ret.toString();
> +             }
> +         }
> +     }
> +-    frame->evaluateJavaScript("console.error('Bad header callback given, use phantom.callback);", QString());
> ++    frame->evaluateJavaScript("console.error('Bad header callback given, use phantom.callback);");
> +     return QString();
> + }
> + 
> + QString WebPage::header(int page, int numPages)
> +@@ -1353,9 +1353,9 @@
> + }
> + 
> + void WebPage::_appendScriptElement(const QString& scriptUrl)
> + {
> +-    m_currentFrame->evaluateJavaScript(QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl), scriptUrl);
> ++    m_currentFrame->evaluateJavaScript(QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl));
> + }
> + 
> + QObject* WebPage::_getGenericCallback()
> + {
> +Last-Update: 2016-02-15
> +Forwarded: not-needed
> +Bug-Upstream: https://github.com/ariya/phantomjs/issues/13727
> +Author: Ximin Luo <infinity0@debian.org>
> +Reviewed-By: Dmitry Smirnov <onlyjob@debian.org>
> +Description: Port to Qt 5.5
> + - Remove "webSecurity" option since that's not exposed in Qt 5.5
> +
> +--- a/src/consts.h
> ++++ b/src/consts.h
> +@@ -63,9 +63,8 @@
> + #define PAGE_SETTINGS_USERNAME              "userName"
> + #define PAGE_SETTINGS_PASSWORD              "password"
> + #define PAGE_SETTINGS_MAX_AUTH_ATTEMPTS     "maxAuthAttempts"
> + #define PAGE_SETTINGS_RESOURCE_TIMEOUT      "resourceTimeout"
> +-#define PAGE_SETTINGS_WEB_SECURITY_ENABLED  "webSecurityEnabled"
> + #define PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS   "javascriptCanOpenWindows"
> + #define PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS  "javascriptCanCloseWindows"
> + 
> + #define DEFAULT_WEBDRIVER_CONFIG            "127.0.0.1:8910"
> +--- a/src/phantom.cpp
> ++++ b/src/phantom.cpp
> +@@ -135,9 +135,8 @@
> +     m_defaultPageSettings[PAGE_SETTINGS_JS_ENABLED] = QVariant::fromValue(true);
> +     m_defaultPageSettings[PAGE_SETTINGS_XSS_AUDITING] = QVariant::fromValue(false);
> +     m_defaultPageSettings[PAGE_SETTINGS_USER_AGENT] = QVariant::fromValue(m_page->userAgent());
> +     m_defaultPageSettings[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE] = QVariant::fromValue(m_config.localToRemoteUrlAccessEnabled());
> +-    m_defaultPageSettings[PAGE_SETTINGS_WEB_SECURITY_ENABLED] = QVariant::fromValue(m_config.webSecurityEnabled());
> +     m_defaultPageSettings[PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS] = QVariant::fromValue(m_config.javascriptCanOpenWindows());
> +     m_defaultPageSettings[PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS] = QVariant::fromValue(m_config.javascriptCanCloseWindows());
> +     m_page->applySettings(m_defaultPageSettings);
> + 
> +--- a/src/webpage.cpp
> ++++ b/src/webpage.cpp
> +@@ -367,9 +367,8 @@
> +     // attribute "WebSecurityEnabled" must be applied during the initializing
> +     // security context for Document instance. Setting up it later will not cause any effect
> +     // see <qt\src\3rdparty\webkit\Source\WebCore\dom\Document.cpp:4468>
> +     QWebSettings* settings = m_customWebPage->settings();
> +-    settings->setAttribute(QWebSettings::WebSecurityEnabled, phantomCfg->webSecurityEnabled());
> + 
> +     m_mainFrame = m_customWebPage->mainFrame();
> +     m_currentFrame = m_mainFrame;
> +     m_mainFrame->setHtml(BLANK_HTML, baseUrl);
> +@@ -621,9 +620,8 @@
> +     opt->setAttribute(QWebSettings::AutoLoadImages, def[PAGE_SETTINGS_LOAD_IMAGES].toBool());
> +     opt->setAttribute(QWebSettings::JavascriptEnabled, def[PAGE_SETTINGS_JS_ENABLED].toBool());
> +     opt->setAttribute(QWebSettings::XSSAuditingEnabled, def[PAGE_SETTINGS_XSS_AUDITING].toBool());
> +     opt->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, def[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE].toBool());
> +-    opt->setAttribute(QWebSettings::WebSecurityEnabled, def[PAGE_SETTINGS_WEB_SECURITY_ENABLED].toBool());
> +     opt->setAttribute(QWebSettings::JavascriptCanOpenWindows, def[PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS].toBool());
> +     opt->setAttribute(QWebSettings::JavascriptCanCloseWindows, def[PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS].toBool());
> + 
> +     if (def.contains(PAGE_SETTINGS_USER_AGENT)) {
> +Last-Update: 2016-02-15
> +Forwarded: no
> +Bug-Upstream: https://github.com/ariya/phantomjs/issues/13727
> +Author: Ximin Luo <infinity0@debian.org>
> +Reviewed-By: Dmitry Smirnov <onlyjob@debian.org>
> +Description: Port to Qt 5.5
> + - In webpage, don't inherit QWebFrame::PrintCallback since it's not public
> +
> +--- a/src/webpage.cpp
> ++++ b/src/webpage.cpp
> +@@ -1254,9 +1254,9 @@
> +     }
> + 
> +     printer.setPageMargins(marginLeft, marginTop, marginRight, marginBottom, QPrinter::Point);
> + 
> +-    m_mainFrame->print(&printer, this);
> ++    m_mainFrame->print(&printer);
> +     return true;
> + }
> + 
> + void WebPage::setZoomFactor(qreal zoom)
> +--- a/src/webpage.h
> ++++ b/src/webpage.h
> +@@ -44,9 +44,9 @@
> + class NetworkAccessManager;
> + class QWebInspector;
> + class Phantom;
> + 
> +-class WebPage : public QObject, public QWebFrame::PrintCallback
> ++class WebPage : public QObject
> + {
> +     Q_OBJECT
> +     Q_PROPERTY(QString title READ title)
> +     Q_PROPERTY(QString frameTitle READ frameTitle)
> diff --git a/gnu/packages/qt.scm b/gnu/packages/qt.scm
> index b442356..8ce1192 100644
> --- a/gnu/packages/qt.scm
> +++ b/gnu/packages/qt.scm
> @@ -5,6 +5,7 @@
>  ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
>  ;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
>  ;;; Copyright © 2016 Thomas Danckaert <post@thomasdanckaert.be>
> +;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
>  ;;;
>  ;;; This file is part of GNU Guix.
>  ;;;
> @@ -1285,3 +1286,258 @@ embed content from the World Wide Web into your Qt application.  At the same
>  time Web content can be enhanced with native controls.")
>  
>      (license license:lgpl2.1+)))
> +
> +(define-public qtbase55
> +  (package
> +    (inherit qtbase)
> +    (name "qtbase")
> +    (version "5.5.1")
> +    (source (origin
> +              (method url-fetch)
> +              (uri (string-append "https://download.qt.io/official_releases/qt/"
> +                                  (version-major+minor version) "/" version
> +                                  "/submodules/" name "-opensource-src-"
> +                                  version ".tar.xz"))
> +              (sha256
> +               (base32
> +                "05p91m1d9b3gdfm5pgmxw63rk0fdxqz87s77hn9bdip4syjfi96z"))
> +              (modules '((guix build utils)))
> +              (snippet
> +               '(begin
> +                  ;; Remove one of the two bundled harfbuzz copies in addition
> +                  ;; to passing "-system-harfbuzz".
> +                  (delete-file-recursively "src/3rdparty/harfbuzz-ng")
> +                  ;; Remove the bundled sqlite copy in addition to
> +                  ;; passing "-system-sqlite".
> +                  (delete-file-recursively "src/3rdparty/sqlite")))))))
> +
> +(define-public qtsvg55
> +  (package (inherit qtbase55)
> +    (name "qtsvg")
> +    (version "5.5.1")
> +    (source (origin
> +             (method url-fetch)
> +             (uri (string-append "https://download.qt.io/official_releases/qt/"
> +                                 (version-major+minor version) "/" version
> +                                 "/submodules/" name "-opensource-src-"
> +                                 version ".tar.xz"))
> +             (sha256
> +              (base32
> +               "1iwibbh835cpxbfh7rnrpvl9k20valr6h256np59rzdy92z8ixgp"))))
> +    (propagated-inputs `())
> +    (native-inputs `(("perl" ,perl)))
> +    (inputs
> +     `(("mesa" ,mesa)
> +       ("qtbase" ,qtbase55)
> +       ("zlib" ,zlib)))
> +    (arguments
> +     `(#:phases
> +       (modify-phases %standard-phases
> +         (replace 'configure
> +           (lambda* (#:key outputs #:allow-other-keys)
> +             (let ((out (assoc-ref outputs "out")))
> +               (and (zero? (system* "qmake" (string-append "PREFIX=" out)))
> +                    (system* "make" "clean"))))) ; Generate broken Makefiles
> +                                                 ; to be substituted
> +         (add-before 'build 'fix-Makefiles
> +           (lambda* (#:key inputs outputs #:allow-other-keys)
> +             (let ((out (assoc-ref outputs "out"))
> +                   (qtbase (assoc-ref inputs "qtbase")))
> +               (substitute* (find-files "." "Makefile")
> +                 (((string-append "-Wl,-rpath," qtbase "/lib") all)
> +                  (string-append all " -Wl,-rpath," out "/lib "))
> +                 (((string-append "INSTALL_ROOT)" qtbase))
> +                  (string-append "INSTALL_ROOT)" out)))))))))))
> +
> +(define-public qtxmlpatterns55
> +  (package (inherit qtsvg55)
> +    (name "qtxmlpatterns")
> +    (version "5.5.1")
> +    (source (origin
> +             (method url-fetch)
> +             (uri (string-append "https://download.qt.io/official_releases/qt/"
> +                                 (version-major+minor version) "/" version
> +                                 "/submodules/" name "-opensource-src-"
> +                                 version ".tar.xz"))
> +             (sha256
> +              (base32
> +               "1v78s0jygg83yzyldwms8zb72cwp718cc5ialc2ki3lqa81fndxm"))))
> +    (native-inputs `(("perl" ,perl)))
> +    (inputs `(("qtbase" ,qtbase55)))))
> +
> +(define-public qtdeclarative55
> +  (package (inherit qtsvg55)
> +    (name "qtdeclarative")
> +    (version "5.5.1")
> +    (source (origin
> +             (method url-fetch)
> +             (uri (string-append "https://download.qt.io/official_releases/qt/"
> +                                 (version-major+minor version) "/" version
> +                                 "/submodules/" name "-opensource-src-"
> +                                 version ".tar.xz"))
> +             (sha256
> +              (base32
> +               "14b7naaa0rk4q6cxf0w62gvamxk812kr65k82zxkdzrzp3plxlaz"))))
> +    (native-inputs
> +     `(("perl" ,perl)
> +       ("pkg-config" ,pkg-config)
> +       ("python" ,python-2)
> +       ("qtsvg" ,qtsvg55)
> +       ("qtxmlpatterns" ,qtxmlpatterns55)))
> +    (inputs
> +     `(("mesa" ,mesa)
> +       ("qtbase" ,qtbase55)))))
> +
> +(define-public qtwebkit55
> +  (package
> +    (inherit qtwebkit)
> +    (name "qtwebkit")
> +    (version "5.5.1")
> +    (source (origin
> +              (method url-fetch)
> +              (uri (string-append
> +                    "http://download.qt.io/official_releases/qt/"
> +                    (version-major+minor version)
> +                    "/" version
> +                    "/submodules/" name "-opensource-src-"
> +                    version ".tar.xz"))
> +              (sha256
> +               (base32
> +                "0sbdglcf57lmgbcybimvvbpqikn3blb1pxvd71sdhsiypnfkyn3p"))))
> +    (inputs
> +     `(("icu" ,icu4c)
> +       ("libjpeg" ,libjpeg)
> +       ("libpng" ,libpng)
> +       ("libwebp" ,libwebp)
> +       ("sqlite" ,sqlite)
> +       ("fontconfig" ,fontconfig)
> +       ("libxrender", libxrender)
> +       ("qtbase" ,qtbase55)
> +       ("qtdeclarative" ,qtdeclarative55)
> +       ("libxml2" ,libxml2)
> +       ("libxslt" ,libxslt)
> +       ("libx11" ,libx11)
> +       ("libxcomposite" ,libxcomposite)))
> +    (arguments
> +     `(#:phases
> +       (modify-phases %standard-phases
> +         (replace 'configure
> +                  (lambda* (#:key outputs #:allow-other-keys)
> +                    (let ((out (assoc-ref outputs "out")))
> +                      (setenv "QMAKEPATH"
> +                              (string-append (getcwd) "/Tools/qmake:"
> +                                             (getenv "QMAKEPATH")))
> +                      (system* "qmake"))))
> +         ;; prevent webkit from trying to install into the qtbase store directory,
> +         ;; and replace references to the build directory in linker options:
> +         (add-before 'build 'patch-installpaths
> +                     (lambda* (#:key outputs inputs #:allow-other-keys)
> +                       (let* ((out (assoc-ref outputs "out"))
> +                              (qtbase (assoc-ref inputs "qtbase"))
> +                              (builddir (getcwd))
> +                              (linkbuild (string-append "-L" builddir))
> +                              (linkout (string-append "-L" out))
> +                              (makefiles
> +                               (map-in-order
> +                                (lambda (i)
> +                                  (let* ((in (car i))
> +                                         (mf (string-append (dirname in) "/"
> +                                                            (cdr i))))
> +                                    ;; by default, these Makefiles are
> +                                    ;; generated during install, but we need
> +                                    ;; to generate them now
> +                                    (system* "qmake" in "-o" mf)
> +                                    mf))
> +                                '(("Source/api.pri" . "Makefile.api")
> +                                  ("Source/widgetsapi.pri"
> +                                   . "Makefile.widgetsapi")
> +                                  ("Source/WebKit2/WebProcess.pro"
> +                                   . "Makefile.WebProcess")
> +                                  ("Source/WebKit2/PluginProcess.pro"
> +                                   . "Makefile.PluginProcess")
> +                                  ("Source/WebKit/qt/declarative/public.pri"
> +                                   . "Makefile.declarative.public")
> +                                  ("Source/WebKit/qt/declarative/experimental/experimental.pri"
> +                                   . "Makefile.declarative.experimental")
> +                                  ("Source/WebKit/qt/examples/platformplugin/platformplugin.pro"
> +                                   . "Makefile")))))
> +                         ;; Order of qmake calls and substitutions matters here.
> +                         (system* "qmake" "-prl" "Source/widgetsapi.pri"
> +                                  "-o" "Source/Makefile")
> +                         (substitute* (find-files "lib" "libQt5.*\\.prl")
> +                           ((linkbuild) linkout))
> +                         (substitute* (find-files "lib"
> +                                                  "libQt5WebKit.*\\.la")
> +                           (("libdir='.*'")
> +                            (string-append "libdir='" out "/lib'"))
> +                           ((linkbuild) linkout))
> +                         (substitute* (find-files "lib/pkgconfig"
> +                                                  "Qt5WebKit.*\\.pc")
> +                           (((string-append "prefix=" qtbase))
> +                            (string-append "prefix=" out))
> +                           ((linkbuild) linkout))
> +                         ;; Makefiles must be modified after .prl/.la/.pc
> +                         ;; files, lest they get rebuilt:
> +                         (substitute* makefiles
> +                           (((string-append "\\$\\(INSTALL_ROOT\\)" qtbase))
> +                            out )
> +                           (((string-append "-Wl,-rpath," builddir))
> +                            (string-append "-Wl,-rpath," out))
> +                           (((string-append "-Wl,-rpath," qtbase "/lib") all)
> +                            (string-append all " -Wl,-rpath," out "/lib ")))))))))))
> +
> +(define-public phantomjs
> +  (package
> +    (name "phantomjs")
> +    (version "2.1.1")
> +    (source (origin
> +              (method url-fetch)
> +              (uri (string-append
> +                    "https://github.com/ariya/phantomjs/archive/"
> +                    version ".tar.gz"))
> +              (file-name (string-append name "-" version ".tar.gz"))
> +              (patches (search-patches "phantomjs-qt55.patch"))
> +              (sha256
> +               (base32
> +                "1wccz46bhg0kkxr10xs30i1p055fxrac5zqszz4akma8rpln67mx"))))
> +    (native-inputs
> +     `(("python" ,python-2)
> +       ("qmake" ,qtbase55)))
> +    (inputs
> +     `(("qtwebkit" ,qtwebkit55)))
> +    (build-system gnu-build-system)
> +    (arguments
> +     `(#:tests? #f ; no check target
> +       #:phases
> +       (modify-phases %standard-phases
> +         (delete 'configure)
> +         (replace 'build
> +           (lambda* (#:key inputs outputs #:allow-other-keys)
> +             (let* ((out (assoc-ref outputs "out"))
> +                    (qmake (string-append (assoc-ref inputs "qmake")
> +                                           "/bin/qmake"))
> +                    (python (string-append (assoc-ref inputs "python")
> +                                           "/bin/python")))
> +               (substitute* "build.py"
> +                 (("return os.path.abspath[(]\\\"src/qt/qtbase/bin/\\\" [+] exe[)]")
> +                  (string-append "return \"" qmake "\"")))
> +               (zero?
> +                (system* python "build.py"
> +                         "--skip-git"
> +                         "--skip-qtbase"
> +                         "--skip-qtwebkit"
> +                         "--confirm"
> +                         "--release")))))
> +         (replace 'install
> +                  (lambda* (#:key inputs outputs #:allow-other-keys)
> +                    (let* ((out (assoc-ref outputs "out"))
> +                           (bin (string-append out "/bin")))
> +                      (mkdir-p bin)
> +                      (copy-file "bin/phantomjs"
> +                                 (string-append bin "/phantomjs"))))))))
> +    (home-page "https://github.com/ariya/phantomjs")
> +    (synopsis "Headless QT-WebKit with JavaScript")
> +    (description "PhantomJS is a headless QT-based WebKit with JavaScript API.
> +It has ative support for various web standards: DOM handling, CSS selector,
> +JSON, Canvas, and SVG.")
> +    (license license:bsd-3)))
> -- 
> 2.10.2
>
>
> -- 
> Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond http://lilypond.org
> Freelance IT http://JoyofSource.com | Avatar®  http://AvatarAcademy.nl
Jan Nieuwenhuizen - Dec. 14, 2016, 6:14 p.m.
ng0 writes:

> I think it will be easier to review when you split it. This is
> all somewhat related, but those are 6 new public(?) packages and
> one very long patch.

Sure I can do that, I'll prepare a new series.

> I don't know much about Qt, skipping through this I just saw one
> http which could be changed to https, that's all so far.

Okay.
Greetings,
Jan

Patch

From 25f9e007ee2c7f641e7761d990c61bc142440430 Mon Sep 17 00:00:00 2001
From: Jan Nieuwenhuizen <janneke@gnu.org>
Date: Thu, 17 Nov 2016 11:39:00 +0100
Subject: [PATCH] gnu: Add phantomjs.

* gnu/packages/patches/phantomjs-qt55.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/qt.scm (qtbase55, qtsvg55, qtxmlpatterns55, qtdeclarative55,
qtwebkit55, phantomjs): New variable.
---
 gnu/local.mk                              |   1 +
 gnu/packages/patches/phantomjs-qt55.patch | 277 ++++++++++++++++++++++++++++++
 gnu/packages/qt.scm                       | 256 +++++++++++++++++++++++++++
 3 files changed, 534 insertions(+)
 create mode 100644 gnu/packages/patches/phantomjs-qt55.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index f780b24..96fde14 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -787,6 +787,7 @@  dist_patch_DATA =						\
   %D%/packages/patches/perl-module-pluggable-search.patch	\
   %D%/packages/patches/perl-reproducible-build-date.patch	\
   %D%/packages/patches/perl-www-curl-remove-symbol.patch	\
+  %D%/packages/patches/phantomjs-qt55.patch			\
   %D%/packages/patches/pidgin-add-search-path.patch		\
   %D%/packages/patches/pinball-const-fix.patch			\
   %D%/packages/patches/pinball-cstddef.patch			\
diff --git a/gnu/packages/patches/phantomjs-qt55.patch b/gnu/packages/patches/phantomjs-qt55.patch
new file mode 100644
index 0000000..2a306f0
--- /dev/null
+++ b/gnu/packages/patches/phantomjs-qt55.patch
@@ -0,0 +1,277 @@ 
+Taken from Debian phantomjs/debian/patches/
+
+Last-Update: 2016-02-15
+Forwarded: no
+Author: Dmitry Smirnov <onlyjob@debian.org>
+Description: fix FTBFS.
+
+--- a/src/phantomjs.pro
++++ b/src/phantomjs.pro
+@@ -8,9 +8,9 @@
+ }
+ 
+ TEMPLATE = app
+ TARGET = phantomjs
+-QT += network webkitwidgets
++QT += network webkitwidgets printsupport
+ CONFIG += console
+ 
+ DESTDIR = ../bin
+ 
+Last-Update: 2016-02-15
+Forwarded: no
+Bug-Upstream: https://github.com/ariya/phantomjs/issues/13727
+Author: Ximin Luo <infinity0@debian.org>
+Reviewed-By: Dmitry Smirnov <onlyjob@debian.org>
+Description: Port to Qt 5.5
+ - Remove second argument to evaluateJavascript(), which was not really used
+   for anything, anyways
+
+--- a/src/utils.cpp
++++ b/src/utils.cpp
+@@ -37,8 +37,9 @@
+ #include <QDateTime>
+ #include <QDir>
+ #include <QtWebKitWidggets/QWebFrame>
+ 
++
+ static QString findScript(const QString& jsFilePath, const QString& libraryPath)
+ {
+     if (!jsFilePath.isEmpty()) {
+         QFile jsFile;
+@@ -131,9 +132,9 @@
+         }
+         return false;
+     }
+     // Execute JS code in the context of the document
+-    targetFrame->evaluateJavaScript(scriptBody, QString(JAVASCRIPT_SOURCE_CODE_URL).arg(QFileInfo(scriptPath).fileName()));
++    targetFrame->evaluateJavaScript(scriptBody);
+     return true;
+ }
+ 
+ bool loadJSForDebug(const QString& jsFilePath, const QString& libraryPath, QWebFrame* targetFrame, const bool autorun)
+@@ -146,12 +147,12 @@
+     QString scriptPath = findScript(jsFilePath, libraryPath);
+     QString scriptBody = jsFromScriptFile(scriptPath, jsFileLanguage, jsFileEnc);
+ 
+     scriptBody = QString("function __run() {\n%1\n}").arg(scriptBody);
+-    targetFrame->evaluateJavaScript(scriptBody, QString(JAVASCRIPT_SOURCE_CODE_URL).arg(QFileInfo(scriptPath).fileName()));
++    targetFrame->evaluateJavaScript(scriptBody);
+ 
+     if (autorun) {
+-        targetFrame->evaluateJavaScript("__run()", QString());
++        targetFrame->evaluateJavaScript("__run()");
+     }
+ 
+     return true;
+ }
+--- a/src/repl.cpp
++++ b/src/repl.cpp
+@@ -146,9 +146,9 @@
+     // Set the static callback to offer Completions to the User
+     linenoiseSetCompletionCallback(REPL::offerCompletion);
+ 
+     // Inject REPL utility functions
+-    m_webframe->evaluateJavaScript(Utils::readResourceFileUtf8(":/repl.js"), QString(JAVASCRIPT_SOURCE_PLATFORM_URL).arg("repl.js"));
++    m_webframe->evaluateJavaScript(Utils::readResourceFileUtf8(":/repl.js"));
+ 
+     // Add self to JavaScript world
+     m_webframe->addToJavaScriptWindowObject("_repl", this);
+ 
+@@ -183,10 +183,9 @@
+     // This will return an array of String with the possible completions
+     QStringList completions = REPL::getInstance()->m_webframe->evaluateJavaScript(
+                                   QString(JS_RETURN_POSSIBLE_COMPLETIONS).arg(
+                                       toInspect,
+-                                      toComplete),
+-                                  QString()
++                                      toComplete)
+                               ).toStringList();
+ 
+     foreach(QString c, completions) {
+         if (lastIndexOfDot > -1) {
+@@ -209,9 +208,9 @@
+         if (userInput[0] != '\0') {
+             // Send the user input to the main Phantom frame for evaluation
+             m_webframe->evaluateJavaScript(
+                 QString(JS_EVAL_USER_INPUT).arg(
+-                    QString(userInput).replace('"', "\\\"")), QString("phantomjs://repl-input"));
++                    QString(userInput).replace('"', "\\\"")));
+ 
+             // Save command in the REPL history
+             linenoiseHistoryAdd(userInput);
+             linenoiseHistorySave(m_historyFilepath.data()); //< requires "char *"
+--- a/src/phantom.cpp
++++ b/src/phantom.cpp
+@@ -380,9 +380,9 @@
+         "require.cache['" + filename + "']._getRequire()," +
+         "require.cache['" + filename + "'].exports," +
+         "require.cache['" + filename + "']" +
+         "));";
+-    m_page->mainFrame()->evaluateJavaScript(scriptSource, QString(JAVASCRIPT_SOURCE_PLATFORM_URL).arg(QFileInfo(filename).fileName()));
++    m_page->mainFrame()->evaluateJavaScript(scriptSource);
+ }
+ 
+ bool Phantom::injectJs(const QString& jsFilePath)
+ {
+@@ -477,10 +477,9 @@
+     m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this);
+ 
+     // Bootstrap the PhantomJS scope
+     m_page->mainFrame()->evaluateJavaScript(
+-        Utils::readResourceFileUtf8(":/bootstrap.js"),
+-        QString(JAVASCRIPT_SOURCE_PLATFORM_URL).arg("bootstrap.js")
++        Utils::readResourceFileUtf8(":/bootstrap.js")
+     );
+ }
+ 
+ bool Phantom::setCookies(const QVariantList& cookies)
+--- a/src/config.cpp
++++ b/src/config.cpp
+@@ -176,9 +176,9 @@
+     QWebPage webPage;
+     // Add this object to the global scope
+     webPage.mainFrame()->addToJavaScriptWindowObject("config", this);
+     // Apply the JSON config settings to this very object
+-    webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig), QString());
++    webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig));
+ }
+ 
+ QString Config::helpText() const
+ {
+--- a/src/webpage.cpp
++++ b/src/webpage.cpp
+@@ -752,10 +752,10 @@
+ 
+     qDebug() << "WebPage - evaluateJavaScript" << function;
+ 
+     evalResult = m_currentFrame->evaluateJavaScript(
+-                     function,                                   //< function evaluated
+-                     QString("phantomjs://webpage.evaluate()")); //< reference source file
++                     function                                   //< function evaluated
++                     );
+ 
+     qDebug() << "WebPage - evaluateJavaScript result" << evalResult;
+ 
+     return evalResult;
+@@ -925,9 +925,9 @@
+         networkOp = QNetworkAccessManager::DeleteOperation;
+     }
+ 
+     if (networkOp == QNetworkAccessManager::UnknownOperation) {
+-        m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');", QString());
++        m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');");
+         return;
+     }
+ 
+     if (address == "about:blank") {
+@@ -1314,9 +1314,9 @@
+                 return ret.toString();
+             }
+         }
+     }
+-    frame->evaluateJavaScript("console.error('Bad header callback given, use phantom.callback);", QString());
++    frame->evaluateJavaScript("console.error('Bad header callback given, use phantom.callback);");
+     return QString();
+ }
+ 
+ QString WebPage::header(int page, int numPages)
+@@ -1353,9 +1353,9 @@
+ }
+ 
+ void WebPage::_appendScriptElement(const QString& scriptUrl)
+ {
+-    m_currentFrame->evaluateJavaScript(QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl), scriptUrl);
++    m_currentFrame->evaluateJavaScript(QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl));
+ }
+ 
+ QObject* WebPage::_getGenericCallback()
+ {
+Last-Update: 2016-02-15
+Forwarded: not-needed
+Bug-Upstream: https://github.com/ariya/phantomjs/issues/13727
+Author: Ximin Luo <infinity0@debian.org>
+Reviewed-By: Dmitry Smirnov <onlyjob@debian.org>
+Description: Port to Qt 5.5
+ - Remove "webSecurity" option since that's not exposed in Qt 5.5
+
+--- a/src/consts.h
++++ b/src/consts.h
+@@ -63,9 +63,8 @@
+ #define PAGE_SETTINGS_USERNAME              "userName"
+ #define PAGE_SETTINGS_PASSWORD              "password"
+ #define PAGE_SETTINGS_MAX_AUTH_ATTEMPTS     "maxAuthAttempts"
+ #define PAGE_SETTINGS_RESOURCE_TIMEOUT      "resourceTimeout"
+-#define PAGE_SETTINGS_WEB_SECURITY_ENABLED  "webSecurityEnabled"
+ #define PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS   "javascriptCanOpenWindows"
+ #define PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS  "javascriptCanCloseWindows"
+ 
+ #define DEFAULT_WEBDRIVER_CONFIG            "127.0.0.1:8910"
+--- a/src/phantom.cpp
++++ b/src/phantom.cpp
+@@ -135,9 +135,8 @@
+     m_defaultPageSettings[PAGE_SETTINGS_JS_ENABLED] = QVariant::fromValue(true);
+     m_defaultPageSettings[PAGE_SETTINGS_XSS_AUDITING] = QVariant::fromValue(false);
+     m_defaultPageSettings[PAGE_SETTINGS_USER_AGENT] = QVariant::fromValue(m_page->userAgent());
+     m_defaultPageSettings[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE] = QVariant::fromValue(m_config.localToRemoteUrlAccessEnabled());
+-    m_defaultPageSettings[PAGE_SETTINGS_WEB_SECURITY_ENABLED] = QVariant::fromValue(m_config.webSecurityEnabled());
+     m_defaultPageSettings[PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS] = QVariant::fromValue(m_config.javascriptCanOpenWindows());
+     m_defaultPageSettings[PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS] = QVariant::fromValue(m_config.javascriptCanCloseWindows());
+     m_page->applySettings(m_defaultPageSettings);
+ 
+--- a/src/webpage.cpp
++++ b/src/webpage.cpp
+@@ -367,9 +367,8 @@
+     // attribute "WebSecurityEnabled" must be applied during the initializing
+     // security context for Document instance. Setting up it later will not cause any effect
+     // see <qt\src\3rdparty\webkit\Source\WebCore\dom\Document.cpp:4468>
+     QWebSettings* settings = m_customWebPage->settings();
+-    settings->setAttribute(QWebSettings::WebSecurityEnabled, phantomCfg->webSecurityEnabled());
+ 
+     m_mainFrame = m_customWebPage->mainFrame();
+     m_currentFrame = m_mainFrame;
+     m_mainFrame->setHtml(BLANK_HTML, baseUrl);
+@@ -621,9 +620,8 @@
+     opt->setAttribute(QWebSettings::AutoLoadImages, def[PAGE_SETTINGS_LOAD_IMAGES].toBool());
+     opt->setAttribute(QWebSettings::JavascriptEnabled, def[PAGE_SETTINGS_JS_ENABLED].toBool());
+     opt->setAttribute(QWebSettings::XSSAuditingEnabled, def[PAGE_SETTINGS_XSS_AUDITING].toBool());
+     opt->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, def[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE].toBool());
+-    opt->setAttribute(QWebSettings::WebSecurityEnabled, def[PAGE_SETTINGS_WEB_SECURITY_ENABLED].toBool());
+     opt->setAttribute(QWebSettings::JavascriptCanOpenWindows, def[PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS].toBool());
+     opt->setAttribute(QWebSettings::JavascriptCanCloseWindows, def[PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS].toBool());
+ 
+     if (def.contains(PAGE_SETTINGS_USER_AGENT)) {
+Last-Update: 2016-02-15
+Forwarded: no
+Bug-Upstream: https://github.com/ariya/phantomjs/issues/13727
+Author: Ximin Luo <infinity0@debian.org>
+Reviewed-By: Dmitry Smirnov <onlyjob@debian.org>
+Description: Port to Qt 5.5
+ - In webpage, don't inherit QWebFrame::PrintCallback since it's not public
+
+--- a/src/webpage.cpp
++++ b/src/webpage.cpp
+@@ -1254,9 +1254,9 @@
+     }
+ 
+     printer.setPageMargins(marginLeft, marginTop, marginRight, marginBottom, QPrinter::Point);
+ 
+-    m_mainFrame->print(&printer, this);
++    m_mainFrame->print(&printer);
+     return true;
+ }
+ 
+ void WebPage::setZoomFactor(qreal zoom)
+--- a/src/webpage.h
++++ b/src/webpage.h
+@@ -44,9 +44,9 @@
+ class NetworkAccessManager;
+ class QWebInspector;
+ class Phantom;
+ 
+-class WebPage : public QObject, public QWebFrame::PrintCallback
++class WebPage : public QObject
+ {
+     Q_OBJECT
+     Q_PROPERTY(QString title READ title)
+     Q_PROPERTY(QString frameTitle READ frameTitle)
diff --git a/gnu/packages/qt.scm b/gnu/packages/qt.scm
index b442356..8ce1192 100644
--- a/gnu/packages/qt.scm
+++ b/gnu/packages/qt.scm
@@ -5,6 +5,7 @@ 
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
 ;;; Copyright © 2016 Thomas Danckaert <post@thomasdanckaert.be>
+;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -1285,3 +1286,258 @@  embed content from the World Wide Web into your Qt application.  At the same
 time Web content can be enhanced with native controls.")
 
     (license license:lgpl2.1+)))
+
+(define-public qtbase55
+  (package
+    (inherit qtbase)
+    (name "qtbase")
+    (version "5.5.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://download.qt.io/official_releases/qt/"
+                                  (version-major+minor version) "/" version
+                                  "/submodules/" name "-opensource-src-"
+                                  version ".tar.xz"))
+              (sha256
+               (base32
+                "05p91m1d9b3gdfm5pgmxw63rk0fdxqz87s77hn9bdip4syjfi96z"))
+              (modules '((guix build utils)))
+              (snippet
+               '(begin
+                  ;; Remove one of the two bundled harfbuzz copies in addition
+                  ;; to passing "-system-harfbuzz".
+                  (delete-file-recursively "src/3rdparty/harfbuzz-ng")
+                  ;; Remove the bundled sqlite copy in addition to
+                  ;; passing "-system-sqlite".
+                  (delete-file-recursively "src/3rdparty/sqlite")))))))
+
+(define-public qtsvg55
+  (package (inherit qtbase55)
+    (name "qtsvg")
+    (version "5.5.1")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "https://download.qt.io/official_releases/qt/"
+                                 (version-major+minor version) "/" version
+                                 "/submodules/" name "-opensource-src-"
+                                 version ".tar.xz"))
+             (sha256
+              (base32
+               "1iwibbh835cpxbfh7rnrpvl9k20valr6h256np59rzdy92z8ixgp"))))
+    (propagated-inputs `())
+    (native-inputs `(("perl" ,perl)))
+    (inputs
+     `(("mesa" ,mesa)
+       ("qtbase" ,qtbase55)
+       ("zlib" ,zlib)))
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (replace 'configure
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out")))
+               (and (zero? (system* "qmake" (string-append "PREFIX=" out)))
+                    (system* "make" "clean"))))) ; Generate broken Makefiles
+                                                 ; to be substituted
+         (add-before 'build 'fix-Makefiles
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out"))
+                   (qtbase (assoc-ref inputs "qtbase")))
+               (substitute* (find-files "." "Makefile")
+                 (((string-append "-Wl,-rpath," qtbase "/lib") all)
+                  (string-append all " -Wl,-rpath," out "/lib "))
+                 (((string-append "INSTALL_ROOT)" qtbase))
+                  (string-append "INSTALL_ROOT)" out)))))))))))
+
+(define-public qtxmlpatterns55
+  (package (inherit qtsvg55)
+    (name "qtxmlpatterns")
+    (version "5.5.1")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "https://download.qt.io/official_releases/qt/"
+                                 (version-major+minor version) "/" version
+                                 "/submodules/" name "-opensource-src-"
+                                 version ".tar.xz"))
+             (sha256
+              (base32
+               "1v78s0jygg83yzyldwms8zb72cwp718cc5ialc2ki3lqa81fndxm"))))
+    (native-inputs `(("perl" ,perl)))
+    (inputs `(("qtbase" ,qtbase55)))))
+
+(define-public qtdeclarative55
+  (package (inherit qtsvg55)
+    (name "qtdeclarative")
+    (version "5.5.1")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "https://download.qt.io/official_releases/qt/"
+                                 (version-major+minor version) "/" version
+                                 "/submodules/" name "-opensource-src-"
+                                 version ".tar.xz"))
+             (sha256
+              (base32
+               "14b7naaa0rk4q6cxf0w62gvamxk812kr65k82zxkdzrzp3plxlaz"))))
+    (native-inputs
+     `(("perl" ,perl)
+       ("pkg-config" ,pkg-config)
+       ("python" ,python-2)
+       ("qtsvg" ,qtsvg55)
+       ("qtxmlpatterns" ,qtxmlpatterns55)))
+    (inputs
+     `(("mesa" ,mesa)
+       ("qtbase" ,qtbase55)))))
+
+(define-public qtwebkit55
+  (package
+    (inherit qtwebkit)
+    (name "qtwebkit")
+    (version "5.5.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "http://download.qt.io/official_releases/qt/"
+                    (version-major+minor version)
+                    "/" version
+                    "/submodules/" name "-opensource-src-"
+                    version ".tar.xz"))
+              (sha256
+               (base32
+                "0sbdglcf57lmgbcybimvvbpqikn3blb1pxvd71sdhsiypnfkyn3p"))))
+    (inputs
+     `(("icu" ,icu4c)
+       ("libjpeg" ,libjpeg)
+       ("libpng" ,libpng)
+       ("libwebp" ,libwebp)
+       ("sqlite" ,sqlite)
+       ("fontconfig" ,fontconfig)
+       ("libxrender", libxrender)
+       ("qtbase" ,qtbase55)
+       ("qtdeclarative" ,qtdeclarative55)
+       ("libxml2" ,libxml2)
+       ("libxslt" ,libxslt)
+       ("libx11" ,libx11)
+       ("libxcomposite" ,libxcomposite)))
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (replace 'configure
+                  (lambda* (#:key outputs #:allow-other-keys)
+                    (let ((out (assoc-ref outputs "out")))
+                      (setenv "QMAKEPATH"
+                              (string-append (getcwd) "/Tools/qmake:"
+                                             (getenv "QMAKEPATH")))
+                      (system* "qmake"))))
+         ;; prevent webkit from trying to install into the qtbase store directory,
+         ;; and replace references to the build directory in linker options:
+         (add-before 'build 'patch-installpaths
+                     (lambda* (#:key outputs inputs #:allow-other-keys)
+                       (let* ((out (assoc-ref outputs "out"))
+                              (qtbase (assoc-ref inputs "qtbase"))
+                              (builddir (getcwd))
+                              (linkbuild (string-append "-L" builddir))
+                              (linkout (string-append "-L" out))
+                              (makefiles
+                               (map-in-order
+                                (lambda (i)
+                                  (let* ((in (car i))
+                                         (mf (string-append (dirname in) "/"
+                                                            (cdr i))))
+                                    ;; by default, these Makefiles are
+                                    ;; generated during install, but we need
+                                    ;; to generate them now
+                                    (system* "qmake" in "-o" mf)
+                                    mf))
+                                '(("Source/api.pri" . "Makefile.api")
+                                  ("Source/widgetsapi.pri"
+                                   . "Makefile.widgetsapi")
+                                  ("Source/WebKit2/WebProcess.pro"
+                                   . "Makefile.WebProcess")
+                                  ("Source/WebKit2/PluginProcess.pro"
+                                   . "Makefile.PluginProcess")
+                                  ("Source/WebKit/qt/declarative/public.pri"
+                                   . "Makefile.declarative.public")
+                                  ("Source/WebKit/qt/declarative/experimental/experimental.pri"
+                                   . "Makefile.declarative.experimental")
+                                  ("Source/WebKit/qt/examples/platformplugin/platformplugin.pro"
+                                   . "Makefile")))))
+                         ;; Order of qmake calls and substitutions matters here.
+                         (system* "qmake" "-prl" "Source/widgetsapi.pri"
+                                  "-o" "Source/Makefile")
+                         (substitute* (find-files "lib" "libQt5.*\\.prl")
+                           ((linkbuild) linkout))
+                         (substitute* (find-files "lib"
+                                                  "libQt5WebKit.*\\.la")
+                           (("libdir='.*'")
+                            (string-append "libdir='" out "/lib'"))
+                           ((linkbuild) linkout))
+                         (substitute* (find-files "lib/pkgconfig"
+                                                  "Qt5WebKit.*\\.pc")
+                           (((string-append "prefix=" qtbase))
+                            (string-append "prefix=" out))
+                           ((linkbuild) linkout))
+                         ;; Makefiles must be modified after .prl/.la/.pc
+                         ;; files, lest they get rebuilt:
+                         (substitute* makefiles
+                           (((string-append "\\$\\(INSTALL_ROOT\\)" qtbase))
+                            out )
+                           (((string-append "-Wl,-rpath," builddir))
+                            (string-append "-Wl,-rpath," out))
+                           (((string-append "-Wl,-rpath," qtbase "/lib") all)
+                            (string-append all " -Wl,-rpath," out "/lib ")))))))))))
+
+(define-public phantomjs
+  (package
+    (name "phantomjs")
+    (version "2.1.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/ariya/phantomjs/archive/"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (patches (search-patches "phantomjs-qt55.patch"))
+              (sha256
+               (base32
+                "1wccz46bhg0kkxr10xs30i1p055fxrac5zqszz4akma8rpln67mx"))))
+    (native-inputs
+     `(("python" ,python-2)
+       ("qmake" ,qtbase55)))
+    (inputs
+     `(("qtwebkit" ,qtwebkit55)))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f ; no check target
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (replace 'build
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (qmake (string-append (assoc-ref inputs "qmake")
+                                           "/bin/qmake"))
+                    (python (string-append (assoc-ref inputs "python")
+                                           "/bin/python")))
+               (substitute* "build.py"
+                 (("return os.path.abspath[(]\\\"src/qt/qtbase/bin/\\\" [+] exe[)]")
+                  (string-append "return \"" qmake "\"")))
+               (zero?
+                (system* python "build.py"
+                         "--skip-git"
+                         "--skip-qtbase"
+                         "--skip-qtwebkit"
+                         "--confirm"
+                         "--release")))))
+         (replace 'install
+                  (lambda* (#:key inputs outputs #:allow-other-keys)
+                    (let* ((out (assoc-ref outputs "out"))
+                           (bin (string-append out "/bin")))
+                      (mkdir-p bin)
+                      (copy-file "bin/phantomjs"
+                                 (string-append bin "/phantomjs"))))))))
+    (home-page "https://github.com/ariya/phantomjs")
+    (synopsis "Headless QT-WebKit with JavaScript")
+    (description "PhantomJS is a headless QT-based WebKit with JavaScript API.
+It has ative support for various web standards: DOM handling, CSS selector,
+JSON, Canvas, and SVG.")
+    (license license:bsd-3)))
-- 
2.10.2