about summary refs log blame commit diff
path: root/nix/buildGo/external/default.nix
blob: 42592c67e482a1446c62f33eff9aa46c73a74d0d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

                                     
                           

   





                    
               


                  
                              

          

                                              
                                                              
 


                                                                      
                                                       
                    
                           
                             
















                                                                      

                      
                                          

                                                       

                                      
                                             
       














                                                                                                  
 

                                                    
                                        
        
 


                                                                    
                                                       
        
 
                         
                                                                    
        

                                                                     
 


                          


                                                                  





                             
 
                         
                                                             

                                                                


                                                                              

                                               
                                                                                  
  
# Copyright 2019 Google LLC.
# SPDX-License-Identifier: Apache-2.0
{ pkgs, program, package }:

let
  inherit (builtins)
    elemAt
    foldl'
    fromJSON
    head
    length
    listToAttrs
    readFile
    replaceStrings
    tail
    unsafeDiscardStringContext
    throw;

  inherit (pkgs) lib runCommand go jq ripgrep;

  pathToName = p: replaceStrings [ "/" ] [ "_" ] (toString p);

  # Collect all non-vendored dependencies from the Go standard library
  # into a file that can be used to filter them out when processing
  # dependencies.
  stdlibPackages = runCommand "stdlib-pkgs.json" { } ''
    export HOME=$PWD
    export GOPATH=/dev/null
    ${go}/bin/go list std | \
      ${ripgrep}/bin/rg -v 'vendor' | \
      ${jq}/bin/jq -R '.' | \
      ${jq}/bin/jq -c -s 'map({key: ., value: true}) | from_entries' \
      > $out
  '';

  analyser = program {
    name = "analyser";

    srcs = [
      ./main.go
    ];

    x_defs = {
      "main.stdlibList" = "${stdlibPackages}";
    };
  };

  mkset = path: value:
    if path == [ ] then { gopkg = value; }
    else { "${head path}" = mkset (tail path) value; };

  last = l: elemAt l ((length l) - 1);

  toPackage = self: src: path: depMap: entry:
    let
      localDeps = map
        (d: lib.attrByPath (d ++ [ "gopkg" ])
          (
            throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
          )
          self)
        entry.localDeps;

      foreignDeps = map
        (d: lib.attrByPath [ d.path ]
          (
            throw "missing foreign dependency '${d.path}' in '${path}, imported at ${d.position}'"
          )
          depMap)
        entry.foreignDeps;

      args = {
        srcs = map (f: src + ("/" + f)) entry.files;
        deps = localDeps ++ foreignDeps;
      };

      libArgs = args // {
        name = pathToName entry.name;
        path = lib.concatStringsSep "/" ([ path ] ++ entry.locator);
        sfiles = map (f: src + ("/" + f)) entry.sfiles;
      };

      binArgs = args // {
        name = (last ((lib.splitString "/" path) ++ entry.locator));
      };
    in
    if entry.isCommand then (program binArgs) else (package libArgs);

in
{ src, path, deps ? [ ] }:
let
  # Build a map of dependencies (from their import paths to their
  # derivation) so that they can be conditionally imported only in
  # sub-packages that require them.
  depMap = listToAttrs (map
    (d: {
      name = d.goImportPath;
      value = d;
    })
    (map (d: d.gopkg) deps));

  name = pathToName path;
  analysisOutput = runCommand "${name}-structure.json" { } ''
    ${analyser}/bin/analyser -path ${path} -source ${src} > $out
  '';
  # readFile adds the references of the read in file to the string context for
  # Nix >= 2.6 which would break the attribute set construction in fromJSON
  analysis = fromJSON (unsafeDiscardStringContext (readFile analysisOutput));
in
lib.fix (self: foldl' lib.recursiveUpdate { } (
  map (entry: mkset entry.locator (toPackage self src path depMap entry)) analysis
))