Yocto supports Golang recipes, but they are slightly different to standard ones.
Simple Recipe
For a basic recipe without any dependancies, it is still quite simple.
SUMMARY = "This is a simple example recipe that cross-compiles a Go program." SECTION = "examples" HOMEPAGE = "https://golang.org/" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI = "git://go.googlesource.com/example;branch=master;protocol=https" SRCREV = "32022caedd6a177a7717aa8680cbe179e1045935" UPSTREAM_CHECK_COMMITS = "1" inherit go GO_IMPORT = "golang.org/x/example" GO_INSTALL = "${GO_IMPORT}/hello" # New Go versions has Go modules support enabled by default export GO111MODULE="off" # This is just to make clear where this example is do_install:append() { mv ${D}${bindir}/hello ${D}${bindir}/${BPN} }
Some of the key things that are different with a Golang recipe:
You need to inherit go
(to bring in the go class) and tell BitBake that this is a Golang recipe.
You need to set the GO_IMPORT
variable. This is because the GOPATH is created at ${WORKDIR}/${BPN}-${PV}
and so source code is not downloaded to ${WORKDIR}/${BPN}-${PV}/src/
but to ${WORKDIR}/${PN}-${PV}/src/${GO_IMPORT}
.
Note also, the resulting binary gets placed in /usr/bin.
A More Complex Golang Recipe with Module Dependancies
When your Golang project contains dependancies, it becomes a little more complex. As BitBake does not access the network outside of the do_fetch()
task, it does not pull down the dependancies within the source code. This means you need to include all of the dependant modules in your SRC_URI
.
SUMMARY = "This is a simple example recipe that cross-compiles a Go program."
SECTION = "examples"
HOMEPAGE = "https://golang.org/"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
PV = "1.0"
PR = "r0"
inherit go
GO_IMPORT = "github.com/ming4real/ini-demo"
# New Go versions has Go modules support enabled by default
export GO111MODULE="off"
S = "${WORKDIR}/git"
SRC_URI = " \
git://git@github.com/ming4real/ini-demo.git;branch=main;protocol=ssh;name=demo \
git://git@github.com/go-ini/ini.git;branch=main;protocol=ssh;name=goini;destsuffix=git/src/gopkg.in/ini.v1 \
"
SRCREV_FORMAT = "demo"
SRCREV_demo = "${AUTOREV}"
SRCREV_goini = "${AUTOREV}"
UPSTREAM_CHECK_COMMITS = "1"
# This is just to make clear where this example is
do_install:append() {
install -d ${D}/usr/local/bin
mv ${D}${bindir}/ini-demo ${D}/usr/local/bin/${BPN}
}
FILES:${PN} += " \
/usr/bin \
/usr/local/bin/${BPN} \
"
The two main changes you need to make are:
Name your Sources
Because there are multiple SRC_URI
s, each one needs a unique name so that we can identify it to specify the SRCREV
s individually. this is done with the ;name=XXX
parameter in the URI.
This also allows you to have individual licences for each source if that is required.
Specify the Destination
Because each package has its GO_IMPORT value, we need to manually place the module into the working tree. This is done with the destsuffix=XXX
parameter, where XXX will be git/src/<Module Path>
. The module path is the one found in the go.mod
file of your project.
As a side note, I have moved my binary to /usr/local/bin
out of personal preference to keep things that I create separate from ‘standard’ Linux binaries.