From 7d371328265a4912fb323779adf95cc922a83541 Mon Sep 17 00:00:00 2001
From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Date: Fri, 28 Feb 2014 11:27:02 +0100
Subject: [PATCH] Deploy QtWebEngineCore as a Qt module

This delegates the linking step from ninja to qmake so that we can
let qmake decide the destination of the target itself, easing the
deployment and installation logic across platforms.

The module is only deployed as a binary and no header are available
outside of the source tree. This is only to make sure that the
dependence of the QtWebEngine and QtWebEngineWidgets libraries on it
is resolved at runtime exactly the same way as with other Qt modules,
on all platforms.

Ninja still takes care of the compilation and gyp lets qmake know how
and what to link by dumping the list of flags and input files in a
generated .pri file.

This has to be done in a separate .pro file so that we can make sure
that ninja is run inconditionally before make reaches the dependency
check in core_module.pro, ensured by the parent Makefile.

Note 1: This patch removes RPATH hacks that are no longer necessary

Note 2: Other targets like ffmpegsumo are still linked by ninja. The
same logic could be moved to a qmake file but this require some more
work to make sure that some switches (e.g. -stdlib=libc++) are
coordinated between gyp and qmake.

Change-Id: If65968547bde5b9cf732e31e97931c17ae1921a7
Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu>
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
---
 ...Allow-letting-qmake-do-the-link-step.patch | 70 +++++++++++++++++++
 qtwebengine.pro                               | 12 ++--
 src/3rdparty                                  |  2 +-
 src/core/core.pro                             |  8 ++-
 src/core/core_gyp_generator.pro               | 19 +----
 src/core/core_module.pro                      | 15 ++++
 src/core/qtwebengine.gypi                     |  3 +
 src/process/process.pro                       | 10 +--
 src/webengine/webengine.pro                   | 10 +--
 src/webenginewidgets/webenginewidgets.pro     | 19 +----
 10 files changed, 105 insertions(+), 63 deletions(-)
 create mode 100644 patches/chromium/tools/gyp/0003-Allow-letting-qmake-do-the-link-step.patch
 create mode 100644 src/core/core_module.pro

