-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/go: go.mod: using environment variable for replacement #27824
Comments
Why not fix this with tooling? For example, have you tried @rogpeppe's https://github.com/rogpeppe/gohack? |
What is the underlying problem you want to solve? Customization hooks add complexity, to both the implementation and the user-facing documentation, and the documentation for modules is already much more complex than I'd like. We should only add hooks if they provide a substantial enough benefit to offset that complexity, so we need to understand the concrete benefit you're hoping to provide. |
@bcmills The underlying idea of adding For example of this: module example
require example.io/foo v0
replace example.io/foo => /path/to/my/module/base It works for one dev, but complains for the other having The other benefits of having $ go build and $ MYDIR=/my/module/base go build should work perfectly for this module differently: module example
using env MYDIR /default/module/base
require example.io/foo v0.0.0
replace example.io/foo => $MYDIR/foo I'm not sure if I understand the customization hooks you mentioned. But I think such This brings great flexibility when using Such an improvement will allow authors to define their own project-specific building variables ( Introducing the |
I would consider creating a "template" file such as |
@dmitris @bcmills I think when we're building a When we're building directly, aka. typing #!/bin/bash
# helper build script `build.sh`
sed 's|MYDIR|/a/variable/location/calculated/somehow|' > go.mod && go build # helper `makefile` working with `make`
build:
# do something to fix the `go.mod` file
go build It will definitely work and shouldn't be very difficult to apply. Or the author could also ask the audience to fix the When we're building indirectly, a hardcoded replacement should be easily fixed by other build systems, for example of Another benefit when we have # .bash_profile
GOPATH=/my/favorite/go/path
MYDIR=/my/favorite/project/path
MYFOO=/my/favorite/project/third_party/foo So that the $ go build -o were_all_happy This is very important when our required module is too deep in the require graph. It's really frustrating to $ MYFOO=/dont/complain/please go build -o all_right or
Questions
|
@duzy, I still don't understand what concrete problem you want to address with these
|
@bcmills The
module foo
require example.io/bar
replace example.io/bar /my/local/source/bar This works perfectly me, but not for all in-house devs. Because devs could place module foo
using env MYPAT /my/local/source
require example.io/bar
replace example.io/bar $MYPAT/bar If this works in
module foo
using env MYPAT /my/local/source
require example.io/third/bar
replace example.io/third/bar $MYPAT/bar I believe there could have many cases of using I wish this help you to find out why the proposal useful. |
@bcmills By the way, I have another proposal which is more interesting. But I'm not sure if you like to add it. The second proposal is inspired by For example, say if we have the package package modinfo // or any special name preferred
import (
"go/mod"
)
func init() {
var s = "example.io/third/bar"
// do any calculation for `s`...
mod.Require(s)
} Or package modinfo // or any special name preferred
import (
"go/tooling"
)
func GoRequire(m *tooling.Mod) {
var s = "example.io/third/bar"
// do any calculation for `s`...
m.Require(s)
}
func GoBuild(b *tooling.Build) {
b.Run()
} In Go code like this, we're possible to do anything we want! All we need to do is to populate $ go build # it calls GoRequire and GoBuild This approach could allow us to complete very much more interesting jobs related to building. |
@duzy - if this is all in-house, why not put everything in a single repo? Then this problem goes away entirely, as does the overhead of maintaining separate repos. Especially if you are checking in If these |
In general the expectation is that those be published somewhere, even if it's only accessible within your local network. (For example, if your company is If you need to edit those modules simultaneously, well-known environment variables don't seem like a scalable solution: if you need to fix an upstream module, how would you know which variables you need to set to work on it? I'd rather we address that use-case directly; see #27542.
That should be fine today: the target of a
I believe you can already do that today using a Git |
@myitcv I think in-house (office) development and separating the system into multiple repos (packages) are two different kind of problems. To decide whether you should go all in the same repos or split the system into many, it's up to the scale of the project or the design principle of the system. To me, if a part of the system is reusable to others or useful (feature) in the future, I would consider move it into a new package. It could make thing easier rather then introducing maintaining costs. In-house is not a good suggestion that everything should be in one repos. The changes to those I think yes, if you're not going to add my second proposal, I'm interested to make it possible through the |
@bcmills Ideally, yes, by having our own
I think git hook could be a solution too. But I prefer to see if my second proposal is possible now as it's more interesting than So could you please give me some suggestions on how to implement this idea: package foo_tooling
import (
// or "cmd/go/tooling" to make use of some features in "cmd/go/internal"
// without an official tooling package, we might use the "gohack" approach or just
// move custom implementation into "cmd/go" to make use of the cmd/go/internal
"go/tooling"
)
// helps build, get, download, etc.
func GoRequire(a *tooling.Action) {
// a.Name == "build", "get", "download"...
var s = "example.io/third/bar"
var ver = "v0.0.0-20181818000000-xxxxxxxx"
// do any calculation for `s`...
a.Require(s, ver)
}
// go build
func GoBuild(b *tooling.Build) {
// do something meaningful here...
b.Run()
} Which work with |
Just so we're not talking past each other on a couple of points. In a pre-modules world, the repository was the unit of versioning. Repositories contain multiple (related) packages. In the world of Go modules, a module is a collection of related packages. The module is the unit of versioning. A repo can contain multiple modules. So my suggestion about moving towards a mono-repo is really motivated by the fact that Go modules enable multi-module repos, and it sounds like you have/need multiple modules. Of course you don't need to have multiple modules to justify a mono repo.
Please can you share a few more details on your workflow? Because I can't see a reason for If they are more permanent it suggests to me you aren't relying on the version requirement relationship between modules, and instead using
If you do need multiple modules, then yes, I think the |
I think we have the common understanding on these (modules, repos, packages). Just in the context of my case, I placed my common reusable packages in a place like the
I think your suggestion is very positive and useful actually and the motivation is rational to me. I really appreciate that and I'm very happy to talk. I think in my context things are different as I'm not only working with Go modules and go-module is different then repo in my environment. So I think using the term
So as said above, I have commonly shared packages in In Go module environment, things are different as it's not searching into So my pre-module workflow was broken. Luckily the package main
import "example.io/foo/blah" // without Go module and `replace`, it was like "my/foo/blah"
func main() {
blah.Hey()
} And in
This works for me to replace the But the problems came into my mind, why do I hardcode the I found that I'm not the only being troubled at this point. And I learned that someone is using So that module foo
using env MYDIR /local/path/to
require example.io/foo v0.0.0
replace example.io/foo $MYDIR/my/foo This will solve things well: $ MYDIR=/local/alt/path go build -o foo .
The reason why I'd like to look in hack into "cmd/go/internal" is that I wish to make something like The purpose of using package foo_tooling
import "go/tooling" // or "cmd/go/tooling"
func GoRequire(a *tooling.Invocation) {
...
}
func GoBuild(a *tooling.Invocation) {
...
}
func GoDownload(a *tooling.Invocation) {
...
} And the package dir could be like: $ ls
foo.go foo_test.go foo_tooling.go The While using Go code to describe the Go module requirements ( In this The remaining question is that how |
Last I checked a real domain name is $12/yr., and I'm not sure that you even need that: a reserved local IP address (even a loopback address to your local machine!) would suffice, as long as the
I'm not sure what you mean. If you're importing a package from the same repository, you can use relative
“More interesting” is a fine criterion for hobby projects, but it's not a good basis for inclusion in the Go toolchain: we try very hard to do make things “simple” rather than “interesting”. |
A mechanical program to produce a Even environment substitution would add a lot of complexity in order to address a fairly niche use-case. Moreover, there already a lot of alternatives available, such as a local server with I appreciate the thought you've put into this, but we won't be supporting these features in the |
For just building a project, do you think we (users) really need to buy a domain name and set a The old It's nice to see the
The second proposal is just another topic than the Regarding to the I proposed the Thanks again. |
For “just building a project”, I would expect that most users either have a domain name already or use a (free) code hosting service. (If #28835 is accepted, that would potentially enable some other workflows as well, but if you want to interact with a global namespace of modules, at some point you need a unique name within that namespace.)
When I say it “would add a huge amount of complexity”, I mean it would be complex to use, not (just) complex to implement. The more features we add, the more features people have to understand in order to interact with the projects that use them. |
I would be agree with you that the more we add, the more complexity (of using it) it might be. Comparing to the Regarding to using the But I do believe that If I'm going to implement a I like this second approach because it's all in Go, no need to have extra grammars like For a summary:
I think these two principles make me feel interesting on this issue. As it's following the initial saying of Go that Go is making programming interesting again (comparing to C/C++ or other languages). |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?go111
Does this issue reproduce with the latest release?
Not an issue, but a request which should be very useful, especially for local editing.
What did you expect to see?
Looking to introduce a variable for being expended in go.mod:
Or something like this might be better:
This will allow us to specify
MYDIR
working very much like a customGOPATH
.Or sending
MYARG
to go.mod, for example of using-mod-arg
or anything better:The text was updated successfully, but these errors were encountered: