1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
{
lib,
stdenv,
callPackage,
fetchFromGitHub,
apple-sdk_14,
ncurses,
gettext,
pkg-config,
cscope,
ruby_3_4,
tcl,
perl,
luajit,
python3,
# Setting withXcodePath makes it use that instead of the system-default Xcode.
# This can be set to one of the `darwin.xcode_*` packages as well.
# If set, this should be a path to Xcode.app, e.g. `"/Applications/Xcode.app"`.
withXcodePath ? null,
}:
# Try to match MacVim's documented script interface compatibility
let
# Ruby 3.4
ruby = ruby_3_4;
in
let
common = callPackage ./common.nix { inherit stdenv; };
in
stdenv.mkDerivation (finalAttrs: {
pname = "macvim";
version = "182";
src = fetchFromGitHub {
owner = "macvim-dev";
repo = "macvim";
tag =
let
releaseType = if lib.hasInfix "." finalAttrs.version then "prerelease" else "release";
in
"${releaseType}-${finalAttrs.version}";
hash = "sha256-JEb71wZcvFsz94vb3+gC83BhlEccjlPrpr9RCXDUEIo=";
};
enableParallelBuilding = true;
nativeBuildInputs = [
pkg-config
];
buildInputs = [
# MacVim references up to MAC_OS_VERSION_14_0 in its source
# Update this SDK if it adds APIs that use newer versions
# (check both MAC_OS_VERSION_* and MAC_OS_X_VERSION_*)
apple-sdk_14
gettext
ncurses
cscope
luajit
ruby
tcl
perl
python3
];
patches = [
./macvim.patch
# Xcode 26.0 sets *_DEPLOYMENT_TARGET env vars for all platforms in shell script build phases.
# This breaks invocations of clang in those phases, as they target the wrong platform.
# Note: The shell script build phase in question uses /bin/zsh.
# This also adds --jobs=1 to the shell script build phase invocation of `make` as running in
# parallel is causing the gvim.1 manpage to go missing.
./macvim-xcode26.patch
];
# Fix clang version detection in configure script, it's getting tripped up
# because the InstalledDir matches the same pattern
postPatch = ''
substituteInPlace src/auto/configure \
--replace-fail /usr/bin/grep grep \
--replace-fail '$CC --version 2>/dev/null |' '$CC --version 2>/dev/null | head -1 |'
''
# Remove $(VIMTARGET) from the installrtbase rule deps. MacVim already comments out the usage of
# this executable in this rule, and for some reason Xcode is deleting it after copying it into
# MacVim.app/Contents/MacOS/, so this is getting rebuilt unnecessarily and causing issues.
+ ''
substituteInPlace src/Makefile \
--replace-fail \
'installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(VIMTARGET) $(DEST_RT)' \
'installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(DEST_RT)'
''
# Patch in the xcode path we want
+ ''
xcodebuildPath=${
if withXcodePath == null then
"$(DEVELOPER_DIR= /usr/bin/xcrun -find xcodebuild)"
else
lib.escapeShellArg "${withXcodePath}/Contents/Developer/usr/bin/xcodebuild"
}
substituteInPlace src/Makefile \
--replace-fail xcodebuild "$xcodebuildPath"
''
# QuickLookStephen calls `qlmanage -r` in a shell script phase
+ ''
substituteInPlace src/MacVim/qlstephen/QuickLookStephen.xcodeproj/project.pbxproj \
--replace-fail qlmanage /usr/bin/qlmanage
'';
configureFlags = [
"--enable-cscope"
"--enable-fail-if-missing"
"--with-features=huge"
"--enable-gui=macvim"
"--enable-multibyte"
"--enable-nls"
"--enable-luainterp=yes"
"--enable-python3interp=yes"
"--enable-perlinterp=yes"
"--enable-rubyinterp=yes"
"--enable-tclinterp=yes"
"--without-local-dir"
"--with-luajit"
"--with-lua-prefix=${luajit}"
"--with-python3-command=${python3}/bin/python3"
"--with-ruby-command=${ruby}/bin/ruby"
"--with-tclsh=${tcl}/bin/tclsh"
"--with-tlib=ncurses"
"--with-compiledby=Nix"
"--disable-sparkle"
];
preConfigure = ''
configureFlagsArray+=(
--with-developer-dir="$DEVELOPER_DIR"
CFLAGS="-Wno-error=implicit-function-declaration"
)
''
# Having `$LD` set causes Xcode to invoke `ld` instead of `clang` as the linker, but it still
# passes flags intended for clang.
+ ''
unset LD
''
# When building with nix-daemon, we need to pass -derivedDataPath or else it tries to use
# a folder rooted in /var/empty and fails. Unfortunately we can't just pass -derivedDataPath
# by itself as this flag requires the use of -scheme or -xctestrun (not sure why), but MacVim
# by default just runs `xcodebuild -project src/MacVim/MacVim.xcodeproj`, relying on the default
# behavior to build the first target in the project. Experimentally, there seems to be a scheme
# called MacVim, so we'll explicitly select that. We also need to specify the configuration too
# as the scheme seems to have the wrong default.
# Passing ENABLE_CODE_COVERAGE=NO because it's defaulting on for some reason.
# Passing ONLY_ACTIVE_ARCH=YES because QuickLookStephen.xcodeproj is building Universal by default.
+ ''
configureFlagsArray+=(
XCODEFLAGS="-scheme MacVim -derivedDataPath $NIX_BUILD_TOP/derivedData ENABLE_CODE_COVERAGE=NO ONLY_ACTIVE_ARCH=YES"
--with-xcodecfg="Release"
)
'';
postConfigure = ''
substituteInPlace src/MacVim/vimrc --subst-var-by CSCOPE ${cscope}/bin/cscope
'';
# Note that $out/MacVim.app has a misnamed set of binaries in the Contents/bin folder (the V is
# capitalized) and is missing a bunch of them. This is why we're grabbing the version from the
# build folder.
postInstall = ''
mkdir -p $out/Applications
cp -r src/MacVim/build/Release/MacVim.app $out/Applications
rm -rf $out/MacVim.app
mkdir -p $out/bin
for prog in ex vi {,g,m,r}vi{m,mdiff,ew}; do
ln -s $out/Applications/MacVim.app/Contents/bin/mvim $out/bin/$prog
done
for prog in {,g}vimtutor xxd; do
ln -s $out/Applications/MacVim.app/Contents/bin/$prog $out/bin/$prog
done
ln -s $out/Applications/MacVim.app/Contents/bin/gvimtutor $out/bin/mvimtutor
mkdir -p $out/share
ln -s $out/Applications/MacVim.app/Contents/man $out/share/man
# Remove manpages from tools we aren't providing
find $out/Applications/MacVim.app/Contents/man \( -name evim.1 -or -name eview.1 \) -delete
'';
# macvim obj-c log macro triggers -Wformat-security (seems like a bug? it's a string literal!)
hardeningDisable = common.hardeningDisable ++ [ "format" ];
# os_log also enables -Werror,-Wformat by default
env.NIX_CFLAGS_COMPILE = "-DOS_LOG_FORMAT_WARNINGS";
# We rely on the user's Xcode install to build. It may be located in an arbitrary place, and
# it's not clear what system-level components it may require, so for now we'll just allow full
# filesystem access. This way the package still can't access the network.
sandboxProfile = ''
(allow file-read* file-write* process-exec mach-lookup)
; block homebrew dependencies
(deny file-read* file-write* process-exec mach-lookup (subpath "/usr/local") (with no-log))
'';
meta = {
description = "Vim - the text editor - for macOS";
homepage = "https://macvim.org/";
license = lib.licenses.vim;
maintainers = with lib.maintainers; [ lilyball ];
platforms = lib.platforms.darwin;
hydraPlatforms = [ ]; # hydra can't build this as long as we rely on Xcode and sandboxProfile
};
})
|