From 3300873bba24594e4773d0e0a127d33a5a0f303c Mon Sep 17 00:00:00 2001
From: Pierre Rossi <pierre.rossi@digia.com>
Date: Fri, 19 Apr 2013 11:07:15 +0200
Subject: [PATCH] New qmake approach

This should allow us to have much better integration by generating the necessary gyp
files directly from qmake.
Mostly works for now, though we will most likely need to build the gyp generation
as we go.

  * Out dir logic is still crap and needs to be (re)worked.
  * In the same vein, we probably don't want the generated gyp
  content ending up in the source tree in the long run, which could prove tricky
  with relative paths to sources and all.
---
 .qmake.conf                                  |  6 +++
 README                                       |  2 +-
 blinq.pro                                    |  8 ++++
 build/build.pro                              | 25 ++++++++++
 gyp_blinq => build/gyp_blinq                 | 34 ++------------
 build/qmake/mkspecs/features/default_pre.prf |  4 ++
 build/qmake/mkspecs/features/functions.prf   |  9 ++++
 build/qmake/mkspecs/features/gypi_gen.prf    | 48 ++++++++++++++++++++
 lib/lib.gyp                                  | 32 -------------
 lib/lib.pro                                  | 20 ++++++++
 process/process.gyp                          | 14 ------
 process/process.pro                          | 11 +++++
 12 files changed, 137 insertions(+), 76 deletions(-)
 create mode 100644 .qmake.conf
 create mode 100644 blinq.pro
 create mode 100644 build/build.pro
 rename gyp_blinq => build/gyp_blinq (74%)
 create mode 100644 build/qmake/mkspecs/features/default_pre.prf
 create mode 100644 build/qmake/mkspecs/features/functions.prf
 create mode 100644 build/qmake/mkspecs/features/gypi_gen.prf
 delete mode 100644 lib/lib.gyp
 create mode 100644 lib/lib.pro
 delete mode 100644 process/process.gyp
 create mode 100644 process/process.pro

diff --git a/.qmake.conf b/.qmake.conf
new file mode 100644
index 000000000..716685d2a
--- /dev/null
+++ b/.qmake.conf
@@ -0,0 +1,6 @@
+# The qmake generated module files belong into our build/qmake dir
+MODULE_QMAKE_OUTDIR = $$shadowed($$PWD/build/qmake)
+QMAKEPATH += $$PWD/build/qmake $$MODULE_QMAKE_OUTDIR
+load(qt_build_config)
+
+MODULE_VERSION = 5.2.0
diff --git a/README b/README
index 6b120d018..dfb29b523 100644
--- a/README
+++ b/README
@@ -15,7 +15,7 @@ This is a prototype of allowing embedding Chromium/Blink into Qt.
 (2) (Re-)generating the ninja build files after changing a gyp file:
 
     * set the CHROMIUM_SRC_DIR environment variable to point to /path/to/src/
-    * Run gyp_blinq
+    * Simply run qmake in the top-level directory
 
 (3) build with ninja -C out/Release (or out/Debug depending on the needs)
 
diff --git a/blinq.pro b/blinq.pro
new file mode 100644
index 000000000..cb7c33b7e
--- /dev/null
+++ b/blinq.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+
+CONFIG += ordered
+
+SUBDIRS = lib \ # Contains a dummy lib target that is used to generate qt_generated.gypi
+          build \ # This is where we use the generated qt_generated.gypi and run gyp
+          example \
+
diff --git a/build/build.pro b/build/build.pro
new file mode 100644
index 000000000..279823371
--- /dev/null
+++ b/build/build.pro
@@ -0,0 +1,25 @@
+# This .pro file serves a dual purpose:
+# 1) invoking gyp through the gyp_blinq script, which in turn makes use of the generated gypi include files
+# 2) produce a Makefile that will run ninja, and take care of actually building everything.
+
+TEMPLATE = aux
+
+# Fetched from environment for now
+CHROMIUM_SRC_DIR = $$(CHROMIUM_SRC_DIR)
+isEmpty(CHROMIUM_SRC_DIR):error("please set CHOMIUM_SRC_DIR")
+
+message(Running Gyp...)
+GYP_OUTPUT = $$system(./gyp_blinq)
+message($$GYP_OUTPUT)
+
+ninja.target = ninja
+# FIXME: Don't hardcode Release... might be tricky to get right if we also don't want to hardcode 'out'
+ninja.commands = $$CHROMIUM_SRC_DIR/../depot_tools/ninja -C $$BLINQ_ROOT/out/Release
+ninja.depends: qmake
+QMAKE_EXTRA_TARGETS += ninja
+
+build_pass:build_all:default_target.target = all
+else: default_target.target = first
+default_target.depends = ninja
+
+QMAKE_EXTRA_TARGETS += default_target
diff --git a/gyp_blinq b/build/gyp_blinq
similarity index 74%
rename from gyp_blinq
rename to build/gyp_blinq
index e98e3e8ab..b22e759b7 100755
--- a/gyp_blinq
+++ b/build/gyp_blinq
@@ -5,16 +5,12 @@ import os
 import subprocess
 import sys
 
