summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Boeckel <mathstuf@users.noreply.github.com>2016-10-12 12:58:12 -0400
committerTodd Gamblin <tgamblin@llnl.gov>2016-10-12 09:58:12 -0700
commitb369be65d778cdc634d777c1a0c59f1fd1e070e4 (patch)
treecf5f3817693cd6fdaf31f7a20d4766e644d7bd07 /lib
parent1925db5c770427f99c0e23dacbf16ac2b707ffa3 (diff)
downloadspack-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.py2
-rw-r--r--lib/spack/spack/compiler.py26
-rw-r--r--lib/spack/spack/compilers/clang.py79
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)