1010 zlib ,
1111 openssl ,
1212 R ,
13- libsForQt5 ,
13+ fontconfig ,
1414 quarto ,
1515 libuuid ,
1616 hunspellDicts ,
2222 yaml-cpp ,
2323 soci ,
2424 sqlite ,
25+ apple-sdk_11 ,
26+ xcbuild ,
2527 nodejs ,
28+ npmHooks ,
29+ fetchNpmDeps ,
2630 yarn ,
2731 yarnConfigHook ,
2832 fetchYarnDeps ,
33+ zip ,
34+ git ,
35+ makeWrapper ,
36+ electron_33 ,
2937 server ? false , # build server version
3038 pam ,
3139 nixosTests ,
3240} :
3341
3442let
43+ # Note: we shouldn't use the latest electron here, since the node-abi dependency might
44+ # need to be updated every time the latest electron gets a new abi version number
45+ electron = electron_33 ;
46+
47+ # unpack tarball containing electron's headers
48+ electron-headers = runCommand "electron-headers" { } ''
49+ mkdir -p $out
50+ tar -C $out --strip-components=1 -xvf ${ electron . headers }
51+ '' ;
52+
3553 mathJaxSrc = fetchzip {
3654 url = "https://s3.amazonaws.com/rstudio-buildtools/mathjax-27.zip" ;
3755 hash = "sha256-J7SZK/9q3HcXTD7WFHxvh++ttuCd89Vc4SEBrUEU0AI=" ;
5876 # rstudio assumes quarto bundles pandoc into bin/tools/
5977 quartoWrapper = runCommand "quarto-wrapper" { } ''
6078 mkdir -p $out/bin/tools
61- ln -s ${ lib . getExe quarto } $out/bin/quarto
6279 ln -s ${ lib . getExe pandoc } $out/bin/tools/pandoc
80+ ln -s ${ lib . getExe quarto } $out/bin/quarto
81+ ln -s ${ quarto } /share $out/share
6382 '' ;
6483in
6584stdenv . mkDerivation rec {
@@ -74,7 +93,7 @@ stdenv.mkDerivation rec {
7493 src = fetchFromGitHub {
7594 owner = "rstudio" ;
7695 repo = "rstudio" ;
77- rev = "refs/tags/ v${ version } " ;
96+ tag = "v${ version } " ;
7897 hash = "sha256-j258eW1MYQrB6kkpjyolXdNuwQ3zSWv9so4q0QLsZuw=" ;
7998 } ;
8099
@@ -86,9 +105,14 @@ stdenv.mkDerivation rec {
86105 nodejs
87106 yarn
88107 yarnConfigHook
108+ zip
109+ git
89110 ]
111+ ++ lib . optionals stdenv . hostPlatform . isDarwin [ xcbuild ]
90112 ++ lib . optionals ( ! server ) [
91- libsForQt5 . wrapQtAppsHook
113+ ( nodejs . python . withPackages ( ps : [ ps . setuptools ] ) )
114+ npmHooks . npmConfigHook
115+ makeWrapper
92116 ] ;
93117
94118 buildInputs =
@@ -102,30 +126,30 @@ stdenv.mkDerivation rec {
102126 soci
103127 sqlite . dev
104128 ]
129+ ++ lib . optionals stdenv . hostPlatform . isDarwin [ apple-sdk_11 ]
105130 ++ lib . optionals server [ pam ]
106- ++ lib . optionals ( ! server ) [
107- libsForQt5 . qtbase
108- libsForQt5 . qtxmlpatterns
109- libsForQt5 . qtsensors
110- libsForQt5 . qtwebengine
111- libsForQt5 . qtwebchannel
112- ] ;
131+ ++ lib . optionals ( ! server ) [ fontconfig ] ;
113132
114133 cmakeFlags =
115134 [
116- ( lib . cmakeFeature "RSTUDIO_TARGET" ( if server then "Server" else "Desktop " ) )
135+ ( lib . cmakeFeature "RSTUDIO_TARGET" ( if server then "Server" else "Electron " ) )
117136 ( lib . cmakeBool "RSTUDIO_USE_SYSTEM_SOCI" true )
118137 ( lib . cmakeBool "RSTUDIO_USE_SYSTEM_BOOST" true )
119138 ( lib . cmakeBool "RSTUDIO_USE_SYSTEM_YAML_CPP" true )
120139 ( lib . cmakeBool "RSTUDIO_DISABLE_CHECK_FOR_UPDATES" true )
121140 ( lib . cmakeBool "QUARTO_ENABLED" true )
122- ( lib . cmakeFeature "CMAKE_INSTALL_PREFIX" "${ placeholder "out" } /lib/rstudio" )
141+ ( lib . cmakeBool "RSTUDIO_CRASHPAD_ENABLED" false ) # This is a NOOP except on x86_64-darwin
142+ ( lib . cmakeFeature "CMAKE_INSTALL_PREFIX" (
143+ ( placeholder "out" ) + ( if stdenv . isDarwin then "/Applications" else "/lib/rstudio" )
144+ ) )
123145 ]
124146 ++ lib . optionals ( ! server ) [
125- ( lib . cmakeFeature "QT_QMAKE_EXECUTABLE" "${ libsForQt5 . qmake } /bin/qmake" )
126- ( lib . cmakeBool "RSTUDIO_INSTALL_FREEDESKTOP" true )
147+ ( lib . cmakeBool "RSTUDIO_INSTALL_FREEDESKTOP" stdenv . hostPlatform . isLinux )
127148 ] ;
128149
150+ # on Darwin, cmake uses find_library to locate R instead of using the PATH
151+ env . NIX_LDFLAGS = "-L${ R } /lib/R/lib" ;
152+
129153 patches = [
130154 # Hack RStudio to only use the input R and provided libclang.
131155 ( replaceVars ./r-location.patch {
@@ -139,6 +163,9 @@ stdenv.mkDerivation rec {
139163 ./ignore-etc-os-release.patch
140164 ./dont-yarn-install.patch
141165 ./boost-1.86.patch
166+ ./fix-darwin.patch
167+ # needed for rebuilding for later electron versions
168+ ./update-nan-and-node-abi.patch
142169 ] ;
143170
144171 postPatch = ''
@@ -158,6 +185,21 @@ stdenv.mkDerivation rec {
158185
159186 dontYarnInstallDeps = true ; # will call manually in preConfigure
160187
188+ npmRoot = "src/node/desktop" ;
189+
190+ # don't build native modules with node headers
191+ npmFlags = [ "--ignore-scripts" ] ;
192+
193+ npmDeps = fetchNpmDeps {
194+ name = "rstudio-${ version } -npm-deps" ;
195+ inherit src ;
196+ patches = [ ./update-nan-and-node-abi.patch ] ;
197+ postPatch = "cd ${ npmRoot } " ;
198+ hash = "sha256-CtHCN4sWeHNDd59TV/TgTC4d6h7X1Cl4E/aJkAfRk7g=" ;
199+ } ;
200+
201+ env . ELECTRON_SKIP_BINARY_DOWNLOAD = "1" ;
202+
161203 preConfigure = ''
162204 # set up node_modules directory inside quarto so that panmirror can be built
163205 mkdir src/gwt/lib/quarto
@@ -182,26 +224,84 @@ stdenv.mkDerivation rec {
182224 # version in dependencies/common/install-mathjax
183225 ln -s ${ mathJaxSrc } dependencies/mathjax-27
184226
185- # version in CMakeGlobals.txt (RSTUDIO_INSTALLED_NODE_VERSION)
186227 mkdir -p dependencies/common/node
228+ # node used by cmake
229+ # version in CMakeGlobals.txt (RSTUDIO_NODE_VERSION)
230+ ln -s ${ nodejs } dependencies/common/node/18.18.2
231+ # node used at runtime
232+ # version in CMakeGlobals.txt (RSTUDIO_INSTALLED_NODE_VERSION)
187233 ln -s ${ nodejs } dependencies/common/node/18.20.3
234+
235+ ${ lib . optionalString ( ! server ) ''
236+ pushd $npmRoot
237+
238+ substituteInPlace package.json \
239+ --replace-fail "npm ci && " ""
240+
241+ # use electron's headers to make node-gyp compile against the electron ABI
242+ export npm_config_nodedir="${ electron-headers } "
243+
244+ ### override the detected electron version
245+ substituteInPlace node_modules/@electron-forge/core-utils/dist/electron-version.js \
246+ --replace-fail "return version" "return '${ electron . version } '"
247+
248+ ### create the electron archive to be used by electron-packager
249+ cp -r ${ electron . dist } electron-dist
250+ chmod -R u+w electron-dist
251+
252+ pushd electron-dist
253+ zip -0Xqr ../electron.zip .
254+ popd
255+
256+ rm -r electron-dist
257+
258+ # force @electron/packager to use our electron instead of downloading it
259+ substituteInPlace node_modules/@electron/packager/src/index.js \
260+ --replace-fail "await this.getElectronZipPath(downloadOpts)" "'$(pwd)/electron.zip'"
261+
262+ # Work around known nan issue for electron_33 and above
263+ # https://github.com/nodejs/nan/issues/978
264+ substituteInPlace node_modules/nan/nan.h \
265+ --replace-fail '#include "nan_scriptorigin.h"' ""
266+
267+ # now that we patched everything, we still have to run the scripts we ignored with --ignore-scripts
268+ npm rebuild
269+
270+ popd
271+ '' }
188272 '' ;
189273
190274 postInstall = ''
191275 mkdir -p $out/bin
192276
193- ${ lib . optionalString server ''
277+ ${ lib . optionalString ( server && stdenv . hostPlatform . isLinux ) ''
194278 ln -s $out/lib/rstudio/bin/{crash-handler-proxy,postback,r-ldpath,rpostback,rserver,rserver-pam,rsession,rstudio-server} $out/bin
195279 '' }
196280
197- ${ lib . optionalString ( ! server ) ''
198- ln -s $out/lib/rstudio/bin/{diagnostics,rpostback,rstudio} $out/bin
281+ ${ lib . optionalString ( ! server && stdenv . hostPlatform . isLinux ) ''
282+ # remove unneeded electron files, since we'll wrap the app with our own electron
283+ shopt -s extglob
284+ rm -r $out/lib/rstudio/!(locales|resources|resources.pak)
285+
286+ makeWrapper ${ lib . getExe electron } "$out/bin/rstudio" \
287+ --add-flags "$out/lib/rstudio/resources/app/" \
288+ --set-default ELECTRON_FORCE_IS_PACKAGED 1 \
289+ --suffix PATH : ${ lib . makeBinPath [ gnumake ] }
290+
291+ ln -s $out/lib/rstudio/resources/app/bin/{diagnostics,rpostback} $out/bin
199292 '' }
200- '' ;
201293
202- qtWrapperArgs = lib . optionals ( ! server ) [
203- "--suffix PATH : ${ lib . makeBinPath [ gnumake ] } "
204- ] ;
294+ ${ lib . optionalString ( server && stdenv . hostPlatform . isDarwin ) ''
295+ ln -s $out/Applications/RStudio.app/Contents/MacOS/{crash-handler-proxy,postback,r-ldpath,rpostback,rserver,rserver-pam,rsession,rstudio-server} $out/bin
296+ '' }
297+
298+ ${ lib . optionalString ( ! server && stdenv . hostPlatform . isDarwin ) ''
299+ # electron can't find its files if we use a symlink here
300+ makeWrapper $out/Applications/RStudio.app/Contents/MacOS/RStudio $out/bin/rstudio
301+
302+ ln -s $out/Applications/RStudio.app/Contents/Resources/app/bin/{diagnostics,rpostback} $out/bin
303+ '' }
304+ '' ;
205305
206306 passthru = {
207307 inherit server ;
@@ -211,15 +311,15 @@ stdenv.mkDerivation rec {
211311 } ;
212312
213313 meta = {
214- broken = ( stdenv . hostPlatform . isLinux && stdenv . hostPlatform . isAarch64 ) ;
215314 description = "Set of integrated tools for the R language" ;
216315 homepage = "https://www.rstudio.com/" ;
217316 license = lib . licenses . agpl3Only ;
218317 maintainers = with lib . maintainers ; [
219318 ciil
220319 cfhammill
320+ tomasajt
221321 ] ;
222322 mainProgram = "rstudio" + lib . optionalString server "-server" ;
223- platforms = lib . platforms . linux ;
323+ platforms = lib . platforms . linux ++ lib . platforms . darwin ;
224324 } ;
225325}
0 commit comments