Browse Source

improve the setup targets in the build script

* better detection of Debian/Ubuntu and derived distributions
* building on 32-bit distributions is supported (for i386 targets)
* introduce separate target to setup the MinGW-w64 toolchain
Ashish Kulkarni 11 years ago
parent
commit
e645739081
2 changed files with 72 additions and 49 deletions
  1. 23 12
      INSTALL.md
  2. 49 37
      scripts/build.py

+ 23 - 12
INSTALL.md

@@ -2,32 +2,43 @@ Clone this repository by running the following command:
 
     git clone --recursive https://github.com/wkhtmltopdf/wkhtmltopdf.git
 
-If you are on Windows, make sure that you are cloning in a location without spaces/special characters in the name.
+If you are on Windows, make sure that you are cloning in a location without
+spaces/special characters in the name.
 
 Prerequisites: Linux
 --------------------
 
-Building is currently supported only on recent 64-bit Debian/Ubuntu releases. All binaries are produced in a self-contained chroot environment for the target distribution, so you will need to setup it up first by running ```scripts/build.py```. The following distributions are currently supported:
+Building is currently supported only on recent Debian/Ubuntu releases. All
+binaries are produced in a self-contained chroot environment for the target
+distribution, so you will need to setup it up first by running 
+```scripts/build.py```. The following targets are currently supported:
 
-Distribution   | Command for Setup
-------------   | -----------------
-Debian Wheezy  | ```scripts/build.py setup-schroot-wheezy```
-CentOS 5       | ```scripts/build.py setup-schroot-centos5```
+Target         | Command for Setup
+------         | -----------------
+Debian Wheezy  | ```sudo scripts/build.py setup-schroot-wheezy```
+CentOS 5       | ```sudo scripts/build.py setup-schroot-centos5```
+MinGW-w64      | ```sudo scripts/build.py setup-mingw-w64```
 
-Please note a MinGW-w64 toolchain (which can cross-compile Windows binaries from Linux) is setup by default -- it is useful for targetting Windows XP/Windows 2003, which are not supported by default when compiling with MSVC 2013.
+The MinGW-w64 toolchain can cross-compile 32/64-bit Windows binaries from 
+Linux -- it is useful for targetting Windows XP/Windows 2003, which are not
+supported by default when compiling with MSVC 2013.
 
 Prerequisites: Windows
 ----------------------
 