-#FIXME(pierre): mandatory until we have a git submodule, for now we can't guess where the chromium checkout lives.
-if "CHROMIUM_SRC_DIR" not in os.environ:
-  print "Please set the environment variable CHROMIUM_SRC_DIR to point to your checkout of chromium's 'src' directory"
-  sys.exit(1)
-
-chrome_src = os.path.abspath(os.environ.get('CHROMIUM_SRC_DIR'));
-script_dir = os.path.abspath(os.path.join(chrome_src, 'build'));
+chrome_src = os.path.abspath(os.environ.get('CHROMIUM_SRC_DIR')) # null-checked in build.pro
+script_dir = os.path.abspath(os.path.join(chrome_src, 'build'))
 if not os.path.isdir(script_dir):
   print script_dir + " is not a valid directory"
   sys.exit(1)
+root_dir = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
 
 sys.path.insert(0, script_dir)
 import gyp_helper
@@ -60,7 +56,7 @@ def additional_include_files(args=[]):
 
 # TODO: later we probably want to hook that up with qmake to allow shadow builds. (Might not play nice with the rest of chromium though)
 def get_output_dir():
-  outdir = os.path.join(os.getcwd(), "out") # Hardcode for now
+  outdir = os.path.join(root_dir, "out") # Hardcode for now
   if not os.path.isdir(outdir):
     os.mkdir(outdir)
 
@@ -80,7 +76,7 @@ if __name__ == '__main__':
       break
 
   if not gyp_file_specified:
-      args.append(os.path.join(os.getcwd(), 'blinq.gyp'))
+      args.append(os.path.join(root_dir, 'blinq.gyp'))
 
   args.extend(['-I' + i for i in additional_include_files(args)])
 
@@ -96,27 +92,7 @@ if __name__ == '__main__':
   if sys.platform not in ('darwin',):
     args.append('--no-circular-check')
 
-  # QMake detection
-  proc = subprocess.Popen(["qmake", "-query"], stdout=subprocess.PIPE)
-  out = proc.communicate()[0].split('\n')
-  for line in out:
-    if line.startswith("QT_INSTALL_LIBS"):
-      qt_libs = line.split(':')[1]
-    elif line.startswith("QT_INSTALL_HEADERS"):
-      qt_headers = line.split(':')[1]
-    elif line.startswith("QMAKE_SPEC"):
-      qmake_spec = line.split(':')[1]
-    elif line.startswith("QT_VERSION"):
-      qt_version = line.split(':')[1]
-      # FIXME: remove this check once it's move up in the pro file
-      if not qt_version.startswith('5'):
-        print "Qt 5 is a minimum requirement for Blinq"
-        sys.exit(5)
-
   args.extend(['-D', 'use_aura=1'])
-  args.extend(['-D', 'qt_libdir=' + qt_libs])
-  args.extend(['-D', 'qt_headers=' + qt_headers])
-  args.extend(['-D', 'qmake_spec=' + qmake_spec])
   args.extend(['-D', 'webkit_src_dir=' + chrome_src + '/third_party/WebKit'])
   args.extend(["--depth=" + chrome_src])
   args.extend(['-D', 'chromium_src_dir=' + chrome_src])
diff --git a/build/qmake/mkspecs/features/default_pre.prf b/build/qmake/mkspecs/features/default_pre.prf
new file mode 100644
index 000000000..c54908efd
--- /dev/null
+++ b/build/qmake/mkspecs/features/default_pre.prf
@@ -0,0 +1,4 @@
+# Resolve root directories for sources
+BLINQ_ROOT = $$replace(PWD, /build/qmake/mkspecs/features$,)
+
+# TODO: Build dir logic
diff --git a/build/qmake/mkspecs/features/functions.prf b/build/qmake/mkspecs/features/functions.prf
new file mode 100644
index 000000000..8d0df1a4e
--- /dev/null
+++ b/build/qmake/mkspecs/features/functions.prf
@@ -0,0 +1,9 @@
+# Map to the correct target type for gyp
+defineReplace(toGypTargetType) {
+  equals(TEMPLATE, "app"):return("executable")
+  equals(TEMPLATE, "lib") {
+    CONFIG(static): return("static_library")
+    return("shared_library")
+  }
+  return("none")
+}
diff --git a/build/qmake/mkspecs/features/gypi_gen.prf b/build/qmake/mkspecs/features/gypi_gen.prf
new file mode 100644
index 000000000..ee32c3661
--- /dev/null
+++ b/build/qmake/mkspecs/features/gypi_gen.prf
@@ -0,0 +1,48 @@
+# This file is loaded after the dummy .pro and all the default_post ran.
+# This is the right point to extract the variables we're interested in and generate
+# the .gyp file that we'll use later on when running gyp
+
+load(functions)
+
+GYPI_FILE = $$replace(_PRO_FILE_, .pro$, .gyp)
+
+TARGET_TYPE = $$toGypTargetType()
+
+GYPI_CONTENTS =  "{" \
+                 "  'targets': [" \
+                 "  {" \
+                 "    'target_name': '$$TARGET'," \
+                 "    'type': '$$TARGET_TYPE'," \
+                 "    'includes': [" \
+                 "      '../blinq.gypi'," \
+                 "    ]," \
+                 "    'ldflags': ["
+for (lib, LIBS): GYPI_CONTENTS += "      '$$lib',"
+!isEmpty(QMAKE_RPATHDIR): GYPI_CONTENTS += "      '$$QMAKE_RPATH$$QMAKE_RPATHDIR',"
+
+GYPI_CONTENTS += "    ],"
+
+!isEmpty(DEFINES) {
+  GYPI_CONTENTS += "    'defines': ["
+  for (define, DEFINES): GYPI_CONTENTS += "      '$$define',"
+  GYPI_CONTENTS += "    ],"
+}
+GYPI_CONTENTS += "    'sources': ["
+for (sourcefile, SOURCES): GYPI_CONTENTS += "      '$$sourcefile',"
+for (headerfile, HEADERS): GYPI_CONTENTS += "      '$$headerfile',"
+GYPI_CONTENTS += "    ],"
+!isEmpty(INCLUDEPATH) {
+  GYPI_CONTENTS += "    'include_dirs': ["
+  for (path, INCLUDEPATH): GYPI_CONTENTS += "      '$$path',"
+  GYPI_CONTENTS += "    ],"
+}
+GYPI_CONTENTS += "  }," \
+                 "  ]," \
+                 "}"
+
+write_file($$GYPI_FILE, GYPI_CONTENTS)
+
+# The generated Makefile shouldn't build anything by itself, just re-run qmake if necessary
+TEMPLATE = aux
+SOURCES =
+HEADERS =
diff --git a/lib/lib.gyp b/lib/lib.gyp
deleted file mode 100644
index fee379de2..000000000
--- a/lib/lib.gyp
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  'targets': [
-  {
-    'target_name': 'blinq',
-      'type': 'shared_library',
-      'includes': [
-        '../blinq.gypi',
-      ],
-      'sources': [
-        'blinqpage.cpp',
-        'blinqpage.h',
-      ],
-      'libraries': [
-        '-lQt5Core',
-        '-lQt5Gui',
-      ],
-      'ldflags': [
-        '-L<(qt_libdir)',
-        '-Wl,-rpath,<(qt_libdir)',
-      ],
-      'cflags': [
-        '-DQT_NO_KEYWORDS',
-      ],
-      'include_dirs': [
-        '<(qt_headers)',
-        '<(qt_headers)/QtCore',
-        '<(qt_headers)/QtGui',
-        '<(qt_headers)/QtGui/5.2.0/QtGui',
-      ],
-  },
-    ],
-}
diff --git a/lib/lib.pro b/lib/lib.pro
new file mode 100644
index 000000000..e79923236
--- /dev/null
+++ b/lib/lib.pro
@@ -0,0 +1,20 @@
+# This is a dummy .pro file used to extract some aspects of the used configuration and feed them to gyp
+# We want the gyp generation step to happen after all the other config steps. For that we need to prepend
+# our gypi_gen.prf feature to the CONFIG variable since it is processed backwards
+CONFIG = gypi_gen $$CONFIG
+
+TEMPLATE = lib
+
+TARGET = blinq
+
+# Defining keywords such as 'signal' clashes with the chromium code base.
+DEFINES += QT_NO_KEYWORDS
+
+QT += gui-private
+
+SOURCES = \
+        blinqpage.cpp
+
+HEADERS = \
+        blinqpage.h
+
diff --git a/process/process.gyp b/process/process.gyp
deleted file mode 100644
index c055c2e9f..000000000
--- a/process/process.gyp
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  'targets': [
-  {
-    'target_name': 'blinq_process',
-      'type': 'executable',
-      'includes': [
-        '../blinq.gypi',
-      ],
-      'sources': [
-        'main.cpp',
-      ],
-  },
-    ],
-}
diff --git a/process/process.pro b/process/process.pro
new file mode 100644
index 000000000..efb517a5f
--- /dev/null
+++ b/process/process.pro
@@ -0,0 +1,11 @@
+# This is a dummy .pro file used to extract some aspects of the used configuration and feed them to gyp
+# We want the gyp generation step to happen after all the other config steps. For that we need to prepend
+# our gypi_gen.prf feature to the CONFIG variable since it is processed backwards
+CONFIG = gypi_gen $$CONFIG
+
+TARGET = blinq_process
+TEMPLATE = app
+
+QT -= gui core
+
+SOURCES = main.cpp
-- 
GitLab