Skip to content
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

Add build tags support #796

Merged
merged 4 commits into from
Sep 10, 2024
Merged

Add build tags support #796

merged 4 commits into from
Sep 10, 2024

Conversation

rgrandl
Copy link
Collaborator

@rgrandl rgrandl commented Sep 4, 2024

go build allows the user to specify build tags. These tags enable the user to discard files based on various tags when they build the application binary.

weaver generate which is a wrapper around go build doesn't allow the user to specify build tags.

This PR adds built tags support for the weaver generate command.

The syntax of passing build tags to the weaver generate command is similar to how build tags are specified when using go build.

E.g.,

weaver generate -tags good,prod
weaver generate --tags=good

@rgrandl rgrandl force-pushed the add_build_tags branch 2 times, most recently from a7cd571 to 874b8bf Compare September 4, 2024 19:49
`go build` allows the user to specify build tags. These tags enable the
user to discard files based on various tags when they build the
application binary.

`weaver generate` which is a wrapper around `go build` doesn't allow the
user to specify build tags.

This PR adds built tags support for the `weaver generate` command.

The syntax of passing build tags to the `weaver generate` command is similar to how build tags are specified when using `go build`.

E.g.,

weaver generate -tags good,prod
weaver generate --tags=good
Copy link
Collaborator

@ghemawat ghemawat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable, just some nits.

@@ -74,11 +74,25 @@ func main() {
switch flag.Arg(0) {
case "generate":
generateFlags := flag.NewFlagSet("generate", flag.ExitOnError)
tags := generateFlags.String("tags", "not specified", "Optional tags for the generate command")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not quite sure why we need "not specified". Can't we just say that if empty, we add no tags except for our internal weaver tag, and if non-empty, we add the specified tags + our internal weaver tag.

If we really need to detect whether or not tags were specified on the command line, a less messy alternative to "not specified" would be to call flags.Visit() to see if it reports "tags" as one of the flags set on the command line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think I implemented this before understanding that I need to define tags as a flag on generateFlags instead of defining a new flag set.

if err := generate.Generate(".", flag.Args()[1:], generate.Options{}); err != nil {
buildTags := "--tags=ignoreWeaverGen"
if *tags != "not specified" { // tags flag was specified
if *tags == "" || *tags == "." {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a special case for "."?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't. Removed all this complicated logic.

// extra validation at some point.
buildTags = buildTags + "," + *tags
}
idx := len(flag.Args()) - len(generateFlags.Args())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to use flag.Args()[idx:] instead passing generateFlags.Args() to generate.Generate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point again.

@@ -54,7 +54,7 @@ const (
Usage = `Generate code for a Service Weaver application.

Usage:
weaver generate [packages]
weaver generate [tags] [packages]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to:

weaver generate [-tags taglist] [packages]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// If non-nil, use the specified function to report warnings.
Warn func(error)
Warn func(error) // If non-nil, use the specified function to report warnings
BuildTags string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the BuildTags fields includes the "-tags=" prefix. That seems a bit wrong to me. Could just contain the tags, and we would add the -tags= prefix below when setting BuildFlags:

cf.BuildFlags = []string{"-tags", opt.BuildTags}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Fixed

generateFlags.Usage = func() {
fmt.Fprintln(os.Stderr, generate.Usage)
}
generateFlags.Parse(flag.Args()[1:])
if err := generate.Generate(".", flag.Args()[1:], generate.Options{}); err != nil {
buildTags := "--tags=ignoreWeaverGen"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below. I think we should just have "ignoreWeaverGen" here and supply --tags= prefix later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dobe

@@ -237,6 +238,80 @@ func TestGenerator(t *testing.T) {
}
}

// TestGeneratorBuildWithTags runs "weaver generate" on all the files in
// testdata/tags and checks if the command succeeds. Each file should have some build tags.
func TestGeneratorBuildWithTags(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we use runGenerator for this test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runGenerator copies every single file in a temp directory, and tries to build it. I chose this approach because I wanted to run go build on all the files in the directory and check that weaver_gen contains things only for the good files. That adds a little bit of boilerplate code for sure. If you have a strong preference, I can switch to calling runGenerator instead.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with you keeping what you have, but I don't quite understand the downside of using runGenerator. It would copy all of the files and build it. You can still check that weaver_gen.go does not contain the components defined in the bad file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Collaborator Author

@rgrandl rgrandl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Sanjay

Copy link
Collaborator Author

@rgrandl rgrandl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Sanjay

Copy link
Collaborator

@ghemawat ghemawat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the delay. Looks great. A couple of tiny comments you can ignore if you wish.

@@ -219,7 +225,7 @@ func TestGenerator(t *testing.T) {
}

// Run "weaver generate".
output, err := runGenerator(t, dir, filename, contents, []string{"sub1", "sub2"})
output, err := runGenerator(t, dir, filename, contents, []string{"sub1", "sub2"}, []string{})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just pass nil for the empty slice?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

gobuild := exec.Command("go", "build")

var buildTagsArg string
if len(buildTags) > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the earlier code always added "ignoreWeaveGen". So can we supply -tags unconditionally?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great observation. Fixed

Copy link
Collaborator Author

@rgrandl rgrandl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, Sanjay.

@rgrandl rgrandl merged commit 0a1e0d5 into main Sep 10, 2024
10 checks passed
@rgrandl rgrandl deleted the add_build_tags branch September 10, 2024 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants