[tor-commits] [tor-browser-bundle/master] Add gcc, dllwrap, and swig wrappers for Wine.

mikeperry at torproject.org mikeperry at torproject.org
Tue Jan 21 04:47:04 UTC 2014


commit 87142112db32e1999de9ab2a213f5521d37a1e94
Author: David Fifield <david at bamsoftware.com>
Date:   Fri Nov 22 17:22:42 2013 +0000

    Add gcc, dllwrap, and swig wrappers for Wine.
    
    Python distutils, with the "mingw32" compiler profile, is inflexible. It
    hardcodes the names "gcc.exe" and "dllwrap.exe", and passes them fixed
    options. It's not possible to control it with environment variables like
    CC and CFLAGS.
    
    Before Python 2.7.6, distutils always passes the option -mno-cygwin to
    gcc, which causes an error. Additionally, when distutils is run under
    Wine, it passes Windows-style paths with backslashes to our unsuspecting
    i686-w64-mingw32-gcc.
    
    These wrapper programs strip -mno-cygwin, and convert Windows paths to
    Unix paths. They also set LD_PRELOAD and FAKETIME, because those can't
    be set for the outer Wine process.
    
    Doing a subprocess.Popen of a Unix program from within Wine mostly
    works. For example, subprocess.Popen(["/usr/bin/i686-w64-mingw32-gcc"])
    starts a new compiler process. However, if you .wait() on the process
    object, you get a "WindowsError: [Error 6] Invalid handle". The same
    goes for the implicit wait in subprocess.call and
    subprocess.check_output. The .pid of such processes is 0.
    
    What you can do, however, is read from one of the process's output
    streams--it will be closed when the process terminates. Because we know
    we are dealing with gcc subprocesses, we read its stderr and look for
    the string " error: ". If it appears, we return a non-zero status code.
    We don't return non-zero merely on a non-empty stderr, because warnings
    don't usually cause that.
    
    The difficulty doesn't exist when running native Windows binaries.
    That's why we can do subprocess.call(["winepath", ...]): because
    winepath.exe is a native binary that comes with Wine.
---
 gitian/build-helpers/wine-wrappers/common.py   |   27 ++++++++++++++++++
 gitian/build-helpers/wine-wrappers/dllwrap.py  |   36 ++++++++++++++++++++++++
 gitian/build-helpers/wine-wrappers/gcc.py      |   36 ++++++++++++++++++++++++
 gitian/build-helpers/wine-wrappers/settings.py |    2 ++
 gitian/build-helpers/wine-wrappers/setup.py    |    7 +++++
 gitian/build-helpers/wine-wrappers/swig.py     |   33 ++++++++++++++++++++++
 gitian/mkbundle-linux.sh                       |    2 +-
 gitian/mkbundle-mac.sh                         |    2 +-
 gitian/mkbundle-windows.sh                     |    2 +-
 9 files changed, 144 insertions(+), 3 deletions(-)

diff --git a/gitian/build-helpers/wine-wrappers/common.py b/gitian/build-helpers/wine-wrappers/common.py
new file mode 100644
index 0000000..19e994b
--- /dev/null
+++ b/gitian/build-helpers/wine-wrappers/common.py
@@ -0,0 +1,27 @@
+import os
+import subprocess
+
+import settings
+
+def winepath(windowspath):
+    """Convert a Windows path to a Unix path."""
+    return subprocess.check_output(["winepath", "-u", windowspath])[:-1]
+
+def search_startswith(a, elems):
+    """Search for the first element of the array a that startswith any of the
+    members of elems, and return it. Return None if no match was found."""
+    for e in elems:
+        if a.startswith(e):
+            return e
+    return None
+
+def popen_faketime(*args, **kwargs):
+    """Does subprocess.Popen after setting faketime environment variables."""
+    ld_preload = os.getenv("LD_PRELOAD")
+    if ld_preload:
+        # ld.so(8): "The items of [LD_PRELOAD] can be separated by spaces or colons."
+        ld_preload += ":"
+    ld_preload += settings.LD_PRELOAD
+    os.putenv("LD_PRELOAD", ld_preload)
+    os.putenv("FAKETIME", settings.FAKETIME)
+    return subprocess.Popen(*args, **kwargs)
diff --git a/gitian/build-helpers/wine-wrappers/dllwrap.py b/gitian/build-helpers/wine-wrappers/dllwrap.py
new file mode 100755
index 0000000..fdff035
--- /dev/null
+++ b/gitian/build-helpers/wine-wrappers/dllwrap.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+# A wrapper for i686-w64-mingw32-dllwrap that removes -mno-cygwin and converts
+# Windows paths to Unix paths, so that the w64-mingw32 dllwrap can be called by
+# Python distutils.
+
+import os
+import subprocess
+import sys
+
+import common
+
+args = ["/usr/bin/i686-w64-mingw32-dllwrap"]
+sys.argv.pop(0)
+while sys.argv:
+    a = sys.argv.pop(0)
+    if not a.startswith("-"):
+        args.append(common.winepath(a))
+        continue
+    if a == "-mno-cygwin":
+        continue
+    if a in ("-I", "-L", "-s", "--def", "--output-lib"):
+        args.append(a)
+        args.append(common.winepath(sys.argv.pop(0)))
+        continue
+    o = common.search_startswith(a, ("-I", "-L", "--def=", "--output-lib="))
+    if o is not None:
+        path = a[len(o):]
+        args.append("%s%s" % (o, common.winepath(path)))
+        continue
+    args.append(a)
+p = common.popen_faketime(args, stderr=subprocess.PIPE)
+stderr = p.stderr.read()
+sys.stderr.write(stderr)
+if " error: " in stderr:
+    sys.exit(1)
diff --git a/gitian/build-helpers/wine-wrappers/gcc.py b/gitian/build-helpers/wine-wrappers/gcc.py
new file mode 100755
index 0000000..493b27b
--- /dev/null
+++ b/gitian/build-helpers/wine-wrappers/gcc.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+# A wrapper for i686-w64-mingw32-gcc that removes -mno-cygwin and converts
+# Windows paths to Unix paths, so that the w64-mingw32 gcc can be called by
+# Python distutils.
+
+import os
+import subprocess
+import sys
+
+import common
+
+args = ["/usr/bin/i686-w64-mingw32-gcc"]
+sys.argv.pop(0)
+while sys.argv:
+    a = sys.argv.pop(0)
+    if not a.startswith("-"):
+        args.append(common.winepath(a))
+        continue
+    if a == "-mno-cygwin":
+        continue
+    if a in ("-I", "-L"):
+        args.append(a)
+        args.append(common.winepath(sys.argv.pop(0)))
+        continue
+    o = common.search_startswith(a, ("-I", "-L"))
+    if o is not None:
+        path = a[len(o):]
+        args.append("%s%s" % (o, common.winepath(path)))
+        continue
+    args.append(a)
+p = common.popen_faketime(args, stderr=subprocess.PIPE)
+stderr = p.stderr.read()
+sys.stderr.write(stderr)
+if " error: " in stderr:
+    sys.exit(1)
diff --git a/gitian/build-helpers/wine-wrappers/settings.py b/gitian/build-helpers/wine-wrappers/settings.py
new file mode 100644
index 0000000..f395433
--- /dev/null
+++ b/gitian/build-helpers/wine-wrappers/settings.py
@@ -0,0 +1,2 @@
+LD_PRELOAD = "/usr/lib/faketime/libfaketime.so.1"
+FAKETIME = "2000-01-01 00:00:00"
diff --git a/gitian/build-helpers/wine-wrappers/setup.py b/gitian/build-helpers/wine-wrappers/setup.py
new file mode 100644
index 0000000..797015e
--- /dev/null
+++ b/gitian/build-helpers/wine-wrappers/setup.py
@@ -0,0 +1,7 @@
+from distutils.core import setup
+import py2exe
+setup(
+    console=["gcc.py", "dllwrap.py", "swig.py"],
+    zipfile=None,
+    options={"py2exe": {"bundle_files": 1, "compressed": True}}
+)
diff --git a/gitian/build-helpers/wine-wrappers/swig.py b/gitian/build-helpers/wine-wrappers/swig.py
new file mode 100755
index 0000000..45941f4
--- /dev/null
+++ b/gitian/build-helpers/wine-wrappers/swig.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+# A wrapper for swig that converts Windows paths to Unix paths, so that swig can
+# be called by Python distutils.
+
+import os
+import subprocess
+import sys
+
+import common
+
+args = ["/usr/bin/swig"]
+sys.argv.pop(0)
+while sys.argv:
+    a = sys.argv.pop(0)
+    if not a.startswith("-"):
+        args.append(common.winepath(a))
+        continue
+    if a in ("-I",):
+        args.append(a)
+        args.append(common.winepath(sys.argv.pop(0)))
+        continue
+    o = common.search_startswith(a, ("-I",))
+    if o is not None:
+        path = a[len(o):]
+        args.append("%s%s" % (o, common.winepath(path)))
+        continue
+    args.append(a)
+p = common.popen_faketime(args, stderr=subprocess.PIPE)
+stderr = p.stderr.read()
+sys.stderr.write(stderr)
+if " Error: " in stderr:
+    sys.exit(1)
diff --git a/gitian/mkbundle-linux.sh b/gitian/mkbundle-linux.sh
index 9ef0910..3b92216 100755
--- a/gitian/mkbundle-linux.sh
+++ b/gitian/mkbundle-linux.sh
@@ -41,7 +41,7 @@ echo "pref(\"torbrowser.version\", \"$TORBROWSER_VERSION-Linux\");" > $GITIAN_DI
 echo "$TORBROWSER_VERSION" > $GITIAN_DIR/inputs/bare-version
 cp -a $WRAPPER_DIR/$VERSIONS_FILE $GITIAN_DIR/inputs/versions
 
-cp $WRAPPER_DIR/build-helpers/* $GITIAN_DIR/inputs/
+cp -r $WRAPPER_DIR/build-helpers/* $GITIAN_DIR/inputs/
 
 cd $WRAPPER_DIR/..
 rm -f $GITIAN_DIR/inputs/relativelink-src.zip
diff --git a/gitian/mkbundle-mac.sh b/gitian/mkbundle-mac.sh
index 8e4da79..69ef3ed 100755
--- a/gitian/mkbundle-mac.sh
+++ b/gitian/mkbundle-mac.sh
@@ -41,7 +41,7 @@ echo "pref(\"torbrowser.version\", \"$TORBROWSER_VERSION-MacOS\");" > $GITIAN_DI
 echo "$TORBROWSER_VERSION" > $GITIAN_DIR/inputs/bare-version
 cp -a $WRAPPER_DIR/$VERSIONS_FILE $GITIAN_DIR/inputs/versions
 
-cp $WRAPPER_DIR/build-helpers/* $GITIAN_DIR/inputs/
+cp -r $WRAPPER_DIR/build-helpers/* $GITIAN_DIR/inputs/
 
 cd $WRAPPER_DIR/..
 rm -f $GITIAN_DIR/inputs/relativelink-src.zip
diff --git a/gitian/mkbundle-windows.sh b/gitian/mkbundle-windows.sh
index 33e8a2b..9542604 100755
--- a/gitian/mkbundle-windows.sh
+++ b/gitian/mkbundle-windows.sh
@@ -42,7 +42,7 @@ echo "pref(\"torbrowser.version\", \"$TORBROWSER_VERSION-Windows\");" > $GITIAN_
 echo "$TORBROWSER_VERSION" > $GITIAN_DIR/inputs/bare-version
 cp -a $WRAPPER_DIR/$VERSIONS_FILE $GITIAN_DIR/inputs/versions
 
-cp $WRAPPER_DIR/build-helpers/* $GITIAN_DIR/inputs/
+cp -r $WRAPPER_DIR/build-helpers/* $GITIAN_DIR/inputs/
 cp $WRAPPER_DIR/gpg/ubuntu-wine.gpg $GITIAN_DIR/inputs/
 
 cd $WRAPPER_DIR/..





More information about the tor-commits mailing list