-* Install Visual Studio 2008 or later ([2013 Express](http://www.microsoft.com/en-US/download/details.aspx?id=40787) is recommended) or follow instructions for [Windows SDK 7.1](http://qt-project.org/wiki/Category:Tools::msvc)
+* Install Visual Studio 2008 or later ([2013 Express](http://www.microsoft.com/en-US/download/details.aspx?id=40787)
+  is recommended) or follow instructions for [Windows SDK 7.1](http://qt-project.org/wiki/Category:Tools::msvc)
 * Do "Windows Update" to ensure that VC/SDK security patches are up-to-date
-* Install latest ActivePerl from http://www.activestate.com/activeperl/downloads
-* Install latest Python 2.7 from http://www.python.org/downloads/windows/
-* Install NSIS 2.46 from http://nsis.sourceforge.net/Download
+* Install the latest [ActivePerl](http://www.activestate.com/activeperl/downloads) release
+* Install the latest [Python 2.7](http://www.python.org/downloads/windows/) release
+* Install [NSIS 2.46](http://nsis.sourceforge.net/Download)
 * Make sure that you can run "git". If not, add it to the PATH or reinstall
   with option "Run Git from the Windows Command Prompt".
 
 Building
 --------
 
-Switch to the checked-out folder and run the command ```scripts/build.py``` (or ```scripts\build.py``` if you are on Windows). This will present all the options which you can build. Select the appropriate target and all the requisite output will be generated in the ```static-build``` folder.
+Switch to the checked-out folder and run the command ```scripts/build.py```
+(or ```scripts\build.py``` if you are on Windows). This will present all
+the targets which you can build. Select the appropriate target and the 
+output package will be generated in the ```static-build``` folder.

+ 49 - 37
scripts/build.py

@@ -167,6 +167,7 @@ BUILDERS = {
     'msvc2013-win64':        'msvc',
     'msvc-winsdk71-win32':   'msvc_winsdk71',
     'msvc-winsdk71-win64':   'msvc_winsdk71',
+    'setup-mingw-w64':       'setup_mingw64',
     'setup-schroot-centos5': 'setup_schroot',
     'setup-schroot-wheezy':  'setup_schroot',
     'update-all-schroots':   'update_schroot',
@@ -178,7 +179,6 @@ BUILDERS = {
     'mingw-w64-cross-win64': 'mingw64_cross'
 }
 
-HOST_PACKAGES = ['git-core', 'xz-utils', 'build-essential', 'mingw-w64', 'nsis', 'debootstrap', 'schroot', 'rinse']
 CHROOT_SETUP  = {
     'wheezy': [
         ('debootstrap', 'wheezy', 'http://ftp.us.debian.org/debian/'),
@@ -209,7 +209,7 @@ deb-src http://security.debian.org/   wheezy/updates main contrib non-free"""),
 
 # --------------------------------------------------------------- HELPERS
 
-import os, sys, subprocess, shutil, fnmatch, multiprocessing
+import os, sys, platform, subprocess, shutil, re, fnmatch, multiprocessing
 
 from os.path import exists
 
@@ -229,6 +229,12 @@ def shell(cmd):
     if ret != 0:
         error("command failed: exit code %d" % ret)
 
+def get_output(*cmd):
+    try:
+        return subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip()
+    except subprocess.CalledProcessError:
+        return None
+
 def rmdir(path):
     if exists(path):
         shutil.rmtree(path)
@@ -243,9 +249,8 @@ def get_version(basedir):
         return (text, text)
     version = text[:text.index('-')]
     os.chdir(os.path.join(basedir, '..'))
-    try:
-        hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], stderr=subprocess.STDOUT).strip()
-    except subprocess.CalledProcessError:
+    hash = get_output('git', 'rev-parse', '--short', 'HEAD')
+    if not hash:
         return (text, version)
     return ('%s-%s' % (version, hash), version)
 
@@ -289,32 +294,44 @@ def build_openssl(config, basedir):
 
     return OPENSSL['build'][cfg]['os_libs']
 
-# --------------------------------------------------------------- Linux chroot
-
-def check_setup_schroot(config):
-    import platform
-    if not sys.platform.startswith('linux') or \
-       not platform.architecture()[0].startswith('64') or \
-       platform.linux_distribution()[0] not in ['Ubuntu', 'Debian']:
-        error('This can only be run on a 64-bit Debian/Ubuntu distribution, aborting.')
+def check_running_on_debian():
+    if not sys.platform.startswith('linux') or not exists('/etc/apt/sources.list'):
+        error('This can only be run on a Debian/Ubuntu distribution, aborting.')
 
     if os.geteuid() != 0:
         error('This script must be run as root.')
 
-    try:
-        login = subprocess.check_output(['logname'], stderr=subprocess.STDOUT).strip()
-        if login == 'root':
-            error('Please run via sudo to determine login for which schroot access is to be given.')
-    except subprocess.CalledProcessError:
+    if platform.architecture()[0] == '64bit' and 'amd64' not in ARCH:
+        ARCH.insert(0, 'amd64')
+
+PACKAGE_NAME = re.compile(r'ii\s+(.+?)\s+.*')
+def install_packages(*names):
+    lines = get_output('dpkg-query', '--list', *names).split('\n')
+    avail = [PACKAGE_NAME.match(line).group(1) for line in lines if PACKAGE_NAME.match(line)]
+
+    if len(avail) != len(names):
+        shell('apt-get update')
+        shell('apt-get install --assume-yes %s' % (' '.join(names)))
+
+# --------------------------------------------------------------- Linux chroot
+
+ARCH = ['i386']
+
+def check_setup_schroot(config):
+    check_running_on_debian()
+    login = get_output('logname')
+    if not login:
         error('Unable to determine the login for which schroot access is to be given.')
 
+    if login == 'root':
+        error('Please run via sudo to determine login for which schroot access is to be given.')
+
 def build_setup_schroot(config, basedir):
-    shell('apt-get update')
-    shell('apt-get install --assume-yes %s' % (' '.join(HOST_PACKAGES)))
+    install_packages('git', 'debootstrap', 'schroot', 'rinse')
 
-    login  = subprocess.check_output(['logname'], stderr=subprocess.STDOUT).strip()
+    login  = get_output('logname')
     chroot = config[1+config.rindex('-'):]
-    for arch in ['amd64', 'i386']:
+    for arch in ARCH:
         print '******************* %s-%s' % (chroot, arch)
         root_dir = '/opt/wkhtmltopdf-build/%s-%s' % (chroot, arch)
         rmdir(root_dir)
@@ -348,31 +365,26 @@ def build_setup_schroot(config, basedir):
                 cfg.write('type=directory\ndirectory=%s/\n' % root_dir)
                 cfg.write('description=%s %s for wkhtmltopdf\n' % (command[1], arch))
                 cfg.write('users=%s\nroot-users=root\n' % login)
-                if arch == 'i386':
+                if arch == 'i386' and 'amd64' in ARCH:
                     cfg.write('personality=linux32\n')
                 cfg.close()
 
 def check_update_schroot(config):
-    import platform
-    if not sys.platform.startswith('linux') or \
-       not platform.architecture()[0].startswith('64') or \
-       platform.linux_distribution()[0] not in ['Ubuntu', 'Debian']:
-        error('This can only be run on a 64-bit Debian/Ubuntu distribution, aborting.')
-
-    if os.geteuid() != 0:
-        error('This script must be run as root.')
-
-    try:
-        subprocess.check_output(['schroot', '--list'], stderr=subprocess.STDOUT)
-    except subprocess.CalledProcessError:
+    check_running_on_debian()
+    if not get_output('schroot', '--list'):
         error('Unable to determine the list of available schroots.')
 
 def build_update_schroot(config, basedir):
-    names = subprocess.check_output(['schroot', '--list'], stderr=subprocess.STDOUT).strip()
-    for name in names.split('\n'):
+    for name in get_output('schroot', '--list').split('\n'):
         print '******************* %s' % name[name.index('wkhtmltopdf-'):]
         shell('schroot -c %s -- /bin/bash /update.sh' % name[name.index('wkhtmltopdf-'):])
 
+def check_setup_mingw64(config):
+    check_running_on_debian()
+
+def build_setup_mingw64(config, basedir):
+    install_packages('build-essential', 'mingw-w64', 'nsis')
+
 # --------------------------------------------------------------- MSVC (2008-2013)
 
 MSVC_LOCATION = {