How to make a package that includes runtime dependencies and environment variables? - nix

The question may not be precise, but this is what I am trying to achieve:
The puppeteer-core NPM package requires a headless browser at runtime, and I found that I could use it with the latest Chromium in Nixpkgs. My current workflow:
I have overridden the node2nix-created default.nix with override.nix by adding Chromium to buildInputs:
{pkgs ? import <nixpkgs> {
inherit system;
}, system ? builtins.currentSystem}:
let
nodePackages = import ./default.nix {
inherit pkgs system;
};
in
nodePackages // {
shell = nodePackages.shell.override {
buildInputs = [ pkgs.chromium ];
};
}
Issue nix-shell override.nix -A shell.
export CHROMIUM_PATH=$(which chromium)
Setting up Chromium in the javascript files via process.env.CHROMIUM_PATH.
This works well, and the project can be shared easily with others by creating a tarball, but they would have to set up the environment manually as well, and I also don't like Chromium being included in the build dependencies. I could have just installed it globally with Nix, but the rest of the manual steps would still be there.
I read the manuals, and getting comfortable with the language, but haven't built a derivation or a package yet, therefore I'm sure I missing something obvious.
Some of the discussions I found on the topic:
https://nixos.org/nixos/nix-pills/automatic-runtime-dependencies.html
Runtime-only dependencies #1080
https://discourse.nixos.org/t/handling-dynamic-runtime-dependencies/323

Related

Using conan in Bazel for linux but not for windows

I have a system that is built using Bazel and is using OpenCV as a 3rd party package.
When building on Linux I want to use a prebuilt package using conan, and when using Windows I want to use a locally compiled version, and not use conan.
What I have at the moment is in my WORKSPACE file:
load("#//conan:dependencies.bzl", "load_conan_dependencies")
load_conan_dependencies()
new_local_repository(
name = "windows_opencv",
build_file = "#//third_party:opencv_windows.BUILD",
path = "C:\\opencv\\build",
)
and the conanfile.txt looks like this:
[requires]
OpenCV/3.4.13#company/dev
[generators]
BazelDeps
BazelToolchain
This works well for the Linux part, but because I don't have the OpenCV/3.4.13#company/dev package for Windows, I can't use conan install and not rules are generated, so trying to build on Windows causes this error:
ERROR: error loading package '': Label '//conan:dependencies.bzl' is invalid because 'conan' is not a package; perhaps you meant to put the colon here: '//:conan/dependencies.bzl'?
The way I currently see this is I have 2 options:
Have 2 conanfile.txt, 1 which contains the OpenCV package and another empty only with the generators, to create the necessary conan files so it would pass the load call
Create an empty OpenCV conan package and again just insall it so the load call would pass
Both options seems to me like bad hacks and workarounds, but I'm not familiar enough with Bazel to know if there's a better option.
What I would like to be able to do is only load the conan dependencies rule for Linux and ignore it on Windows.
Currently the selection between Linux & Windows OpenCV is done using alias:
alias(
name = "opencv_binary",
actual = select({
"//mediapipe:windows": "#windows_opencv//:opencv",
"//conditions:default": "#opencv//:opencv",
}),
)
where #opencv//:opencv is the conan pacakge

Launching IDE directly from nix-shell

