aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/applications/editors/vim/macvim.nix
blob: d2cc14c30c481340538df1049410ac25b43d2160 (plain)
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
{ stdenv, fetchFromGitHub, runCommand, ncurses, gettext
, pkgconfig, cscope, ruby, tcl, perl, luajit
, darwin

, usePython27 ? false
, python27 ? null, python37 ? null
}:

let
  python = if usePython27
           then { pkg = python27; name = "python"; }
           else { pkg = python37; name = "python3"; };
in
assert python.pkg != null;

let
  # Building requires a few system tools to be in PATH.
  # Some of these we could patch into the relevant source files (such as xcodebuild and
  # qlmanage) but some are used by Xcode itself and we have no choice but to put them in PATH.
  # Symlinking them in this way is better than just putting all of /usr/bin in there.
  buildSymlinks = runCommand "macvim-build-symlinks" {} ''
    mkdir -p $out/bin
    ln -s /usr/bin/xcrun /usr/bin/xcodebuild /usr/bin/tiffutil /usr/bin/qlmanage $out/bin
  '';
in

stdenv.mkDerivation {
  pname = "macvim";

  version = "8.2.1719";

  src = fetchFromGitHub {
    owner = "macvim-dev";
    repo = "macvim";
    rev = "snapshot-166";
    sha256 = "1p51q59l1dl5lnf1ms960lm8zfg39p8xq0pdjw6wdyypjj3r8v3v";
  };

  enableParallelBuilding = true;

  nativeBuildInputs = [ pkgconfig buildSymlinks ];
  buildInputs = [
    gettext ncurses cscope luajit ruby tcl perl python.pkg
  ];

  patches = [ ./macvim.patch ];

  configureFlags = [
      "--enable-cscope"
      "--enable-fail-if-missing"
      "--with-features=huge"
      "--enable-gui=macvim"
      "--enable-multibyte"
      "--enable-nls"
      "--enable-luainterp=dynamic"
      "--enable-${python.name}interp=dynamic"
      "--enable-perlinterp=dynamic"
      "--enable-rubyinterp=dynamic"
      "--enable-tclinterp=yes"
      "--without-local-dir"
      "--with-luajit"
      "--with-lua-prefix=${luajit}"
      "--with-${python.name}-command=${python.pkg}/bin/${python.name}"
      "--with-ruby-command=${ruby}/bin/ruby"
      "--with-tclsh=${tcl}/bin/tclsh"
      "--with-tlib=ncurses"
      "--with-compiledby=Nix"
      "--disable-sparkle"
  ];

  # Remove references to Sparkle.framework from the project.
  # It's unused (we disabled it with --disable-sparkle) and this avoids
  # copying the unnecessary several-megabyte framework into the result.
  postPatch = ''
    echo "Patching file src/MacVim/MacVim.xcodeproj/project.pbxproj"
    sed -e '/Sparkle\.framework/d' -i src/MacVim/MacVim.xcodeproj/project.pbxproj
  '';

  # This is unfortunate, but we need to use the same compiler as Xcode,
  # but Xcode doesn't provide a way to configure the compiler.
  preConfigure = ''
    CC=/usr/bin/clang

    DEV_DIR=$(/usr/bin/xcode-select -print-path)/Platforms/MacOSX.platform/Developer
    configureFlagsArray+=(
      --with-developer-dir="$DEV_DIR"
      LDFLAGS="-L${ncurses}/lib"
      CPPFLAGS="-isystem ${ncurses.dev}/include"
      CFLAGS="-Wno-error=implicit-function-declaration"
    )
  ''
  # For some reason having LD defined causes PSMTabBarControl to fail at link-time as it
  # passes arguments to ld that it meant 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.
  + ''
    configureFlagsArray+=(
      XCODEFLAGS="-scheme MacVim -derivedDataPath $NIX_BUILD_TOP/derivedData"
      --with-xcodecfg="Release"
    )
  ''
  ;

  # Because we're building with system clang, this means we're building against Xcode's SDK and
  # linking against system libraries. The configure script is picking up Nix Libsystem (via ruby)
  # so we need to patch that out or we'll get linker issues. The MacVim binary built by Xcode links
  # against the system anyway so it doesn't really matter that the Vim binary will too. If we
  # decide that matters, we can always patch it back to the Nix libsystem post-build.
  # It also picks up libiconv, libunwind, and objc4 from Nix. These seem relatively harmless but
  # let's strip them out too.
  #
  # Note: If we do add a post-build install_name_tool patch, we need to add the
  # "LDFLAGS=-headerpad_max_install_names" flag to configureFlags and either patch it into the
  # Xcode project or pass it as a flag to xcodebuild as well.
  postConfigure = ''
    substituteInPlace src/auto/config.mk \
      --replace "PERL_CFLAGS	=" "PERL_CFLAGS	= -I${darwin.libutil}/include" \
      --replace " -L${stdenv.cc.libc}/lib" "" \
      --replace " -L${darwin.libobjc}/lib" "" \
      --replace " -L${darwin.libunwind}/lib" "" \
      --replace " -L${darwin.libiconv}/lib" ""

    # All the libraries we stripped have -osx- in their name as of this time.
    # Assert now that this pattern no longer appears in config.mk.
    ( # scope variable
      while IFS="" read -r line; do
        if [[ "$line" == LDFLAGS*-osx-* ]]; then
          echo "WARNING: src/auto/config.mk contains reference to Nix osx library" >&2
        fi
      done <src/auto/config.mk
    )

    substituteInPlace src/MacVim/vimrc --subst-var-by CSCOPE ${cscope}/bin/cscope
  '';

  postInstall = ''
    mkdir -p $out/Applications
    cp -r src/MacVim/build/Release/MacVim.app $out/Applications
    rm -rf $out/MacVim.app

    rm $out/bin/*

    cp src/vimtutor $out/bin
    for prog in mvim ex vi vim vimdiff view rvim rvimdiff rview; do
      ln -s $out/Applications/MacVim.app/Contents/bin/mvim $out/bin/$prog
    done

    # Fix rpaths
    exe="$out/Applications/MacVim.app/Contents/MacOS/Vim"
    libperl=$(dirname $(find ${perl} -name "libperl.dylib"))
    install_name_tool -add_rpath ${luajit}/lib $exe
    install_name_tool -add_rpath ${tcl}/lib $exe
    install_name_tool -add_rpath ${python.pkg}/lib $exe
    install_name_tool -add_rpath $libperl $exe
    install_name_tool -add_rpath ${ruby}/lib $exe

    # Remove manpages from tools we aren't providing
    find $out/share/man \( -name eVim.1 -or -name xxd.1 \) -delete
  '';

  # 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 = with stdenv.lib; {
    description = "Vim - the text editor - for macOS";
    homepage    = "https://github.com/macvim-dev/macvim";
    license = licenses.vim;
    maintainers = with maintainers; [ cstrahan lilyball ];
    platforms   = platforms.darwin;
    hydraPlatforms = []; # hydra can't build this as long as we rely on Xcode and sandboxProfile
  };
}