From 2660037f8cdf6bb69bacbf3d9d2f9f72d056c8d6 Mon Sep 17 00:00:00 2001 From: Austin Seipp Date: Thu, 14 Jan 2021 23:52:23 -0600 Subject: [PATCH] yosys: enable loading "out of band" plugins By default, when yosys looks for plugins with the `-m` flag or `plugin` command, it always looks in `YOSYS_PREFIX/share/yosys/plugins` for a `.so` file, and loads that. By design, this is intended to be a single, global, mutable location such as `/usr/share/yosys/...` on disk, and plugins are supposed to install their `.so` files here after yosys is installed, and they all coexist together. Obviously, this won't work for us, but users might expect these plugins to still work. More importantly, they won't want to add special cases to their build systems. Instead, to allow Nix users to use yosys plugins with the same UX (e.g. natively call `plugin bluespec` or `-m ghdl`), we add a patch to yosys that allows it to search a new `NIX_YOSYS_PLUGIN_DIRS` search path environment variable. In tandem, we add a setup hook that adds to this search path if a package has a `$out/share/yosys/plugins` directory. Thus, it's enough to just include `yosys`, and any package that has a yosys plugin in `$out/share/yosys/plugins`, and you can load it with `-m` or the `plugin` command. We could use a style like the haskellPackages set, where the set of packages are "encased" in a lambda, and we pass packages that are compatible with that version of the compiler: haskell.packages.ghc8102.ghcWithPackages (p: with p; [ ... ]) but, realistically, there will probably only ever be one version of yosys and one set of compatible plugins, so this seems overdone. Signed-off-by: Austin Seipp --- pkgs/development/compilers/yosys/default.nix | 3 ++ .../compilers/yosys/plugin-search-dirs.patch | 34 +++++++++++++++++++ .../development/compilers/yosys/setup-hook.sh | 5 +++ 3 files changed, 42 insertions(+) create mode 100644 pkgs/development/compilers/yosys/plugin-search-dirs.patch create mode 100644 pkgs/development/compilers/yosys/setup-hook.sh diff --git a/pkgs/development/compilers/yosys/default.nix b/pkgs/development/compilers/yosys/default.nix index 51f0b7ed45a..3c292deabc6 100644 --- a/pkgs/development/compilers/yosys/default.nix +++ b/pkgs/development/compilers/yosys/default.nix @@ -49,6 +49,7 @@ stdenv.mkDerivation rec { makeFlags = [ "ENABLE_PROTOBUF=1" "PREFIX=${placeholder "out"}"]; patchPhase = '' + patch -p1 < ${./plugin-search-dirs.patch} substituteInPlace ./Makefile \ --replace 'CXX = clang' "" \ --replace 'LD = clang++' 'LD = $(CXX)' \ @@ -96,6 +97,8 @@ stdenv.mkDerivation rec { postBuild = "ln -sfv ${abc-verifier}/bin/abc ./yosys-abc"; postInstall = "ln -sfv ${abc-verifier}/bin/abc $out/bin/yosys-abc"; + setupHook = ./setup-hook.sh; + meta = with stdenv.lib; { description = "Open RTL synthesis framework and tools"; homepage = "http://www.clifford.at/yosys/"; diff --git a/pkgs/development/compilers/yosys/plugin-search-dirs.patch b/pkgs/development/compilers/yosys/plugin-search-dirs.patch new file mode 100644 index 00000000000..0cb0aee9c7e --- /dev/null +++ b/pkgs/development/compilers/yosys/plugin-search-dirs.patch @@ -0,0 +1,34 @@ +diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc +index 3ed19497..f9534bd0 100644 +--- a/passes/cmds/plugin.cc ++++ b/passes/cmds/plugin.cc +@@ -75,8 +75,27 @@ void load_plugin(std::string filename, std::vector aliases) + #endif + + void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL); +- if (hdl == NULL && orig_filename.find('/') == std::string::npos) +- hdl = dlopen((proc_share_dirname() + "plugins/" + orig_filename + ".so").c_str(), RTLD_LAZY|RTLD_LOCAL); ++ if (hdl == NULL && orig_filename.find('/') == std::string::npos) { ++ std::string install_dir = proc_share_dirname() + "plugins"; ++ ++ vector all_dirs; ++ all_dirs.push_back(install_dir); ++ ++ char* plugin_dirs = getenv("NIX_YOSYS_PLUGIN_DIRS"); ++ if (plugin_dirs != NULL) { ++ std::string p(plugin_dirs), t; ++ std::stringstream ss(p); ++ ++ while(std::getline(ss, t, ':')) { ++ all_dirs.push_back(t); ++ } ++ } ++ ++ for (auto dir : all_dirs) { ++ hdl = dlopen((dir + "/" + orig_filename + ".so").c_str(), RTLD_LAZY|RTLD_LOCAL); ++ if (hdl != NULL) break; ++ } ++ } + if (hdl == NULL) + log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror()); + loaded_plugins[orig_filename] = hdl; diff --git a/pkgs/development/compilers/yosys/setup-hook.sh b/pkgs/development/compilers/yosys/setup-hook.sh new file mode 100644 index 00000000000..d01bbdd1a8c --- /dev/null +++ b/pkgs/development/compilers/yosys/setup-hook.sh @@ -0,0 +1,5 @@ +addYosysPluginPath() { + addToSearchPath NIX_YOSYS_PLUGIN_DIRS "$1/share/yosys/plugins" +} + +addEnvHooks "$targetOffset" addYosysPluginPath