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
--- 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: