{ lib, stdenv, fetchurl, system, snapshotPath, autoPatchelfHook, python3, libxcrypt-legacy, }: let # Mapping from GCS component architecture names to Nix architecture names arches = { x86 = "i686"; x86_64 = "x86_64"; arm = "aarch64"; }; # Mapping from GCS component operating systems to Nix operating systems oses = { LINUX = "linux"; MACOSX = "darwin"; WINDOWS = "windows"; CYGWIN = "cygwin"; }; # Convert an archicecture + OS to a Nix platform toNixPlatform = arch: os: let arch' = arches.${arch} or (throw "unsupported architecture '${arch}'"); os' = oses.${os} or (throw "unsupported OS '${os}'"); in "${arch'}-${os'}"; # All architectures that are supported by GCS allArches = builtins.attrNames arches; # A description of all available google-cloud-sdk components. # It's a JSON file with a list of components, along with some metadata snapshot = lib.importJSON snapshotPath; # Generate a snapshot file for a single component. It has the same format as # `snapshot`, but only contains a single component. These files are # installed with google-cloud-sdk to let it know which components are # available. snapshotFromComponent = { component, revision, schema_version, version, }: builtins.toJSON { components = [ component ]; inherit revision schema_version version; }; # Generate a set of components from a JSON file describing these components componentsFromSnapshot = { components, revision, schema_version, version, ... }: lib.fix ( self: builtins.listToAttrs ( builtins.map (component: { name = component.id; value = componentFromSnapshot self { inherit component revision schema_version version ; }; }) components ) ); # Generate a single component from its snapshot, along with a set of # available dependencies to choose from. componentFromSnapshot = # Component derivations that can be used as dependencies components: # This component's snapshot { component, revision, schema_version, version, }@attrs: let baseUrl = builtins.dirOf schema_version.url; # Architectures supported by this component. Defaults to all available # architectures. architectures = builtins.filter (arch: builtins.elem arch (builtins.attrNames arches)) ( lib.attrByPath [ "platform" "architectures" ] allArches component ); # Operating systems supported by this component operating_systems = builtins.filter ( os: builtins.elem os (builtins.attrNames oses) ) component.platform.operating_systems; in mkComponent { pname = component.id; version = component.version.version_string; src = lib.optionalString (lib.hasAttrByPath [ "data" "source" ] component) "${baseUrl}/${component.data.source}"; sha256 = lib.attrByPath [ "data" "checksum" ] "" component; dependencies = builtins.map (dep: builtins.getAttr dep components) component.dependencies; platforms = if component.platform == { } then lib.platforms.all else builtins.concatMap (arch: builtins.map (os: toNixPlatform arch os) operating_systems) architectures; snapshot = snapshotFromComponent attrs; }; # Filter out dependencies not supported by current system filterForSystem = builtins.filter (drv: builtins.elem system drv.meta.platforms); # Make a google-cloud-sdk component mkComponent = { pname, version, # Source tarball, if any src ? "", # Checksum for the source tarball, if there is a source sha256 ? "", # Other components this one depends on dependencies ? [ ], # Short text describing the component description ? "", # Platforms supported platforms ? lib.platforms.all, # The snapshot corresponding to this component snapshot, }: stdenv.mkDerivation { inherit pname version snapshot; src = lib.optionalString (src != "") (fetchurl { url = src; inherit sha256; }); dontUnpack = true; installPhase = '' mkdir -p $out/google-cloud-sdk/.install # If there is a source, unpack it if [ ! -z "$src" ]; then tar -xf $src -C $out/google-cloud-sdk/ # If the source has binaries, link them to `$out/bin` if [ -d "$out/google-cloud-sdk/bin" ]; then mkdir $out/bin find $out/google-cloud-sdk/bin/ -type f -exec ln -s {} $out/bin/ \; fi fi # Write the snapshot file to the `.install` folder cp $snapshotPath $out/google-cloud-sdk/.install/${pname}.snapshot.json ''; nativeBuildInputs = [ python3 stdenv.cc.cc ] ++ lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ]; buildInputs = [ libxcrypt-legacy ]; passthru = { dependencies = filterForSystem dependencies; }; passAsFile = [ "snapshot" ]; meta = { inherit description platforms; }; }; in componentsFromSnapshot snapshot