Accessing outer 'src' in subderivation?

I am trying to write a derivation to build that involves building dependencies from source. The way I am attempting to do this is to have mkDerivation’s running within my outermost mkDerivation. My issue is I need to access specific patch files within the inner mkDerivation that are pulled as part of the outer mkDerivation.

An example of my structure is the following:

# Outer derivation
stdenv.mkDerivation rec {
  ...
  # Outer 'src'
  src = fetchFromGitHub {
    ...
  };

  inner-deriv = 
    let
      base_src = src;
    in stdenv.mkDerivation rec {
      ...
      # Inner src
      src = fetchurl {
        ...
      };
      patches = [ (base_path)/patch.diff ];
    };
}

For the patch path I have currently tried using ${base_src}/binutils-2.32.diff, $base_src/binutils-2.32.diff, and (base_src)/binutils-2.32.diff. The first two result in errors related to $ sign (“syntax error, unexpected DOLLAR_CURLY” and “syntax error, unexpected invalid token” respectively). The third option seems to be the most promising as it is only complaining about the path being incorrect.

If there is no way to do this I can try to fetch the patch again within the inner derivation, however this seems like a waste as they have already been downloaded by the main derivation

Full derivation file

Here is the full code for my current attempt. Ignore any issues in the build/install phases (unless they are somehow affecting the patch phase) as they are still WIP because the program crashes before reaching them

{ config
, lib
, stdenv
, fetchFromGitHub
, fetchurl

, gmp4
, mpfr
, libmpc
, texinfo
, wget

, libiconvReal
}:

stdenv.mkDerivation rec {
  pname   = "libxenon";
  version = "44580f2";

  src = fetchFromGitHub {
    owner           = "Free60Project";
    repo            = "libxenon";
    fetchSubmodules = true;
    rev             = "44580f2dbbb7a1b5f45b0e8f5ac0264086dea3e7";
    hash            = "sha256-LjAmftsa1gkYTMhVGjEbIjyOg4ooBhLNsoKqB5OgOsA=";
  };

  # Build required libraries
  binutils-xenon = 
  let
    base_src = src;
  in stdenv.mkDerivation rec {
      name = "binutils-2.32-xenon";
      src = fetchurl {
        url  = "http://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.gz";
        hash = "sha256-mw2Xs9MN8YTTArztEvl2qh5fv0sL5pbN68bMowQRpG4=";
      };

      patches = [ ${base_src}/binutils-2.32.diff ];

      configurePhase = ''
        ./configure --target=xenon --prefix=$PWD/binutils_out --enable-multilib --disable-nls --disable-werror 
      '';

      installPhase = ''
        ls
      '';
    };

  gcc-xenon = 
    let
      base_src = src;
    in stdenv.mkDerivation rec {
      name = "gcc-9.2.0-xenon";
      src = fetchurl {
        url  = "ftp://ftp.gnu.org/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.gz";
        hash = "sha256-qTGnUNb+ray+7LMh1zklzV67bfp+/wgCmErzrvY3WfQ=";
      };
      nativeBuildInputs = [ gmp4 mpfr libmpc libiconvReal ];

      patches = [ (base_src)/gcc-9.2.0.diff ];

      configurePhase = ''
        ./configure --target=xenon --prefix=$PWD/gcc_out --with-libiconv-prefix=${libiconvReal} --with-cpu=cell \
          --with-gmp=${gmp4} --with-mpfr=${mpfr} --disable-decimal-float --disable-libquadmath \
          --enable-languages=c,c++ --disable-libssp --disable-libsanitizer --with-newlib --enable-cxx-flags="-G0" \
          --disable-libmudflap --disable-nls --disable-shared --disable-linux-futex --enable-altivec \
          --disable-libatomic --disable-threads --disable-libgomp 00disable-libitm
      '';
    };

  newlib-xenon = 
    let
      base_src = src;
    in stdenv.mkDerivation rec {
      name = "newlib-3.1.0-xenon";
      src = fetchurl {
        url  = "ftp://sourceware.org/pub/newlib/newlib-3.1.0.tar.gz";
        hash = "sha256-+0+hzCHpBgcZIIMAphQg5AidbebvWc9TO1f+dIAdECo=";
      };

      patches = [ (base_src)/newlib-3.1.0.diff ];

      configurePhase = ''
        ./configure --target=xenon --prefix=$PWD/newlib_out --enable-multilib --disable-nls \
          CFLAGS="-DHAVE_BLKSIZE -O2"\
          --enable-newlib-io-long-long --enable-newlib-io-long-double
      '';
    };

  nativeBuildInputs = [ gmp4 mpfr libmpc texinfo wget binutils-xenon gcc-xenon newlib-xenon];

  buildPhase = ''
    cd toolchain
    
    substituteInPlace build-xenon-toolchain \
      --replace "BINUTILS=binutils-2.32" "BINUTILS=${binutils-xenon}" \
      --replace "GCC=gcc-9.2.0" "GCC=${gcc-xenon}" \
      --replace "NEWLIB=newlib-3.1.0" "NEWLIB=${newlib-xenon}" \
      --replace "BUILD_BINUTILS=true" "BUILD_BINUTILS=false" \
      --replace "BUILD_NEWLIB=true" "BUILD_NEWLIB=false"

    export PREFIX=./out/
    patchShebangs ./build-xenon-toolchain
  '';
}

The ${...} is used for interpolating values in strings.

For fetchers, URLs with the same hash should only be fetched once.

The issue with base_src/binutils-2.32.diff is that file isn’t in the repo.

Oh shoot you are correct! The path should be toolchain/binutils-2.32.diff. However, I am still experiencing the same issue with the path being incorrect. When using (base_src)/toolchain/binutils-2.32.diff the path is evaluated to /toolchain/binutils-2.32.diff, while using base_src/toolchain/binutils-2.32.diff will evaluate to /etc/nixos/custom_packages/libxenon/base_src/toolchain/binutils-2.32.diff (the location I am writing the derivation, followed with base_src/...).

Attempting to pass the path as a string (using ${base_src}) however appears to solve the issue (the actual derivation does not seem to work, but it is able to move past the patch phase now so for now I am assuming this is an issue with the derivation still being a WIP). Is this the proper way to do something like this, or did I just get lucky with this specific use case? IMO if any path type can be represented with a string type, it feels a bit redundant to even have a path type