diff options
author | Ben Boeckel <mathstuf@users.noreply.github.com> | 2016-10-12 12:58:12 -0400 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2016-10-12 09:58:12 -0700 |
commit | b369be65d778cdc634d777c1a0c59f1fd1e070e4 (patch) | |
tree | cf5f3817693cd6fdaf31f7a20d4766e644d7bd07 /lib | |
parent | 1925db5c770427f99c0e23dacbf16ac2b707ffa3 (diff) | |
download | spack-b369be65d778cdc634d777c1a0c59f1fd1e070e4.tar.gz spack-b369be65d778cdc634d777c1a0c59f1fd1e070e4.tar.bz2 spack-b369be65d778cdc634d777c1a0c59f1fd1e070e4.tar.xz spack-b369be65d778cdc634d777c1a0c59f1fd1e070e4.zip |
Mock up Xcode devdir to make Qt5 work on Mac OS X (#1832)
* build_environment: allow compilers to set up an environment
* clang: mock up a toolchain directory for xcode
Some projects ignore CC and CXX flags and instead use xcode to find the
toolchain. Clang on Apple should set up the environment properly.
Arguably, every compiler could do this on Apple, but let's see how this
works out just for AppleClang for now.
The Documentation directory is ~1.7G and the excluded platforms add up
to about 7G. Ignoring swift saves another 500M. The resulting Xcode.app
copy is in the 2G range.
* compiler: set member variables early
This is required so that later methods can query things such as the
version of the compiler.
* compiler: support finding the real path of the compiler
On Apple, the /usr/bin compilers are actually wrapping tools themselves
which query xcrun for the currently selected Xcode installation. Pierce
this veil and get the real, full path the to underlying compilers
instead.
* icu4c: install with rpath
On macOS, icu installs with a library ID of the library name. Enabling
rpath makes its ID its full installed path which lets Qt5 link against
it successfully.
* qt: no -no-gtkstyle flag on Qt5 on macOS
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/build_environment.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/compiler.py | 26 | ||||
-rw-r--r-- | lib/spack/spack/compilers/clang.py | 79 |
3 files changed, 102 insertions, 5 deletions
diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 15fb943ca4..792cd09eb8 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -223,6 +223,8 @@ def set_compiler_environment_variables(pkg, env): for mod in compiler.modules: load_module(mod) + compiler.setup_custom_environment(env) + return env diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index a77991e4dc..fc663ea646 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -114,9 +114,15 @@ class Compiler(object): def __init__(self, cspec, operating_system, paths, modules=[], alias=None, **kwargs): + self.operating_system = operating_system + self.spec = cspec + self.modules = modules + self.alias = alias + def check(exe): if exe is None: return None + exe = self._find_full_path(exe) _verify_executables(exe) return exe @@ -138,11 +144,6 @@ class Compiler(object): if value is not None: self.flags[flag] = value.split() - self.operating_system = operating_system - self.spec = cspec - self.modules = modules - self.alias = alias - @property def version(self): return self.spec.version @@ -269,6 +270,21 @@ class Compiler(object): successful.reverse() return dict(((v, p, s), path) for v, p, s, path in successful) + def _find_full_path(self, path): + """Return the actual path for a tool. + + Some toolchains use forwarding executables (particularly Xcode-based + toolchains) which can be manipulated by external environment variables. + This method should be used to extract the actual path used for a tool + by finding out the end executable the forwarding executables end up + running. + """ + return path + + def setup_custom_environment(self, env): + """Set any environment variables necessary to use the compiler.""" + pass + def __repr__(self): """Return a string representation of the compiler toolchain.""" return self.__str__() diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index f7f1bf106b..34eec4ea7b 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -23,11 +23,14 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## import re +import os +import spack import spack.compiler as cpr from spack.compiler import * from spack.util.executable import * import llnl.util.tty as tty from spack.version import ver +from shutil import copytree, ignore_patterns class Clang(Compiler): @@ -107,3 +110,79 @@ class Clang(Compiler): cpr._version_cache[comp] = ver return cpr._version_cache[comp] + + def _find_full_path(self, path): + basename = os.path.basename(path) + + if not self.is_apple or basename not in ('clang', 'clang++'): + return super(Clang, self)._find_full_path(path) + + xcrun = Executable('xcrun') + full_path = xcrun('-f', basename, output=str) + return full_path.strip() + + def setup_custom_environment(self, env): + """Set the DEVELOPER_DIR environment for the Xcode toolchain. + + On macOS, not all buildsystems support querying CC and CXX for the + compilers to use and instead query the Xcode toolchain for what + compiler to run. This side-steps the spack wrappers. In order to inject + spack into this setup, we need to copy (a subset of) Xcode.app and + replace the compiler executables with symlinks to the spack wrapper. + Currently, the stage is used to store the Xcode.app copies. We then set + the 'DEVELOPER_DIR' environment variables to cause the xcrun and + related tools to use this Xcode.app. + """ + super(Clang, self).setup_custom_environment(env) + + if not self.is_apple: + return + + xcode_select = Executable('xcode-select') + real_root = xcode_select('--print-path', output=str).strip() + real_root = os.path.dirname(os.path.dirname(real_root)) + developer_root = os.path.join(spack.stage_path, + 'xcode-select', + self.name, + str(self.version)) + xcode_link = os.path.join(developer_root, 'Xcode.app') + + if not os.path.exists(developer_root): + tty.warn('Copying Xcode from %s to %s in order to add spack ' + 'wrappers to it. Please do not interrupt.' + % (real_root, developer_root)) + + # We need to make a new Xcode.app instance, but with symlinks to + # the spack wrappers for the compilers it ships. This is necessary + # because some projects insist on just asking xcrun and related + # tools where the compiler runs. These tools are very hard to trick + # as they do realpath and end up ignoring the symlinks in a + # "softer" tree of nothing but symlinks in the right places. + copytree(real_root, developer_root, symlinks=True, + ignore=ignore_patterns('AppleTV*.platform', + 'Watch*.platform', + 'iPhone*.platform', + 'Documentation', + 'swift*')) + + real_dirs = [ + 'Toolchains/XcodeDefault.xctoolchain/usr/bin', + 'usr/bin', + ] + + bins = ['c++', 'c89', 'c99', 'cc', 'clang', 'clang++', 'cpp'] + + for real_dir in real_dirs: + dev_dir = os.path.join(developer_root, + 'Contents', + 'Developer', + real_dir) + for fname in os.listdir(dev_dir): + if fname in bins: + os.unlink(os.path.join(dev_dir, fname)) + os.symlink(os.path.join(spack.build_env_path, 'cc'), + os.path.join(dev_dir, fname)) + + os.symlink(developer_root, xcode_link) + + env.set('DEVELOPER_DIR', xcode_link) |