{ stdenv, runCommand, nettools, perl, kmod, writeTextFile, coffeescript }: with stdenv.lib; let # Function to parse the config file to get the features supported readFeatures = config: let configParser = writeTextFile { name = "config-parser"; executable=true; text = '' #!${coffeescript}/bin/coffee fs = require "fs" events = require "events" lineEmitter = new events.EventEmitter() buffer = new Buffer 0 input = fs.createReadStream process.argv[2] input.on 'data', (data) -> nextBuffer = new Buffer buffer.length + data.length buffer.copy(nextBuffer) data.copy(nextBuffer, buffer.length) start = 0 offset = buffer.length buffer = nextBuffer for i in [1..data.length] if data[i] == '\n'.charCodeAt 0 end = i+offset+1 line = buffer.slice start, end - 1 start = end lineEmitter.emit "line", line.toString() buffer = buffer.slice start input.once 'end', -> input.destroy() if safeToWrite output.end "}" output.destroySoon() else output.once 'drain', -> output.end "}" output.destroySoon() output = fs.createWriteStream process.env["out"] output.setMaxListeners 0 safeToWrite = output.write "{\n" unless safeToWrite output.once 'drain', -> safeToWrite = true escapeNixString = (str) -> str.replace("'''", "''''").replace("''${", "'''''${") lineEmitter.on 'line', (line) -> unless line.length is 0 or line.charAt(0) is '#' split = line.split '=' name = split[0].substring "CONFIG_".length value = escapeNixString split.slice(1).join "" lineToWrite = "\"#{name}\" = '''#{value}''';\n" if safeToWrite safeToWrite = output.write lineToWrite else input.pause() output.once 'drain', -> safeToWrite = output.write lineToWrite input.resume() '';}; configAttrs = import "${runCommand "attrList.nix" {} "${configParser} ${config}"}"; getValue = option: if hasAttr option configAttrs then getAttr option configAttrs else null; isYes = option: (getValue option) == "y"; in { modular = isYes "MODULES"; }; in { # The kernel version version, # The version of the kernel module directory modDirVersion ? version, # The kernel source (tarball, git checkout, etc.) src, # Any patches patches ? [], # The kernel .config file config, # Manually specified features the kernel supports # If unspecified, this will be autodetected from the .config features ? readFeatures config }: let commonMakeFlags = [ "O=../build" "INSTALL_PATH=$(out)" "INSTALLKERNEL=${installkernel}" ]; installkernel = writeTextFile { name = "installkernel"; executable=true; text = '' #!/bin/sh mkdir $4 mv -v $2 $4 mv -v $3 $4 '';}; in stdenv.mkDerivation ({ name = "linux-${version}"; enableParallelBuilding = true; passthru = { inherit version modDirVersion features; }; inherit patches src; prePatch = '' for mf in $(find -name Makefile -o -name Makefile.include); do echo "stripping FHS paths in \`$mf'..." sed -i "$mf" -e 's|/usr/bin/||g ; s|/bin/||g ; s|/sbin/||g' done ''; configurePhase = '' runHook preConfigure mkdir ../build make $makeFlags "''${makeFlagsArray[@]}" mrproper ln -sv ${config} ../build/.config make $makeFlags "''${makeFlagsArray[@]}" oldconfig rm ../build/.config.old runHook postConfigure ''; buildNativeInputs = [ perl nettools kmod ]; makeFlags = commonMakeFlags; meta = { description = "The Linux kernel"; license = "GPLv2"; homepage = http://www.kernel.org/; maintainers = [ maintainers.shlevy ]; platforms = lib.platforms.linux; }; } // optionalAttrs (features ? modular && features.modular) { makeFlags = commonMakeFlags ++ [ "MODLIB=\"$(out)/lib/modules/${modDirVersion}\"" ]; postInstall = '' make modules_install $makeFlags "''${makeFlagsArray[@]}" \ $installFlags "''${installFlagsArray[@]}" rm -f $out/lib/modules/${modDirVersion}/{build,source} cd .. mv $sourceRoot $out/lib/modules/${modDirVersion}/source mv build $out/lib/modules/${modDirVersion}/build unlink $out/lib/modules/${modDirVersion}/build/source ln -sv $out/lib/modules/${modDirVersion}/{,build/}source ''; postFixup = '' if [ -z "$dontStrip" ]; then find $out -name "*.ko" -print0 | xargs -0 strip -S fi ''; })