{ stdenv, lib, fetchFromGitHub, fetchurl, jdk, ant , libusb, libusb1, unzip, zlib, ncurses, readline , withGui ? false, gtk2 ? null, withTeensyduino ? false /* Packages needed for Teensyduino */ , upx, fontconfig, xorg, gcc, xdotool, xvfb_run , atk, glib, pango, gdk_pixbuf, libpng12, expat, freetype }: assert withGui -> gtk2 != null; assert withTeensyduino -> withGui; # TODO: Teensyduino is disabled for i686-linux due to an indefinite hang in the # xdotool script; the cause of this hang is not yet known. # TODO: There is a fair chance that Teensyduino works with arm-linux, but it # has not yet been tested. if withTeensyduino && (stdenv.system != "x86_64-linux") then throw "Teensyduino is only supported on x86_64-linux at this time (patches welcome)." else let externalDownloads = import ./downloads.nix {inherit fetchurl; inherit (lib) optionalAttrs; inherit (stdenv) system;}; # Some .so-files are later copied from .jar-s to $HOME, so patch them beforehand patchelfInJars = lib.optional (stdenv.system == "x86_64-linux") {jar = "share/arduino/lib/jssc-2.8.0.jar"; file = "libs/linux/libjSSC-2.8_x86_64.so";} ++ lib.optional (stdenv.system == "i686-linux") {jar = "share/arduino/lib/jssc-2.8.0.jar"; file = "libs/linux/libjSSC-2.8_x86.so";} ; # abiVersion 6 is default, but we need 5 for `avrdude_bin` executable ncurses5 = ncurses.override { abiVersion = "5"; }; teensy_libpath = stdenv.lib.makeLibraryPath [ atk expat fontconfig freetype gcc.cc.lib gdk_pixbuf glib gtk2 libpng12 libusb pango xorg.libSM xorg.libX11 xorg.libXext xorg.libXft xorg.libXinerama zlib ]; teensy_architecture = lib.optionalString (stdenv.system == "x86_64-linux") "linux64" + lib.optionalString (stdenv.system == "i686-linux") "linux32" + lib.optionalString (stdenv.system == "arm-linux") "linuxarm"; flavor = (if withTeensyduino then "teensyduino" else "arduino") + stdenv.lib.optionalString (!withGui) "-core"; in stdenv.mkDerivation rec { version = "1.6.12"; name = "${flavor}-${version}"; src = fetchFromGitHub { owner = "arduino"; repo = "Arduino"; rev = "${version}"; sha256 = "0rz8dv1mncwx2wkafakxqdi2y0rq3f72fr57cg0z5hgdgdm89lkh"; }; teensyduino_src = fetchurl { url = "http://www.pjrc.com/teensy/td_131/TeensyduinoInstall.${teensy_architecture}"; sha256 = lib.optionalString ("${teensy_architecture}" == "linux64") "1q4wv6s0900hyv9z1mjq33fr2isscps4q3bsy0h12wi3l7ir94g9" + lib.optionalString ("${teensy_architecture}" == "linux32") "06fl951f44avqyqim5qmy73siylbqcnsmz55zmj2dzhgf4sflkvc" + lib.optionalString ("${teensy_architecture}" == "linuxarm") "0ldf33w8wkqwklcj8fn4p22f23ibpwpf7873dc6i2jfmmbx0yvxn"; }; buildInputs = [ jdk ant libusb libusb1 unzip zlib ncurses5 readline ] ++ stdenv.lib.optionals withTeensyduino [ upx xvfb_run xdotool ]; downloadSrcList = builtins.attrValues externalDownloads; downloadDstList = builtins.attrNames externalDownloads; buildPhase = '' # Copy pre-downloaded files to proper locations download_src=($downloadSrcList) download_dst=($downloadDstList) while [[ "''${#download_src[@]}" -ne 0 ]]; do file_src=''${download_src[0]} file_dst=''${download_dst[0]} mkdir -p $(dirname $file_dst) download_src=(''${download_src[@]:1}) download_dst=(''${download_dst[@]:1}) cp -v $file_src $file_dst done cd ./arduino-core && ant cd ../build && ant cd .. ''; # This will be patched into `arduino` wrapper script # Java loads gtk dynamically, so we need to provide it using LD_LIBRARY_PATH dynamicLibraryPath = lib.makeLibraryPath [gtk2]; javaPath = lib.makeBinPath [jdk]; # Everything else will be patched into rpath rpath = (lib.makeLibraryPath [zlib libusb libusb1 readline ncurses5 stdenv.cc.cc]); installPhase = '' mkdir -p $out/share/arduino cp -r ./build/linux/work/* "$out/share/arduino/" #*/ echo ${version} > $out/share/arduino/lib/version.txt ${stdenv.lib.optionalString withGui '' mkdir -p $out/bin substituteInPlace $out/share/arduino/arduino \ --replace "JAVA=java" "JAVA=$javaPath/java" \ --replace "LD_LIBRARY_PATH=" "LD_LIBRARY_PATH=$dynamicLibraryPath:" ln -sr "$out/share/arduino/arduino" "$out/bin/arduino" cp -r build/shared/icons $out/share/arduino mkdir -p $out/share/applications cp build/linux/dist/desktop.template $out/share/applications/arduino.desktop substituteInPlace $out/share/applications/arduino.desktop \ --replace '' "$out/bin/arduino" \ --replace '' "$out/share/arduino/icons/128x128/apps/arduino.png" ''} ${stdenv.lib.optionalString withTeensyduino '' # Extract and patch the Teensyduino installer cp ${teensyduino_src} ./TeensyduinoInstall.${teensy_architecture} chmod +w ./TeensyduinoInstall.${teensy_architecture} upx -d ./TeensyduinoInstall.${teensy_architecture} patchelf --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \ --set-rpath "${teensy_libpath}" \ ./TeensyduinoInstall.${teensy_architecture} chmod +x ./TeensyduinoInstall.${teensy_architecture} # Run the GUI-only installer in a virtual X server # Script thanks to AUR package. See: # echo "Running Teensyduino installer..." # Trick the GUI into using HOME as the install directory. export HOME=$out/share/arduino # Run the installer in a virtual X server in memory. xvfb-run -n 99 ./TeensyduinoInstall.${teensy_architecture} & sleep 4 echo "Waiting for Teensyduino to install (about 1 minute)..." # Control the installer GUI with xdotool. DISPLAY=:99 xdotool search --class "teensyduino" \ windowfocus \ key space sleep 1 \ key Tab sleep 0.4 \ key Tab sleep 0.4 \ key Tab sleep 0.4 \ key Tab sleep 0.4 \ key space sleep 1 \ key Tab sleep 0.4 \ key Tab sleep 0.4 \ key Tab sleep 0.4 \ key Tab sleep 0.4 \ key space sleep 1 \ key Tab sleep 0.4 \ key space sleep 35 \ key space sleep 2 & # Wait for xdotool to terminate and swallow the inevitable XIO error wait $! || true # Check for successful installation [ -d $out/share/arduino/hardware/teensy ] || exit 1 ''} ''; # So we don't accidentally mess with firmware files dontStrip = true; dontPatchELF = true; preFixup = '' for file in $(find $out -type f \( -perm /0111 -o -name \*.so\* \) ); do patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" || true patchelf --set-rpath ${rpath}:$out/lib $file || true done ${lib.concatMapStringsSep "\n" ({jar, file}: '' jar xvf $out/${jar} ${file} patchelf --set-rpath $rpath ${file} jar uvf $out/${jar} ${file} rm -f ${file} '' ) patchelfInJars} # avrdude_bin is linked against libtinfo.so.5 mkdir $out/lib/ ln -s ${lib.makeLibraryPath [ncurses5]}/libncursesw.so.5 $out/lib/libtinfo.so.5 ${stdenv.lib.optionalString withTeensyduino '' # Patch the Teensy loader binary patchelf --debug \ --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \ --set-rpath "${teensy_libpath}" \ $out/share/arduino/hardware/tools/teensy ''} ''; meta = with stdenv.lib; { description = "Open-source electronics prototyping platform"; homepage = http://arduino.cc/; license = stdenv.lib.licenses.gpl2; platforms = platforms.linux; maintainers = with maintainers; [ antono auntie robberer bjornfor ]; }; }