Bug 840588 - Create a mach wrapper that searches up from $CWD for a topsrcdir [r=gps]
authorMatt Brubeck <mbrubeck@mozilla.com>
Fri, 01 Mar 2013 15:51:11 -0800
changeset 123523 e7ac597e55b685c597f5d1d0dab7a2a78ba498a0
parent 123522 ab0dfce25486d6e6069bb97b9728244f159fb463
child 123524 e6a9a560661769b5237d57bfb2526faf5f5a435a
push id1395
push userryanvm@gmail.com
push dateSun, 03 Mar 2013 04:46:03 +0000
treeherderfx-team@78a7a63eec08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs840588
milestone22.0a1
Bug 840588 - Create a mach wrapper that searches up from $CWD for a topsrcdir [r=gps]
build/mach_bootstrap.py
mach
copy from mach
copy to build/mach_bootstrap.py
--- a/mach
+++ b/build/mach_bootstrap.py
@@ -4,30 +4,21 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import print_function, unicode_literals
 
 import os
 import platform
 import sys
 
-# Ensure we are running Python 2.7+. We put this check here so we generate a
-# user-friendly error message rather than a cryptic stack trace on module
-# import.
-if sys.version_info[0] != 2 or sys.version_info[1] < 7:
-    print('Python 2.7 or above (but not Python 3) is required to run mach.')
-    print('You are running Python', platform.python_version())
-    sys.exit(1)
-
 # TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
 SEARCH_PATHS = [
     'python/mach',
     'python/mozboot',
     'python/mozbuild',
-    'build',
     'build/pymake',
     'python/blessings',
     'python/psutil',
     'python/which',
     'other-licenses/ply',
     'xpcom/idl-parser',
     'testing',
     'testing/xpcshell',
@@ -43,24 +34,27 @@ MACH_MODULES = [
     'python/mozboot/mozboot/mach_commands.py',
     'python/mozbuild/mozbuild/config.py',
     'python/mozbuild/mozbuild/mach_commands.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'testing/mochitest/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
 ]
 
-our_dir = os.path.dirname(os.path.abspath(__file__))
-
-try:
-    import mach.main
-except ImportError:
-    sys.path[0:0] = [os.path.join(our_dir, path) for path in SEARCH_PATHS]
+def bootstrap(topsrcdir):
+    # Ensure we are running Python 2.7+. We put this check here so we generate a
+    # user-friendly error message rather than a cryptic stack trace on module
+    # import.
+    if sys.version_info[0] != 2 or sys.version_info[1] < 7:
+        print('Python 2.7 or above (but not Python 3) is required to run mach.')
+        print('You are running Python', platform.python_version())
+        sys.exit(1)
 
-    import mach.main
-
-# All of the code is in a module because EVERYTHING IS A LIBRARY.
-mach = mach.main.Mach(our_dir)
+    try:
+        import mach.main
+    except ImportError:
+        sys.path[0:0] = [os.path.join(topsrcdir, path) for path in SEARCH_PATHS]
+        import mach.main
 
-for path in MACH_MODULES:
-    mach.load_commands_from_file(os.path.join(our_dir, path))
-
-sys.exit(mach.run(sys.argv[1:]))
+    mach = mach.main.Mach(topsrcdir)
+    for path in MACH_MODULES:
+        mach.load_commands_from_file(os.path.join(topsrcdir, path))
+    return mach
--- a/mach
+++ b/mach
@@ -1,66 +1,51 @@
 #!/usr/bin/env python
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import print_function, unicode_literals
 
 import os
-import platform
 import sys
 
-# Ensure we are running Python 2.7+. We put this check here so we generate a
-# user-friendly error message rather than a cryptic stack trace on module
-# import.
-if sys.version_info[0] != 2 or sys.version_info[1] < 7:
-    print('Python 2.7 or above (but not Python 3) is required to run mach.')
-    print('You are running Python', platform.python_version())
-    sys.exit(1)
+def ancestors(path):
+    while path:
+        yield path
+        (path, child) = os.path.split(path)
+        if child == "":
+            break
 
-# TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
-SEARCH_PATHS = [
-    'python/mach',
-    'python/mozboot',
-    'python/mozbuild',
-    'build',
-    'build/pymake',
-    'python/blessings',
-    'python/psutil',
-    'python/which',
-    'other-licenses/ply',
-    'xpcom/idl-parser',
-    'testing',
-    'testing/xpcshell',
-    'testing/mozbase/mozprocess',
-    'testing/mozbase/mozfile',
-    'testing/mozbase/mozinfo',
-]
+def load_mach(topsrcdir):
+    sys.path[0:0] = [os.path.join(topsrcdir, "build")]
+    import mach_bootstrap
+    return mach_bootstrap.bootstrap(topsrcdir)
 
-# Individual files providing mach commands.
-MACH_MODULES = [
-    'addon-sdk/mach_commands.py',
-    'layout/tools/reftest/mach_commands.py',
-    'python/mozboot/mozboot/mach_commands.py',
-    'python/mozbuild/mozbuild/config.py',
-    'python/mozbuild/mozbuild/mach_commands.py',
-    'python/mozbuild/mozbuild/frontend/mach_commands.py',
-    'testing/mochitest/mach_commands.py',
-    'testing/xpcshell/mach_commands.py',
-]
-
-our_dir = os.path.dirname(os.path.abspath(__file__))
+# Check whether the current directory is within a mach src or obj dir.
+for dir_path in ancestors(os.getcwd()):
+    # If we find a "mozinfo.json" file, we are in the objdir.
+    mozinfo_path = os.path.join(dir_path, "mozinfo.json")
+    if os.path.isfile(mozinfo_path):
+        import json
+        info = json.load(open(mozinfo_path))
+        if "mozconfig" in info and "MOZCONFIG" not in os.environ:
+            # If the MOZCONFIG environment variable is not already set, set it
+            # to the value from mozinfo.json.  This will tell the build system
+            # to look for a config file at the path in $MOZCONFIG rather than
+            # its default locations.
+            #
+            # Note: subprocess requires native strings in os.environ Python
+            # 2.7.2 and earlier on Windows.
+            os.environ[b"MOZCONFIG"] = str(info["mozconfig"])
 
-try:
-    import mach.main
-except ImportError:
-    sys.path[0:0] = [os.path.join(our_dir, path) for path in SEARCH_PATHS]
-
-    import mach.main
+        if "topsrcdir" in info:
+            # Continue searching for mach_bootstrap in the source directory.
+            dir_path = info["topsrcdir"]
 
-# All of the code is in a module because EVERYTHING IS A LIBRARY.
-mach = mach.main.Mach(our_dir)
+    # If we find the mach bootstrap module, we are in the srcdir.
+    mach_path = os.path.join(dir_path, "build/mach_bootstrap.py")
+    if os.path.isfile(mach_path):
+        mach = load_mach(dir_path)
+        sys.exit(mach.run(sys.argv[1:]))
 
-for path in MACH_MODULES:
-    mach.load_commands_from_file(os.path.join(our_dir, path))
-
-sys.exit(mach.run(sys.argv[1:]))
+print("Could not run mach: No mach source directory found")
+sys.exit(1)