diff options
Diffstat (limited to 'nixpkgs/pkgs/applications/science/electronics/eagle')
3 files changed, 311 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/applications/science/electronics/eagle/eagle.nix b/nixpkgs/pkgs/applications/science/electronics/eagle/eagle.nix new file mode 100644 index 000000000000..7c5942d825a9 --- /dev/null +++ b/nixpkgs/pkgs/applications/science/electronics/eagle/eagle.nix @@ -0,0 +1,80 @@ +{ stdenv, mkDerivation, fetchurl, makeDesktopItem +, libXrender, libXrandr, libXcursor, libX11, libXext, libXi, libxcb + , libGL, glib, nss, nspr, expat, alsaLib +, qtbase, qtdeclarative, qtsvg, qtlocation, qtwebchannel, qtwebengine +}: + +let + libPath = stdenv.lib.makeLibraryPath + [ libXrender libXrandr libXcursor libX11 libXext libXi libxcb + libGL glib nss nspr expat alsaLib + qtbase qtdeclarative qtsvg qtlocation qtwebchannel qtwebengine + ]; + in + mkDerivation rec { + pname = "eagle"; + version = "9.6.0"; + + src = fetchurl { + url = "https://eagle-updates.circuits.io/downloads/${builtins.replaceStrings ["."] ["_"] version}/Autodesk_EAGLE_${version}_English_Linux_64bit.tar.gz"; + sha256 = "1crkyc7ws2zz5dfs00h6rj4z2hyqb97kp6r4hxhmcgg5647ij4z8"; + }; + + desktopItem = makeDesktopItem { + name = "eagle"; + exec = "eagle"; + icon = "eagle"; + comment = "Schematic capture and PCB layout"; + desktopName = "Eagle"; + genericName = "Schematic editor"; + categories = "Application;Development;"; + }; + + buildInputs = + [ libXrender libXrandr libXcursor libX11 libXext libXi libxcb + libGL glib nss nspr expat alsaLib + qtbase qtdeclarative qtsvg qtlocation qtwebchannel qtwebengine + ]; + + installPhase = '' + # Extract eagle tarball + mkdir "$out" + tar -xzf "$src" -C "$out" + + # Install manpage + mkdir -p "$out"/share/man/man1 + ln -s "$out"/eagle-${version}/doc/eagle.1 "$out"/share/man/man1/eagle.1 + + patchelf \ + --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \ + --set-rpath "${libPath}:$out/eagle-${version}/lib:${stdenv.cc.cc.lib}/lib" \ + "$out"/eagle-${version}/eagle + + mkdir -p "$out"/bin + ln -s "$out"/eagle-${version}/eagle "$out"/bin/eagle + + # Remove bundled libraries that are available in nixpkgs + # TODO: There still may be unused bundled libraries + rm "$out"/eagle-${version}/lib/libQt5*.so.5 + rm "$out"/eagle-${version}/lib/{libxcb-*.so.*,libX*.so.*,libxshmfence.so.1} + rm "$out"/eagle-${version}/lib/{libEGL.so.1,libglapi.so.0,libgbm.so.1} + + # No longer needed (we don't use the bundled Qt libraries) + rm -r "$out"/eagle-${version}/libexec + rm -r "$out"/eagle-${version}/plugins + + # Make desktop item + mkdir -p "$out"/share/applications + cp "$desktopItem"/share/applications/* "$out"/share/applications/ + mkdir -p "$out"/share/icons + ln -s "$out/eagle-${version}/bin/eagle-logo.png" "$out"/share/icons/eagle.png + ''; + + meta = with stdenv.lib; { + description = "Schematic editor and PCB layout tool from Autodesk (formerly CadSoft)"; + homepage = "https://www.autodesk.com/products/eagle/overview"; + license = licenses.unfree; + platforms = [ "x86_64-linux" ]; + maintainers = [ maintainers.rittelle ]; + }; + } diff --git a/nixpkgs/pkgs/applications/science/electronics/eagle/eagle7.nix b/nixpkgs/pkgs/applications/science/electronics/eagle/eagle7.nix new file mode 100644 index 000000000000..a9528b05a311 --- /dev/null +++ b/nixpkgs/pkgs/applications/science/electronics/eagle/eagle7.nix @@ -0,0 +1,97 @@ +{ stdenv, fetchurl, makeDesktopItem, patchelf, zlib, freetype, fontconfig +, openssl, libXrender, libXrandr, libXcursor, libX11, libXext, libXi +, libxcb, cups, xkeyboardconfig, runtimeShell +}: + +let + + libPath = stdenv.lib.makeLibraryPath + [ zlib freetype fontconfig openssl libXrender libXrandr libXcursor libX11 + libXext libXi libxcb cups + ]; + +in + +stdenv.mkDerivation rec { + pname = "eagle"; + version = "7.7.0"; + + src = + if stdenv.hostPlatform.system == "i686-linux" then + fetchurl { + url = "ftp://ftp.cadsoft.de/eagle/program/7.7/eagle-lin32-${version}.run"; + sha256 = "16fa66p77xigc7zvzfm7737mllrcs6nrgk2p7wvkjw3p9lvbz7z1"; + } + else if stdenv.hostPlatform.system == "x86_64-linux" then + fetchurl { + url = "ftp://ftp.cadsoft.de/eagle/program/7.7/eagle-lin64-${version}.run"; + sha256 = "18dcn6wqph1sqh0ah98qzfi05wip8a8ifbkaq79iskbrsi8iqnrg"; + } + else + throw "Unsupported system: ${stdenv.hostPlatform.system}"; + + desktopItem = makeDesktopItem { + name = "eagle"; + exec = "eagle"; + icon = "eagle"; + comment = "Schematic capture and PCB layout"; + desktopName = "Eagle"; + genericName = "Schematic editor"; + categories = "Application;Development;"; + }; + + buildInputs = + [ patchelf zlib freetype fontconfig openssl libXrender libXrandr libXcursor + libX11 libXext libXi + ]; + + phases = [ "installPhase" ]; + + # NOTES: + # Eagle for Linux comes as a self-extracting shell script with embedded + # tarball. The tarball data (.tar.bz2) starts after a __DATA__ marker. + # + # Eagle apparently doesn't like binary patching. This is what happens: + # $ ./result/eagle-6.4.0/bin/eagle + # argv[0] (/home/bfo/nixpkgs/result/eagle-6.4.0/bin/eagle) is not the currently executed program version! + installPhase = '' + # Extract eagle tarball + mkdir "$out" + sed '1,/^__DATA__$/d' "$src" | tar -xjf - -C "$out" + + # Install manpage + mkdir -p "$out"/share/man/man1 + ln -s "$out"/eagle-${version}/doc/eagle.1 "$out"/share/man/man1/eagle.1 + + # Build LD_PRELOAD library that redirects license file access to the home + # directory of the user + mkdir -p "$out"/lib + gcc -shared -fPIC -DEAGLE_PATH=\"$out/eagle-${version}\" ${./eagle7_fixer.c} -o "$out"/lib/eagle_fixer.so -ldl + + # Make wrapper script + dynlinker="$(cat $NIX_CC/nix-support/dynamic-linker)" + mkdir -p "$out"/bin + cat > "$out"/bin/eagle << EOF + #!${runtimeShell} + export LD_LIBRARY_PATH="${stdenv.cc.cc.lib}/lib:${libPath}" + export LD_PRELOAD="$out/lib/eagle_fixer.so" + export QT_XKB_CONFIG_ROOT="${xkeyboardconfig}/share/X11/xkb" + exec "$dynlinker" "$out/eagle-${version}/bin/eagle" "\$@" + EOF + chmod a+x "$out"/bin/eagle + + # Make desktop item + mkdir -p "$out"/share/applications + cp "$desktopItem"/share/applications/* "$out"/share/applications/ + mkdir -p "$out"/share/icons + ln -s "$out/eagle-${version}/bin/eagleicon50.png" "$out"/share/icons/eagle.png + ''; + + meta = with stdenv.lib; { + description = "Schematic editor and PCB layout tool from CadSoft"; + homepage = http://www.cadsoftusa.com/; + license = licenses.unfree; + platforms = platforms.linux; + maintainers = [ maintainers.bjornfor ]; + }; +} diff --git a/nixpkgs/pkgs/applications/science/electronics/eagle/eagle7_fixer.c b/nixpkgs/pkgs/applications/science/electronics/eagle/eagle7_fixer.c new file mode 100644 index 000000000000..da9da4dcbd3a --- /dev/null +++ b/nixpkgs/pkgs/applications/science/electronics/eagle/eagle7_fixer.c @@ -0,0 +1,134 @@ +/* + * LD_PRELOAD trick to make Eagle (schematic editor and PCB layout tool from + * CadSoft) work from a read-only installation directory. + * + * When Eagle starts, it looks for the license file in <eagle>/bin/eagle.key + * (where <eagle> is the install path). If eagle.key is not found, Eagle checks + * for write access to <eagle>/bin/, shows a license dialog to the user and + * then attempts to write a license file to <eagle>/bin/. + * + * This will of course fail when Eagle is installed in the read-only Nix store. + * Hence this library that redirects accesses to the those paths in the + * following way: + * + * <eagle>/bin => $HOME + * <eagle>/bin/eagle.key => $HOME/.eagle.key + * + * Also, if copying an example project to ~/eagle/ (in the Eagle GUI), Eagle + * chmod's the destination with read-only permission bits (presumably because + * the source is read-only) and fails to complete the copy operation. + * Therefore, the mode argument in calls to chmod() is OR'ed with the S_IWUSR + * bit (write by owner). + * + * Usage: + * gcc -shared -fPIC -DEAGLE_PATH="$out/eagle-${version}" eagle_fixer.c -o eagle_fixer.so -ldl + * LD_PRELOAD=$PWD/eagle_fixer.so ./result/bin/eagle + * + * To see the paths that are modified at runtime, set the environment variable + * EAGLE_FIXER_DEBUG to 1. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <dlfcn.h> +#include <limits.h> +#include <sys/stat.h> + +#ifndef EAGLE_PATH +#error Missing EAGLE_PATH, path to the eagle-${version} installation directory. +#endif + +typedef FILE *(*fopen_func_t)(const char *path, const char *mode); +typedef int (*access_func_t)(const char *pathname, int mode); +typedef int (*chmod_func_t)(const char *path, mode_t mode); + +/* + * Map <eagle>/bin to $HOME and <eagle>/bin/eagle.key to $HOME/.eagle.key + * + * Path is truncated if bigger than PATH_MAX. It's not threadsafe, but that's + * OK. + */ +static const char *redirect(const char *pathname) +{ + static char buffer[PATH_MAX]; + const char *homepath; + const char *new_path; + static int have_warned; + + homepath = getenv("HOME"); + if (!homepath) { + homepath = "/"; + if (!have_warned && getenv("EAGLE_FIXER_DEBUG")) { + fprintf(stderr, "eagle_fixer: HOME is unset, using \"/\" (root) instead.\n"); + have_warned = 1; + } + } + + new_path = pathname; + if (strcmp(EAGLE_PATH "/bin", pathname) == 0) { + /* redirect to $HOME */ + new_path = homepath; + } else if (strcmp(EAGLE_PATH "/bin/eagle.key", pathname) == 0) { + /* redirect to $HOME/.eagle.key */ + snprintf(buffer, PATH_MAX, "%s/.eagle.key", homepath); + buffer[PATH_MAX-1] = '\0'; + new_path = buffer; + } + + return new_path; +} + +FILE *fopen(const char *pathname, const char *mode) +{ + FILE *fp; + const char *path; + fopen_func_t orig_fopen; + + orig_fopen = (fopen_func_t)dlsym(RTLD_NEXT, "fopen"); + path = redirect(pathname); + fp = orig_fopen(path, mode); + + if (path != pathname && getenv("EAGLE_FIXER_DEBUG")) { + fprintf(stderr, "eagle_fixer: fopen(\"%s\", \"%s\") => \"%s\": fp=%p\n", pathname, mode, path, fp); + } + + return fp; +} + +int access(const char *pathname, int mode) +{ + int ret; + const char *path; + access_func_t orig_access; + + orig_access = (access_func_t)dlsym(RTLD_NEXT, "access"); + path = redirect(pathname); + ret = orig_access(path, mode); + + if (path != pathname && getenv("EAGLE_FIXER_DEBUG")) { + fprintf(stderr, "eagle_fixer: access(\"%s\", %d) => \"%s\": ret=%d\n", pathname, mode, path, ret); + } + + return ret; +} + +int chmod(const char *pathname, mode_t mode) +{ + int ret; + mode_t new_mode; + chmod_func_t orig_chmod; + + orig_chmod = (chmod_func_t)dlsym(RTLD_NEXT, "chmod"); + new_mode = mode | S_IWUSR; + ret = orig_chmod(pathname, new_mode); + + if (getenv("EAGLE_FIXER_DEBUG")) { + fprintf(stderr, "eagle_fixer: chmod(\"%s\", %o) => %o: ret=%d\n", pathname, mode, new_mode, ret); + } + + return ret; +} |