Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at netboot-syslinux-multiplatform 241 lines 8.3 kB view raw
1/* 2 3# Usage 4 5`emacs.pkgs.withPackages` takes a single argument: a function from a package 6set to a list of packages (the packages that will be available in 7Emacs). For example, 8``` 9emacs.pkgs.withPackages (epkgs: [ epkgs.evil epkgs.magit ]) 10``` 11All the packages in the list should come from the provided package 12set. It is possible to add any package to the list, but the provided 13set is guaranteed to have consistent dependencies and be built with 14the correct version of Emacs. 15 16# Overriding 17 18`emacs.pkgs.withPackages` inherits the package set which contains it, so the 19correct way to override the provided package set is to override the 20set which contains `emacs.pkgs.withPackages`. For example, to override 21`emacs.pkgs.emacs.pkgs.withPackages`, 22``` 23let customEmacsPackages = 24 emacs.pkgs.overrideScope' (self: super: { 25 # use a custom version of emacs 26 emacs = ...; 27 # use the unstable MELPA version of magit 28 magit = self.melpaPackages.magit; 29 }); 30in customEmacsPackages.withPackages (epkgs: [ epkgs.evil epkgs.magit ]) 31``` 32 33*/ 34 35{ lib, lndir, makeWrapper, runCommand, gcc }: self: 36 37with lib; 38 39let 40 41 inherit (self) emacs; 42 43 nativeComp = emacs.nativeComp or false; 44 45 treeSitter = emacs.treeSitter or false; 46 47in 48 49packagesFun: # packages explicitly requested by the user 50 51let 52 explicitRequires = 53 if lib.isFunction packagesFun 54 then packagesFun self 55 else packagesFun; 56in 57 58runCommand 59 (appendToName "with-packages" emacs).name 60 { 61 nativeBuildInputs = [ emacs lndir makeWrapper ]; 62 inherit emacs explicitRequires; 63 64 preferLocalBuild = true; 65 allowSubstitutes = false; 66 67 # Store all paths we want to add to emacs here, so that we only need to add 68 # one path to the load lists 69 deps = runCommand "emacs-packages-deps" 70 ({ 71 inherit explicitRequires lndir emacs; 72 nativeBuildInputs = lib.optional nativeComp gcc; 73 } // lib.optionalAttrs nativeComp { 74 inherit (emacs) LIBRARY_PATH; 75 }) 76 '' 77 findInputsOld() { 78 local pkg="$1"; shift 79 local var="$1"; shift 80 local propagatedBuildInputsFiles=("$@") 81 82 # TODO(@Ericson2314): Restore using associative array once Darwin 83 # nix-shell doesn't use impure bash. This should replace the O(n) 84 # case with an O(1) hash map lookup, assuming bash is implemented 85 # well :D. 86 local varSlice="$var[*]" 87 # ''${..-} to hack around old bash empty array problem 88 case "''${!varSlice-}" in 89 *" $pkg "*) return 0 ;; 90 esac 91 unset -v varSlice 92 93 eval "$var"'+=("$pkg")' 94 95 if ! [ -e "$pkg" ]; then 96 echo "build input $pkg does not exist" >&2 97 exit 1 98 fi 99 100 local file 101 for file in "''${propagatedBuildInputsFiles[@]}"; do 102 file="$pkg/nix-support/$file" 103 [[ -f "$file" ]] || continue 104 105 local pkgNext 106 for pkgNext in $(< "$file"); do 107 findInputsOld "$pkgNext" "$var" "''${propagatedBuildInputsFiles[@]}" 108 done 109 done 110 } 111 mkdir -p $out/bin 112 mkdir -p $out/share/emacs/site-lisp 113 ${optionalString nativeComp '' 114 mkdir -p $out/share/emacs/native-lisp 115 ''} 116 ${optionalString treeSitter '' 117 mkdir -p $out/lib 118 ''} 119 120 local requires 121 for pkg in $explicitRequires; do 122 findInputsOld $pkg requires propagated-user-env-packages 123 done 124 # requires now holds all requested packages and their transitive dependencies 125 126 linkPath() { 127 local pkg=$1 128 local origin_path=$2 129 local dest_path=$3 130 131 # Add the path to the search path list, but only if it exists 132 if [[ -d "$pkg/$origin_path" ]]; then 133 $lndir/bin/lndir -silent "$pkg/$origin_path" "$out/$dest_path" 134 fi 135 } 136 137 linkEmacsPackage() { 138 linkPath "$1" "bin" "bin" 139 linkPath "$1" "share/emacs/site-lisp" "share/emacs/site-lisp" 140 ${optionalString nativeComp '' 141 linkPath "$1" "share/emacs/native-lisp" "share/emacs/native-lisp" 142 ''} 143 ${optionalString treeSitter '' 144 linkPath "$1" "lib" "lib" 145 ''} 146 } 147 148 # Iterate over the array of inputs (avoiding nix's own interpolation) 149 for pkg in "''${requires[@]}"; do 150 linkEmacsPackage $pkg 151 done 152 153 siteStart="$out/share/emacs/site-lisp/site-start.el" 154 siteStartByteCompiled="$siteStart"c 155 subdirs="$out/share/emacs/site-lisp/subdirs.el" 156 subdirsByteCompiled="$subdirs"c 157 158 # A dependency may have brought the original siteStart or subdirs, delete 159 # it and create our own 160 # Begin the new site-start.el by loading the original, which sets some 161 # NixOS-specific paths. Paths are searched in the reverse of the order 162 # they are specified in, so user and system profile paths are searched last. 163 # 164 # NOTE: Avoid displaying messages early at startup by binding 165 # inhibit-message to t. This would prevent the Emacs GUI from showing up 166 # prematurely. The messages would still be logged to the *Messages* 167 # buffer. 168 rm -f $siteStart $siteStartByteCompiled $subdirs $subdirsByteCompiled 169 cat >"$siteStart" <<EOF 170 (let ((inhibit-message t)) 171 (load-file "$emacs/share/emacs/site-lisp/site-start.el")) 172 (add-to-list 'load-path "$out/share/emacs/site-lisp") 173 (add-to-list 'exec-path "$out/bin") 174 ${optionalString nativeComp '' 175 (add-to-list 'native-comp-eln-load-path "$out/share/emacs/native-lisp/") 176 ''} 177 ${optionalString treeSitter '' 178 (add-to-list 'treesit-extra-load-path "$out/lib/") 179 ''} 180 EOF 181 182 # Generate a subdirs.el that statically adds all subdirectories to load-path. 183 $emacs/bin/emacs \ 184 --batch \ 185 --load ${./mk-wrapper-subdirs.el} \ 186 --eval "(prin1 (macroexpand-1 '(mk-subdirs-expr \"$out/share/emacs/site-lisp\")))" \ 187 > "$subdirs" 188 189 # Byte-compiling improves start-up time only slightly, but costs nothing. 190 $emacs/bin/emacs --batch -f batch-byte-compile "$siteStart" "$subdirs" 191 192 ${optionalString nativeComp '' 193 $emacs/bin/emacs --batch \ 194 --eval "(add-to-list 'native-comp-eln-load-path \"$out/share/emacs/native-lisp/\")" \ 195 -f batch-native-compile "$siteStart" "$subdirs" 196 ''} 197 ''; 198 199 inherit (emacs) meta; 200 } 201 '' 202 mkdir -p "$out/bin" 203 204 # Wrap emacs and friends so they find our site-start.el before the original. 205 for prog in $emacs/bin/*; do # */ 206 local progname=$(basename "$prog") 207 rm -f "$out/bin/$progname" 208 209 substitute ${./wrapper.sh} $out/bin/$progname \ 210 --subst-var-by bash ${emacs.stdenv.shell} \ 211 --subst-var-by wrapperSiteLisp "$deps/share/emacs/site-lisp" \ 212 --subst-var-by wrapperSiteLispNative "$deps/share/emacs/native-lisp:" \ 213 --subst-var prog 214 chmod +x $out/bin/$progname 215 done 216 217 # Wrap MacOS app 218 # this has to pick up resources and metadata 219 # to recognize it as an "app" 220 if [ -d "$emacs/Applications/Emacs.app" ]; then 221 mkdir -p $out/Applications/Emacs.app/Contents/MacOS 222 cp -r $emacs/Applications/Emacs.app/Contents/Info.plist \ 223 $emacs/Applications/Emacs.app/Contents/PkgInfo \ 224 $emacs/Applications/Emacs.app/Contents/Resources \ 225 $out/Applications/Emacs.app/Contents 226 227 228 substitute ${./wrapper.sh} $out/Applications/Emacs.app/Contents/MacOS/Emacs \ 229 --subst-var-by bash ${emacs.stdenv.shell} \ 230 --subst-var-by wrapperSiteLisp "$deps/share/emacs/site-lisp" \ 231 --subst-var-by wrapperSiteLispNative "$deps/share/emacs/native-lisp:" \ 232 --subst-var-by prog "$emacs/Applications/Emacs.app/Contents/MacOS/Emacs" 233 chmod +x $out/Applications/Emacs.app/Contents/MacOS/Emacs 234 fi 235 236 mkdir -p $out/share 237 # Link icons and desktop files into place 238 for dir in applications icons info man emacs; do 239 ln -s $emacs/share/$dir $out/share/$dir 240 done 241 ''