go build -buildvcs does not insert vcs.revision buildinfo - go

This question poses problems that are distinct from those discussed here: How do you read debug VCS version info from a Go 1.18 binary?
I am having trouble getting go build -buildvcs=true to insert correct version information when building executables out of a git repo that has the following structure:
go version go1.18.4 linux/amd64
in project:
go.mod
cmd/exe1/main.go
cmd/exe2/main.go
pkg/pkg1/...
pkg/pkg2/...
(1) If I cd project;go build -buildvcs=true -o /tmp/exe1 cmd/exe1/main.go then the BuildInfo included in the exe includes Deps entries for all the dependencies of all the packages, but there is no embedded Setting with key vcs.revision, and the Dep entry for the module named in go.mod is (devel). I guess this latter issue is related to how to specify versions for modules, which I have not yet looked into, and therefore I assume it's using a default value.
(2) If I cd project/cmd/exe1;go build -buildvcs=true -o /tmp/exe1 (leaving out any relative path specifying what to build) then the BuildInfo included in the exe does NOT include Deps entries but DOES include the vcs.revision
Questions:
Is there any way to get both Deps and vcs.revision into BuildInfo?
Is this directory structure ok? The documentation for this stuff is not in "reference" format, and many important details are spread out throughout all of the tutorials and howtos. Quite frustrating to get to the bottom of these behaviors.
It seems to me go should embed a vcs.revision whenever generating an executable, but before I open a bug, I wanted to get community feedback on whether this is expected behavior when specifying a relative target on the command line. I've seen that that can be an issue in general, with go build.
Any pointers to the right place to read a comprehensive guide about this would be great.

Related

'is not within a known GOPATH/src' error on dep init

When I run dep init in project folder, the error occurs:
init failed: unable to detect the containing GOPATH: D:\projects\foo is not within a known GOPATH/src
My projects are located on another drive and not %GOPATH%/src (i.e. %USERPROFILE%\go\src).
It's a known error but it's unclear what is the solution.
How can I use dep without moving Go projects to %GOPATH%/src?
Go makes this choice so that there is nothing like a CLASSPATH (ie: Java) to deal with. You specify a $GOPATH that has a consistent src tree inside of it. If your repo makes references to particular git commits (rather than the ones checked out into $GOPATH/src/github.com/$githubUser/$githubProjectName), then those will be in the ./vendor directory of your project.
If you have a different Go project that uses a completely different set of checkouts, due to versioning issues, then you can have multiple $GOPATH values to deal with that.
How can I use dep without moving Go projects to %GOPATH%/src?
Not at all.
Go projects require that your project is within its path..
So first do a
$ go env
to find out where that is. Lets say it says /home/turgut/go
move the project that you downloaded that needs the dep to:
/home/turgut/go/src/myproject
then cd /home/turgut/go/src/myproject
and try the
dep ensure
command now.
what does go env command say your GOPATH is? Set GOPATH for your environment as per this doc
Follow steps here https://deployer.org/docs/7.x/installation
you can use this command vendor/bin/dep init instead of dep init

Set Go variable with ldflags conflicts with vendor folder

I'm currently developing a small Go app and I want to set a specific variable (like Version, GitCommit, BuildID...etc.) at build or runtime (with go build or go run) by using the -ldflags option.
Because in my company we have several projects with the same base, I decided to extract the code with these variables in a separate "info" module which could be imported in every project.
Here's my problem, say I'm running the app like this:
go run -ldflags "-X git.mycompany.com/utils/info.Version=1.0.0" app.go
This works well, and the variable is set correctly even though the variable is not part of the "main" app but in a dependency.
Then I decided to deploy the app so I used the new dep tool to generate the vendor folder.
Therefore, the "info" dependency is now in: vendor/git.mycompany.com/utils/info
Now when I run the same command as above, the said variable (Version) is not set anymore.
Am I missing something here ?
As soon as I delete the vendor folder, everything works fine again. It's like this vendor folder is conflicting with the -ldflags option or something.
Thanks in advance!
We had exactly the same problem, after lots of research we stumbled upon the solution in a comment to GitHub issue: cmd/link: -X doesn't work for vendored packages.
Solution: the full path name, relative to $GOPATH should be specified.
It works when developing git.mycompany.com/utils/info because the full path is correct.
It doesn't work for vendored dependencies because the full path from $GOPATH would be like git.mycompany.com/name-of/package/vendor/git.mycompany.com/utils/info.Version=1.0.0
Unfortunately, no documentation seem to be present about this ( for further info look at the issue ) but as Dave Cheney points out in a comment:
this is a side effect of the language way vendoring is implemented

Go dep and forks of libraries

I'm trying to understand how to work with Golang and forks. The situation is the following, I'm writing a library project which depends on library github.com/other/some_dependency, which isn't mine.
Because some_dependency is missing some methods that I need, I fork it to github.com/me/some_dependency. However, I can't just do go get github.com/me/some_dependency, the library references itself so it breaks.
In this article they give a possible solution:
go get github.com/other/some_dependency
cd $GOPATH/src/github.com/other/some_dependency
git remote add fork git#github.com:me/some_dependency
git rebase fork/master
Now, this is hacky at best. There is no way from the code of the library to know that the dependency is coming from a different repo. Anyone doing go get of my library wouldn't manage to make it work.
As dep is expected to be the official dependency manager. I've found how to fix the version:
dep ensure -add github.com/foo/bar#v1.0.0
But I cannot find how to set a different remote. Is is possible to do it?
As an example, in Node.js with npm it is dead simple:
npm install git+https://git#github.com/visionmedia/express.git
If you look at the help you will see this:
<import path>[:alt source URL][#<constraint>]
So to add github.com/foo/bar from location github.com/fork/bar you have to add it like this:
dep ensure -add github.com/foo/bar:github.com/fork/bar
The source location will be added as source attribute in the Gopkg.toml.
Gopkg docs for dependency rules constraint and override

Modifying an imported library in Go

My Problem
Elastic Beats is an open source project for log shippers written in Go. It features several log outputs, including console, Elasticsearch and Redis. I would like to add an output of my own - to AWS Kinesis.
I have cloned the repo to ~/github/beats, and tried building it:
$ cd filebeat; go build main.go
However, it failed due to a missing library which is a part of the project:
main.go:6:2: cannot find package "github.com/elastic/beats/filebeat/cmd" in any of:
/usr/local/go/src/github.com/elastic/beats/filebeat/cmd (from $GOROOT)
/Users/adam/go/src/github.com/elastic/beats/filebeat/cmd (from $GOPATH)
A directory of the project is dependent on a package from the same repo, but instead of looking one directory up the hierarchy it looks in the GOPATH.
So, go get github.com/elastic/beats/filebeat/cmd fetched the code, and now go build main.go works. Changing the code in my GOPATH is reflected in these builds.
This leaves me with an structural inconvenience. Some of my code is at a working directory, and some of it is at my GOPATH and included by the code in my working directory.
I would like to have all my code in a single directory for various reasons, not the least being keeping everything under version control.
What Have I Tried
Mostly searching for the problem. I am quite new to Go, so I might have missed the correct terminology.
My Question
What is the right way to edit the code of an imported library in Go?
One of the recommended ways to work with other's packages is:
Get the sources of the original package:
go get github.com/elastic/beats
As a result you will clone project's git repository to the folder
$GOPATH/src/github.com/elastic/beats
Make some fixes, compile code, fix, compile... When you make go install package will be compiled and installed to your system. When you need merge updates from original repository you can git pull them.
Everything is OK. What's next? How to share your work with others?
Fork project on github, suppose it will be github.com/username/beats
Add this fork as another remote mycopy (or any other name you like) to your local repository
git remote add mycopy git://github.com/username/beats.git
When all is done you can push updated sources to your repo on github
git push mycopy
and then open a pull-request to original sources. This way you can share your work with others. And keep your changes in sync with mainstream.
Previous answers to this question are obsolete when developing projects that using Go Modules.
For projects that using Go Modules, one may use the following command to replace an imported library(eg. example.com/imported/module) with a local module(eg. ./local/module):
go mod edit -replace=example.com/imported/module=./local/module
Or by adding the following line into the go.mod file:
replace example.com/imported/module => ./local/module
Reference Docs: https://golang.org/doc/modules/managing-dependencies#unpublished
A project working copy should be checked out into $GOPATH/src/package/import/path - for example, this project should be checked out into /Users/adam/go/src/github.com/elastic/beats. With the project in the correct location, the go tooling will be able to operate on it normally; otherwise, it will not be able to resolve imports correctly. See go help gopath for more info.

Is it best-practise to commit the `BUILD.bazel` files generated by Gazelle?

I have a Go project that uses rules_go (Bazel) to build the project. I'm using Gazelle to generate BUILD.bazel files. Is it considered best-practise to commit the generated BUILD.bazel files into version control? Or is it best-practise to always do bazel run //:gazelle on new checkout and when new files have been added?
Yes, it's generally best practice to commit build files for several reasons.
Build files frequently contain rules, comments, and annotations which are not generated. For example, you might need to write a genrule to replace go generate. Or you might write a test that checks the copyright headers in your source files are up to date. Or you may want to tweak the visibility rules for some of your libraries.
If any repository depends on your repository as a remote, it's convenient to have build files already checked in.
In general, it's nice not to have to re-run Gazelle and similar tools before a build.

Resources