diff --git a/flake.lock b/flake.lock index 144e324..eb4fb82 100644 --- a/flake.lock +++ b/flake.lock @@ -20,18 +20,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1703110697, - "narHash": "sha256-n7/5rcNGo/JYaFpStPUo0SmiZmjVkRwZK0UwC9C8WkI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "617e0a5cf51ae10bef08c9c110e98f5cac88de6d", - "type": "github" + "dirtyRev": "bcb1a9c7e1d8568c5e58316fe3254eb8f4455439-dirty", + "dirtyShortRev": "bcb1a9c7e1d8-dirty", + "lastModified": 1704738119, + "narHash": "sha256-FZ4iFQEMt790dl5I4l3/vc/NuB9jyrppW0q315adCWQ=", + "type": "git", + "url": "file:///home/lxsameer/src/nixpkgs" }, "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "617e0a5cf51ae10bef08c9c110e98f5cac88de6d", - "type": "github" + "type": "git", + "url": "file:///home/lxsameer/src/nixpkgs" } }, "root": { diff --git a/flake.nix b/flake.nix index 5312788..c05daf2 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,7 @@ { description = "Serene programming language"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/617e0a5cf51ae10bef08c9c110e98f5cac88de6d"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/bcb1a9c7e1d8568c5e58316fe3254eb8f4455439"; #inputs.nixpkgs.url = "/home/lxsameer/src/nixpkgs/"; inputs.flake-utils.url = "github:numtide/flake-utils"; @@ -84,6 +84,11 @@ # We don't need systemd at all util-linux = prev.util-linux.override { systemdSupport = false; }; + linux-pam = prev.linux-pam.overrideAttrs (old: { + postConfigure = '' + sed 's/examples//' -i Makefile + ''; + }); # iwyu = (prev.include-what-you-use.overrideAttrs (old: # let # version = "0.20"; @@ -106,14 +111,24 @@ if system == "x86_64-linux" then import nixpkgs { inherit system overlays; - crossSystem = nixpkgs.lib.systems.examples.musl64; #// { useLLVM = true; }; - # config.replaceCrossStdenv = { buildPackages, baseStdenv }: - # buildPackages.stdenvAdapters.overrideCC baseStdenv buildPackages.llvmPackages_17.clangUseLLVM; + crossSystem = nixpkgs.lib.systems.examples.musl64 // { useLLVM = true; }; + config.replaceCrossStdenv = { buildPackages, baseStdenv }: + buildPackages.stdenvAdapters.overrideCC baseStdenv buildPackages.llvmPackages_16.clangUseLLVM; } else import nixpkgs { inherit system overlays; }; + mkExtraBuildCommands0 = cc: major: '' + rsrc="$out/resource-root" + mkdir "$rsrc" + ln -s "${cc.lib}/lib/clang/${major}/include" "$rsrc" + echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags + ''; + mkExtraBuildCommands = cc: major: cr: (mkExtraBuildCommands0 cc major) + '' + ln -s "${cr.out}/lib" "$rsrc/lib" + ln -s "${cr.out}/share" "$rsrc/share" + ''; pkgs = get_pkgs system; @@ -124,7 +139,7 @@ # # stdenv = pkgs.stdenvAdapters.overrideCC pkgs.stdenv sereneLLVM; # stdenv = pkgs.stdenv; - stdenv' = pkgs.stdenvAdapters.overrideCC pkgs.stdenv pkgs.llvmPackages_16.clangUseLLVM; + stdenv' = pkgs.stdenvAdapters.overrideCC pkgs.stdenv pkgs.llvmPackages_17.clangUseLLVM; utils = (pkgs.callPackage ./nix/utils.nix {}); @@ -149,6 +164,60 @@ stdenv = stdenv'; }); + libcxx = (pkgs.callPackage ./nix/libcxx { + inherit llvm_source utils; + llvm_libcxxabi = libcxxabi; + llvm_libunwind = libunwind; + stdenv = stdenv'; + }); + + compiler-rt = (pkgs.callPackage ./nix/compiler-rt { + inherit llvm_source utils; + llvm_libcxxabi = libcxxabi; + stdenv = stdenv'; + }); + + # ullvm = pkgs.stellvmPackages_17; + # clang' = pkgs.wrapCCWith rec { + # libcxx = ullvm.libcxx; + # cc = ullvm.clang; + # libc = ullvm.musl; + # bintools = ullvm.bintools; + # extraPackages = [ + # libcxxabi + # compiler-rt + # ] ++ pkgs.lib.optionals (!pkgs.stdenv.targetPlatform.isWasm) [ + # ullvm.libunwind + # ]; + # extraBuildCommands = mkExtraBuildCommands cc llvm_source.major compiler-rt; + # nixSupport.cc-cflags = + # [ "-rtlib=compiler-rt" + # "-Wno-unused-command-line-argument" + # "-B${compiler-rt}/lib" + # ] + # ++ pkgs.lib.optional (!pkgs.stdenv.targetPlatform.isWasm) "--unwindlib=libunwind" + # ++ pkgs.lib.optional + # (!stdenv'.targetPlatform.isWasm) + # "-lunwind" + # ++ pkgs.lib.optional pkgs.stdenv.targetPlatform.isWasm "-fno-exceptions"; + # }; + # stdenv'' = pkgs.stdenvAdapters.overrideCC pkgs.stdenv clang'; + + + # llvm = (pkgs.callPackage ./nix/llvm { + # inherit llvm_source utils; + # buildLlvmTools = pkgs.llvmPackages_17; + # stdenv = stdenv''; + # }); + llvm = (pkgs.callPackage ./nix/llvm.nix { + inherit llvm_source utils; + + # llvm_libcxx = libcxx; + # llvm_libcxxabi = libcxxabi; + # llvm_compiler-rt = compiler-rt; + # llvm_libunwind = libunwind; + stdenv = pkgs.stdenv; + }); #with pkgs; native_build_inputs = @@ -177,11 +246,11 @@ # hash = "sha256-ajUZGf+JvafJXIlUcmAYaNs9qrlqlYs44DYokNWHYLY="; # }; # })) - # .override { - # llvmPackages = pkgs.__splicedPackages.llvmPackages_16;# .overrideAttrs (oldLLVM: { - # # cmakeFlags = builtins.trace ">> ${toString(filterCmakeFlags oldLLVM.cmakeFlags)}" filterCmakeFlags oldLLVM.cmakeFlags; - # # }); - # }; + # .override { + # llvmPackages = pkgs.__splicedPackages.llvmPackages_16;# .overrideAttrs (oldLLVM: { + # # cmakeFlags = builtins.trace ">> ${toString(filterCmakeFlags oldLLVM.cmakeFlags)}" filterCmakeFlags oldLLVM.cmakeFlags; + # # }); + # }; # mlir_16' = pkgs.mlir_16.overrideAttrs (old: { # }); @@ -197,8 +266,12 @@ zsh-syntax-highlighting python3 #sereneLLVM - libunwind - libcxxabi + # libunwind + # libcxxabi + # libcxx + # compiler-rt + llvm + #.override {stdenv = stdenv';} # mlir_17 ]); @@ -236,7 +309,8 @@ packages.llvm_unwind = libunwind; packages.llvm_libcxxabi = libcxxabi; packages.llvm_cxx_headers = cxx-headers; - packages.llvm = pkgs.llvmPackages_16.llvm.override { stdenv = stdenv'; }; + packages.llvm_compiler-rt = compiler-rt; + packages.llvm = llvm; } ); } diff --git a/nix/clang/default.nix b/nix/clang/default.nix new file mode 100644 index 0000000..cf86807 --- /dev/null +++ b/nix/clang/default.nix @@ -0,0 +1,160 @@ +# Serene Programming Language +# +# Copyright (c) 2019-2023 Sameer Rahmani +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +{ lib, + stdenv, + utils, + llvm_source, + runCommand, + substituteAll, + cmake, + ninja, + libxml2, + libllvm, + version, + python3, + buildLlvmTools, + fixDarwinDylibNames, + enableManpages ? false +}: + +let + self = stdenv.mkDerivation (rec { + pname = "clang"; + inherit version; + + src = runCommand "${pname}-src-${version}" {} '' + mkdir -p "$out" + cp -r ${monorepoSrc}/cmake "$out" + cp -r ${monorepoSrc}/${pname} "$out" + cp -r ${monorepoSrc}/clang-tools-extra "$out" + ''; + + sourceRoot = "${src.name}/${pname}"; + + nativeBuildInputs = [ cmake ninja python3 ] + ++ lib.optional enableManpages python3.pkgs.sphinx + ++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames; + + buildInputs = [ libxml2 libllvm ]; + + cmakeFlags = [ + "-DCLANG_INSTALL_PACKAGE_DIR=${placeholder "dev"}/lib/cmake/clang" + "-DCLANGD_BUILD_XPC=OFF" + "-DLLVM_ENABLE_RTTI=ON" + "-DLLVM_INCLUDE_TESTS=OFF" + ] ++ lib.optionals enableManpages [ + "-DCLANG_INCLUDE_DOCS=ON" + "-DLLVM_ENABLE_SPHINX=ON" + "-DSPHINX_OUTPUT_MAN=ON" + "-DSPHINX_OUTPUT_HTML=OFF" + "-DSPHINX_WARNINGS_AS_ERRORS=OFF" + ] ++ lib.optionals (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ + "-DLLVM_TABLEGEN_EXE=${buildLlvmTools.llvm}/bin/llvm-tblgen" + "-DCLANG_TABLEGEN=${buildLlvmTools.libclang.dev}/bin/clang-tblgen" + # Added in LLVM15: + # `clang-tidy-confusable-chars-gen`: https://github.com/llvm/llvm-project/commit/c3574ef739fbfcc59d405985a3a4fa6f4619ecdb + # `clang-pseudo-gen`: https://github.com/llvm/llvm-project/commit/cd2292ef824591cc34cc299910a3098545c840c7 + "-DCLANG_TIDY_CONFUSABLE_CHARS_GEN=${buildLlvmTools.libclang.dev}/bin/clang-tidy-confusable-chars-gen" + "-DCLANG_PSEUDO_GEN=${buildLlvmTools.libclang.dev}/bin/clang-pseudo-gen" + ]; + + patches = [ + ./purity.patch + # https://reviews.llvm.org/D51899 + ./gnu-install-dirs.patch + ../../common/clang/add-nostdlibinc-flag.patch + (substituteAll { + src = ../../clang-at-least-16-LLVMgold-path.patch; + libllvmLibdir = "${libllvm.lib}/lib"; + }) + ]; + + postPatch = '' + (cd tools && ln -s ../../clang-tools-extra extra) + '' + lib.optionalString stdenv.hostPlatform.isMusl '' + sed -i -e 's/lgcc_s/lgcc_eh/' lib/Driver/ToolChains/*.cpp + ''; + + outputs = [ "out" "lib" "dev" "python" ]; + + postInstall = '' + ln -sv $out/bin/clang $out/bin/cpp + + mkdir -p $lib/lib/clang + mv $lib/lib/17 $lib/lib/clang/17 + + # Move libclang to 'lib' output + moveToOutput "lib/libclang.*" "$lib" + moveToOutput "lib/libclang-cpp.*" "$lib" + substituteInPlace $dev/lib/cmake/clang/ClangTargets-release.cmake \ + --replace "\''${_IMPORT_PREFIX}/lib/libclang." "$lib/lib/libclang." \ + --replace "\''${_IMPORT_PREFIX}/lib/libclang-cpp." "$lib/lib/libclang-cpp." + + mkdir -p $python/bin $python/share/clang/ + mv $out/bin/{git-clang-format,scan-view} $python/bin + if [ -e $out/bin/set-xcode-analyzer ]; then + mv $out/bin/set-xcode-analyzer $python/bin + fi + mv $out/share/clang/*.py $python/share/clang + rm $out/bin/c-index-test + patchShebangs $python/bin + + mkdir -p $dev/bin + cp bin/{clang-tblgen,clang-tidy-confusable-chars-gen,clang-pseudo-gen} $dev/bin + ''; + + passthru = { + inherit libllvm; + isClang = true; + hardeningUnsupportedFlags = [ "fortify3" ]; + }; + + meta = llvm_meta // { + homepage = "https://clang.llvm.org/"; + description = "A C language family frontend for LLVM"; + longDescription = '' + The Clang project provides a language front-end and tooling + infrastructure for languages in the C language family (C, C++, Objective + C/C++, OpenCL, CUDA, and RenderScript) for the LLVM project. + It aims to deliver amazingly fast compiles, extremely useful error and + warning messages and to provide a platform for building great source + level tools. The Clang Static Analyzer and clang-tidy are tools that + automatically find bugs in your code, and are great examples of the sort + of tools that can be built using the Clang frontend as a library to + parse C/C++ code. + ''; + mainProgram = "clang"; + }; + } // lib.optionalAttrs enableManpages { + pname = "clang-manpages"; + + ninjaFlags = [ "docs-clang-man" ]; + + installPhase = '' + mkdir -p $out/share/man/man1 + # Manually install clang manpage + cp docs/man/*.1 $out/share/man/man1/ + ''; + + outputs = [ "out" ]; + + doCheck = false; + + meta = llvm_meta // { + description = "man page for Clang ${version}"; + }; + }); +in self diff --git a/nix/compiler-rt/X86-support-extension.patch b/nix/compiler-rt/X86-support-extension.patch new file mode 100644 index 0000000..3eb36e1 --- /dev/null +++ b/nix/compiler-rt/X86-support-extension.patch @@ -0,0 +1,21 @@ +diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt +index 3a66dd9c3fb..7efc85d9f9f 100644 +--- a/lib/builtins/CMakeLists.txt ++++ b/lib/builtins/CMakeLists.txt +@@ -348,4 +348,8 @@ if (NOT MSVC) + ++ set(i486_SOURCES ${i386_SOURCES}) ++ set(i586_SOURCES ${i386_SOURCES}) ++ set(i686_SOURCES ${i386_SOURCES}) ++ + if (WIN32) + set(i386_SOURCES + ${i386_SOURCES} +@@ -723,6 +723,7 @@ else () + endif() + + foreach (arch ${BUILTIN_SUPPORTED_ARCH}) ++ message("arch: ${arch}") + if (CAN_TARGET_${arch}) + # For ARM archs, exclude any VFP builtins if VFP is not supported + if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em)$") diff --git a/nix/compiler-rt/darwin-plistbuddy-workaround.patch b/nix/compiler-rt/darwin-plistbuddy-workaround.patch new file mode 100644 index 0000000..1032e03 --- /dev/null +++ b/nix/compiler-rt/darwin-plistbuddy-workaround.patch @@ -0,0 +1,25 @@ +CMake tries to read a list field from SDKSettings.plist, but the output of +xcbuild PlistBuddy is incompatible with Apple's. (Plus we don't want it in our +dependencies.) + +Simply assume ARM64 is supported by the SDK. We already limit the actual archs +we build for by setting DARWIN_osx_BUILTIN_ARCHS explicitely. + +--- a/cmake/builtin-config-ix.cmake ++++ b/cmake/builtin-config-ix.cmake +@@ -97,14 +97,7 @@ if(APPLE) + set(DARWIN_osx_BUILTIN_MIN_VER 10.5) + set(DARWIN_osx_BUILTIN_MIN_VER_FLAG + -mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER}) +- set(DARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64}) +- # Add support for arm64 macOS if available in SDK. +- foreach(arch ${ARM64}) +- sdk_has_arch_support(${DARWIN_osx_SYSROOT} macosx ${arch} MACOS_ARM_SUPPORT) +- if (MACOS_ARM_SUPPORT) +- list(APPEND DARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS ${arch}) +- endif() +- endforeach(arch) ++ set(DARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64} ${ARM64}) + + if(COMPILER_RT_ENABLE_IOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS ios) diff --git a/nix/compiler-rt/darwin-targetconditionals.patch b/nix/compiler-rt/darwin-targetconditionals.patch new file mode 100644 index 0000000..574a74e --- /dev/null +++ b/nix/compiler-rt/darwin-targetconditionals.patch @@ -0,0 +1,71 @@ +diff --git a/lib/sanitizer_common/sanitizer_mac.cpp b/lib/sanitizer_common/sanitizer_mac.cpp +--- a/lib/sanitizer_common/sanitizer_mac.cpp ++++ b/lib/sanitizer_common/sanitizer_mac.cpp +@@ -613,9 +613,15 @@ HandleSignalMode GetHandleSignalMode(int signum) { + // Offset example: + // XNU 17 -- macOS 10.13 -- iOS 11 -- tvOS 11 -- watchOS 4 + constexpr u16 GetOSMajorKernelOffset() { +- if (TARGET_OS_OSX) return 4; +- if (TARGET_OS_IOS || TARGET_OS_TV) return 6; +- if (TARGET_OS_WATCH) return 13; ++#if TARGET_OS_OSX ++ return 4; ++#endif ++#if TARGET_OS_IOS || TARGET_OS_TV ++ return 6; ++#endif ++#if TARGET_OS_WATCH ++ return 13; ++#endif + } + + using VersStr = char[64]; +@@ -627,13 +633,13 @@ static uptr ApproximateOSVersionViaKernelVersion(VersStr vers) { + u16 os_major = kernel_major - offset; + + const char *format = "%d.0"; +- if (TARGET_OS_OSX) { +- if (os_major >= 16) { // macOS 11+ +- os_major -= 5; +- } else { // macOS 10.15 and below +- format = "10.%d"; +- } ++#if TARGET_OS_OSX ++ if (os_major >= 16) { // macOS 11+ ++ os_major -= 5; ++ } else { // macOS 10.15 and below ++ format = "10.%d"; + } ++#endif + return internal_snprintf(vers, sizeof(VersStr), format, os_major); + } + +@@ -681,15 +687,14 @@ void ParseVersion(const char *vers, u16 *major, u16 *minor) { + // Aligned versions example: + // macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6 + static void MapToMacos(u16 *major, u16 *minor) { +- if (TARGET_OS_OSX) +- return; +- +- if (TARGET_OS_IOS || TARGET_OS_TV) ++#if !TARGET_OS_OSX ++#if TARGET_OS_IOS || TARGET_OS_TV + *major += 2; +- else if (TARGET_OS_WATCH) ++#elif TARGET_OS_WATCH + *major += 9; +- else ++#else + UNREACHABLE("unsupported platform"); ++#endif + + if (*major >= 16) { // macOS 11+ + *major -= 5; +@@ -697,6 +702,7 @@ static void MapToMacos(u16 *major, u16 *minor) { + *minor = *major; + *major = 10; + } ++#endif + } + + static MacosVersion GetMacosAlignedVersionInternal() { diff --git a/nix/compiler-rt/default.nix b/nix/compiler-rt/default.nix new file mode 100644 index 0000000..73681bd --- /dev/null +++ b/nix/compiler-rt/default.nix @@ -0,0 +1,160 @@ +# Serene Programming Language +# +# Copyright (c) 2019-2023 Sameer Rahmani +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +{ lib, + stdenv, + llvm_source, + runCommand, + cmake, + ninja, + python3, + xcbuild, + libllvm, + linuxHeaders, + llvm_libcxxabi, + libxcrypt, + utils, +}: + +let + baseName = "llvm_compiler-rt"; + isDarwinStatic = stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isStatic; + haveLibc = stdenv.cc.libc != null; + useLLVM = true; + bareMetal = false; + inherit (stdenv.hostPlatform) isMusl; + +in stdenv.mkDerivation rec { + pname = baseName + lib.optionalString (haveLibc) "-libc"; + inherit (llvm_source) version; + + src = runCommand "${pname}-src-${version}" {} '' + mkdir -p "$out" + cp -r ${llvm_source}/cmake "$out" + cp -r ${llvm_source}/compiler-rt "$out" + ''; + + sourceRoot = "${src.name}/compiler-rt"; + + nativeBuildInputs = [ cmake ninja python3 libllvm.dev ] + ++ lib.optional stdenv.isDarwin xcbuild.xcrun; + buildInputs = + lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders + ++ lib.optional stdenv.hostPlatform.isDarwin llvm_libcxxabi; + + env.NIX_CFLAGS_COMPILE = toString ([ + "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0" + ] ++ lib.optionals (!haveLibc) [ + # The compiler got stricter about this, and there is a usellvm patch below + # which patches out the assert include causing an implicit definition of + # assert. It would be nicer to understand why compiler-rt thinks it should + # be able to #include in the first place; perhaps it's in the + # wrong, or perhaps there is a way to provide an assert.h. + "-Wno-error=implicit-function-declaration" + ]); + + cmakeFlags = [ + "-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON" + "-DCMAKE_C_COMPILER_TARGET=${stdenv.hostPlatform.config}" + "-DCMAKE_ASM_COMPILER_TARGET=${stdenv.hostPlatform.config}" + ] ++ lib.optionals (haveLibc && stdenv.hostPlatform.libc == "glibc") [ + "-DSANITIZER_COMMON_CFLAGS=-I${libxcrypt}/include" + ] ++ lib.optionals (useLLVM || bareMetal || isMusl || isDarwinStatic) [ + "-DCOMPILER_RT_BUILD_SANITIZERS=OFF" + "-DCOMPILER_RT_BUILD_XRAY=OFF" + "-DCOMPILER_RT_BUILD_LIBFUZZER=OFF" + "-DCOMPILER_RT_BUILD_MEMPROF=OFF" + "-DCOMPILER_RT_BUILD_ORC=OFF" # may be possible to build with musl if necessary + ] ++ lib.optionals (useLLVM || bareMetal) [ + "-DCOMPILER_RT_BUILD_PROFILE=OFF" + ] ++ lib.optionals ((useLLVM && !haveLibc) || bareMetal || isDarwinStatic ) [ + "-DCMAKE_CXX_COMPILER_WORKS=ON" + ] ++ lib.optionals ((useLLVM && !haveLibc) || bareMetal) [ + "-DCMAKE_C_COMPILER_WORKS=ON" + "-DCOMPILER_RT_BAREMETAL_BUILD=ON" + "-DCMAKE_SIZEOF_VOID_P=${toString (stdenv.hostPlatform.parsed.cpu.bits / 8)}" + ] ++ lib.optionals (useLLVM && !haveLibc) [ + "-DCMAKE_C_FLAGS=-nodefaultlibs" + ] ++ lib.optionals (useLLVM) [ + "-DCOMPILER_RT_BUILD_BUILTINS=ON" + #https://stackoverflow.com/questions/53633705/cmake-the-c-compiler-is-not-able-to-compile-a-simple-test-program + "-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY" + ] ++ lib.optionals (bareMetal) [ + "-DCOMPILER_RT_OS_DIR=baremetal" + ] ++ lib.optionals (stdenv.hostPlatform.isDarwin) [ + "-DCMAKE_LIPO=${lib.getBin stdenv.cc.bintools.bintools}/bin/${stdenv.cc.targetPrefix}lipo" + "-DDARWIN_macosx_OVERRIDE_SDK_VERSION=ON" + "-DDARWIN_osx_ARCHS=${stdenv.hostPlatform.darwinArch}" + "-DDARWIN_osx_BUILTIN_ARCHS=${stdenv.hostPlatform.darwinArch}" + + # `COMPILER_RT_DEFAULT_TARGET_ONLY` does not apply to Darwin: + # https://github.com/llvm/llvm-project/blob/27ef42bec80b6c010b7b3729ed0528619521a690/compiler-rt/cmake/base-config-ix.cmake#L153 + "-DCOMPILER_RT_ENABLE_IOS=OFF" + ]; + + outputs = [ "out" "dev" ]; + + patches = [ + ./X86-support-extension.patch # Add support for i486 i586 i686 by reusing i386 config + ./gnu-install-dirs.patch + # ld-wrapper dislikes `-rpath-link //nix/store`, so we normalize away the + # extra `/`. + ./normalize-var.patch + # Prevent a compilation error on darwin + ./darwin-targetconditionals.patch + # See: https://github.com/NixOS/nixpkgs/pull/186575 + ./darwin-plistbuddy-workaround.patch + # See: https://github.com/NixOS/nixpkgs/pull/194634#discussion_r999829893 + # ../../common/compiler-rt/armv7l-15.patch + ]; + + # TSAN requires XPC on Darwin, which we have no public/free source files for. We can depend on the Apple frameworks + # to get it, but they're unfree. Since LLVM is rather central to the stdenv, we patch out TSAN support so that Hydra + # can build this. If we didn't do it, basically the entire nixpkgs on Darwin would have an unfree dependency and we'd + # get no binary cache for the entire platform. If you really find yourself wanting the TSAN, make this controllable by + # a flag and turn the flag off during the stdenv build. + postPatch = lib.optionalString (!stdenv.isDarwin) '' + substituteInPlace cmake/builtin-config-ix.cmake \ + --replace 'set(X86 i386)' 'set(X86 i386 i486 i586 i686)' + '' + lib.optionalString stdenv.isDarwin '' + substituteInPlace cmake/config-ix.cmake \ + --replace 'set(COMPILER_RT_HAS_TSAN TRUE)' 'set(COMPILER_RT_HAS_TSAN FALSE)' + '' + lib.optionalString (useLLVM && !haveLibc) '' + substituteInPlace lib/builtins/int_util.c \ + --replace "#include " "" + substituteInPlace lib/builtins/clear_cache.c \ + --replace "#include " "" + substituteInPlace lib/builtins/cpu_model.c \ + --replace "#include " "" + ''; + + # Hack around weird upsream RPATH bug + postInstall = lib.optionalString (stdenv.hostPlatform.isDarwin) '' + ln -s "$out/lib"/*/* "$out/lib" + '' + lib.optionalString (useLLVM && stdenv.hostPlatform.isLinux) '' + ln -s $out/lib/*/clang_rt.crtbegin-*.o $out/lib/crtbegin.o + ln -s $out/lib/*/clang_rt.crtend-*.o $out/lib/crtend.o + # Note the history of crt{begin,end}S in previous versions of llvm in nixpkg: + # The presence of crtbegin_shared has been added and removed; it's possible + # people have added/removed it to get it working on their platforms. + # Try each in turn for now. + ln -s $out/lib/*/clang_rt.crtbegin-*.o $out/lib/crtbeginS.o + ln -s $out/lib/*/clang_rt.crtend-*.o $out/lib/crtendS.o + ln -s $out/lib/*/clang_rt.crtbegin_shared-*.o $out/lib/crtbeginS.o + ln -s $out/lib/*/clang_rt.crtend_shared-*.o $out/lib/crtendS.o + ''; + + inherit (utils) meta; +} diff --git a/nix/compiler-rt/gnu-install-dirs.patch b/nix/compiler-rt/gnu-install-dirs.patch new file mode 100644 index 0000000..f3b1f63 --- /dev/null +++ b/nix/compiler-rt/gnu-install-dirs.patch @@ -0,0 +1,20 @@ +diff --git a/cmake/base-config-ix.cmake b/cmake/base-config-ix.cmake +index 8a6219568b3f..30ee68a47ccf 100644 +--- a/cmake/base-config-ix.cmake ++++ b/cmake/base-config-ix.cmake +@@ -100,13 +100,13 @@ endif() + if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + set(COMPILER_RT_OUTPUT_LIBRARY_DIR + ${COMPILER_RT_OUTPUT_DIR}/lib) +- extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" lib) ++ extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_LIBDIR}") + set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH + "Path where built compiler-rt libraries should be installed.") + else(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + set(COMPILER_RT_OUTPUT_LIBRARY_DIR + ${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR}) +- extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "lib/${COMPILER_RT_OS_DIR}") ++ extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_LIBDIR}/${COMPILER_RT_OS_DIR}") + set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH + "Path where built compiler-rt libraries should be installed.") + endif() diff --git a/nix/compiler-rt/normalize-var.patch b/nix/compiler-rt/normalize-var.patch new file mode 100644 index 0000000..5cbefc7 --- /dev/null +++ b/nix/compiler-rt/normalize-var.patch @@ -0,0 +1,16 @@ +diff --git a/cmake/Modules/CompilerRTUtils.cmake b/cmake/Modules/CompilerRTUtils.cmake +index 4c85551d7766..297d7a47c54b 100644 +--- a/cmake/Modules/CompilerRTUtils.cmake ++++ b/cmake/Modules/CompilerRTUtils.cmake +@@ -328,8 +328,9 @@ macro(load_llvm_config) + endif() + endif() + +- set(LLVM_LIBRARY_OUTPUT_INTDIR +- ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) ++ get_filename_component(LLVM_LIBRARY_OUTPUT_INTDIR ++ ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX} ++ REALPATH) + + set(LLVM_MAIN_SRC_DIR "${LLVM_MAIN_SRC_DIR_DEFAULT}" CACHE PATH "Path to LLVM source tree") + message(STATUS "LLVM_MAIN_SRC_DIR: \"${LLVM_MAIN_SRC_DIR}\"") diff --git a/nix/libcxx/default.nix b/nix/libcxx/default.nix index 5c56384..ffde722 100644 --- a/nix/libcxx/default.nix +++ b/nix/libcxx/default.nix @@ -82,7 +82,7 @@ stdenv.mkDerivation rec { buildInputs = lib.optionals (!headersOnly) [ llvm_libcxxabi ] - ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [ llvm_libunwind ]; + ++ lib.optionals (!stdenv.hostPlatform.isWasm) [ llvm_libunwind ]; cmakeFlags = let # See: https://libcxx.llvm.org/BuildingLibcxx.html#cmdoption-arg-libcxx-cxx-abi-string @@ -94,11 +94,6 @@ stdenv.mkDerivation rec { "-DLLVM_ENABLE_RUNTIMES=libcxx" "-DLIBCXX_CXX_ABI=${if headersOnly then "none" else libcxx_cxx_abi_opt}" "-DLIBCXX_ENABLE_SHARED=OFF" - ] ++ lib.optional (!headersOnly && llvm_libcxxabi.libName == "c++abi") - "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${llvm_libcxxabi.dev}/include/c++/v1" - ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) - "-DLIBCXX_HAS_MUSL_LIBC=1" - ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [ "-DLIBCXX_USE_COMPILER_RT=ON" # There's precedent for this in llvm-project/libcxx/cmake/caches. # In a monorepo build you might do the following in the libcxxabi build: @@ -106,6 +101,10 @@ stdenv.mkDerivation rec { # -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On # libcxx appears to require unwind and doesn't pull it in via other means. "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind" + ] ++ lib.optional (!headersOnly && llvm_libcxxabi.libName == "c++abi") + "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${llvm_libcxxabi.dev}/include/c++/v1" + ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [ + "-DLIBCXX_HAS_MUSL_LIBC=1" ] ++ lib.optionals stdenv.hostPlatform.isWasm [ "-DLIBCXX_ENABLE_THREADS=OFF" "-DLIBCXX_ENABLE_FILESYSTEM=OFF" diff --git a/nix/libcxxabi/default.nix b/nix/libcxxabi/default.nix index 4b69cc4..a87a8e6 100644 --- a/nix/libcxxabi/default.nix +++ b/nix/libcxxabi/default.nix @@ -86,7 +86,7 @@ stdenv.mkDerivation rec { # CMake however checks for this anyways; this flag tells it not to. See: # https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243 "-DCMAKE_CXX_COMPILER_WORKS=ON" - ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [ + ] ++ lib.optionals (!stdenv.hostPlatform.isWasm) [ "-DLLVM_ENABLE_LIBCXX=ON" "-DLIBCXXABI_USE_LLVM_UNWINDER=ON" # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib, @@ -94,6 +94,7 @@ stdenv.mkDerivation rec { # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc). "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib" "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib" + "-DLIBCXXABI_USE_COMPILER_RT=ON" ] ++ lib.optionals stdenv.hostPlatform.isWasm [ "-DCMAKE_C_COMPILER_WORKS=ON" "-DCMAKE_CXX_COMPILER_WORKS=ON" diff --git a/nix/llvm.nix b/nix/llvm.nix index d96828a..09f7389 100644 --- a/nix/llvm.nix +++ b/nix/llvm.nix @@ -15,14 +15,21 @@ # along with this program. If not, see . { lib, stdenv, + llvm_source, + utils, cmake, ninja, libxml2, python3, fetchgit, fetchurl, - zlib, + # llvm_libcxx, + # llvm_compiler-rt, + # llvm_libcxxabi, + # llvm_libunwind, + zlib, wrapCCWith, + runCommand, overrideCC, ccache ? null, useCcache ? false, @@ -32,8 +39,9 @@ ref ? "refs/tags/llvmorg-${version}" }: let - ncpus = builtins.getEnv "NIX_BUILD_CORES"; - major = lib.versions.major version; + useLLVM = true; + ncpus = "32"; #builtins.getEnv "NIX_BUILD_CORES"; + major = llvm_source.major; target = stdenv.targetPlatform.config; # We're going to build "include-what-you-use" with our llvm build @@ -53,15 +61,31 @@ let # ''; }; - vanilla = builtins.trace ">.> " (stdenv.mkDerivation rec{ - inherit version; + vanilla = stdenv.mkDerivation rec{ + inherit (llvm_source) version; pname = "serene_llvm"; - src = fetchgit { - inherit url hash; - rev = ref; - }; + NIX_CFLAGS_COMPILE = [ "-v" ]; + NIX_CXXFLAGS_COMPILE = [ "-v" ]; + src = runCommand "${pname}-src-${version}" {} '' + mkdir -p "$out" + cp -r ${llvm_source}/cmake "$out" + cp -r ${llvm_source}/libcxxabi "$out" + cp -r ${llvm_source}/libcxx "$out/libcxx" + cp -r ${llvm_source}/llvm "$out" + cp -r ${llvm_source}/lld "$out" + cp -r ${llvm_source}/clang-tools-extra "$out" + cp -r ${llvm_source}/clang "$out" + cp -r ${llvm_source}/compiler-rt "$out" + cp -r ${llvm_source}/mlir "$out" + cp -r ${llvm_source}/bolt "$out" + cp -r ${llvm_source}/libunwind "$out" + cp -r ${llvm_source}/third-party "$out" + cp -r ${llvm_source}/utils "$out" + + cp -r ${llvm_source}/runtimes "$out" + ''; sourceRoot = "${src.name}/llvm"; nativeBuildInputs = [ cmake ninja python3 zlib ]; @@ -96,7 +120,7 @@ let # Serene uses static libs, so no shared lib "-DLLVM_ENABLE_PIC=OFF" - # "-DLLVM_BUILD_STATIC=ON" + "-DLLVM_BUILD_STATIC=OFF" "-DLLVM_LINK_LLVM_DYLIB=off" "-DLLVM_ENABLE_LIBXML2=OFF" @@ -107,7 +131,7 @@ let "-DCMAKE_POSITION_INDEPENDENT_CODE=ON" "-DCLANG_DEFAULT_CXX_STDLIB=libc++" - "-DCLANG_DEFAULT_LINKER=lld" + #"-DCLANG_DEFAULT_LINKER=lld" "-DCLANG_DEFAULT_OBJCOPY=llvm-objcopy" "-DCLANG_DEFAULT_RTLIB=compiler-rt" "-DCLANG_VENDOR_UTI=serene.toolchain" @@ -125,11 +149,13 @@ let "-DLLVM_INCLUDE_GO_TESTS=OFF" "-DLLVM_ENABLE_BINDINGS=OFF" #"-DLLVM_TARGETS_TO_BUILD": "X86;AArch64;AMDGPU;ARM;RISCV;WebAssembly" - "-DLLVM_STATIC_LINK_CXX_STDLIB=ON" + "-DLLVM_STATIC_LINK_CXX_STDLIB=OFF" "-DPACKAGE_VENDOR=Serene" "-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON" "-DENABLE_X86_RELAX_RELOCATIONS=ON" "-DBUILD_SHARED_LIBS=OFF" + "-DLIBUNWIND_ENABLE_SHARED=OFF" + "-DLIBUNWIND_ENABLE_STATIC=ON" "-DCLANG_ENABLE_BOOTSTRAP=ON" "-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON" "-DLIBCXXABI_ENABLE_SHARED=OFF" @@ -144,6 +170,9 @@ let "-DLIBCLANG_BUILD_STATIC=ON" "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}" + "-DCOMPILER_RT_ENABLE_STATIC_UNWINDER=ON" + "-DSANITIZER_USE_STATIC_LLVM_UNWINDER=ON" + "-DSANITIZER_USE_STATIC_CXX_ABI=ON" ] ++ lib.optional (stdenv.hostPlatform.isMusl) [ "-DDLIBCXX_HAS_MUSL_LIBC=ON" # ] ++ lib.optional (stdenv.hostPlatform.isStatic) [ @@ -163,8 +192,16 @@ let "-DBUILTINS_${target}_CMAKE_BUILD_WITH_INSTALL_RPATH=ON" "-DBUILTINS_${target}_COMPILER_RT_BAREMETAL_BUILD=ON" "-DBUILTINS_${target}_COMPILER_RT_DEFAULT_TARGET_ONLY=ON" - ] ++ lib.optional (stdenv.hostPlatform.useLLVM) [ - "-DBUILTINS_${target}_LLVM_USE_LINKER=lld" + "-DBUILTINS_${target}_LIBUNWIND_ENABLE_SHARED=OFF" + "-DBUILTINS_${target}_LIBUNWIND_ENABLE_STATIC=ON" + "-DBUILTINS_${target}_LIBCXXABI_ENABLE_SHARED=OFF" + "-DBUILTINS_${target}_LIBCXX_ENABLE_SHARED=OFF" + + "-DBUILTINS_${target}_COMPILER_RT_ENABLE_STATIC_UNWINDER=ON" + "-DBUILTINS_${target}_SANITIZER_USE_STATIC_LLVM_UNWINDER=ON" + "-DBUILTINS_${target}_SANITIZER_USE_STATIC_CXX_ABI=ON" + ] ++ lib.optional (useLLVM) [ + #"-DBUILTINS_${target}_LLVM_USE_LINKER=lld" ] ++ lib.optional (useCcache) [ "-DBUILTINS_${target}_LLVM_CCACHE_BUILD=ON" ]; @@ -180,13 +217,14 @@ let "-DRUNTIMES_${target}_LLVM_USE_LTO=ON" # Make sure we use libc++ from the tree instead from the system. + "-DRUNTIMES_${target}_LIBCXX_ENABLE_SHARED=OFF" "-DRUNTIMES_${target}_SANITIZER_CXX_ABI=libc++" "-DRUNTIMES_${target}_SANITIZER_CXX_ABI_INTREE=ON" "-DRUNTIMES_${target}_LIBCXX_CXX_ABI=libcxxabi" "-DRUNTIMES_${target}_LIBCXX_USE_COMPILER_RT=ON" "-DRUNTIMES_${target}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON" "-DRUNTIMES_${target}_LIBCXX_ABI_UNSTABLE=ON" - "-DRUNTIMES_${target}_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=ON" + "-DRUNTIMES_${target}_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=OFF" "-DRUNTIMES_${target}_LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON" "-DRUNTIMES_${target}_LIBCXX_ABI_VERSION=2" "-DRUNTIMES_${target}_LIBCXXABI_ENABLE_THREADS=ON" @@ -194,12 +232,12 @@ let "-DRUNTIMES_${target}_LIBCXXABI_USE_COMPILER_RT=ON" "-DRUNTIMES_${target}_LIBCXXABI_USE_LLVM_UNWINDER=ON" "-DRUNTIMES_${target}_LIBCXXABI_ENABLE_STATIC_UNWINDER=ON" - "-DRUNTIMES_${target}_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY=ON" + "-DRUNTIMES_${target}_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY=OFF" "-DRUNTIMES_${target}_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=ON" "-DRUNTIMES_${target}_LIBCXXABI_ENABLE_SHARED=OFF" "-DRUNTIMES_${target}_LIBUNWIND_USE_COMPILER_RT=ON" - ] ++ (lib.optional (stdenv.hostPlatform.useLLVM) [ - "-DRUNTIMES_${target}_LLVM_USE_LINKER=lld" + ] ++ (lib.optional (useLLVM) [ + #"-DRUNTIMES_${target}_LLVM_USE_LINKER=lld" ]) ++ lib.optional (useCcache) [ "-DRUNTIMES_${target}_LLVM_CCACHE_BUILD=ON" ] ++ (lib.optional (stdenv.hostPlatform.isMusl) [ @@ -220,18 +258,25 @@ let # Only build these if we enable sanitizers since they depend # on the sanitizer common runtime "-DRUNTIMES_${target}_COMPILER_RT_BUILD_MEMPROF=ON" - "-DRUNTIMES_${target}_COMPILER_RT_BUILD_LIBFUZZER=ON" + "-DRUNTIMES_${target}_COMPILER_RT_BUILD_LIBFUZZER=OFF" "-DRUNTIMES_${target}_COMPILER_RT_BUILD_ORC=ON" + "-DRUNTIMES_${target}_LIBUNWIND_ENABLE_SHARED=OFF" + "-DRUNTIMES_${target}_LIBUNWIND_ENABLE_STATIC=ON" + + "-DRUNTIMES_${target}_COMPILER_RT_ENABLE_STATIC_UNWINDER=ON" + "-DRUNTIMES_${target}_SANITIZER_USE_STATIC_LLVM_UNWINDER=ON" + "-DRUNTIMES_${target}_SANITIZER_USE_STATIC_CXX_ABI=ON" ]); cmakeFlags = cmakeFlags' ++ builtinFlags ++ runtimeFlags; ninjaFlags = [ + "-v" #"install-clang" - "install-builtins" - "install-compiler-rt" - "install-runtimes" - "tools/iwyu/install" + # "install-builtins" + # "install-compiler-rt" + # "install-runtimes" + # "tools/iwyu/install" ]; @@ -269,7 +314,7 @@ let lib.platforms.riscv ++ lib.platforms.m68k; }; - }); + }; tools = lib.makeExtensible (tools: let @@ -291,22 +336,17 @@ let cc = vanilla; libcxx = vanilla; libc = stdenv.cc.libc; - extraPackages = [ - vanilla - ]; extraBuildCommands = mkExtraBuildCommands cc; nixSupport.cc-cflags = [ "-rtlib=compiler-rt" + "-lc++" + "-lc++abi" "-Wno-unused-command-line-argument" "-B${vanilla}/lib" ] ++ lib.optional (!stdenv.targetPlatform.isWasm) "--unwindlib=libunwind" - ++ lib.optional (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false) + ++ lib.optional (!stdenv.targetPlatform.isWasm && (useLLVM || false)) "-lunwind" ++ lib.optional stdenv.targetPlatform.isWasm "-fno-exceptions"; }; }); -in { - inherit (tools) clang; - llvm = vanilla; - stdenv = overrideCC stdenv tools.clang; -} +in vanilla diff --git a/nix/llvm/TLI-musl.patch b/nix/llvm/TLI-musl.patch new file mode 100644 index 0000000..fd2a0e5 --- /dev/null +++ b/nix/llvm/TLI-musl.patch @@ -0,0 +1,34 @@ +From 5c571082fdaf61f6df19d9b7137dc26d71334058 Mon Sep 17 00:00:00 2001 +From: Natanael Copa +Date: Thu, 18 Feb 2016 10:33:04 +0100 +Subject: [PATCH 2/3] Fix build with musl libc + +On musl libc the fopen64 and fopen are the same thing, but for +compatibility they have a `#define fopen64 fopen`. Same applies for +fseek64, fstat64, fstatvfs64, ftello64, lstat64, stat64 and tmpfile64. +--- + include/llvm/Analysis/TargetLibraryInfo.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h +index 7becdf0..7f14427 100644 +--- a/include/llvm/Analysis/TargetLibraryInfo.h ++++ b/include/llvm/Analysis/TargetLibraryInfo.h +@@ -18,6 +18,15 @@ + #include "llvm/IR/Module.h" + #include "llvm/Pass.h" + ++#undef fopen64 ++#undef fseeko64 ++#undef fstat64 ++#undef fstatvfs64 ++#undef ftello64 ++#undef lstat64 ++#undef stat64 ++#undef tmpfile64 ++ + namespace llvm { + /// VecDesc - Describes a possible vectorization of a function. + /// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized +-- +2.7.3 diff --git a/nix/llvm/default.nix b/nix/llvm/default.nix new file mode 100644 index 0000000..313b7d7 --- /dev/null +++ b/nix/llvm/default.nix @@ -0,0 +1,399 @@ +# Serene Programming Language +# +# Copyright (c) 2019-2023 Sameer Rahmani +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +{ lib, + stdenv, + utils, + llvm_source, + pkgsBuildBuild, + runCommand, + cmake, + darwin, + ninja, + python3, + python3Packages, + libffi, + enableGoldPlugin ? true, + libbfd, + libpfm, + libxml2, + ncurses, + zlib, + which, + sysctl, + buildLlvmTools, + debugVersion ? false, + doCheck ? (!stdenv.isx86_32 /* TODO: why */) && (!stdenv.hostPlatform.isMusl) + && (stdenv.hostPlatform == stdenv.buildPlatform), + enableSharedLibraries ? false, + enablePFM ? false, + enablePolly ? true, +}: + +let + inherit (lib) optional optionals optionalString; + release_version = llvm_source.version; + + # Used when creating a version-suffixed symlink of libLLVM.dylib + shortVersion = with lib; + concatStringsSep "." (take 1 (splitString "." release_version)); + + # Ordinarily we would just the `doCheck` and `checkDeps` functionality + # `mkDerivation` gives us to manage our test dependencies (instead of breaking + # out `doCheck` as a package level attribute). + # + # Unfortunately `lit` does not forward `$PYTHONPATH` to children processes, in + # particular the children it uses to do feature detection. + # + # This means that python deps we add to `checkDeps` (which the python + # interpreter is made aware of via `$PYTHONPATH` – populated by the python + # setup hook) are not picked up by `lit` which causes it to skip tests. + # + # Adding `python3.withPackages (ps: [ ... ])` to `checkDeps` also doesn't work + # because this package is shadowed in `$PATH` by the regular `python3` + # package. + # + # So, we "manually" assemble one python derivation for the package to depend + # on, taking into account whether checks are enabled or not: + python = if doCheck then + # Note that we _explicitly_ ask for a python interpreter for our host + # platform here; the splicing that would ordinarily take care of this for + # us does not seem to work once we use `withPackages`. + let + checkDeps = ps: with ps; [ psutil ]; + in pkgsBuildBuild.targetPackages.python3.withPackages checkDeps + else python3; + +in + +stdenv.mkDerivation (rec { + pname = "llvm_llvm"; + inherit (llvm_source) version; + + src = runCommand "${pname}-src-${version}" {} ('' + mkdir -p "$out" + cp -r ${llvm_source}/cmake "$out" + cp -r ${llvm_source}/llvm "$out" + cp -r ${llvm_source}/third-party "$out" + '' + lib.optionalString enablePolly '' + chmod u+w "$out/llvm/tools" + cp -r ${llvm_source}/polly "$out/llvm/tools" + ''); + + sourceRoot = "${src.name}/llvm"; + + outputs = [ "out" "lib" "dev" "python" ]; + + nativeBuildInputs = [ cmake ninja python ]; + + buildInputs = [ libxml2 libffi ] + ++ optional enablePFM libpfm; # exegesis + + propagatedBuildInputs = [ ncurses zlib ]; + + nativeCheckInputs = [ + which + ] ++ lib.optional stdenv.isDarwin sysctl; + + patches = [ + ./gnu-install-dirs.patch + + # Running the tests involves invoking binaries (like `opt`) that depend on + # the LLVM dylibs and reference them by absolute install path (i.e. their + # nix store path). + # + # Because we have not yet run the install phase (we're running these tests + # as part of `checkPhase` instead of `installCheckPhase`) these absolute + # paths do not exist yet; to work around this we point the loader (`ld` on + # unix, `dyld` on macOS) at the `lib` directory which will later become this + # package's `lib` output. + # + # Previously we would just set `LD_LIBRARY_PATH` to include the build `lib` + # dir but: + # - this doesn't generalize well to other platforms; `lit` doesn't forward + # `DYLD_LIBRARY_PATH` (macOS): + # + https://github.com/llvm/llvm-project/blob/0d89963df354ee309c15f67dc47c8ab3cb5d0fb2/llvm/utils/lit/lit/TestingConfig.py#L26 + # - even if `lit` forwarded this env var, we actually cannot set + # `DYLD_LIBRARY_PATH` in the child processes `lit` launches because + # `DYLD_LIBRARY_PATH` (and `DYLD_FALLBACK_LIBRARY_PATH`) is cleared for + # "protected processes" (i.e. the python interpreter that runs `lit`): + # https://stackoverflow.com/a/35570229 + # - other LLVM subprojects deal with this issue by having their `lit` + # configuration set these env vars for us; it makes sense to do the same + # for LLVM: + # + https://github.com/llvm/llvm-project/blob/4c106cfdf7cf7eec861ad3983a3dd9a9e8f3a8ae/clang-tools-extra/test/Unit/lit.cfg.py#L22-L31 + # + # !!! TODO: look into upstreaming this patch + ./llvm-lit-cfg-add-libs-to-dylib-path.patch + + # `lit` has a mode where it executes run lines as a shell script which is + # constructs; this is problematic for macOS because it means that there's + # another process in between `lit` and the binaries being tested. As noted + # above, this means that `DYLD_LIBRARY_PATH` is cleared which means that our + # tests fail with dyld errors. + # + # To get around this we patch `lit` to reintroduce `DYLD_LIBRARY_PATH`, when + # present in the test configuration. + # + # It's not clear to me why this isn't an issue for LLVM developers running + # on macOS (nothing about this _seems_ nix specific).. + ./lit-shell-script-runner-set-dyld-library-path.patch + ] ++ lib.optionals enablePolly [ + ./gnu-install-dirs-polly.patch + + # Just like the `llvm-lit-cfg` patch, but for `polly`. + ./polly-lit-cfg-add-libs-to-dylib-path.patch + ]; + + postPatch = optionalString stdenv.isDarwin '' + substituteInPlace cmake/modules/AddLLVM.cmake \ + --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \ + --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' "" + + # As of LLVM 15, marked as XFAIL on arm64 macOS but lit doesn't seem to pick + # this up: https://github.com/llvm/llvm-project/blob/c344d97a125b18f8fed0a64aace73c49a870e079/llvm/test/MC/ELF/cfi-version.ll#L7 + rm test/MC/ELF/cfi-version.ll + + # This test tries to call `sw_vers` by absolute path (`/usr/bin/sw_vers`) + # and thus fails under the sandbox: + substituteInPlace unittests/TargetParser/Host.cpp \ + --replace '/usr/bin/sw_vers' "${(builtins.toString darwin.DarwinTools) + "/bin/sw_vers" }" + + # This test tries to call the intrinsics `@llvm.roundeven.f32` and + # `@llvm.roundeven.f64` which seem to (incorrectly?) lower to `roundevenf` + # and `roundeven` on macOS. + # + # However these functions are glibc specific so the test fails: + # - https://www.gnu.org/software/gnulib/manual/html_node/roundevenf.html + # - https://www.gnu.org/software/gnulib/manual/html_node/roundeven.html + # + substituteInPlace test/ExecutionEngine/Interpreter/intrinsics.ll \ + --replace "%roundeven32 = call float @llvm.roundeven.f32(float 0.000000e+00)" "" \ + --replace "%roundeven64 = call double @llvm.roundeven.f64(double 0.000000e+00)" "" + '' + optionalString (stdenv.isDarwin && stdenv.hostPlatform.isx86) '' + # This test fails on darwin x86_64 because `sw_vers` reports a different + # macOS version than what LLVM finds by reading + # `/System/Library/CoreServices/SystemVersion.plist` (which is passed into + # the sandbox on macOS). + # + # The `sw_vers` provided by nixpkgs reports the macOS version associated + # with the `CoreFoundation` framework with which it was built. Because + # nixpkgs pins the SDK for `aarch64-darwin` and `x86_64-darwin` what + # `sw_vers` reports is not guaranteed to match the macOS version of the host + # that's building this derivation. + # + # Astute readers will note that we only _patch_ this test on aarch64-darwin + # (to use the nixpkgs provided `sw_vers`) instead of disabling it outright. + # So why does this test pass on aarch64? + # + # Well, it seems that `sw_vers` on aarch64 actually links against the _host_ + # CoreFoundation framework instead of the nixpkgs provided one. + # + # Not entirely sure what the right fix is here. I'm assuming aarch64 + # `sw_vers` doesn't intentionally link against the host `CoreFoundation` + # (still digging into how this ends up happening, will follow up) but that + # aside I think the more pertinent question is: should we be patching LLVM's + # macOS version detection logic to use `sw_vers` instead of reading host + # paths? This *is* a way in which details about builder machines can creep + # into the artifacts that are produced, affecting reproducibility, but it's + # not clear to me when/where/for what this even gets used in LLVM. + # + # TODO(@rrbutani): fix/follow-up + substituteInPlace unittests/TargetParser/Host.cpp \ + --replace "getMacOSHostVersion" "DISABLED_getMacOSHostVersion" + + # This test fails with a `dysmutil` crash; have not yet dug into what's + # going on here (TODO(@rrbutani)). + rm test/tools/dsymutil/ARM/obfuscated.test + '' + '' + # FileSystem permissions tests fail with various special bits + substituteInPlace unittests/Support/CMakeLists.txt \ + --replace "Path.cpp" "" + rm unittests/Support/Path.cpp + substituteInPlace unittests/IR/CMakeLists.txt \ + --replace "PassBuilderCallbacksTest.cpp" "" + rm unittests/IR/PassBuilderCallbacksTest.cpp + rm test/tools/llvm-objcopy/ELF/mirror-permissions-unix.test + '' + optionalString stdenv.hostPlatform.isMusl '' + patch -p1 -i ${./TLI-musl.patch} + substituteInPlace unittests/Support/CMakeLists.txt \ + --replace "add_subdirectory(DynamicLibrary)" "" + rm unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp + # valgrind unhappy with musl or glibc, but fails w/musl only + rm test/CodeGen/AArch64/wineh4.mir + '' + optionalString stdenv.hostPlatform.isAarch32 '' + # skip failing X86 test cases on 32-bit ARM + rm test/DebugInfo/X86/convert-debugloc.ll + rm test/DebugInfo/X86/convert-inlined.ll + rm test/DebugInfo/X86/convert-linked.ll + rm test/tools/dsymutil/X86/op-convert.test + rm test/tools/gold/X86/split-dwarf.ll + rm test/tools/llvm-dwarfdump/X86/prettyprint_types.s + rm test/tools/llvm-dwarfdump/X86/simplified-template-names.s + rm test/CodeGen/RISCV/attributes.ll + rm test/CodeGen/RISCV/xtheadmempair.ll + '' + optionalString (stdenv.hostPlatform.system == "armv6l-linux") '' + # Seems to require certain floating point hardware (NEON?) + rm test/ExecutionEngine/frem.ll + '' + '' + patchShebangs test/BugPoint/compile-custom.ll.py + ''; + + preConfigure = '' + # Workaround for configure flags that need to have spaces + cmakeFlagsArray+=( + -DLLVM_LIT_ARGS="-svj''${NIX_BUILD_CORES} --no-progress-bar" + ) + ''; + + # Defensive check: some paths (that we make symlinks to) depend on the release + # version, for example: + # - https://github.com/llvm/llvm-project/blob/406bde9a15136254f2b10d9ef3a42033b3cb1b16/clang/lib/Headers/CMakeLists.txt#L185 + # + # So we want to sure that the version in the source matches the release + # version we were given. + # + # We do this check here, in the LLVM build, because it happens early. + postConfigure = let + v = lib.versions; + major = v.major release_version; + minor = v.minor release_version; + patch = v.patch release_version; + in '' + # $1: part, $2: expected + check_version() { + part="''${1^^}" + part="$(cat include/llvm/Config/llvm-config.h | grep "#define LLVM_VERSION_''${part} " | cut -d' ' -f3)" + + if [[ "$part" != "$2" ]]; then + echo >&2 \ + "mismatch in the $1 version! we have version ${release_version}" \ + "and expected the $1 version to be '$2'; the source has '$part' instead" + exit 3 + fi + } + + check_version major ${major} + check_version minor ${minor} + check_version patch ${patch} + ''; + + # E.g. mesa.drivers use the build-id as a cache key (see #93946): + LDFLAGS = optionalString (enableSharedLibraries && !stdenv.isDarwin) "-Wl,--build-id=sha1"; + + cmakeBuildType = if debugVersion then "Debug" else "Release"; + + cmakeFlags = with stdenv; let + # These flags influence llvm-config's BuildVariables.inc in addition to the + # general build. We need to make sure these are also passed via + # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native + # will return different results from the cross llvm-config. + # + # Some flags don't need to be repassed because LLVM already does so (like + # CMAKE_BUILD_TYPE), others are irrelevant to the result. + flagsForLlvmConfig = [ + "-DLLVM_INSTALL_PACKAGE_DIR=${placeholder "dev"}/lib/cmake/llvm" + "-DLLVM_ENABLE_RTTI=ON" + ] ++ optionals enableSharedLibraries [ + "-DLLVM_LINK_LLVM_DYLIB=ON" + ]; + in flagsForLlvmConfig ++ [ + "-DLLVM_INSTALL_UTILS=ON" # Needed by rustc + "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}" + "-DLLVM_ENABLE_FFI=ON" + "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}" + "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}" + "-DLLVM_ENABLE_DUMP=ON" + + + "-DLLVM_ENABLE_LIBCXX=ON" + "-DLLVM_ENABLE_LIBCXXABI=ON" + + # Static build options ===== + # Disables building of shared libs, -fPIC is still injected by cc-wrapper + "-DLLVM_ENABLE_PIC=OFF" + "-DLLVM_BUILD_STATIC=ON" + "-DLLVM_LINK_LLVM_DYLIB=off" + # libxml2 needs to be disabled because the LLVM build system ignores its .la + # file and doesn't link zlib as well. + # https://github.com/ClangBuiltLinux/tc-build/issues/150#issuecomment-845418812 + "-DLLVM_ENABLE_LIBXML2=OFF" + # ==== + + ] ++ optionals stdenv.hostPlatform.isDarwin [ + "-DCAN_TARGET_i386=false" + ] ++ optionals enableGoldPlugin [ + # For LLVMgold plugin + "-DLLVM_BINUTILS_INCDIR=${libbfd.dev}/include" + ] ++ optionals ((stdenv.hostPlatform != stdenv.buildPlatform) && !(stdenv.buildPlatform.canExecute stdenv.hostPlatform)) [ + "-DCMAKE_CROSSCOMPILING=True" + "-DLLVM_TABLEGEN=${buildLlvmTools.llvm}/bin/llvm-tblgen" + ( + let + nativeCC = pkgsBuildBuild.targetPackages.stdenv.cc; + nativeBintools = nativeCC.bintools.bintools; + nativeToolchainFlags = [ + "-DCMAKE_C_COMPILER=${nativeCC}/bin/${nativeCC.targetPrefix}cc" + "-DCMAKE_CXX_COMPILER=${nativeCC}/bin/${nativeCC.targetPrefix}c++" + "-DCMAKE_AR=${nativeBintools}/bin/${nativeBintools.targetPrefix}ar" + "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip" + "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib" + ]; + # We need to repass the custom GNUInstallDirs values, otherwise CMake + # will choose them for us, leading to wrong results in llvm-config-native + nativeInstallFlags = [ + "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}" + "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin" + "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include" + "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib" + "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec" + ]; + in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=" + + lib.concatStringsSep ";" (lib.concatLists [ + flagsForLlvmConfig + nativeToolchainFlags + nativeInstallFlags + ]) + ) + ]; + + postInstall = '' + mkdir -p $python/share + mv $out/share/opt-viewer $python/share/opt-viewer + moveToOutput "bin/llvm-config*" "$dev" + substituteInPlace "$dev/lib/cmake/llvm/LLVMExports-${if debugVersion then "debug" else "release"}.cmake" \ + --replace "\''${_IMPORT_PREFIX}/lib/lib" "$lib/lib/lib" \ + --replace "$out/bin/llvm-config" "$dev/bin/llvm-config" + substituteInPlace "$dev/lib/cmake/llvm/LLVMConfig.cmake" \ + --replace 'set(LLVM_BINARY_DIR "''${LLVM_INSTALL_PREFIX}")' 'set(LLVM_BINARY_DIR "'"$lib"'")' + '' + + optionalString (stdenv.isDarwin && enableSharedLibraries) '' + ln -s $lib/lib/libLLVM.dylib $lib/lib/libLLVM-${shortVersion}.dylib + ln -s $lib/lib/libLLVM.dylib $lib/lib/libLLVM-${release_version}.dylib + '' + + optionalString ((stdenv.buildPlatform != stdenv.hostPlatform) && !(stdenv.buildPlatform.canExecute stdenv.hostPlatform)) '' + cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native + ''; + + inherit doCheck; + + checkTarget = "check-all"; + + # For the update script: + passthru.monorepoSrc = llvm_source; + + requiredSystemFeatures = [ "big-parallel" ]; + inherit (utils) meta; +}) diff --git a/nix/llvm/gnu-install-dirs-polly.patch b/nix/llvm/gnu-install-dirs-polly.patch new file mode 100644 index 0000000..b01363e --- /dev/null +++ b/nix/llvm/gnu-install-dirs-polly.patch @@ -0,0 +1,19 @@ +This is the one remaining Polly install dirs related change that hasn't made it +into upstream yet; previously this patch file also included: +https://reviews.llvm.org/D117541 + +diff --git a/tools/polly/cmake/polly_macros.cmake b/tools/polly/cmake/polly_macros.cmake +index 518a09b45a42..bd9d6f5542ad 100644 +--- a/tools/polly/cmake/polly_macros.cmake ++++ b/tools/polly/cmake/polly_macros.cmake +@@ -44,8 +44,8 @@ macro(add_polly_library name) + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LLVMPolly") + install(TARGETS ${name} + EXPORT LLVMExports +- LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} +- ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) ++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}) + endif() + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name}) + endmacro(add_polly_library) diff --git a/nix/llvm/gnu-install-dirs.patch b/nix/llvm/gnu-install-dirs.patch new file mode 100644 index 0000000..a903974 --- /dev/null +++ b/nix/llvm/gnu-install-dirs.patch @@ -0,0 +1,137 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 471817d68286..c51463304159 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1010,7 +1010,7 @@ if (NOT TENSORFLOW_AOT_PATH STREQUAL "") + add_subdirectory(${TENSORFLOW_AOT_PATH}/xla_aot_runtime_src + ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/tf_runtime) + install(TARGETS tf_xla_runtime EXPORT LLVMExports +- ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT tf_xla_runtime) ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX} COMPONENT tf_xla_runtime) + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS tf_xla_runtime) + # Once we add more modules, we should handle this more automatically. + if (DEFINED LLVM_OVERRIDE_MODEL_HEADER_INLINERSIZEMODEL) +diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake +index 230620c37027..dd16cab1835e 100644 +--- a/cmake/modules/AddLLVM.cmake ++++ b/cmake/modules/AddLLVM.cmake +@@ -876,8 +876,8 @@ macro(add_llvm_library name) + get_target_export_arg(${name} LLVM export_to_llvmexports ${umbrella}) + install(TARGETS ${name} + ${export_to_llvmexports} +- LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name} +- ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name} ++ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" COMPONENT ${name} ++ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" COMPONENT ${name} + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT ${name}) + + if (NOT LLVM_ENABLE_IDE) +@@ -2069,7 +2069,7 @@ function(llvm_install_library_symlink name dest type) + set(LLVM_LINK_OR_COPY copy) + endif() + +- set(output_dir lib${LLVM_LIBDIR_SUFFIX}) ++ set(output_dir ${CMAKE_INSTALL_FULL_LIBDIR}${LLVM_LIBDIR_SUFFIX}) + if(WIN32 AND "${type}" STREQUAL "SHARED") + set(output_dir "${CMAKE_INSTALL_BINDIR}") + endif() +@@ -2344,16 +2344,37 @@ function(llvm_setup_rpath name) + + if (APPLE) + set(_install_name_dir INSTALL_NAME_DIR "@rpath") +- set(_install_rpath "@loader_path/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) ++ set(_install_rpath "@loader_path/../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "AIX" AND BUILD_SHARED_LIBS) + # $ORIGIN is not interpreted at link time by aix ld. + # Since BUILD_SHARED_LIBS is only recommended for use by developers, + # hardcode the rpath to build/install lib dir first in this mode. + # FIXME: update this when there is better solution. +- set(_install_rpath "${LLVM_LIBRARY_OUTPUT_INTDIR}" "${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) ++ set(_install_rpath "${LLVM_LIBRARY_OUTPUT_INTDIR}" "${CMAKE_INSTALL_FULL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) + elseif(UNIX) +- set(_build_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) +- set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}") ++ # Note that we add `extra_libdir` (aka `LLVM_LIBRARY_DIR` in our case) back ++ # to `_install_rpath` here. ++ # ++ # In nixpkgs we do not build and install LLVM alongside rdeps of LLVM (i.e. ++ # clang); instead LLVM is its own package and thus lands at its own nix ++ # store path. This makes it so that the default relative rpath (`../lib/`) ++ # does not point at the LLVM shared objects. ++ # ++ # More discussion here: ++ # - https://github.com/NixOS/nixpkgs/pull/235624#discussion_r1220150329 ++ # - https://reviews.llvm.org/D146918 (16.0.5+) ++ # ++ # Note that we leave `extra_libdir` in `_build_rpath`: without FHS there is ++ # no potential that this will result in us pulling in the "wrong" LLVM. ++ # Adding this to the build rpath means we aren't forced to use ++ # `installCheckPhase` instead of `checkPhase` (i.e. binaries in the build ++ # dir, pre-install, will have the right rpath for LLVM). ++ # ++ # As noted in the differential above, an alternative solution is to have ++ # all rdeps of nixpkgs' LLVM (that use the AddLLVM.cmake machinery) set ++ # `CMAKE_INSTALL_RPATH`. ++ set(_build_rpath "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) ++ set(_install_rpath "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) + if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)") + set_property(TARGET ${name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-z,origin ") +diff --git a/cmake/modules/AddOCaml.cmake b/cmake/modules/AddOCaml.cmake +index 891c9e6d618c..8d963f3b0069 100644 +--- a/cmake/modules/AddOCaml.cmake ++++ b/cmake/modules/AddOCaml.cmake +@@ -147,9 +147,9 @@ function(add_ocaml_library name) + endforeach() + + if( APPLE ) +- set(ocaml_rpath "@executable_path/../../../lib${LLVM_LIBDIR_SUFFIX}") ++ set(ocaml_rpath "@executable_path/../../../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}") + elseif( UNIX ) +- set(ocaml_rpath "\\$ORIGIN/../../../lib${LLVM_LIBDIR_SUFFIX}") ++ set(ocaml_rpath "\\$ORIGIN/../../../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}") + endif() + list(APPEND ocaml_flags "-ldopt" "-Wl,-rpath,${ocaml_rpath}") + +diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt +index d99af79aa38e..21e794224b99 100644 +--- a/cmake/modules/CMakeLists.txt ++++ b/cmake/modules/CMakeLists.txt +@@ -127,7 +127,7 @@ set(LLVM_CONFIG_INCLUDE_DIRS + ) + list(REMOVE_DUPLICATES LLVM_CONFIG_INCLUDE_DIRS) + +-extend_path(LLVM_CONFIG_LIBRARY_DIR "\${LLVM_INSTALL_PREFIX}" "lib\${LLVM_LIBDIR_SUFFIX}") ++extend_path(LLVM_CONFIG_LIBRARY_DIR "\${LLVM_INSTALL_PREFIX}" "${CMAKE_INSTALL_LIBDIR}\${LLVM_LIBDIR_SUFFIX}") + set(LLVM_CONFIG_LIBRARY_DIRS + "${LLVM_CONFIG_LIBRARY_DIR}" + # FIXME: Should there be other entries here? +diff --git a/tools/llvm-config/BuildVariables.inc.in b/tools/llvm-config/BuildVariables.inc.in +index 370005cd8d7d..7e790bc52111 100644 +--- a/tools/llvm-config/BuildVariables.inc.in ++++ b/tools/llvm-config/BuildVariables.inc.in +@@ -23,6 +23,7 @@ + #define LLVM_CXXFLAGS "@LLVM_CXXFLAGS@" + #define LLVM_BUILDMODE "@LLVM_BUILDMODE@" + #define LLVM_LIBDIR_SUFFIX "@LLVM_LIBDIR_SUFFIX@" ++#define LLVM_INSTALL_LIBDIR "@CMAKE_INSTALL_LIBDIR@" + #define LLVM_INSTALL_INCLUDEDIR "@CMAKE_INSTALL_INCLUDEDIR@" + #define LLVM_INSTALL_PACKAGE_DIR "@LLVM_INSTALL_PACKAGE_DIR@" + #define LLVM_TARGETS_BUILT "@LLVM_TARGETS_BUILT@" +diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp +index e86eb2b44b10..f63e207e792e 100644 +--- a/tools/llvm-config/llvm-config.cpp ++++ b/tools/llvm-config/llvm-config.cpp +@@ -366,7 +366,11 @@ int main(int argc, char **argv) { + sys::fs::make_absolute(ActivePrefix, Path); + ActiveBinDir = std::string(Path.str()); + } +- ActiveLibDir = ActivePrefix + "/lib" + LLVM_LIBDIR_SUFFIX; ++ { ++ SmallString<256> Path(LLVM_INSTALL_LIBDIR LLVM_LIBDIR_SUFFIX); ++ sys::fs::make_absolute(ActivePrefix, Path); ++ ActiveLibDir = std::string(Path.str()); ++ } + { + SmallString<256> Path(LLVM_INSTALL_PACKAGE_DIR); + sys::fs::make_absolute(ActivePrefix, Path); diff --git a/nix/llvm/lit-shell-script-runner-set-dyld-library-path.patch b/nix/llvm/lit-shell-script-runner-set-dyld-library-path.patch new file mode 100644 index 0000000..82b7b21 --- /dev/null +++ b/nix/llvm/lit-shell-script-runner-set-dyld-library-path.patch @@ -0,0 +1,17 @@ +diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py +index 0242e0b75af3..d732011306f7 100644 +--- a/utils/lit/lit/TestRunner.py ++++ b/utils/lit/lit/TestRunner.py +@@ -1029,6 +1029,12 @@ def executeScript(test, litConfig, tmpBase, commands, cwd): + f.write('@echo off\n') + f.write('\n@if %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands)) + else: ++ # This env var is *purged* when invoking subprocesses so we have to ++ # manually set it from within the bash script in order for the commands ++ # in run lines to see this var: ++ if "DYLD_LIBRARY_PATH" in test.config.environment: ++ f.write(f'export DYLD_LIBRARY_PATH="{test.config.environment["DYLD_LIBRARY_PATH"]}"\n') ++ + for i, ln in enumerate(commands): + match = re.match(kPdbgRegex, ln) + if match: diff --git a/nix/llvm/llvm-lit-cfg-add-libs-to-dylib-path.patch b/nix/llvm/llvm-lit-cfg-add-libs-to-dylib-path.patch new file mode 100644 index 0000000..2e2f98c --- /dev/null +++ b/nix/llvm/llvm-lit-cfg-add-libs-to-dylib-path.patch @@ -0,0 +1,79 @@ +diff --git a/test/Unit/lit.cfg.py b/test/Unit/lit.cfg.py +index 81e8dc04acea..479ff95681e2 100644 +--- a/test/Unit/lit.cfg.py ++++ b/test/Unit/lit.cfg.py +@@ -3,6 +3,7 @@ + # Configuration file for the 'lit' test runner. + + import os ++import platform + import subprocess + + import lit.formats +@@ -55,3 +56,26 @@ if sys.platform in ["win32", "cygwin"] and os.path.isdir(config.shlibdir): + # Win32 may use %SYSTEMDRIVE% during file system shell operations, so propogate. + if sys.platform == "win32" and "SYSTEMDRIVE" in os.environ: + config.environment["SYSTEMDRIVE"] = os.environ["SYSTEMDRIVE"] ++ ++# Add the LLVM dynamic libs to the platform-specific loader search path env var: ++# ++# TODO: this is copied from `clang`'s `lit.cfg.py`; should unify.. ++def find_shlibpath_var(): ++ if platform.system() in ["Linux", "FreeBSD", "NetBSD", "OpenBSD", "SunOS"]: ++ yield "LD_LIBRARY_PATH" ++ elif platform.system() == "Darwin": ++ yield "DYLD_LIBRARY_PATH" ++ elif platform.system() == "Windows": ++ yield "PATH" ++ elif platform.system() == "AIX": ++ yield "LIBPATH" ++ ++for shlibpath_var in find_shlibpath_var(): ++ shlibpath = os.path.pathsep.join( ++ (config.shlibdir, ++ config.environment.get(shlibpath_var, ''))) ++ config.environment[shlibpath_var] = shlibpath ++ break ++else: ++ lit_config.warning("unable to inject shared library path on '{}'" ++ .format(platform.system())) +diff --git a/test/lit.cfg.py b/test/lit.cfg.py +index 75a38b4c5dad..856fc75c9d74 100644 +--- a/test/lit.cfg.py ++++ b/test/lit.cfg.py +@@ -42,6 +42,26 @@ llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True) + llvm_config.with_system_environment( + ["HOME", "INCLUDE", "LIB", "TMP", "TEMP"]) + ++# Add the LLVM dynamic libs to the platform-specific loader search path env var: ++# ++# TODO: this is copied from `clang`'s `lit.cfg.py`; should unify.. ++def find_shlibpath_var(): ++ if platform.system() in ["Linux", "FreeBSD", "NetBSD", "OpenBSD", "SunOS"]: ++ yield "LD_LIBRARY_PATH" ++ elif platform.system() == "Darwin": ++ yield "DYLD_LIBRARY_PATH" ++ elif platform.system() == "Windows": ++ yield "PATH" ++ elif platform.system() == "AIX": ++ yield "LIBPATH" ++ ++for shlibpath_var in find_shlibpath_var(): ++ shlibpath = config.llvm_shlib_dir ++ llvm_config.with_environment(shlibpath_var, shlibpath, append_path = True) ++ break ++else: ++ lit_config.warning("unable to inject shared library path on '{}'" ++ .format(platform.system())) + + # Set up OCAMLPATH to include newly built OCaml libraries. + top_ocaml_lib = os.path.join(config.llvm_lib_dir, "ocaml") +@@ -318,7 +338,7 @@ def have_cxx_shared_library(): + + try: + readobj_cmd = subprocess.Popen( +- [readobj_exe, "--needed-libs", readobj_exe], stdout=subprocess.PIPE ++ [readobj_exe, "--needed-libs", readobj_exe], stdout=subprocess.PIPE, env=config.environment + ) + except OSError: + print("could not exec llvm-readobj") diff --git a/nix/llvm/polly-lit-cfg-add-libs-to-dylib-path.patch b/nix/llvm/polly-lit-cfg-add-libs-to-dylib-path.patch new file mode 100644 index 0000000..a1875e7 --- /dev/null +++ b/nix/llvm/polly-lit-cfg-add-libs-to-dylib-path.patch @@ -0,0 +1,24 @@ +diff --git a/tools/polly/test/lit.cfg b/tools/polly/test/lit.cfg +index 41e3a589c61e..09f3b17498b0 100644 +--- a/tools/polly/test/lit.cfg ++++ b/tools/polly/test/lit.cfg +@@ -36,9 +36,17 @@ base_paths = [config.llvm_tools_dir, config.environment['PATH']] + path = os.path.pathsep.join(base_paths + config.extra_paths) + config.environment['PATH'] = path + ++# (Copied from polly/test/Unit/lit.cfg) ++if platform.system() == 'Darwin': ++ shlibpath_var = 'DYLD_LIBRARY_PATH' ++elif platform.system() == 'Windows': ++ shlibpath_var = 'PATH' ++else: ++ shlibpath_var = 'LD_LIBRARY_PATH' ++ + path = os.path.pathsep.join((config.llvm_libs_dir, +- config.environment.get('LD_LIBRARY_PATH',''))) +-config.environment['LD_LIBRARY_PATH'] = path ++ config.environment.get(shlibpath_var,''))) ++config.environment[shlibpath_var] = path + + llvm_config.use_default_substitutions() + diff --git a/nix/llvm_source.nix b/nix/llvm_source.nix index c42020b..f23337d 100644 --- a/nix/llvm_source.nix +++ b/nix/llvm_source.nix @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . { + lib, stdenv, fetchgit, url ? "https://github.com/llvm/llvm-project.git", @@ -25,6 +26,7 @@ stdenv.mkDerivation rec{ pname = "llvm_source"; inherit version; + major = lib.versions.major version; src = fetchgit { inherit url hash; rev = ref;