diff --git a/patches/chromium/tools/gyp/0003-Allow-letting-qmake-do-the-link-step.patch b/patches/chromium/tools/gyp/0003-Allow-letting-qmake-do-the-link-step.patch
new file mode 100644
index 000000000..8b86bd5ad
--- /dev/null
+++ b/patches/chromium/tools/gyp/0003-Allow-letting-qmake-do-the-link-step.patch
@@ -0,0 +1,70 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+Date: Thu, 27 Feb 2014 17:42:48 +0100
+Subject: Allow letting qmake do the link step
+
+This adds a let_qmake_do_the_linking target variable to tell ninja
+not to link but rather dump the linking information from gyp in a
+file that we'll parse with qmake.
+
+Change-Id: Icfaadae7ce4e9895f76b5fe06e05124e9b980e8b
+Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu>
+Reviewed-by: Andras Becsi <andras.becsi@digia.com>
+---
+ pylib/gyp/generator/ninja.py | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py
+index 6fe07c5..c61f180 100644
+--- a/pylib/gyp/generator/ninja.py
++++ b/pylib/gyp/generator/ninja.py
+@@ -1090,6 +1090,49 @@ class NinjaWriter:
+       else:
+         command = command + '_notoc'
+ 
++      if config.get('let_qmake_do_the_linking', 0):
++        def toAbsPaths(paths):
++          return [os.path.relpath(path, self.toplevel_build) if os.path.isabs(path) else path
++                  for path in paths]
++        def qmakeLiteral(s):
++          return s.replace('"', '\\"')
++
++        # Generate this file for all solink targets, this assumes that
++        # a .pro file will pick up this pri file and do the rest of the work.
++        pri_file = open(os.path.join(self.toplevel_build, self.name + "_linking.pri"), 'w')
++
++        if self.flavor == 'win':
++          # qmake will take care of the manifest
++          ldflags = filter(lambda x: not x.lower().startswith('/manifest'), ldflags)
++
++        # Replace "$!PRODUCT_DIR" with "$$PWD" in link flags (which might contain some -L directives).
++        prefixed_lflags = [self.ExpandSpecial(f, '$$PWD') for f in ldflags]
++        prefixed_library_dirs = ['-L' + self.ExpandSpecial(f, '$$PWD') for f in config.get('library_dirs', [])]
++        prefixed_libraries = gyp.common.uniquer([self.ExpandSpecial(f, '$$PWD') for f in spec.get('libraries', [])])
++        if self.flavor == 'mac':
++          prefixed_libraries = self.xcode_settings.AdjustLibraries(prefixed_libraries)
++        elif self.flavor == 'win':
++          prefixed_libraries = self.msvs_settings.AdjustLibraries(prefixed_libraries)
++
++        # Make sure that we have relative paths to our out/(Release|Debug), where we generate our .pri file, and then prepend $$PWD to them.
++        prefixed_object_and_archives = ['$$PWD/' + o for o in toAbsPaths(link_deps)]
++
++        pri_file.write("QMAKE_LFLAGS += %s\n" % qmakeLiteral(' '.join(prefixed_lflags)))
++        # Follow the logic of the solink rule.
++        if self.flavor != 'mac' and self.flavor != 'win':
++          pri_file.write("LIBS_PRIVATE += -Wl,--whole-archive %s -Wl,--no-whole-archive\n" % qmakeLiteral(' '.join(prefixed_object_and_archives)))
++        else:
++          pri_file.write("LIBS_PRIVATE += %s\n" % qmakeLiteral(' '.join(prefixed_object_and_archives)))
++        # External libs have to come after objects/archives, the linker resolve them in order.
++        pri_file.write("LIBS_PRIVATE += %s\n" % qmakeLiteral(' '.join(prefixed_library_dirs + prefixed_libraries)))
++        # Make sure that if ninja modifies one of the inputs, qmake/make will link again.
++        pri_file.write("POST_TARGETDEPS += %s\n" % qmakeLiteral(' '.join(prefixed_object_and_archives)))
++        pri_file.close()
++
++        # In this mode we prevent letting ninja link at all.
++        command = 'phony'
++        command_suffix = ''
++
+     if len(solibs):
+       extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs)))
+ 
diff --git a/qtwebengine.pro b/qtwebengine.pro
index c3e56fe8e..366446c7a 100644
--- a/qtwebengine.pro
+++ b/qtwebengine.pro
@@ -1,12 +1,8 @@
 load(qt_build_config)
 
-# Examples will only be able to find libQt5WebEngineCore.so if the proper RPATH was set on libQt5WebEngineWidgets.so
-# Arch Linux disables RPATH for security reasons.
-!isEmpty($$QMAKE_LFLAGS_RPATH) {
-    # As long as we are a module separate from the rest of Qt, we want to unconditionally build examples.
-    # Once part of Qt 5, this should be removed and we should respect the Qt wide configuration.
-    QTWEBENGINE_BUILD_PARTS = $$QT_BUILD_PARTS
-    QTWEBENGINE_BUILD_PARTS *= examples
-}
+# As long as we are a module separate from the rest of Qt, we want to unconditionally build examples.
+# Once part of Qt 5, this should be removed and we should respect the Qt wide configuration.
+QTWEBENGINE_BUILD_PARTS = $$QT_BUILD_PARTS
+QTWEBENGINE_BUILD_PARTS *= examples
 
 load(qt_parts)
diff --git a/src/3rdparty b/src/3rdparty
index 9001f7258..95854d944 160000
--- a/src/3rdparty
+++ b/src/3rdparty
@@ -1 +1 @@
-Subproject commit 9001f7258c97c6fe61d6362aa3431af7128f9218
+Subproject commit 95854d944fb9195e2b2871367726f69cea9113d8
diff --git a/src/core/core.pro b/src/core/core.pro
index c5fe808a6..5f0c3c29d 100644
--- a/src/core/core.pro
+++ b/src/core/core.pro
@@ -12,13 +12,17 @@ gyp_configure_target.depends = gyp_configure_host
 
 # gyp_run.pro calls gyp through gyp_qtwebengine on the qmake step, and ninja on the make step.
 gyp_run.file = gyp_run.pro
-
 gyp_run.depends = core_gyp_generator gyp_configure_host gyp_configure_target
 
+# This will take the compile output of ninja, and link+deploy the final binary.
+core_module.file = core_module.pro
+core_module.depends = gyp_run
+
 SUBDIRS += core_gyp_generator \
            gyp_configure_host \
            gyp_configure_target \
-           gyp_run
+           gyp_run \
+           core_module
 
 REPACK_DIR = $$getOutDir()/$$getConfigDir()/gen/repack
 locales.files = $$REPACK_DIR/qtwebengine_locales
diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro
index a75eb733a..25e105da6 100644
--- a/src/core/core_gyp_generator.pro
+++ b/src/core/core_gyp_generator.pro
@@ -7,12 +7,8 @@ GYPINCLUDES += qtwebengine.gypi
 
 TEMPLATE = lib
 
-TARGET = Qt5WebEngineCore
-
-# gyp sets the default install name to /usr/local/lib and we need the module libraries to
-# know its install_name so that they can let the dynamic linker load the core library.
-# FIXME: Remove this and put it in qtwebengine.gypi once we can use a relative path to @loader_path.
-macx: GYP_DYLIB_INSTALL_NAME_BASE = $$getOutDir()/$$getConfigDir()
+# This must match the target name in core_module.pro to allow it to do the linking part.
+TARGET = QtWebEngineCore
 
 QT += qml quick
 QT_PRIVATE += qml-private quick-private gui-private core-private
@@ -104,14 +100,3 @@ HEADERS = \
         yuv_video_node.h \
         qrc_protocol_handler_qt.h \
         url_request_qrc_job_qt.h
-
-VERSION = $$MODULE_VERSION
-win32:CONFIG += skip_target_version_ext
-load(resolve_target)
-TARGET_NAME = $$basename(QMAKE_RESOLVED_TARGET)
-TARGET_NAME = $$replace(TARGET_NAME, .$${VERSION},)
-
-target.files = $$getOutDir()/$$getConfigDir()/lib/$$TARGET_NAME
-target.CONFIG += no_check_exist # Trust us, qmake...
-target.path = $$[QT_INSTALL_LIBS]
-INSTALLS += target
diff --git a/src/core/core_module.pro b/src/core/core_module.pro
new file mode 100644
index 000000000..049bd0596
--- /dev/null
+++ b/src/core/core_module.pro
@@ -0,0 +1,15 @@
+TARGET = QtWebEngineCore
+MODULE = webenginecore
+
+# Look for linking information produced by gyp for our target according to core_generated.gyp
+!include($$getOutDir()/$$getConfigDir()/$${TARGET}_linking.pri) {
+    error("Could not find the linking information that gyp should have generated.")
+}
+
+# We distribute the module binary but headers are only available in-tree.
+CONFIG += no_module_headers
+load(qt_module)
+
+# Using -Wl,-Bsymbolic-functions seems to confuse the dynamic linker
+# and doesn't let Chromium get access to libc symbols through dlsym.
+CONFIG -= bsymbolic_functions
diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi
index 20cac744a..0a179ea26 100644
--- a/src/core/qtwebengine.gypi
+++ b/src/core/qtwebengine.gypi
@@ -1,4 +1,7 @@
 {
+    # This asks gyp to generate a .pri file with linking
+    # information so that qmake can take care of the deployment.
+    'let_qmake_do_the_linking': 1,
     'dependencies': [
       '<(chromium_src_dir)/content/content.gyp:content',
       '<(chromium_src_dir)/content/content.gyp:content_app_browser',
diff --git a/src/process/process.pro b/src/process/process.pro
index cc68e3dda..a9f5d183f 100644
--- a/src/process/process.pro
+++ b/src/process/process.pro
@@ -1,15 +1,9 @@
 TARGET = $$QTWEBENGINEPROCESS_NAME
 TEMPLATE = app
 
-macx {
-    LIBPATH = $$getOutDir()/$$getConfigDir()
-    CONFIG -= app_bundle
-} else:LIBPATH = $$getOutDir()/$$getConfigDir()/lib
-LIBS_PRIVATE += -L$$LIBPATH -lQt5WebEngineCore
-QMAKE_RPATHDIR += $$LIBPATH
+QT_PRIVATE += webenginecore
 
-qnx: QMAKE_RPATHLINKDIR += $${QNX_DIR}/$${QNX_CPUDIR}/usr/lib/qt5/lib
-else: cross_compile: QMAKE_RPATHLINKDIR += $$[QT_INSTALL_LIBS]
+CONFIG -= app_bundle
 
 load(qt_build_paths)
 DESTDIR = $$MODULE_BASE_OUTDIR/libexec
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 062780469..cd175bfcc 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -4,18 +4,10 @@ TARGET = QtWebEngine
 DEFINES += QT_BUILD_WEBENGINE_LIB
 
 QT += qml quick
-QT_PRIVATE += qml-private quick-private gui-private core-private
+QT_PRIVATE += webenginecore qml-private quick-private gui-private core-private
 
 INCLUDEPATH += $$PWD api ../core
 
-# FIXME: all this should eventually be turned into QT += webenginecore
-macx:LIBPATH = $$getOutDir()/$$getConfigDir()
-else:LIBPATH = $$getOutDir()/$$getConfigDir()/lib
-LIBS_PRIVATE += -lQt5WebEngineCore -L$$LIBPATH
-QMAKE_RPATHDIR += $$LIBPATH
-
-#DESTDIR = $$LIBPATH
-
 SOURCES = \
         api/qquickwebengineloadrequest.cpp \
         api/qquickwebenginenewviewrequest.cpp \
diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro
index a871586ae..c97e4b61e 100644
--- a/src/webenginewidgets/webenginewidgets.pro
+++ b/src/webenginewidgets/webenginewidgets.pro
@@ -4,15 +4,7 @@ TARGET = QtWebEngineWidgets
 DEFINES += QT_BUILD_WEBENGINEWIDGETS_LIB
 
 QT += widgets network
-QT_PRIVATE += widgets-private gui-private network-private core-private
-
-# FIXME: all this should eventually be turned into QT += webenginecore
-macx:LIBPATH = $$getOutDir()/$$getConfigDir()
-else:LIBPATH = $$getOutDir()/$$getConfigDir()/lib
-LIBS_PRIVATE += -L$$LIBPATH -lQt5WebEngineCore
-QMAKE_RPATHDIR += $$LIBPATH
-
-DESTDIR = $$LIBPATH
+QT_PRIVATE += webenginecore widgets-private gui-private network-private core-private
 
 INCLUDEPATH += $$PWD api ../core
 
@@ -33,12 +25,3 @@ HEADERS = \
         render_widget_host_view_qt_delegate_webpage.h
 
 load(qt_module)
-
-# Some binutils versions configured for cross compilation only support
-# sysroot-relative rpath values and can't use the rpath specified above.
-# Instead, append an appropriate rpath-link to lib_qt_webenginewidgets.pri.
-cross_compile:!build_pass {
-    local_build_rpath_link = "QMAKE_RPATHLINKDIR += $$LIBPATH"
-    # MODULE_PRI is defined in qt_module_pris.prf
-    write_file($$MODULE_PRI, local_build_rpath_link, append)
-}
-- 
GitLab