Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 55 additions & 23 deletions pkgs/development/compilers/llvm/common/clang-tools/default.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
lib,
stdenv,
runCommand,
writeText,
clang-unwrapped,
clang,
libcxxClang,
Expand All @@ -10,9 +12,7 @@
enableLibcxx ? false,
}:

stdenv.mkDerivation {
unwrapped = clang-unwrapped;

stdenv.mkDerivation (finalAttrs: {
pname = "clang-tools";
version = lib.getVersion clang-unwrapped;
dontUnpack = true;
Expand All @@ -23,37 +23,69 @@ stdenv.mkDerivation {

mkdir -p $out/bin

for tool in $unwrapped/bin/clang-*; do
tool=$(basename "$tool")

# Compilers have their own derivation, no need to include them here:
if [[ $tool == "clang-cl" || $tool == "clang-cpp" ]]; then
continue
fi
for toolPath in ${clang-unwrapped}/bin/clangd ${clang-unwrapped}/bin/clang-*; do
toolName=$(basename "$toolPath")

# Clang's derivation produces a lot of binaries, but the tools we are
# interested in follow the `clang-something` naming convention - except
# for clang-$version (e.g. clang-13), which is the compiler again:
if [[ ! $tool =~ ^clang\-[a-zA-Z_\-]+$ ]]; then
# Compilers have their own derivations, no need to include them here
if [[ $toolName == "clang-cl" || $toolName == "clang-cpp" || $toolName =~ ^clang\-[0-9]+$ ]]; then
continue
fi

ln -s $out/bin/clangd $out/bin/$tool
cp $toolPath $out/bin/$toolName-unwrapped
substituteAll ${./wrapper} $out/bin/$toolName
chmod +x $out/bin/$toolName
done

if [[ -z "$(ls -A $out/bin)" ]]; then
echo "Found no binaries - maybe their location or naming convention changed?"
exit 1
fi

substituteAll ${./wrapper} $out/bin/clangd
chmod +x $out/bin/clangd
# clangd etc. find standard header files by looking at the directory the
# tool is located in and appending `../lib` to the search path. Since we
# are copying the binaries, they expect to find `$out/lib` present right
# within this derivation, containing `stddef.h` and so on.
#
# Note that using `ln -s` instead of `cp` in the loop above wouldn't avoid
# this problem, since it's `clang-unwrapped` which separates libs into a
# different output in the first place - here we are merely "merging" the
# directories back together, as expected by the tools.
ln -s ${clang-unwrapped.lib}/lib $out/lib

runHook postInstall
'';

passthru.tests.smokeOk =
let
src = writeText "main.cpp" ''
#include <iostream>

int main() {
std::cout << "Hi!";
}
'';

in
runCommand "clang-tools-test-smoke-ok" { } ''
${finalAttrs.finalPackage}/bin/clangd --check=${src}
touch $out
'';

passthru.tests.smokeErr =
let
src = writeText "main.cpp" ''
#include <iostream>

int main() {
std::cout << "Hi!";
}
'';

in
runCommand "clang-tools-test-smoke-err" { } ''
(${finalAttrs.finalPackage}/bin/clangd --query-driver='**' --check=${src} 2>&1 || true) \
| grep 'use of undeclared identifier'

touch $out
'';

meta = llvm_meta // {
description = "Standalone command line tools for C++ development";
maintainers = with lib.maintainers; [ patryk27 ];
};
}
})
25 changes: 19 additions & 6 deletions pkgs/development/compilers/llvm/common/clang-tools/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,23 @@ buildcpath() {
echo $path${after:+':'}$after
}

export CPATH=${CPATH}${CPATH:+':'}$(buildcpath ${NIX_CFLAGS_COMPILE} \
$(<@clang@/nix-support/libc-cflags)):@clang@/resource-root/include
export CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}${CPLUS_INCLUDE_PATH:+':'}$(buildcpath ${NIX_CFLAGS_COMPILE} \
$(<@clang@/nix-support/libcxx-cxxflags) \
$(<@clang@/nix-support/libc-cflags)):@clang@/resource-root/include
# When user passes `--query-driver`, avoid extending `CPATH` et al, since we
# don't want to infect user-specified toolchain and headers with our stuff.
extendcpath=true

exec -a "$0" @unwrapped@/bin/$(basename $0) "$@"
for arg in "$@"; do
if [[ "${arg}" == \-\-query\-driver* ]]; then
extendcpath=false
fi
done

if [ "$extendcpath" = true ]; then
export CPATH=${CPATH}${CPATH:+':'}$(buildcpath ${NIX_CFLAGS_COMPILE} \
$(<@clang@/nix-support/libc-cflags))

export CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}${CPLUS_INCLUDE_PATH:+':'}$(buildcpath ${NIX_CFLAGS_COMPILE} \
$(<@clang@/nix-support/libcxx-cxxflags) \
$(<@clang@/nix-support/libc-cflags))
fi

@out@/bin/$(basename $0)-unwrapped "$@"
Loading