Skip to content

Instantly share code, notes, and snippets.

@cfstras
Last active January 30, 2024 14:44
Show Gist options
  • Save cfstras/68619148f869474259eb to your computer and use it in GitHub Desktop.
Save cfstras/68619148f869474259eb to your computer and use it in GitHub Desktop.
Ultimate Golang Build Tool, v2

Note (2024): This was written before Go had modules and workspaces, and even before tools like go dep and go vendor were mainstream. Nowadays, I don't think there's a good reason to use this, but it's still interesting to read for history purposes (IMO).


Intro

I like Go, especially the build system. But what I don't like is the build system:

$ go test
cannot load package: package github.com/cfstras/lfmnn: no buildable Go source files in /home/claus/vcs/go/src/github.com/cfstras/lfmnn

Oh, right, I don't want to test the root package, I want to test all of the packages!

$ go test ...
... time passes ...
^C

This tries to test every package in $GOPATH.

$ go test ./...
bars/bars.go:7:2: cannot find package "github.com/cfstras/go-utils/math" in any of:
... (a lot of missing packages)

Forgot to get my dependencies! Okay, here we go...

$ go get
cannot load package: package github.com/cfstras/lfmnn: no buildable Go source files in /home/claus/vcs/go/src/github.com/cfstras/lfmnn

Wait, damn.
Ah! Something something ...

$ go get ...
package 1.... 2... 3... 4... 5..... ^C

I should have learned from my mistakes -- This gets dependencies for every package in $GOPATH.

$ go get ./...

Okay, now we're ready!

$ go test ./...
error, still packages missing

aaargghhh

$ go get -t ./... # (I'm getting tired of this...)

Final chance...

$ go test ./...
?   	github.com/cfstras/lfmnn/bars	[no test files]
?   	github.com/cfstras/lfmnn/cmd/fmnn	[no test files]
?   	github.com/cfstras/lfmnn/cmd/load	[no test files]
?   	github.com/cfstras/lfmnn/cmd/stat	[no test files]
?   	github.com/cfstras/lfmnn/cmd/testnn	[no test files]
?   	github.com/cfstras/lfmnn/config	[no test files]
?   	github.com/cfstras/lfmnn/ffnn	[no test files]
?   	github.com/cfstras/lfmnn/load	[no test files]

Ok, there are no tests in here. But still.

Back in node.js world, there was npm and you just did

npm install
npm test
npm start

I want that!

b

So, ./b was born. Why a checked-in-script and not a go get-able tool?

  • self-advertisement
  • does not clog up $PATH

I tried using shebang-magic to make a go script, but until now have not found a solution that yields a single file which executes like a script.
Hints?

Prerequisites

A tree like this:

somesite.com/userbla/packagebla/
    ├── blah_support
    │   ├── lib.go
    │   └── lib_test.go
    ├── bleh_blah_blub
    │   ├── init.go
    │   ├── structs.go
    │   └── bleh_test.go
    ├── cmd
    │   ├── util_blub
    │   │   └── main.go
    │   └── util_bleh
    │       └── main.go
    └── README.md

Installing

wget cfs.im/b
chmod a+x b

Using

./b 		get deps & build all packages in cmd/ to bin/
./b update	update deps for all packages in cmd/
./b run <x>	build & run cmd x
./b clean	clean bin

For example:

mkdir -p cmd/hello
echo > cmd/hello/main.go <<EOF
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
EOF

$ ./b run hello
Hello, World!

https://gist.github.com/cfstras/68619148f869474259eb

#!/bin/bash
# Go build tool, v2 by cfstras
# http://cfs.im/b.html
FOLDERS=$(find . -type d | cut -c3-)
CMDS=$(ls cmd)
function build() {
echo "# ./cmd/$1"
go get -d -v -t ./cmd/$1
go build -v -o bin/$1 ./cmd/$1
}
case "$1" in
"")
for i in $CMDS; do
build $i
done
;;
update)
for i in $CMDS; do
echo "# $i"
go get -d -u -v -t ./cmd/$i
done
;;
run)
if [[ "$2" == "" ]]; then
echo "possibilities:"
for i in $CMDS; do
echo " $i"
done
echo "which one?"
else
pkg=$2
shift; shift
build $pkg && bin/$pkg $@
fi
;;
clean)
rm -rf bin
;;
fix)
[[ -x $GOPATH/bin/goimports ]] || go get \
code.google.com/p/go.tools/cmd/goimports
$GOPATH/bin/goimports -l -w $FOLDERS
for f in $(find . -type f -not -path "*/Godeps/*" -a -name "*.go"); do \
go fix "$f"; \
go tool vet -composites=false "$f"; \
done
;;
help)
cat <<EOF
ultimate go build cmd, v2
usage:
./b get deps & build all packages in cmd/ to bin/
./b update update deps for all packages in cmd/
./b run <x> [args] build & run cmd x
./b clean clean bin
./b fix run goimports, go fix and vet on cmd/
EOF
;;
esac
@cfstras
Copy link
Author

cfstras commented Nov 2, 2015

installing:

curl -O cfs.im/b
chmod +x ./b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment