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

Enhancement: Make build tags useable in magefiles #424

Open
oderwat opened this issue Apr 29, 2022 · 6 comments
Open

Enhancement: Make build tags useable in magefiles #424

oderwat opened this issue Apr 29, 2022 · 6 comments

Comments

@oderwat
Copy link

oderwat commented Apr 29, 2022

Describe the feature
I would like to have the possibility to call mage with build tags like mage -tag=audio watch

What problem does this feature address?
Because I want to use the same build script (magefile) for production / headless and developer builds I need a way to exclude packages from the magefile. In this case, it is about using (native) audio output in my magefiles, which is not available (or wanted) when building for production.

Additional context
I use mage with some custom.written auto re-compile / re-start code for backend / frontend development (with go-app). The code basically checks dependencies and if they change it rebuilds (parts) the project (backend, wasm, tailwindcss, docs, protobuf / twirp). If that works without errors it stops the old build executable (server) graceful and starts the new one and this then optionally tells the frontend to reload. As all of this this happens "in the background" I added audio beeps for failures and success on the builds and restarts. This way the developer can change the source, save and wait for the "beep" as feedback.

P.S.: I hope I did not miss any obvious solution. The only one I see would be creating another magefile directory for production use. But this would duplicate a lot of complex code because we also do testing and bootstrapping with it.

I currently made it such that the audio is never included when running mage on Linux, but I want to have the beeps when testing on Raspberry Pi or Ubuntu VMs for example.

@natefinch
Copy link
Member

natefinch commented Apr 29, 2022

There's a few ways to do this without tags. You could pass an environment type to one of the targets, to indicate if you're building for dev or production.

e.g.
mage build dev
vs
mage build prod

for

// Build builds the server for the given environment (prod or dev).
func Build(env string) error {

Or you could have a separate target that just enables audio by setting a global variable somewhere:

mage enableAudio build (dev)
vs
mage build (prod)

You could do it via an environment variable:

ENABLE_AUDIO=true mage build

etc

The only time you really need build tags is if you have code that literally won't compile on some machines (generally syscall stuff). But in those cases, you can use usually use GOOS and GOARCH (which mage supports via -goos=foo and -goarch=bar). So like, if you need different code for unix-like environments vs. windows, you can do this:

beep_windows.go

//go:build mage

func beep() {
   // windows beep code
}

(note that we don't need //go:build windows && mage above, because the _windows.go tells Go to only compile that file for windows... though it honestly might be clearer to also put windows in the go:build line).

beep_nix.go

//go:build !windows && mage

func beep() {
   // linux/macOS beep code
}

You can also combine the above two approaches, so that you use different beep code per platform, but then can still turn it on or off with whatever manual method you prefer.

Build tags are powerful, but honestly, aside from platform-specific code, you very rarely need them.

@oderwat
Copy link
Author

oderwat commented Apr 29, 2022

@natefinch Sorry but there is no way to do this without tags besides using a different code or a precompiler. It all is about having targets to exclude code (and therefore the need for the packages to compile).

It is indeed trivial to add a parameter to Mage which would "not do audio beep" and in fact, I already have an environment variable that disables it for developers who do not want the beeps and other arguments for steering different builds (like with autocerts / local certs or self-signed certs, the domains and some of the configs for running/watching the generated executable).

Your last example about how to use targets for different systems is what I do and described in my post. I do not have the package dependency through a build tag on Linux now. But I want this to be selectable and for this, the magefile needs to compile with a given build tag.

I could use another "go" executable and inject the build tags there. Like a wrapper that calls go {argX} -tags noaudio {args...} to be used with mage -gocmd go-noaudio watch and replace the right parts on the command line for example. But I think that is cumbersome and that having build tags support would be beneficial for Mage and is probably trivial to implement. You can even test for them using build info in the executable.

P.S.: The magefile I am writing about has nearly 500 lines of code and currently has 17 build targets where some of them have parameters and include building multiple targets, "hot-reload" logic, installation of tools, checking versions, clean builds, tests, packaging, and doing bootstrap for Linux, Windows, and OSX targets. I would not write a feature request for something trivial.

@natefinch
Copy link
Member

It all is about having targets to exclude code (and therefore the need for the packages to compile).

But why does that matter?

@oderwat
Copy link
Author

oderwat commented Apr 29, 2022

It all is about having targets to exclude code (and therefore the need for the packages to compile).

But why does that matter?

Short: I want to use the same magefile on the same OS with or without the "syscall" stuff :)

As I wrote in my initial comment I am using an audio package to give feedback about the building process when run by developers on the desktop systems. This is done by using a package that itself uses different audio libraries for different systems. This includes Linux and is fine for desktop Linux. But I do not want to install the needed system libraries (e.g. libasound2-dev) on a production or staging server, nor would I want to have to install this. when for example doing CI scripts or in Docker images. Currently, I omit those packages using GOOS and never have audio on Linux. But I would like to have audio on Linux when used with a graphical frontend, especially as some team members use Linux as their primary development system.

When Mage is compiling the files in the magefile directory with a build tag I can omit the code and do not need to install unused libraries. There are maybe other positive effects of having build tags available for the magefile compilation. especially when creating executables that do not need all the code from a magefile.

I think it is also worth looking at the options if that feature is not available: I could create multiple magefile directories but needed to share a package between them, copy and maintain multiple versions of the code or need to use some preprocessor to create a fitting magefile. All of what seems bulky and unneeded if it would possible to give Mage the build tags.

@natefinch
Copy link
Member

So what you're saying is, if you don't have those audio libraries installed, your go code won't compile?

@oderwat
Copy link
Author

oderwat commented May 12, 2022

So what you're saying is, if you don't have those audio libraries installed, your go code won't compile?

I say that my magefile then does not compile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants