diff options
-rw-r--r-- | var/spack/repos/builtin/packages/llvm-doe/package.py | 319 |
1 files changed, 202 insertions, 117 deletions
diff --git a/var/spack/repos/builtin/packages/llvm-doe/package.py b/var/spack/repos/builtin/packages/llvm-doe/package.py index c384210561..88303fae7d 100644 --- a/var/spack/repos/builtin/packages/llvm-doe/package.py +++ b/var/spack/repos/builtin/packages/llvm-doe/package.py @@ -2,12 +2,14 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import os import os.path import re import sys import llnl.util.tty as tty +import spack.build_environment import spack.util.executable @@ -20,14 +22,20 @@ class LlvmDoe(CMakePackage, CudaPackage): url = "https://github.com/llvm-doe-org/llvm-project/archive/llvmorg-10.0.0.zip" git = "https://github.com/llvm-doe-org/llvm-project" maintainers = ['shintaro-iwasaki'] + tags = ['e4s'] + generator = 'Ninja' + + family = "compiler" # Used by lmod + version('doe', branch='doe', preferred=True) version('upstream', branch='llvm.org/main') version('bolt', branch='bolt/main') version('clacc', branch='clacc/master') version('pragma-clang-loop', branch='sollve/pragma-clang-loop') version('pragma-omp-tile', branch='sollve/pragma-omp-tile') + version('13.0.0', branch='llvm.org/llvmorg-13.0.0') # NOTE: The debug version of LLVM is an order of magnitude larger than # the release version, and may take up 20-30 GB of space. If you want @@ -95,6 +103,11 @@ class LlvmDoe(CMakePackage, CudaPackage): "components in a single shared library", ) variant( + "link_llvm_dylib", + default=False, + description="Link LLVM tools against the LLVM shared library", + ) + variant( "all_targets", default=False, description="Build all supported targets, default targets " @@ -112,6 +125,11 @@ class LlvmDoe(CMakePackage, CudaPackage): description="Build with OpenMP capable thread sanitizer", ) variant( + "omp_as_runtime", + default=True, + description="Build OpenMP runtime via ENABLE_RUNTIME by just-built Clang", + ) + variant( "argobots", default=False, description="Build BOLT/OpenMP with Argobots. Effective when @bolt", @@ -120,16 +138,21 @@ class LlvmDoe(CMakePackage, CudaPackage): description="Enable code-signing on macOS") variant("python", default=False, description="Install python bindings") + variant('version_suffix', default='none', description="Add a symbol suffix") + variant('z3', default=False, description='Use Z3 for the clang static analyzer') + extends("python", when="+python") # Build dependency depends_on("cmake@3.4.3:", type="build") + depends_on('cmake@3.13.4:', type='build', when='@12:') + depends_on("ninja", type="build") depends_on("python", when="~python", type="build") depends_on("pkgconfig", type="build") # Universal dependency depends_on("python", when="+python") - depends_on("z3") + depends_on("z3", when='+clang+z3') # openmp dependencies depends_on("perl-data-dumper", type=("build")) @@ -146,22 +169,56 @@ class LlvmDoe(CMakePackage, CudaPackage): depends_on("py-six", when="+lldb +python") # gold support, required for some features - depends_on("binutils+gold", when="+gold") + depends_on("binutils+gold+ld+plugins", when="+gold") conflicts("+llvm_dylib", when="+shared_libs") + conflicts("+link_llvm_dylib", when="~llvm_dylib") conflicts("+lldb", when="~clang") conflicts("+libcxx", when="~clang") conflicts("+internal_unwind", when="~clang") conflicts("+compiler-rt", when="~clang") + conflicts("+flang", when="~clang") - conflicts("%gcc@:5.0") + conflicts('~mlir', when='+flang', msg='Flang requires MLIR') + + # Older LLVM do not build with newer compilers, and vice versa + conflicts("%gcc@8:", when="@:5") + conflicts("%gcc@:5.0", when="@8:") + # clang/lib: a lambda parameter cannot shadow an explicitly captured entity + conflicts("%clang@8:", when="@:4") + + # When these versions are concretized, but not explicitly with +libcxx, these + # conflicts will enable clingo to set ~libcxx, making the build successful: + + # libc++ of LLVM13, see https://libcxx.llvm.org/#platform-and-compiler-support + # @13 does not support %gcc@:10 https://bugs.llvm.org/show_bug.cgi?id=51359#c1 + # GCC 11 - latest stable release per GCC release page + # Clang: 11, 12 - latest two stable releases per LLVM release page + # AppleClang 12 - latest stable release per Xcode release page + conflicts("%gcc@:10", when="@13:+libcxx") + conflicts("%clang@:10", when="@13:+libcxx") + conflicts("%apple-clang@:11", when="@13:+libcxx") + + # libcxx-4 and compiler-rt-4 fail to build with "newer" clang and gcc versions: + conflicts('%gcc@7:', when='@:4+libcxx') + conflicts('%clang@6:', when='@:4+libcxx') + conflicts('%apple-clang@6:', when='@:4+libcxx') + conflicts('%gcc@7:', when='@:4+compiler-rt') + conflicts('%clang@6:', when='@:4+compiler-rt') + conflicts('%apple-clang@6:', when='@:4+compiler-rt') + + # OMP TSAN exists in > 5.x + conflicts("+omp_tsan", when="@:5") + + # OpenMP via ENABLE_RUNTIME restrictions + conflicts("+omp_as_runtime", when="~clang", msg="omp_as_runtime requires clang being built.") + conflicts("+omp_as_runtime", when="@:11.1", msg="omp_as_runtime works since LLVM 12.") # cuda_arch value must be specified conflicts("cuda_arch=none", when="+cuda", msg="A value for cuda_arch must be specified.") - conflicts("+mlir") - - conflicts("+flang", when="~clang") + # MLIR exists in > 10.x + conflicts("+mlir", when="@:9") # code signing is only necessary on macOS", conflicts('+code_signing', when='platform=linux') @@ -348,8 +405,25 @@ class LlvmDoe(CMakePackage, CudaPackage): 'create this identity.' ) + def flag_handler(self, name, flags): + if name == 'cxxflags': + flags.append(self.compiler.cxx11_flag) + return(None, flags, None) + elif name == 'ldflags' and self.spec.satisfies('%intel'): + flags.append('-shared-intel') + return(None, flags, None) + return(flags, None, None) + def setup_build_environment(self, env): - env.append_flags("CXXFLAGS", self.compiler.cxx11_flag) + """When using %clang, add only its ld.lld-$ver and/or ld.lld to our PATH""" + if self.compiler.name in ['clang', 'apple-clang']: + for lld in 'ld.lld-{0}'.format(self.compiler.version.version[0]), 'ld.lld': + bin = os.path.join(os.path.dirname(self.compiler.cc), lld) + sym = os.path.join(self.stage.path, 'ld.lld') + if os.path.exists(bin) and not os.path.exists(sym): + mkdirp(self.stage.path) + os.symlink(bin, sym) + env.prepend_path('PATH', self.stage.path) def setup_run_environment(self, env): if "+clang" in self.spec: @@ -363,71 +437,87 @@ class LlvmDoe(CMakePackage, CudaPackage): def cmake_args(self): spec = self.spec + define = CMakePackage.define + from_variant = self.define_from_variant + python = spec['python'] cmake_args = [ - "-DLLVM_REQUIRES_RTTI:BOOL=ON", - "-DLLVM_ENABLE_RTTI:BOOL=ON", - "-DLLVM_ENABLE_EH:BOOL=ON", - "-DCLANG_DEFAULT_OPENMP_RUNTIME:STRING=libomp", - "-DPYTHON_EXECUTABLE:PATH={0}".format(python.command.path), - "-DLIBOMP_USE_HWLOC:BOOL=ON", - "-DLIBOMP_HWLOC_INSTALL_DIR={0}".format(spec["hwloc"].prefix), + define("LLVM_REQUIRES_RTTI", True), + define("LLVM_ENABLE_RTTI", True), + define("LLVM_ENABLE_EH", True), + define("CLANG_DEFAULT_OPENMP_RUNTIME", "libomp"), + define("PYTHON_EXECUTABLE", python.command.path), + define("LIBOMP_USE_HWLOC", True), + define("LIBOMP_HWLOC_INSTALL_DIR", spec["hwloc"].prefix), ] - if python.version >= Version("3.0.0"): - cmake_args.append("-DPython3_EXECUTABLE={0}".format( - python.command.path)) + version_suffix = spec.variants['version_suffix'].value + if version_suffix != 'none': + cmake_args.append(define('LLVM_VERSION_SUFFIX', version_suffix)) + + if python.version >= Version("3"): + cmake_args.append(define("Python3_EXECUTABLE", python.command.path)) else: - cmake_args.append("-DPython2_EXECUTABLE={0}".format( - python.command.path)) + cmake_args.append(define("Python2_EXECUTABLE", python.command.path)) projects = [] + runtimes = [] if "+cuda" in spec: - cmake_args.extend( - [ - "-DCUDA_TOOLKIT_ROOT_DIR:PATH=" + spec["cuda"].prefix, - "-DLIBOMPTARGET_NVPTX_COMPUTE_CAPABILITIES={0}".format( - ",".join(spec.variants["cuda_arch"].value) - ), - "-DCLANG_OPENMP_NVPTX_DEFAULT_ARCH=sm_{0}".format( - spec.variants["cuda_arch"].value[-1] - ), - ] - ) + cmake_args.extend([ + define("CUDA_TOOLKIT_ROOT_DIR", spec["cuda"].prefix), + define("LIBOMPTARGET_NVPTX_COMPUTE_CAPABILITIES", + ",".join(spec.variants["cuda_arch"].value)), + define("CLANG_OPENMP_NVPTX_DEFAULT_ARCH", + "sm_{0}".format(spec.variants["cuda_arch"].value[-1])), + ]) + if "+omp_as_runtime" in spec: + cmake_args.extend([ + define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True), + # work around bad libelf detection in libomptarget + define("LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR", + spec["libelf"].prefix.include), + ]) else: # still build libomptarget but disable cuda - cmake_args.extend( - [ - "-DCUDA_TOOLKIT_ROOT_DIR:PATH=IGNORE", - "-DCUDA_SDK_ROOT_DIR:PATH=IGNORE", - "-DCUDA_NVCC_EXECUTABLE:FILEPATH=IGNORE", - "-DLIBOMPTARGET_DEP_CUDA_DRIVER_LIBRARIES:STRING=IGNORE", - ] - ) - - if "+omp_debug" in spec: - cmake_args.append("-DLIBOMPTARGET_ENABLE_DEBUG:Bool=ON") + cmake_args.extend([ + define("CUDA_TOOLKIT_ROOT_DIR", "IGNORE"), + define("CUDA_SDK_ROOT_DIR", "IGNORE"), + define("CUDA_NVCC_EXECUTABLE", "IGNORE"), + define("LIBOMPTARGET_DEP_CUDA_DRIVER_LIBRARIES", "IGNORE"), + ]) - if "+python" in spec and "+lldb" in spec: - cmake_args.append("-DLLDB_USE_SYSTEM_SIX:Bool=TRUE") + cmake_args.append(from_variant("LIBOMPTARGET_ENABLE_DEBUG", "omp_debug")) - if "+lldb" in spec and spec.satisfies("@10.0.0:,doe"): - cmake_args.append("-DLLDB_ENABLE_PYTHON:Bool={0}".format( - 'ON' if '+python' in spec else 'OFF')) - if "+lldb" in spec and spec.satisfies("@:9.9.9"): - cmake_args.append("-DLLDB_DISABLE_PYTHON:Bool={0}".format( - 'ON' if '~python' in spec else 'OFF')) + if "+lldb" in spec: + if spec.version >= Version('10'): + cmake_args.append(from_variant("LLDB_ENABLE_PYTHON", 'python')) + else: + cmake_args.append(define("LLDB_DISABLE_PYTHON", + '~python' in spec)) + if spec.satisfies("@5.0.0: +python"): + cmake_args.append(define("LLDB_USE_SYSTEM_SIX", True)) if "+gold" in spec: cmake_args.append( - "-DLLVM_BINUTILS_INCDIR=" + spec["binutils"].prefix.include + define("LLVM_BINUTILS_INCDIR", spec["binutils"].prefix.include) ) if "+clang" in spec: projects.append("clang") projects.append("clang-tools-extra") - projects.append("openmp") + if "+omp_as_runtime" in spec: + runtimes.append("openmp") + else: + projects.append("openmp") + + if self.spec.satisfies("@8"): + cmake_args.append(define('CLANG_ANALYZER_ENABLE_Z3_SOLVER', + self.spec.satisfies('@8+z3'))) + if self.spec.satisfies("@9:"): + cmake_args.append(define('LLVM_ENABLE_Z3_SOLVER', + self.spec.satisfies('@9:+z3'))) + if "+flang" in spec: projects.append("flang") if "+lldb" in spec: @@ -439,53 +529,48 @@ class LlvmDoe(CMakePackage, CudaPackage): if "+libcxx" in spec: projects.append("libcxx") projects.append("libcxxabi") - cmake_args.append("-DCLANG_DEFAULT_CXX_STDLIB=libc++") if "+mlir" in spec: projects.append("mlir") if "+internal_unwind" in spec: projects.append("libunwind") if "+polly" in spec: projects.append("polly") - cmake_args.append("-DLINK_POLLY_INTO_TOOLS:Bool=ON") - - if "+shared_libs" in spec: - cmake_args.append("-DBUILD_SHARED_LIBS:Bool=ON") - if "+llvm_dylib" in spec: - cmake_args.append("-DLLVM_BUILD_LLVM_DYLIB:Bool=ON") - if "+omp_debug" in spec: - cmake_args.append("-DLIBOMPTARGET_ENABLE_DEBUG:Bool=ON") - - if "+split_dwarf" in spec: - cmake_args.append("-DLLVM_USE_SPLIT_DWARF:Bool=ON") + cmake_args.append(define("LINK_POLLY_INTO_TOOLS", True)) + + cmake_args.extend([ + from_variant("BUILD_SHARED_LIBS", "shared_libs"), + from_variant("LLVM_BUILD_LLVM_DYLIB", "llvm_dylib"), + from_variant("LLVM_LINK_LLVM_DYLIB", "link_llvm_dylib"), + from_variant("LLVM_USE_SPLIT_DWARF", "split_dwarf"), + # By default on Linux, libc++.so is a ldscript. CMake fails to add + # CMAKE_INSTALL_RPATH to it, which fails. Statically link libc++abi.a + # into libc++.so, linking with -lc++ or -stdlib=libc++ is enough. + define('LIBCXX_ENABLE_STATIC_ABI_LIBRARY', True) + ]) if "+all_targets" not in spec: # all is default on cmake targets = ["NVPTX", "AMDGPU"] - if spec.target.family == "x86" or spec.target.family == "x86_64": + if spec.version < Version("3.9.0"): + # Starting in 3.9.0 CppBackend is no longer a target (see + # LLVM_ALL_TARGETS in llvm's top-level CMakeLists.txt for + # the complete list of targets) + targets.append("CppBackend") + + if spec.target.family in ("x86", "x86_64"): targets.append("X86") elif spec.target.family == "arm": targets.append("ARM") elif spec.target.family == "aarch64": targets.append("AArch64") - elif ( - spec.target.family == "sparc" - or spec.target.family == "sparc64" - ): + elif spec.target.family in ("sparc", "sparc64"): targets.append("Sparc") - elif ( - spec.target.family == "ppc64" - or spec.target.family == "ppc64le" - or spec.target.family == "ppc" - or spec.target.family == "ppcle" - ): + elif spec.target.family in ("ppc64", "ppc64le", "ppc", "ppcle"): targets.append("PowerPC") - cmake_args.append( - "-DLLVM_TARGETS_TO_BUILD:STRING=" + ";".join(targets) - ) + cmake_args.append(define("LLVM_TARGETS_TO_BUILD", targets)) - if "+omp_tsan" in spec: - cmake_args.append("-DLIBOMP_TSAN_SUPPORT=ON") + cmake_args.append(from_variant("LIBOMP_TSAN_SUPPORT", "omp_tsan")) if spec.satisfies("@bolt"): projects.remove("openmp") @@ -495,64 +580,64 @@ class LlvmDoe(CMakePackage, CudaPackage): cmake_args.append("-DLIBOMP_USE_ARGOBOTS=ON") if self.compiler.name == "gcc": - gcc_prefix = ancestor(self.compiler.cc, 2) - cmake_args.append("-DGCC_INSTALL_PREFIX=" + gcc_prefix) + compiler = Executable(self.compiler.cc) + gcc_output = compiler('-print-search-dirs', output=str, error=str) + + for line in gcc_output.splitlines(): + if line.startswith("install:"): + # Get path and strip any whitespace + # (causes oddity with ancestor) + gcc_prefix = line.split(":")[1].strip() + gcc_prefix = ancestor(gcc_prefix, 4) + break + cmake_args.append(define("GCC_INSTALL_PREFIX", gcc_prefix)) - if spec.satisfies("platform=cray") or spec.satisfies("platform=linux"): - cmake_args.append("-DCMAKE_BUILD_WITH_INSTALL_RPATH=1") + # if spec.satisfies("platform=cray") or spec.satisfies("platform=linux"): + # cmake_args.append("-DCMAKE_BUILD_WITH_INSTALL_RPATH=1") if self.spec.satisfies("~code_signing platform=darwin"): - cmake_args.append('-DLLDB_USE_SYSTEM_DEBUGSERVER=ON') + cmake_args.append(define('LLDB_USE_SYSTEM_DEBUGSERVER', True)) # Semicolon seperated list of projects to enable - cmake_args.append( - "-DLLVM_ENABLE_PROJECTS:STRING={0}".format(";".join(projects)) - ) + cmake_args.append(define("LLVM_ENABLE_PROJECTS", projects)) - return cmake_args + # Semicolon seperated list of runtimes to enable + if runtimes: + cmake_args.append(define("LLVM_ENABLE_RUNTIMES", runtimes)) - @run_before("build") - def pre_install(self): - with working_dir(self.build_directory): - # When building shared libraries these need to be installed first - make("install-LLVMTableGen") - make("install-LLVMDemangle") - make("install-LLVMSupport") + return cmake_args @run_after("install") def post_install(self): spec = self.spec + define = CMakePackage.define - # unnecessary if we get bootstrap builds in here - if "+cuda" in self.spec: + # unnecessary if we build openmp via LLVM_ENABLE_RUNTIMES + if "+cuda ~omp_as_runtime" in self.spec: ompdir = "build-bootstrapped-omp" + prefix_paths = spack.build_environment.get_cmake_prefix_path(self) + prefix_paths.append(str(spec.prefix)) # rebuild libomptarget to get bytecode runtime library files with working_dir(ompdir, create=True): cmake_args = [ - self.stage.source_path + "/openmp", - "-DCMAKE_C_COMPILER:PATH={0}".format( - spec.prefix.bin + "/clang" - ), - "-DCMAKE_CXX_COMPILER:PATH={0}".format( - spec.prefix.bin + "/clang++" - ), - "-DCMAKE_INSTALL_PREFIX:PATH={0}".format(spec.prefix), + '-G', 'Ninja', + define('CMAKE_BUILD_TYPE', spec.variants['build_type'].value), + define("CMAKE_C_COMPILER", spec.prefix.bin + "/clang"), + define("CMAKE_CXX_COMPILER", spec.prefix.bin + "/clang++"), + define("CMAKE_INSTALL_PREFIX", spec.prefix), + define('CMAKE_PREFIX_PATH', prefix_paths) ] cmake_args.extend(self.cmake_args()) - cmake_args.append( - "-DLIBOMPTARGET_NVPTX_ENABLE_BCLIB:BOOL=TRUE" - ) - - # work around bad libelf detection in libomptarget - cmake_args.append( - "-DLIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR:String={0}".format( - spec["libelf"].prefix.include - ) - ) + cmake_args.extend([ + define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True), + define("LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR", + spec["libelf"].prefix.include), + self.stage.source_path + "/openmp", + ]) cmake(*cmake_args) - make() - make("install") + ninja() + ninja("install") if "+python" in self.spec: install_tree("llvm/bindings/python", site_packages_dir) |