I am new to NixOs and nix-shell and am still getting to know its idioms. Right now I have a Java project which I am using nix-shell via direnv to load up the build tool chain, including a jdk and bazel.
I would like the IDE - in my case ItelliJ - to use this same toolchain. My naive approach is to use a nix-shell script as follows, which is the default.nix in the root of my project, and the one picked up by direnv.
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "my-project";
buildInputs = with pkgs; [
jdk11
bazel
jetbrains.idea-ultimate
];
shellHook = ''
export JAVA_HOME="${pkgs.jdk11}/lib/openjdk"
ln -s ${pkgs.jdk11}/lib/openjdk ./jdk
'';
}
I can then launch IntelliJ with the following command from the shell:
$ idea-ultimate 2>1 > /dev/null &
While it works, I have the following concerns:
Loading up the IDE into my command line shell seems really heavy, especially for the CI build.
It is going to get worse as I add other IDEs the team uses, like Eclipse.
It seems like the wrong way.
I can, of course, install these IDE packages using other Nix facilities, like home manager, which gives me the application launcher in the menu after the right config steps; however, I like directly launching the IDE from the shell to ensure the correct tool chain is in place and in correct paths.
My thought for a next step was to remove the IDE input from this default.nix and create custom nix files which include the inputs for the IDE and a launcher script to actually launch the IDE with nix-shell. My hope is that, if executed from the shell above, it will inherit its inputs, augment it with the IDE input, and then launch the IDE.
Again, my goal is to use nix to launch my IDEs, and use the packages and configs setup by the default.nix which is in the root of the project to ensure consistency.
Suggestions, including alternative approaches, are appreciated.

exiftool-vendored doesn't return when used in an electron app on Mac?

On Mac, when I run my app from WebStorm, exiftool-vendored works great. However, when I build my app (I use electron-builder) and install it on the same Mac, it never returns, even just trying to get the version:
exiftool.version().then(version => writeBreadcrumb('exif', version))
In other words, no error is raised, and the then is never executed when running an installed version of my app, though it works fine running my app from WebStorm (with cd build && electron .)
What am I doing wrong? Is there an example anywhere of how to use exiftool-vendored in an electron app?
You should take a look at what the docs say about making it work with Electron:
How do you make this work with electron?
Electron is notoriously brittle and buggy, and is not officially supported by this package. Although PhotoStructure uses this package within electron, there's a nontrivial amount of auxiliary support code specific to that project to make it work smoothly.
If you're still anxious to try, here are some things to keep in mind:
Note that this package will spawn exiftool external processes, which means the exiftool-vendored.pl and exiftool-vendored.exe packages should be included in your asarUnpack. SmartUnpack might work, but if it doesn't use a pattern like node_modules/{exiftool-vendored.*}/**/*.
If you're requiring exiftool-vendored from within a webview, you're gonna have a bad time. Many things won't work due to a lack of node compatibility within electron.
__dirname at runtime from within an asar package after webpacking will be invalid, so don't rely on that.
— https://github.com/photostructure/exiftool-vendored.js/wiki/FAQ#how-do-you-make-this-work-with-electron
Since I never found a way to get exiftool-vendored to work with electron on Mac, I accepted the above answer, as essentially a warning to steer clear of exiftool-vendored for electron on Mac.
This answer is included for completeness, for those of us who need exiftool in an electron app for both Mac and Windows:
I used node-exiftool with these settings added in package.json for electron-builder:
"build": {
...
"win": {
...
"extraResources": "exiftoolwin/**/*"
},
"mac": {
...
"extraResources": "exiftool/**/*"
}
}
In the root of my project, I added folders exiftoolwin and exiftool. In exiftoolwin, I put exiftool.exe which I obtained by following the Windows Stand-Alone Executable instructions here, and in my exiftool folder I put exiftool and lib which I obtained by extracting the full perl distribution on Mac, as described on the same page.
Then, in my .jsx (I'm using React):
import exiftool from 'node-exiftool';
const exiftoolFolderAndFile = process.platform === 'win32' ? 'exiftoolwin/exiftool.exe' : 'exiftool/exiftool';
const exiftoolPath = path.resolve(__dirname, '../..', exiftoolFolderAndFile);
const ep = new exiftool.ExiftoolProcess(exiftoolPath);
Then I just use ep as described here.
This is working for us:
add this dependency:
"exiftool-vendored": "^15.2.0",
Update package.json "build" section for mac ( not needed for windows as far as we can see )
"build": {
"mac": {
...
"asarUnpack": [
"node_modules/exiftool-vendored/**" ,
"node_modules/exiftool-vendored.pl/**"
]
}
}

How can I use a nix configuration when not using Nixos?

So I've installed Nix on Arch linux and I'm able to run nix-env -i example, however how can I define a Nix configuration?
As I don't have any /nixos/configuration.nix file present.
Is this possible?
My goal here is to be able to define a configuration which I could then use something like nixos-rebuild switch to install and provision all the software.
I use NixOS, but I use /etc/nixos/configuration.nix to describe my system; I keep it fairly minimal and prefer not to install "user" software by editing configuration.nix.
So what I do instead is use my ~/.nixpkgs/config.nix (which I believe you also have an equivalent of even in a non-NixOS nix install? I've never actually used nix separately).
The basic structure I use is this:
{
packageOverrides = nixpkgs: with nixpkgs; rec {
mine = with pkgs; buildEnv {
name = "mine";
paths = [
# your packages here
];
};
};
}
buildEnv is a convenience function from nix that makes an "environment" package out of a bunch of others; installing the package mine depends on (and so installs) all of the things listed in paths, and also makes sure they get included in PATH and things like that.
Then I just use nix-env -riA nixos.mine to deploy changes I've made to my environment description (or to rebuild my environment following channel updates). The -r tells it to remove everything else other than mine from the new generation of my profile, which means I can (ab?)use nix-env -i some-package as a way of "temporarily" installing some-package, and if I don't decide I like it enough to actually record it in my config.nix it'll just get removed anyway next time I deploy.
You can certainly create your own configuration. For example, you can do something like this:
let
pkgs = import <nixpkgs> {};
in
{
packages = [
pkgs.vim
pkgs.gimp
];
}
That would produce a set containing an attribute called packages, containing a list of Nix packages. But, you'd need to develop a tool to build environments from this, which is part of what nix-env does. For example, the tool can use nix-env to determine what is already installed, compare that to the selected packages in the configuration, and then install/uninstall packages accordingly.
You don't have a /etc/nixos/configuration.nix because that's NixOS-specific. So while you can do as you asked, you'd have to roll your own solution.

Point rollup to alternate file for import

Background:
We have an Angular 2 application that we would like to start using AOT compilation for. Simple enough... except for one of my dependencies...
We use autobahn.js for communicating to our servers over a web socket connection. The issue is with loading this dependency in rollup.
The authors of autobahn.js have decided that for their browser version of the library they will host it in bower (fair enough) instead of npm.
We have a library that wraps autobahn.js with some nice utilities and handles other things for us. This is great because it is a universal solution. This library can be used in both the browser and in our node.js servers. (yay)
However the node version of autobahn uses fs, url, and other node specific features. (boo)
The bower version of their library uses the correct equivalents for the browser which is good.
In the wrapper we have an import * as autobahn from 'autobahn'; (we use typescript) This works great in node, and also worked ok with some configuration in SystemJS.
Problem:
How does one tell rollup (or the rollup-plugin-commonjs) to point to the bower_components/autobahnjs/autobahn.js file instead of the node_modules/autobahn/index.js file as it does by default.
Current configuration:
import rollup from 'rollup';
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'dist/iss/index.js',
dest: 'dist/iss/bundle.js',
sourceMap: false,
format: 'iife',
moduleName: 'statusMonitor',
external: [
'autobahn',
'moment',
'moment-timezone'
],
context: 'window',
plugins: [
nodeResolve({jsnext: true, module: true, browser: true}),
commonjs({
include: 'node_modules/**'
}),
json(),
uglify()
]
}
Other Option:
Another option that would work for us is that autobahn also works as a global, and if we could patch rollup to use the global autobahn off window then that would work for our use case.
There's a rollup-plugin-bower-resolve plugin which is analogous to node-resolve – if you include that in your plugins array before node-resolve (or use the skip option in node-resolve) then it should be able to find autobahn.
It's now on npm
https://github.com/crossbario/autobahn-js-browser
The browser version is published to npm under the name autobahn-browser. Install with:
npm install autobahn-browser
Note: the NodeJS version of Autobahn continues to be published under the name autobahn.

Resources