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

make the makefile slightly more elegant #86

Closed
wants to merge 1 commit into from
Closed

make the makefile slightly more elegant #86

wants to merge 1 commit into from

Conversation

mpldr
Copy link
Contributor

@mpldr mpldr commented Oct 21, 2023

No description provided.

@mjl-
Copy link
Owner

mjl- commented Oct 22, 2023

Thanks for the PR mpldr. Some comments below.

There are reasons to have the vendor directory in the repo:

  1. The repo stays self-contained, not requiring additional downloads (dependencies) to build. Only the Go toolchain is currently required. I have a separate CI pipeline that builds without making any requests.
  2. By including dependencies, diffs show the changes in dependencies. This helps both to review changes in dependencies, and it sometimes helps to show that an innocent-looking addition of a dependency actually pulls in a lot of code, which can be a reason to choose another approach.

Not all Makefile changes seem like a clear win (or more elegant) to me, but some of the incremental build changes may be useful. Details:

  • Only generating new docs and api json files when the source files have changed could be good. I'm not so sure the current dependencies for the api files are complete. Types from other packages may be exported too in the API. For the docs, they should also depend on the Go files in the main package that implement the commands. Depending on all go files would be safer, but may also defeat some of the purpose. Perhaps there is a Go command to fetch package dependencies? Question is if it ends up being faster. See below for some more details on incremental build speed.

  • To replace the "go" command, I typically just make sure to set a PATH that has another "go" earlier in the list before running make. No need to add support for replacing commands in all Makefiles. The same would apply to other commands. For example, I regularly run goprev make build test, with:

$ cat $(which goprev)
#!/bin/sh
PATH=$HOME/sdk/goprev/bin:$PATH "$@"
  • Are you sure $gosrc is complete? Including embedded static files. In my experience, the Go tooling is solid and fast enough to let it handle incremental builds. Trying to do it again in a Makefile is bound to get out of date. So I would say it's only worth it if it gives a significant performance boost, and I don't think that's the case.
  • I would not use -trimpath by default. I use the full paths in panic backtraces. With -trimpath, clicking a path:line wouldn't open the file in editors because the path doesn't exist. I think GOFLAGS is also picked up from the environment, so you could just run GOFLAGS=-trimpath make, or set it once in the shell you're running make in.
  • I find target name "lint" misleading. It does checks, but it doesn't call golint, the (once) standard linter in Go.
  • I'm not a fan of ".PHONY". I certainly don't find it elegant. And I don't think they are needed, the targets aren't created in their build steps. Only if someone manually creates files named "check", "test", "test-race", would there be a problem. That will be noticed soon enough.
  • I tend to stay away from the magic makefile variables like "$@". It makes the makefiles unreadable to the untrained eye. And even though I use and write makefiles, I'm eternally untrained because I don't edit them often enough. Just having a few paths duplicated is more clear, even untrained eyes will understand what's going on. Long dependency lists may be more readable as variable though.

As for performance of incremental builds. This is approximately what I'm getting for an incremental build without changes with the current Makefile (durations in real/wall time, not user/system time):

$ time make build
# build early to catch syntax errors
CGO_ENABLED=0 time go build
.3s +/- .1s

CGO_ENABLED=0 time go vet ./...
3.88user 0.98system 0:01.00elapsed 485%CPU (0avgtext+0avgdata 42368maxresident)k
1.5s +/- .5s

CGO_ENABLED=0 time go vet -tags integration
1.55user 0.53system 0:00.62elapsed 334%CPU (0avgtext+0avgdata 41216maxresident)k
1s +/- .3s

time ./gendoc.sh
0.21user 0.06system 0:00.34elapsed 80%CPU (0avgtext+0avgdata 21408maxresident)k
.3s +/- .1s

(cd webadmin && CGO_ENABLED=0 time go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Admin) >webadmin/adminapi.json
.5s +/- .2s

(cd webaccount && CGO_ENABLED=0 time go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >webaccount/accountapi.json
.3s +/- .1s

(cd webmail && CGO_ENABLED=0 time go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Webmail) >webmail/api.json
.3s +/- .1s

time go run vendor/github.com/mjl-/sherpats/cmd/sherpats/main.go -bytes-to-string -slices-nullable -maps-nullable -nullable-optional -namespace api api <webmail/api.json >webmail/api.ts
.2s +/- .1s

# build again, api json files above are embedded
CGO_ENABLED=0 time go build
.3s +/- .1s
  • go build itself is quite fast, only running it when its inputs haven't changed doesn't seem worth it (given the new risk of incomplete dependencies).
  • go vet is slow. Perhaps vet can be started early in the background? I don't know of a Makefile feature for that. Not sure if a shell script with a background job is worth it.
  • The easiest time savings appear to be not running gendocs, sherpadoc and sherpats if not needed.

In general, if changes make the makefile less readable, they make simply not be worth it...

@mpldr
Copy link
Contributor Author

mpldr commented Oct 23, 2023 via email

webmail/api.ts: webmail/api.json $(gomod)
$(GO) run github.com/mjl-/sherpats/cmd/sherpats -bytes-to-string -slices-nullable -maps-nullable -nullable-optional -namespace api api <$< >$@

.mox.tmp: main.go
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would love to get rid of this abomination, but with gendoc.sh creating a circular dependency with the mox target, this has to stay as long as gendoc.sh is a thing.

This also adds the possibility to use the new docker compose subcommand
instead of the standalone command.
@mjl-
Copy link
Owner

mjl- commented Nov 2, 2023 via email

@mpldr
Copy link
Contributor Author

mpldr commented Nov 2, 2023

I think I may have misinterpreted the purpose of this Makefile then :) it's probably best to just close this PR as I don't think this is going to lead anywhere.

@mpldr mpldr closed this Nov 2, 2023
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