experiment with buildGo2, a potential replacement for buildGo
This commit is contained in:
parent
8141fbfccf
commit
d666e85223
12 changed files with 319 additions and 0 deletions
6
go/buildgo2/asm/add.S
Normal file
6
go/buildgo2/asm/add.S
Normal file
|
@ -0,0 +1,6 @@
|
|||
TEXT ·Add(SB),$0-24
|
||||
MOVQ x+0(FP), BX
|
||||
MOVQ y+8(FP), BP
|
||||
ADDQ BP, BX
|
||||
MOVQ BX, ret+16(FP)
|
||||
RET
|
3
go/buildgo2/asm/buildgo2.go
Normal file
3
go/buildgo2/asm/buildgo2.go
Normal file
|
@ -0,0 +1,3 @@
|
|||
package asm
|
||||
|
||||
func Add(x, y int64) int64
|
7
go/buildgo2/asm/default.nix
Normal file
7
go/buildgo2/asm/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{ depot, ... }:
|
||||
|
||||
depot.third_party.buildGo2.package {
|
||||
name = "asm";
|
||||
path = "hg.lukegb.com/lukegb/depot/go/buildgo2/asm";
|
||||
srcs = [ ./buildgo2.go ./add.S ];
|
||||
}
|
6
go/buildgo2/cgo/cgo.c
Normal file
6
go/buildgo2/cgo/cgo.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <stdint.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
int64_t add(int64_t x, int64_t y) {
|
||||
return AddInternal(x + y, 0);
|
||||
}
|
14
go/buildgo2/cgo/cgo.go
Normal file
14
go/buildgo2/cgo/cgo.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package cgo
|
||||
|
||||
// #include "cgo.h"
|
||||
import "C"
|
||||
|
||||
func Add(x, y int64) int64 {
|
||||
return int64(C.add(C.int64_t(x), C.int64_t(y)))
|
||||
}
|
||||
|
||||
//export AddInternal
|
||||
func AddInternal(x, y int64) int64 {
|
||||
|
||||
return x + y
|
||||
}
|
4
go/buildgo2/cgo/cgo.h
Normal file
4
go/buildgo2/cgo/cgo.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
int64_t add(int64_t x, int64_t y);
|
8
go/buildgo2/cgo/default.nix
Normal file
8
go/buildgo2/cgo/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{ depot, ... }:
|
||||
|
||||
depot.third_party.buildGo2.package {
|
||||
name = "cgo";
|
||||
path = "hg.lukegb.com/lukegb/depot/go/buildgo2/cgo";
|
||||
srcs = [ ./cgo.go ./cgo.h ./cgo.c ];
|
||||
cgo = true;
|
||||
}
|
13
go/buildgo2/default.nix
Normal file
13
go/buildgo2/default.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{ depot, ... }@args:
|
||||
|
||||
let
|
||||
asm = import ./asm args;
|
||||
cgo = import ./cgo args;
|
||||
in
|
||||
depot.third_party.buildGo2.program {
|
||||
name = "buildgo2";
|
||||
srcs = [ ./main.go ];
|
||||
deps = [ asm ];
|
||||
} // {
|
||||
inherit asm cgo;
|
||||
}
|
14
go/buildgo2/main.go
Normal file
14
go/buildgo2/main.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"hg.lukegb.com/lukegb/depot/go/buildgo2/asm"
|
||||
//"hg.lukegb.com/lukegb/depot/go/buildgo2/cgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("hi")
|
||||
fmt.Printf("asm: 2 + 3 = %d\n", asm.Add(2, 3))
|
||||
//fmt.Printf("cgo: 2 + 3 = %d\n", cgo.Add(2, 3))
|
||||
}
|
|
@ -15,4 +15,6 @@ args: {
|
|||
access = import ./access args;
|
||||
vault = import ./vault args;
|
||||
tumblrandom = import ./tumblrandom args;
|
||||
|
||||
buildgo2 = import ./buildgo2 args;
|
||||
}
|
||||
|
|
1
third_party/default.nix
vendored
1
third_party/default.nix
vendored
|
@ -125,6 +125,7 @@ rec {
|
|||
|
||||
bat_syntaxes = tvlDepot.third_party.bat_syntaxes;
|
||||
cheddar = tvlDepot.tools.cheddar;
|
||||
buildGo2 = tvlDepot.nix.buildGo2;
|
||||
naersk = nixpkgs.callPackage naerskSrc {};
|
||||
|
||||
crate2nix = import "${crate2nixSrc}" { pkgs = ch.depot.pkgs; };
|
||||
|
|
241
third_party/tvl/nix/buildGo2/default.nix
vendored
Normal file
241
third_party/tvl/nix/buildGo2/default.nix
vendored
Normal file
|
@ -0,0 +1,241 @@
|
|||
# Copyright 2019 Google LLC.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# buildGo provides Nix functions to build Go packages in the style of Bazel's
|
||||
# rules_go.
|
||||
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (pkgs) lib;
|
||||
|
||||
go = pkgs.go;
|
||||
goStdlib = buildStdlib { inherit go; };
|
||||
|
||||
splitSources = srcs: let
|
||||
# exts: { typeName = [ extension ] };
|
||||
exts = {
|
||||
go = [ ".go" ];
|
||||
asm = [ ".s" ".S" ];
|
||||
headers = [ ".h" ".hh" ".hpp" ".hxx" ".inc" ];
|
||||
c = [ ".c" ];
|
||||
cxx = [ ".cc" ".cxx" ".cpp" ];
|
||||
objc = [ ".m" ".mm" ];
|
||||
};
|
||||
# [ extension ] -> { extension = true; }
|
||||
extListToAttrs = exts: builtins.listToAttrs (builtins.map (v: lib.attrsets.nameValuePair v true) exts);
|
||||
# exts': { typeName = { extension = true; } };
|
||||
exts' = builtins.mapAttrs (_: extListToAttrs) exts;
|
||||
|
||||
allExts = lib.lists.flatten (builtins.attrValues exts);
|
||||
allExts' = extListToAttrs allExts;
|
||||
|
||||
matchesExts = exts: src: let
|
||||
srcExtList = builtins.match ".*([.][^.]+)$" (toString src);
|
||||
srcExt = builtins.elemAt srcExtList 0;
|
||||
in
|
||||
srcExtList != null && exts ? "${srcExt}";
|
||||
splitByExt = exts: builtins.filter (matchesExts exts) srcs;
|
||||
|
||||
leftovers = builtins.filter (src: !(matchesExts allExts' src)) srcs;
|
||||
in assert (lib.assertMsg (builtins.length leftovers == 0) "uncategorisable files: ${toString leftovers}"); builtins.mapAttrs (name: value: splitByExt value) exts';
|
||||
|
||||
importconfig = { name, deps }: let
|
||||
# Go through every dep and generate a packagefile importpath=${output}.
|
||||
depPackagefiles = map (dep: if dep ? importpath then "packagefile ${dep.importpath}=${dep}/pkg.a" else "") deps;
|
||||
in ''
|
||||
# nix buildGo ${name}
|
||||
${builtins.concatStringsSep "\n" depPackagefiles}
|
||||
'';
|
||||
|
||||
buildStdlib = { go }: pkgs.stdenv.mkDerivation {
|
||||
pname = "go-stdlib";
|
||||
inherit (go) version;
|
||||
|
||||
nativeBuildInputs = [ go ];
|
||||
|
||||
unpackPhase = ''
|
||||
HOME=$NIX_BUILD_TOP/home
|
||||
mkdir $HOME
|
||||
|
||||
goroot="$(go env GOROOT)"
|
||||
cp -R "$goroot/src" "$goroot/pkg" .
|
||||
'';
|
||||
dontConfigure = true;
|
||||
buildPhase = ''
|
||||
chmod -R +w .
|
||||
GODEBUG=installgoroot=all GOROOT=$NIX_BUILD_TOP go install -v --trimpath std
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
cp -r pkg/*_*/* $out
|
||||
|
||||
find $out -name '*.a' | while read -r ARCHIVE_FULL; do
|
||||
ARCHIVE="''${ARCHIVE_FULL#"$out/"}"
|
||||
PACKAGE="''${ARCHIVE%.a}"
|
||||
echo "packagefile $PACKAGE=$ARCHIVE_FULL"
|
||||
done > $out/importcfg
|
||||
'';
|
||||
dontFixup = true;
|
||||
|
||||
passthru.go = go;
|
||||
};
|
||||
|
||||
package = {
|
||||
name,
|
||||
path,
|
||||
srcs,
|
||||
deps ? [],
|
||||
cgo ? false,
|
||||
cgodeps ? [],
|
||||
go ? goStdlib.go,
|
||||
stdlib ? goStdlib,
|
||||
}@args: assert stdlib != null -> stdlib.go == go; let
|
||||
importcfg = importconfig { inherit name deps; stdlib = go; };
|
||||
|
||||
srcs' = splitSources srcs;
|
||||
stdenv = if cgo then pkgs.stdenv else pkgs.stdenvNoCC;
|
||||
|
||||
cgoSrcs = srcs'.c ++ srcs'.cxx ++ srcs'.objc;
|
||||
noCgoNoC = lib.assertMsg (builtins.length cgoSrcs == 0) "cgo source files present, but cgo not set to true: ${toString cgoSrcs}";
|
||||
|
||||
baseNameOnly = map (f: baseNameOf (toString f));
|
||||
in assert !cgo -> noCgoNoC; stdenv.mkDerivation rec {
|
||||
inherit name;
|
||||
__structuredAttrs = true;
|
||||
|
||||
buildInputs = cgodeps;
|
||||
nativeBuildInputs = [ go ] ++ (if cgo then [ pkgs.pkg-config ] else []);
|
||||
|
||||
passthru = {
|
||||
importpath = path;
|
||||
inherit importcfg stdlib;
|
||||
cgo = cgo || lib.lists.any (x: x.cgo) deps;
|
||||
};
|
||||
|
||||
importcfg = importconfig { inherit name deps; };
|
||||
allSrcs = srcs;
|
||||
goSrcs = baseNameOnly srcs'.go;
|
||||
asmSrcs = baseNameOnly srcs'.asm;
|
||||
cSrcs = baseNameOnly srcs'.c;
|
||||
cxxSrcs = baseNameOnly srcs'.cxx;
|
||||
objcSrcs = baseNameOnly srcs'.objc;
|
||||
|
||||
unpackPhase = ''
|
||||
mkdir src
|
||||
${builtins.concatStringsSep "\n" (map (f: ''
|
||||
cp "${f}" "src/${baseNameOf (toString f)}"
|
||||
'') srcs)}
|
||||
cd src
|
||||
'';
|
||||
configurePhase = ''
|
||||
echo "$importcfg" > $NIX_BUILD_TOP/importcfg
|
||||
${if stdlib != null then ''
|
||||
cat ${stdlib}/importcfg >> $NIX_BUILD_TOP/importcfg
|
||||
'' else ""}
|
||||
for dep in deps; do
|
||||
if [[ ! -f "$dep/importcfg" ]]; then continue; fi
|
||||
cat $dep/importcfg >> $NIX_BUILD_TOP/importcfg
|
||||
done
|
||||
'';
|
||||
buildPhase = ''
|
||||
mkdir -p $out
|
||||
completeFlag="${if cgo then "" else "-complete"}"
|
||||
outputFlag="-o $out/pkg.a"
|
||||
if [ ''${#asmSrcs[@]} -gt 0 ]; then
|
||||
completeFlag=""
|
||||
mkdir $NIX_BUILD_TOP/pack $NIX_BUILD_TOP/include
|
||||
outputFlag="-symabis $NIX_BUILD_TOP/goasm.abi -o $out/pkg.a -asmhdr $NIX_BUILD_TOP/include/go_asm.h"
|
||||
|
||||
touch $NIX_BUILD_TOP/include/go_asm.h
|
||||
|
||||
ASMCMD="go tool asm -trimpath $NIX_BUILD_TOP/src -I $NIX_BUILD_TOP/include -I $(go env GOROOT)/pkg/include -D GOOS=$(go env GOOS) -D GOOS_$(go env GOOS) -D GOARCH=$(go env GOARCH) -D GOARCH_$(go env GOARCH) -p ${path}"
|
||||
$ASMCMD -gensymabis -o $NIX_BUILD_TOP/goasm.abi "''${asmSrcs[@]}"
|
||||
fi
|
||||
${if cgo then ''
|
||||
mkdir $NIX_BUILD_TOP/cgo $NIX_BUILD_TOP/cgo_built
|
||||
go tool cgo -objdir $NIX_BUILD_TOP/cgo -trimpath $NIX_BUILD_TOP/src -importpath "${path}" -- "''${goSrcs[@]}"
|
||||
for f in "''${cSrcs[@]}"; do
|
||||
$CC -I$NIX_BUILD_TOP/cgo -I. -c "$f" -o "$NIX_BUILD_TOP/cgo_built/''${f}.o"
|
||||
done
|
||||
for f in "''${cxxSrcs[@]}"; do
|
||||
$CXX -I$NIX_BUILD_TOP/cgo -I. -c "$f" -o "$NIX_BUILD_TOP/cgo_built/''${f}.o"
|
||||
done
|
||||
for f in "''${objcSrcs[@]}"; do
|
||||
$OBJC -I$NIX_BUILD_TOP/cgo -I. -c "$f" -o "$NIX_BUILD_TOP/cgo_built/''${f}.o"
|
||||
done
|
||||
pushd $NIX_BUILD_TOP/cgo &>/dev/null
|
||||
for f in *.cgo2.c _cgo_export.c _cgo_main.c; do
|
||||
$CC -I$NIX_BUILD_TOP/src -c "$f" -o ''${f}.o
|
||||
done
|
||||
$CC -o _cgo_.o _cgo_main.c.o _cgo_export.c.o $NIX_BUILD_TOP/cgo_built/*.o *.cgo2.c.o
|
||||
popd &>/dev/null
|
||||
go tool cgo -dynpackage "${name}" -dynimport $NIX_BUILD_TOP/cgo/_cgo_.o -dynout $NIX_BUILD_TOP/cgo/_cgo_imports.go
|
||||
shopt -s nullglob
|
||||
goSrcs=($NIX_BUILD_TOP/cgo/*.go)
|
||||
'' else ""}
|
||||
go tool compile $completeFlag -importcfg $NIX_BUILD_TOP/importcfg -trimpath $NIX_BUILD_TOP/src -pack -p "${path}" $outputFlag "''${goSrcs[@]}"
|
||||
if [ ''${#asmSrcs[@]} -gt 0 ]; then
|
||||
$ASMCMD -o $NIX_BUILD_TOP/pack/goasm.o "''${asmSrcs[@]}"
|
||||
go tool pack r $out/pkg.a $NIX_BUILD_TOP/pack/*.o
|
||||
fi
|
||||
${if cgo then ''
|
||||
go tool pack r $out/pkg.a $NIX_BUILD_TOP/cgo/*.cgo2.c.o $NIX_BUILD_TOP/cgo/_cgo_export.c.o $NIX_BUILD_TOP/cgo_built/*.o
|
||||
'' else ""}
|
||||
'';
|
||||
};
|
||||
|
||||
program = {
|
||||
name,
|
||||
deps ? [],
|
||||
...
|
||||
}@args: let
|
||||
pkg = package (args // {
|
||||
name = "${name}-lib";
|
||||
path = "main";
|
||||
});
|
||||
cgo = pkg.cgo;
|
||||
stdenv = if cgo then pkgs.stdenv else pkgs.stdenvNoCC;
|
||||
in stdenv.mkDerivation rec {
|
||||
inherit name;
|
||||
__structuredAttrs = true;
|
||||
|
||||
nativeBuildInputs = [ go ];
|
||||
|
||||
lib = pkg;
|
||||
inherit (pkg) importcfg stdlib;
|
||||
|
||||
dontUnpack = true;
|
||||
configurePhase = ''
|
||||
echo "$importcfg" > importcfg
|
||||
${if stdlib != null then ''
|
||||
cat ${stdlib}/importcfg >> importcfg
|
||||
'' else ""}
|
||||
'';
|
||||
buildPhase = ''
|
||||
mkdir out
|
||||
go tool link -importcfg importcfg -tmpdir "$TMPDIR" -o "out/bin" -s -w $lib/pkg.a
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp out/bin "$out/bin/${name}"
|
||||
'';
|
||||
};
|
||||
|
||||
external = {
|
||||
src,
|
||||
path,
|
||||
deps ? [ ],
|
||||
tags ? [ ],
|
||||
cgo ? false,
|
||||
cgodeps ? [ ],
|
||||
cgocflags ? [ ],
|
||||
cgoldflags ? [ ],
|
||||
}: {};
|
||||
in
|
||||
{
|
||||
#inherit program package proto external;
|
||||
inherit goStdlib package program external;
|
||||
}
|
Loading…
Reference in a new issue