Gogradle is a Gradle plugin. Gradle is a automation build tool working with DSL written in Groovy. Users can write their own build scripts. Here is Gradle documentation.
Before starting your work, you don’t need to install Go and set GOPATH
, of course, there’s no harm if you already did.
gradle
directory/gradlew
file/gradlew.bat
file in this project to the golang project to be builtbuild.gradle
in the golang project to be built with the following content:plugins {
id 'com.github.blindpirate.gogradle' version '0.11.4'
}
golang {
packagePath = 'github.com/your/package' // go import path of project to be built, NOT local file system path!
}
Then, if you are using one of glide/glock/godep/gom/gopm/govendor/gvt/gbvendor/trash/gpm, please run
./gradlew goInit # *nix
gradlew goInit # Windows
to perform a migration. This will tell Gogradle to read the dependency lock file generated by them automatically and import them into build.gradle
. You can generate Gogradle’s own gogradle.lock
later. See Dependency Lock for more details.
Enter root directory of the project and run:
./gradlew goVendor # *nix
gradlew goVendor # Windows
Hereinafter, we will use uniform command form gradlew <task>
on both *nix
and Windows
.
Gogradle will resolve all dependency packages and their transitive dependencies, flatten them, and install them into vendor
according to build.gradle
or gogradle.lock
(which will be talked later). Gogradle sees vendor
as a temporary dependency which contains project-level dependencies. Every time you run this task, Gogradle ensures dependencies in vendor
consistent with build.gradle
or gogradle.lock
. There’re two modes in Gogradle: REPRODUCIBLE
and DEVELOP
(REP
and DEV
for abbreviation). In DEVELOP
mode, Gogradle will resolve dependencies declared in build.gradle
; in REPRODUCIBLE
mode, Gogradle will resolve dependencies locked in gogradle.lock
(if it exists). Default mode is REPRODUCIBLE
. To switch mode, add a command line argument to any task:
gradle xxx -Dgogradle.mode=DEV
or gradle xxx -Dgogradle.mode=DEVELOP
(DEVELOP
mode)
and
gradle xxx -Dgogradle.mode=REP
or gradle xxx -Dgogradle.mode=REPRODUCIBLE
(REPRODUCIBLE
mode)
You can decide whether to check in vendor
directory. Personally, I recommend against it.
./gradlew goBuild # *nix
gradlew goBuild # Windows
goBuild
task depends on resolveBuildDependencies
task. Therefore, even you never specify resolveBuildDependencies
task, it will be executed by Gogradle first, which is similar to make
. That is to say, when build
starts, resolveBuildDependencies
task has already been executed and all dependency packages have been installed into vendor
. By default, build
is equivalent to run go build <current package path> -o <output location>
. To configure the build, see goBuild任务.
Enter root directory of the project and run:
gradlew goTest
If you want to specify some tests:
gradlew goTest --tests main_test.go // Specify a single test
gradlew goTest --tests *_test.go // Wildcard test
If you want to let build depend on test, just add the following line to build.gradle
:
goBuild.dependsOn goTest
Test reports will be generated in <project root>/.gogradle/reports/test
. See goTest task for more details.
If you want to define some custom tasks, I recommend reading Gradle documentation of task mechanism. It’s similar to make
rule but more flexible and powerful.
For example, to add a task to run golint
, add following lines to build.gradle
:
task golint(type: com.github.blindpirate.gogradle.Go) {
dependsOn goVendor // make this task depend on vendor task to guarantee all dependency packages are installed into vendor
environment MY_OWN_ENV1: 'value1', MY_OWN_ENV2: 'value2' // set environment variables
run 'golint github.com/my/project' // specify the command in task
}
goCheck.dependsOn golint
Note that stdout/stderr
redirection and pipe is not available. To do a redirection, e.g., a cross-platform tee
, you should use closure
in Groovy
:
task myTee(type: com.github.blindpirate.gogradle.Go){
dependsOn goVendor // make this task depend on vendor task to guarantee all dependency packages are installed into vendor
go('build -v github.com/my/project') {
stdout { stdoutLine ->
println stdoutLine
new File('stdout.txt').append(stdoutLine)
}
stderr { stderrLine ->
println stderrLine
new File('stderr.txt').append(stderrLine)
}
}
}
And more simple:
task myTee(type: com.github.blindpirate.gogradle.Go){
dependsOn goVendor // make this task depend on vendor task to guarantee all dependency packages are installed into vendor
go('build -v github.com/my/project') {
stdout writeTo('stdout.txt')
stderr appendTo('/this/is/absolute/path/stderr.txt')
}
}
This code snippet tells Gogradle to run build -v github.com/my/project
, and write standard out into stdout.txt
in project root and append standard error to /this/is/absolute/path/stderr.txt
.
Here is a cross-platform /dev/null
:
task outputToDevNull(type: com.github.blindpirate.gogradle.Go){
dependsOn goVendor // make this task depend on vendor task to guarantee all dependency packages are installed into vendor
go('build -v github.com/my/project') {
stdout devNull()
stderr devNull()
}
doLast {
if(exitValue!=0){
println "return code is ${exitValue}"
}
}
}
It tells Gogradle to run go build -v github.com/my/project
and discard all standard out and standard error. If go
process’s return value is not zero, print it. You might have doubts, why not use Shell
and make
instead of such long code?
The answer is:
Shell
has a bad compatibility on multiple platformsTo add a dependency package, just add its name and version into dependencies
block of build.gradle
:
dependencies {
golang {
build 'github.com/a/b@v1.0.0'
test 'github.com/c/d#d3fbe10ecf7294331763e5c219bb5aa3a6a86e80'
}
}
The build
and test
are two independent dependency sets. Java developer should be familiar with the concept. By default, build
dependes on resolveBuildDependencies
, thus when build
runs, only build
dependencies exist in vendor
; test
depends on both resolveBuildDependencies
and resolveTestDependencies
, thus when test
runs, both build
and test
dependencies exist in vendor
.
To learn more details about dependency, see Dependency Management.
gradlew goDependencies
The output is as follows:
build:
github.com/aws/aws-sdk-go
|-- github.com/go-ini/ini:e7fea39
|-- github.com/jmespath/go-jmespath:bd40a43
\-- golang.org/x/tools:bf4b54d
|-- golang.org/x/crypto:0fe9631
\-- golang.org/x/net:5139290
|-- golang.org/x/crypto:0fe9631 (*)
\-- golang.org/x/text:19e5161
\-- golang.org/x/tools:bf4b54d -> bf4b54d (*)
test:
github.com/aws/aws-sdk-go
\-- github.com/stretchr/testify:4d4bfba
|-- github.com/davecgh/go-spew:04cdfd4
|-- github.com/pmezard/go-difflib:d8ed262
\-- github.com/stretchr/objx:cbeaeb1
This is dependency tree of aws-sdk-go at 31484500fe
.
Arrow ->
indicates that the dependency conflicts with another dependency and is resolved to another version; star *
indicates this node’s descendants are ignored because they have been displayed before.
gradlew goLock
This command will let Gogradle generate a gogradle.lock
file in project root directory, which records all dependencies of this project.
gogradle.lock
is recommended by Gogradle. Locking dependencies play an important role in reproducible build. Similar to other package management tools, Gogradle can lock the versions of all dependency packages. Moreover, Gogradle can lock dependency packages even when they are in vendor
!
Gogradle supports transitive dependency/dependency exclusion/customized url, see Dependency Management.
Currently, only Git and Mercurial dependencies are supported, support for other vcs is under development.
The following complete configuration is located in golang
block of build.gradle
.
golang {
// Import path of package to be built
packagePath = 'github.com/user/project'
// The buid mode. There are two alternatives: DEVELOP/REPRODUCIBLE, REPRODUCIBLE by default
// This configuration will be overwritten by command line argument -Dgogradle.mode
// REP/DEV for abbreviation
buildMode = 'REPRODUCIBLE'
// The Go version to use. See https://golang.org/dl/
// If not specified, Gogradle will find local go process. If not found, the latest version will be downloaded and installed automatically
// If specified, Gogradle will check if local go version matches the specific version. If not, the specific version will be downloaded and installed automatcally
goVersion = '1.8.1'
// Default value is "go". Modify this when go is not in $PATH
// You can use goExecutable = 'IGNORE_LOCAL' to ignore local go forcibly
goExecutable = '/path/to/go/executable'
// For custom distribution repository. Gogradle will try to download go distributions from
// http://golangtc.com/static/go/${version}/go${version}.${os}-${arch}${extension}
goBinaryDownloadTemplate == 'http://golangtc.com/static/go/${version}/go${version}.${os}-${arch}${extension}'
// If not set, GOROOT will be <directory of go binary>/..
goRoot = '/path/to/my/goroot'
// aka. build constraint. See https://golang.org/pkg/go/build/#hdr-Build_Constraints
buildTags = ['appengine','anothertag']
}