Contributing via nixpkgs

Let’s say I want to create a PR for a project; in that case, I want to access the source code, make changes, and compile it.

Can I use Nix to improve my workflow?

If I run nix develop nixpkgs#package --debug, how can I access the source code, change it, and then compile it?

It would also be fine for me to clone the repo via VCS normally, and then use nix build against the local folder while sourcing the package.nix from nixpkgs, without having to copy it into the cloned folder or add a flake.nix.

I hope I expressed myself well. I tried searching the documentation for something like this but only found nix develop - Nix Reference Manual, which led me to --redirect. It’s not obvious to me what I should do after running nix develop nixpkgs#PACKAGE --redirect nixpkgs#PACKAGE ..

I obviously need to learn more about Nix, but I thought asking here might lead me to good study directions.

Thank you all!

2 Likes

I’ve actually never known about this --redirect flag, though I suppose you could use it to redirect the src attribute of a derivation, make your changes to the sources, and then override the derivation to use your modified source tree.

1 Like

Hi, @Frontear thank you for replying. Do you know how I could you access the attributes?

nix develop nixpkgs#PACKAGE --debug --redirect nixpkgs#PACKAGE.src . results in:

error: flake 'flake:nixpkgs' does not provide attribute 'devShells.x86_64-linux.PACKAGE.src',
'packages.x86_64-linux.PACKAGE.src', 'legacyPackages.x86_64-linux.PACKAGE.src' 
or 'PACKAGE.src'

If I may ask, how do you usually contribute to a project, leveraging nix [flakes] for building?

1 Like

This explains --redirect:

1 Like

Using GNU Hello as an example:

$ cd $(mktemp -d)
$ nix develop nixpkgs#hello
$ unpackPhase
$ cd hello-2.12.2
# do whatever you want
$ configurePhase
$ buildPhase
$ installPhase
# show outputs
$ ls outputs/out/

If you want to use a local source, skip the unpackPhase.

5 Likes

Okay thank you @oldshensheep. I was trying this the other day, but I had a problem with the source. Which I guess “the derivation I used didn’t provide” :man_shrugging:

> nix develop nixpkgs#telegram-desktop

[nix] > unpackPhase
variable $src or $srcs should point to the source
exit

> nix develop nixpkgs#telegram-desktop

[nix] > src=$(nix build nixpkgs#telegram-desktop --no-link --print-out-paths)

[nix] > unpackPhase
unpacking source archive /nix/store/nrzwszjsxpggdwkxsz04d92sr4a9s8vm-telegram-desktop-6.2.3
source root is telegram-desktop-6.2.3

[nix] > stat -c "%a %n" telegram-desktop-6.2.3/
755 telegram-desktop-6.2.3/

I think like this is okay or I could have cloned the repo via vcs as you said. But why does hello provide the source directly while telegram-desktop doesn’t?

I thought I would have been the one defined at

PS: I think I understand after pasting the last url. It is in unwrapped.nix, but src doesn’t get inherited in default.nix

Am I right?

1 Like

Yes, you can try nix develop nixpkgs#telegram-desktop.unwrapped

3 Likes

That doesn’t always leave you with a usable binary to test, though, like in this case your telegram will be unwrapped.

You can also resort to overriding the package in your configuration and rebuilding that:

{ pkgs, ... }: let
  telegram = pkgs.telegram-desktop.override {
    unwrapped = pkgs.telegram-desktop.unwrapped.overrideAttrs (_: {
      src = ./some/local/path;
    });
  };
in {
  environment.systemPackages = [ telegram ];
}

… obviously that will be tedious to use, since nix will have to rebuild the whole thing from scratch for every edit.

nix develop is definitely the intended way, and much more ergonomic. Might not work on all packages without some work, though.

2 Likes

Thank you both.

I agree it would be tedious for a nixos configuration having it rebuilt everytime, but also for my use case (contributing a PR to a project) since it is unwrapped.

Because now I have:

> nix develop nixpkgs#telegram-desktop.unwrapped

[nix] > unpackPhase
unpacking source archive /nix/store/7m1f6hwsyqkihhpz5ps6bnpnl288xp0c-source
source root is source

[nix] > cd source/

[nix] > configurePhase
no configure script, doing nothing

[nix] > buildPhase
no Makefile or custom buildPhase, doing nothing

Because those would come from the wrapping derivation I believe.

This seems a weird corner case though, in a normal derivation I would have all phases in the default.nix of my package I guess.
There seem to be only 15 wrapped package if I search repo:NixOS/nixpkgs unwrapped.nix
context:global repo:NixO… - Sourcegraph

1 Like

I don’t know bro.

> git clone --depth=1 https://github.com/telegramdesktop/tdesktop src
> nix develop nixpkgs#telegram-desktop --redirect nixpkgs#telegram-desktop.unwrapped ./src
# I also tried redirecting unwrapped.src
# > nix develop nixpkgs#telegram-desktop --redirect nixpkgs#telegram-desktop.unwrapped.src ./src
warning: 'flake:nixpkgs#telegram-desktop.unwrapped.src' (path '/nix/store/7m1f6hwsyqkihhpz5ps6bnpnl288xp0c-source') is not used by this build environment

# Anyway the phases don't work below.

[nix] > declare -F | grep -E ".*Phase"
declare -f buildPhase
declare -f checkPhase
declare -f configurePhase
declare -f distPhase
declare -f fixupPhase
declare -f glibPreInstallPhase
declare -f installCheckPhase
declare -f installPhase
declare -f patchPhase
declare -f runPhase
declare -f showPhaseFooter
declare -f showPhaseHeader
declare -f unpackPhase
declare -f updateAutotoolsGnuConfigScriptsPhase

[nix] > checkPhase
no Makefile or custom checkPhase, doing nothing

[nix] > configurePhase
no configure script, doing nothing

[nix] > runPhase
Running phase:
bash: : invalid variable name

[nix] > buildPhase
no Makefile or custom buildPhase, doing nothing

I might end up just copying the files from nixpkgs into a quick flake.nix to do the PR, but thought this would be easier and more integrated :slight_smile:

1 Like

Telegram uses cmake and ninja to build the program.
Both cmake and ninja have custom setup-hooks.
see:
ninja setup-hooks.sh source
cmake setup-hooks.sh source

cmake setup-hooks set variable configurePhase to cmakeConfigurePhase
ninja setup-hooks set variable buildPhase to ninjaBuildPhase

Both approaches should work:

$ unpackPhase
$ cd source/
$ cmakeConfigurePhase  # $configurePhase
$ ninjaBuildPhase      # $buildPhase

Use this, this is better.

$ runPhase unpackPhase
$ runPhase configurePhase
$ runPhase buildPhase

You can run type runPhase to see the function definition.

Part of the function(shell is kinda funky):

...
eval "${!curPhase:-$curPhase}";
...

pesudo code:
if ${$curPhase} == null then $curPhase else ${$curPhase}

nix log nixpkgs#telegram-desktop.unwrapped shows the build log and can help with debugging.

2 Likes

Thank you again.
The tip about cmake and ninja configuring the phases was perfect thank you.

Where is it defined though? in unwrapped.nix I only see the cmakeFlags attribute and ninja as a nativeBuildInput is that all that’s needed for them to hook the phases?


The runHook portion didn’t work for me though:

> nix develop nixpkgs#telegram-desktop.unwrapped

[nix] > type runHook
runHook is a function
runHook ()
{
    local hookName="$1";
    shift;
    local hooksSlice="${hookName%Hook}Hooks[@]";
    local hook;
    for hook in "_callImplicitHook 0 $hookName" ${!hooksSlice+"${!hooksSlice}"};
    do
        _logHook "$hookName" "$hook" "$@";
        _eval "$hook" "$@";
    done;
    return 0
}

[nix] > runHook configurePhase
no configure script, doing nothing

[nix] > runHook buildPhase
no Makefile or custom buildPhase, doing nothing

Mistyped. It’s runPhase.
It’s implemented in stdenv.mkDerivation and will run the hooks in <pkgs>/nix-support/<hook> (I don’t quite remember exactly), so you only need to include the package.

2 Likes