Skip to content
Closed
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
13 changes: 0 additions & 13 deletions pkgs/by-name/cl/cling/no-clang-cpp.patch

This file was deleted.

247 changes: 62 additions & 185 deletions pkgs/by-name/cl/cling/package.nix
Original file line number Diff line number Diff line change
@@ -1,225 +1,102 @@
{
apple-sdk,
cmake,
fetchFromGitHub,
git,
lib,
libffi,
llvmPackages_13,
makeWrapper,
ncurses,
mkLLVMPackages,
llvmPackages,
fetchFromGitHub,
cmake,
ninja,
python3,
zlib,

# *NOT* from LLVM 13!
# The compiler used to compile Cling may affect the runtime include and lib
# directories it expects to be run with. Cling builds against (a fork of) Clang,
# so we prefer to use Clang as the compiler as well for consistency.
# It would be cleanest to use LLVM 9's clang, but it errors. So, we use a later
# version of Clang to compile, but we check out the Cling fork of Clang 9 to
# build Cling against.
clangStdenv,

# For runtime C++ standard library
gcc-unwrapped,

# Build with debug symbols
debug ? false,

# Build with libc++ (LLVM) rather than stdlibc++ (GCC).
# This is experimental and not all features work.
useLLVMLibcxx ? clangStdenv.hostPlatform.isDarwin,
wrapCCWith,
linkFarm,
}:

let
stdenv = clangStdenv;

# The patched clang lives in the LLVM megarepo
clangSrc = fetchFromGitHub {
owner = "root-project";
repo = "llvm-project";
# cling-llvm13 branch
rev = "3610201fbe0352a63efb5cb45f4ea4987702c735";
sha256 = "sha256-Cb7BvV7yobG+mkaYe7zD2KcnPvm8/vmVATNWssklXyk=";
sparseCheckout = [ "clang" ];
};

llvm = llvmPackages_13.llvm.override { enableSharedLibraries = false; };

unwrapped = stdenv.mkDerivation rec {
inherit (llvmPackages) stdenv;

# Cling requires its own fork of LLVM.
llvmPackages_cling =
(mkLLVMPackages {
version = "18.1.8+cling-llvm18-20250721-01";
officialRelease.version = "18.1.8";

monorepoSrc = fetchFromGitHub {
owner = "root-project";
repo = "llvm-project";
tag = "cling-llvm18-20250721-01";
hash = "sha256-3nZDFsq6pRPVctTBpX+Ed6Y5LjvNxKFKDX9aOppdFn0=";

# The fork has a backported patch that we also backport. This
# hack undoes the patch so that it can apply again cleanly.
postFetch = ''
substituteInPlace $out/llvm/include/llvm/ADT/SmallVector.h \
--replace-fail $'#include <cstdint>\n' ""
'';
};
}).value;

cling-unwrapped = stdenv.mkDerivation {
pname = "cling-unwrapped";
version = "1.0";

src = "${clangSrc}/clang";
version = "1.2-unstable-2025-09-01";

clingSrc = fetchFromGitHub {
src = fetchFromGitHub {
owner = "root-project";
repo = "cling";
rev = "v${version}";
sha256 = "sha256-Ye8EINzt+dyNvUIRydACXzb/xEPLm0YSkz08Xxw3xp4=";
rev = "d68b46dc7555da9f2fea067caefd0c1b195785df";
hash = "sha256-JP7wgctIQbnD2ZcrUm3rRbX8qBQA3QNyXCJz/VK/y1Q=";
};

prePatch = ''
echo "add_llvm_external_project(cling)" >> tools/CMakeLists.txt

cp -r $clingSrc tools/cling
chmod -R a+w tools/cling
'';

patches = [
./no-clang-cpp.patch
];

nativeBuildInputs = [
python3
git
cmake
ninja
python3
];

buildInputs = [
libffi
ncurses
zlib
llvmPackages_cling.llvm
llvmPackages_cling.libclang
];

strictDeps = true;

cmakeFlags = [
"-DLLVM_BINARY_DIR=${llvm.out}"
"-DLLVM_CONFIG=${llvm.dev}/bin/llvm-config"
"-DLLVM_LIBRARY_DIR=${llvm.lib}/lib"
"-DLLVM_MAIN_INCLUDE_DIR=${llvm.dev}/include"
"-DLLVM_TABLEGEN_EXE=${llvm.out}/bin/llvm-tblgen"
"-DLLVM_TOOLS_BINARY_DIR=${llvm.out}/bin"
"-DLLVM_BUILD_TOOLS=Off"
"-DLLVM_TOOL_CLING_BUILD=ON"

"-DLLVM_TARGETS_TO_BUILD=host;NVPTX"
"-DLLVM_ENABLE_RTTI=ON"

# Setting -DCLING_INCLUDE_TESTS=ON causes the cling/tools targets to be built;
# see cling/tools/CMakeLists.txt
"-DCLING_INCLUDE_TESTS=ON"
"-DCLANG-TOOLS=OFF"
]
++ lib.optionals debug [
"-DCMAKE_BUILD_TYPE=Debug"
]
++ lib.optionals useLLVMLibcxx [
"-DLLVM_ENABLE_LIBCXX=ON"
"-DLLVM_ENABLE_LIBCXXABI=ON"
];

CPPFLAGS = if useLLVMLibcxx then [ "-stdlib=libc++" ] else [ ];

postInstall = lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
mkdir -p $out/share/Jupyter
cp -r /build/clang/tools/cling/tools/Jupyter/kernel $out/share/Jupyter
'';

dontStrip = debug;
passthru = {
isClang = true;
langC = true;
langCC = true;
};

meta = with lib; {
meta = {
description = "Interactive C++ Interpreter";
mainProgram = "cling";
homepage = "https://root.cern/cling/";
license = with licenses; [
license = with lib.licenses; [
lgpl21
ncsa
];
maintainers = with maintainers; [ thomasjm ];
platforms = platforms.unix;
maintainers = with lib.maintainers; [ thomasjm ];
platforms = lib.platforms.unix;
};
};

# The flags passed to the wrapped cling should
# a) prevent it from searching for system include files and libs, and
# b) provide it with the include files and libs it needs (C and C++ standard library plus
# its own stuff)

# These are also exposed as cling.flags because it's handy to be able to pass them to tools
# that wrap Cling, particularly Jupyter kernels such as xeus-cling and the built-in
# jupyter-cling-kernel, which use Cling as a library.
# Thus, if you're packaging a Jupyter kernel, you either need to pass these flags as extra
# args to xcpp (for xeus-cling) or put them in the environment variable CLING_OPTS
# (for jupyter-cling-kernel).
flags = [
"-nostdinc"
"-nostdinc++"

"-resource-dir"
"${llvm.lib}/lib"

"-isystem"
"${lib.getLib unwrapped}/lib/clang/${llvmPackages_13.clang.version}/include"
]
++ lib.optionals useLLVMLibcxx [
"-I"
"${lib.getDev llvmPackages_13.libcxx}/include/c++/v1"
"-L"
"${llvmPackages_13.libcxx}/lib"
"-l"
"${llvmPackages_13.libcxx}/lib/libc++${stdenv.hostPlatform.extensions.sharedLibrary}"
]
++ lib.optionals (!useLLVMLibcxx) [
"-I"
"${gcc-unwrapped}/include/c++/${gcc-unwrapped.version}"
"-I"
"${gcc-unwrapped}/include/c++/${gcc-unwrapped.version}/${stdenv.hostPlatform.config}"
]
++ [
# System libc on Linux
# On Darwin, this is an empty directory, so we need a separate include with
# apple-sdk (see below)
"-isystem"
"${lib.getDev stdenv.cc.libc}/include"

# cling includes
"-isystem"
"${lib.getDev unwrapped}/include"
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
# On Darwin, we need the system includes
"-isystem"
"${apple-sdk}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include"
];

in

stdenv.mkDerivation {
pname = "cling";
version = unwrapped.version;

nativeBuildInputs = [ makeWrapper ];
inherit unwrapped flags;
inherit (unwrapped) meta;

dontUnpack = true;
dontConfigure = true;

buildPhase = ''
runHook preBuild

makeWrapper $unwrapped/bin/cling $out/bin/cling \
--add-flags "$flags"

runHook postBuild
'';

doCheck = true;
checkPhase = ''
runHook preCheck

output=$($out/bin/cling <<EOF
#include <iostream>
std::cout << "hello world" << std::endl
EOF
)
llvmPackages_cling.clang.override (prev: {
cc = linkFarm "cling-${cling-unwrapped.version}" {
"bin/clang++" = "${cling-unwrapped}/bin/cling";
};

echo "$output" | grep -q "Type C++ code and press enter to run it"
echo "$output" | grep -q "hello world"
extraBuildCommands = prev.extraBuildCommands or "" + ''
mv $out/bin/clang++ $out/bin/cling

runHook postCheck
# Drop the symlinks to the bintools.
find $out/bin -type l -delete
'';

dontInstall = true;
}
nixSupport = prev.nixSupport or { } // {
# Cling doesn’t support response files.
cc-wrapper-hook = "NIX_CC_USE_RESPONSE_FILE=0";
};
})
Loading