Bug 1382697 - Detect symlink and hard link support in configure; r?glandium draft
authorGregory Szorc <gps@mozilla.com>
Thu, 20 Jul 2017 09:06:27 -0700
changeset 613672 64f2a9a404205690fa6bb53dacf8471b0e4810c7
parent 613671 2544a1304096c9e7baa4ab04f594e1afb6a67244
child 613673 c12dbdf52f38041e2a2b2475c3139522efd1c745
push id69832
push usergszorc@mozilla.com
push dateSat, 22 Jul 2017 06:27:51 +0000
reviewersglandium
bugs1382697
milestone56.0a1
Bug 1382697 - Detect symlink and hard link support in configure; r?glandium Various components of the build system want to "install" files into the objdir. While there are N>1 components that do this (nsinstall, nsinstall.py, mozpack, etc), they all rely on run-time detection for filesystem feature support to determine whether a symlink can be performed (if allowed, of course). Historically, symlinks have mostly just worked. Although periodically a developer will complain that it is difficult to copy the dist directory to another machine because it contains symlinks into the source directory. And more recently MacOS sandboxing is experiencing problems with symlinks, possibly necessitating the use of file copying or hard links. Because file installation strategy is non-trivial and is something that users may wish to configure depending on their development workflow, it makes sense to formalize support for various file install mechanisms. The first step of that is to detect various file installation support in configure. This commit teaches configure to look for symlink and hard link support between topsrcdir and topobjdir. Currently, detection is trivial: it just attempts to create a symlink and hard link using available Python functions. It doesn't yet support links on Windows/NTFS. Nor does it attempt to detect common hard link bugs. These can be added later. MozReview-Commit-ID: 2lsXAhgWqYp
build/moz.configure/init.configure
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -717,16 +717,74 @@ set_define('XP_LINUX', target_is_linux)
 
 @depends(target)
 def target_is_solaris(target):
     if target.kernel == 'SunOS':
         return True
 
 set_define('XP_SOLARIS', target_is_solaris)
 
+# Filesystem feature support
+# ===================================
+
+@template
+def check_links(sym_or_hard, desc, source=None):
+    func_name = {
+        'symbolic': 'symlink',
+        'hard': 'link',
+    }[sym_or_hard]
+
+    source_name = source
+
+    @depends(check_build_environment)
+    @checking('for %s link support %s' % (sym_or_hard, desc))
+    @imports(_from='__builtin__', _import='OSError')
+    @imports(_from='__builtin__', _import='open')
+    @imports('errno')
+    @imports('os')
+    def check(build_env):
+        func = getattr(os, func_name, None)
+        if not func:
+            return None
+
+        if source_name:
+            source = os.path.join(build_env.topsrcdir, source_name)
+        else:
+            source = os.path.join(build_env.topobjdir, '%s.source' % sym_or_hard)
+            with open(source, 'a'):
+                pass
+
+        dest = os.path.join(build_env.topobjdir, '%s.test' % sym_or_hard)
+
+        try:
+            os.remove(dest)
+        except OSError as e:
+            if e.errno != errno.ENOENT:
+                raise
+
+        try:
+            func(source, dest)
+        except OSError:
+            return None
+
+        os.remove(dest)
+
+        return True
+
+    return check
+
+topobjdir_symlinks = check_links('symbolic', 'from topsrcdir to topobjdir',
+                                 'mach')
+set_config('TOPOBJDIR_TOPSRCDIR_SYMLINKS', topobjdir_symlinks)
+topobjdir_hardlinks = check_links('hard', 'from topsrcdir to topobjdir',
+                                  'mach')
+set_config('TOPOBJDIR_TOPSRCDIR_HARDLINKS', topobjdir_hardlinks)
+set_config('TOPOBJDIR_INTRA_HARDLINKS',
+           check_links('hard', 'within topobjdir'))
+
 # The application/project to build
 # ==============================================================
 option('--enable-application', nargs=1, env='MOZ_BUILD_APP',
        help='Application to build. Same as --enable-project.')
 
 @depends('--enable-application', '--help')
 def application(app, help):
     if app: