at master 7.9 kB view raw
1{ 2 lib, 3 stdenv, 4 fetchFromGitHub, 5 runCommand, 6 ncurses, 7 gettext, 8 pkg-config, 9 cscope, 10 ruby_3_2, 11 tcl, 12 perl540, 13 luajit, 14 darwin, 15 libiconv, 16 python3, 17}: 18 19# Try to match MacVim's documented script interface compatibility 20let 21 perl = perl540; 22 # Ruby 3.2 23 ruby = ruby_3_2; 24 25 # Building requires a few system tools to be in PATH. 26 # Some of these we could patch into the relevant source files (such as xcodebuild and 27 # qlmanage) but some are used by Xcode itself and we have no choice but to put them in PATH. 28 # Symlinking them in this way is better than just putting all of /usr/bin in there. 29 buildSymlinks = runCommand "macvim-build-symlinks" { } '' 30 mkdir -p $out/bin 31 ln -s /usr/bin/xcrun /usr/bin/xcodebuild /usr/bin/tiffutil /usr/bin/qlmanage $out/bin 32 ''; 33in 34 35stdenv.mkDerivation (finalAttrs: { 36 pname = "macvim"; 37 38 version = "179"; 39 40 src = fetchFromGitHub { 41 owner = "macvim-dev"; 42 repo = "macvim"; 43 rev = "release-${finalAttrs.version}"; 44 hash = "sha256-L9LVXyeA09aMtNf+b/Oo+eLpeVEKTD1/oNWCiFn5FbU="; 45 }; 46 47 enableParallelBuilding = true; 48 49 nativeBuildInputs = [ 50 pkg-config 51 buildSymlinks 52 ]; 53 buildInputs = [ 54 gettext 55 ncurses 56 cscope 57 luajit 58 ruby 59 tcl 60 perl 61 python3 62 ]; 63 64 patches = [ ./macvim.patch ]; 65 66 configureFlags = [ 67 "--enable-cscope" 68 "--enable-fail-if-missing" 69 "--with-features=huge" 70 "--enable-gui=macvim" 71 "--enable-multibyte" 72 "--enable-nls" 73 "--enable-luainterp=dynamic" 74 "--enable-python3interp=dynamic" 75 "--enable-perlinterp=dynamic" 76 "--enable-rubyinterp=dynamic" 77 "--enable-tclinterp=yes" 78 "--without-local-dir" 79 "--with-luajit" 80 "--with-lua-prefix=${luajit}" 81 "--with-python3-command=${python3}/bin/python3" 82 "--with-ruby-command=${ruby}/bin/ruby" 83 "--with-tclsh=${tcl}/bin/tclsh" 84 "--with-tlib=ncurses" 85 "--with-compiledby=Nix" 86 "--disable-sparkle" 87 ]; 88 89 # Remove references to Sparkle.framework from the project. 90 # It's unused (we disabled it with --disable-sparkle) and this avoids 91 # copying the unnecessary several-megabyte framework into the result. 92 postPatch = '' 93 echo "Patching file src/MacVim/MacVim.xcodeproj/project.pbxproj" 94 sed -e '/Sparkle\.framework/d' -i src/MacVim/MacVim.xcodeproj/project.pbxproj 95 ''; 96 97 # This is unfortunate, but we need to use the same compiler as Xcode, but Xcode doesn't provide a 98 # way to configure the compiler. We also need to pull in lib/include paths for some of our build 99 # inputs since we don't have cc-wrapper to do that for us. 100 preConfigure = 101 let 102 # ideally we'd recurse, but we don't need that right now 103 inputs = [ ncurses ] ++ perl.propagatedBuildInputs; 104 ldflags = map (drv: "-L${lib.getLib drv}/lib") inputs; 105 cppflags = map (drv: "-isystem ${lib.getDev drv}/include") inputs; 106 in 107 '' 108 unset DEVELOPER_DIR # Use the system Xcode not the nixpkgs SDK. 109 110 CC=/usr/bin/clang 111 112 DEV_DIR=$(/usr/bin/xcode-select -print-path)/Platforms/MacOSX.platform/Developer 113 configureFlagsArray+=( 114 --with-developer-dir="$DEV_DIR" 115 LDFLAGS=${lib.escapeShellArg ldflags} 116 CPPFLAGS=${lib.escapeShellArg cppflags} 117 CFLAGS="-Wno-error=implicit-function-declaration" 118 ) 119 '' 120 # For some reason having LD defined causes PSMTabBarControl to fail at link-time as it 121 # passes arguments to ld that it meant for clang. 122 + '' 123 unset LD 124 '' 125 # When building with nix-daemon, we need to pass -derivedDataPath or else it tries to use 126 # a folder rooted in /var/empty and fails. Unfortunately we can't just pass -derivedDataPath 127 # by itself as this flag requires the use of -scheme or -xctestrun (not sure why), but MacVim 128 # by default just runs `xcodebuild -project src/MacVim/MacVim.xcodeproj`, relying on the default 129 # behavior to build the first target in the project. Experimentally, there seems to be a scheme 130 # called MacVim, so we'll explicitly select that. We also need to specify the configuration too 131 # as the scheme seems to have the wrong default. 132 + '' 133 configureFlagsArray+=( 134 XCODEFLAGS="-scheme MacVim -derivedDataPath $NIX_BUILD_TOP/derivedData" 135 --with-xcodecfg="Release" 136 ) 137 ''; 138 139 # Because we're building with system clang, this means we're building against Xcode's SDK and 140 # linking against system libraries. The configure script is picking up Nix Libsystem (via ruby) 141 # so we need to patch that out or we'll get linker issues. The MacVim binary built by Xcode links 142 # against the system anyway so it doesn't really matter that the Vim binary will too. If we 143 # decide that matters, we can always patch it back to the Nix libsystem post-build. 144 # It also picks up libiconv, libunwind, and objc4 from Nix. These seem relatively harmless but 145 # let's strip them out too. 146 # 147 # Note: If we do add a post-build install_name_tool patch, we need to add the 148 # "LDFLAGS=-headerpad_max_install_names" flag to configureFlags and either patch it into the 149 # Xcode project or pass it as a flag to xcodebuild as well. 150 postConfigure = '' 151 substituteInPlace src/auto/config.mk \ 152 --replace " -L${stdenv.cc.libc}/lib" "" \ 153 --replace " -L${darwin.libunwind}/lib" "" \ 154 --replace " -L${libiconv}/lib" "" 155 156 # All the libraries we stripped have -osx- in their name as of this time. 157 # Assert now that this pattern no longer appears in config.mk. 158 ( # scope variable 159 while IFS="" read -r line; do 160 if [[ "$line" == LDFLAGS*-osx-* ]]; then 161 echo "WARNING: src/auto/config.mk contains reference to Nix osx library" >&2 162 fi 163 done <src/auto/config.mk 164 ) 165 166 substituteInPlace src/MacVim/vimrc --subst-var-by CSCOPE ${cscope}/bin/cscope 167 ''; 168 169 # Note that $out/MacVim.app has a misnamed set of binaries in the Contents/bin folder (the V is 170 # capitalized) and is missing a bunch of them. This is why we're grabbing the version from the 171 # build folder. 172 postInstall = '' 173 mkdir -p $out/Applications 174 cp -r src/MacVim/build/Release/MacVim.app $out/Applications 175 rm -rf $out/MacVim.app 176 177 mkdir -p $out/bin 178 for prog in ex vi {,g,m,r}vi{m,mdiff,ew}; do 179 ln -s $out/Applications/MacVim.app/Contents/bin/mvim $out/bin/$prog 180 done 181 for prog in {,g}vimtutor xxd; do 182 ln -s $out/Applications/MacVim.app/Contents/bin/$prog $out/bin/$prog 183 done 184 ln -s $out/Applications/MacVim.app/Contents/bin/gvimtutor $out/bin/mvimtutor 185 186 mkdir -p $out/share 187 ln -s $out/Applications/MacVim.app/Contents/man $out/share/man 188 189 # Fix rpaths 190 exe="$out/Applications/MacVim.app/Contents/MacOS/Vim" 191 libperl=$(dirname $(find ${perl} -name "libperl.dylib")) 192 install_name_tool -add_rpath ${luajit}/lib $exe 193 install_name_tool -add_rpath ${tcl}/lib $exe 194 install_name_tool -add_rpath ${python3}/lib $exe 195 install_name_tool -add_rpath $libperl $exe 196 install_name_tool -add_rpath ${ruby}/lib $exe 197 198 # Remove manpages from tools we aren't providing 199 find $out/Applications/MacVim.app/Contents/man -name evim.1 -delete 200 ''; 201 202 # We rely on the user's Xcode install to build. It may be located in an arbitrary place, and 203 # it's not clear what system-level components it may require, so for now we'll just allow full 204 # filesystem access. This way the package still can't access the network. 205 sandboxProfile = '' 206 (allow file-read* file-write* process-exec mach-lookup) 207 ; block homebrew dependencies 208 (deny file-read* file-write* process-exec mach-lookup (subpath "/usr/local") (with no-log)) 209 ''; 210 211 meta = with lib; { 212 description = "Vim - the text editor - for macOS"; 213 homepage = "https://macvim.org/"; 214 license = licenses.vim; 215 maintainers = [ ]; 216 platforms = platforms.darwin; 217 hydraPlatforms = [ ]; # hydra can't build this as long as we rely on Xcode and sandboxProfile 218 }; 219})