4 ms·
They should really be using bash for this, not make. There is nothing wrong with bash scripts calling Make -- for building with DEPENDENCIES. But when you are
by chubot 11y ago
They should really be using bash for this, not make. There is nothing wrong with bash scripts calling Make -- for building with DEPENDENCIES. But when you aren't doing that, just use bash (because Make is actually Make + bash to begin with).
This is dumb:
restart-frontend: ## Restart the frontend and admin apps in dev
@make stop-frontend-dev && make run-frontend-dev
@echo "Frontend app restarted"
Write it with a shell script like this:
stop-frontend-dev() {
...
}
run-frontend-dev() {
...
}
restart-front-end() {
stop-frontend-dev
run-frontend-dev
echo "Frontend app restarted"
}
build() {
make # this actually does stuff you can't do in bash.
}
"$@" # call function $1 with args $2... Can also print help here.
This is a lot cleaner. The PID stuff can be done with bash too.
- accatyyc 11y agoBut why does it matter? With your solution they'll have two "task files" to manage instead of one.
- antocv 11y agoBecause make is for managing dependencies, which it tracks by files, as soon as you need to do something which doesnt leave files around, such as start a new service, you then need to plug this hole, by using "touch" and leaving files around, which this example doesnt do so it may actually leave the system inconsistent and make the makefile do things it shouldnt, thus causing errors difficult to diagnose. But then you run into the problem of making make have functions of a service manager, which it isnt, and you will most likely fail doing that. Use Make when you need to track dependencies based on files, such as for build systems whose output is files, and bash/other script for managing a hosts services which are/may be required for the build system.
- xaduha 11y agoNope, to me it isn't cleaner. Also, make has "make -n" which is absolutely golden.
- exDM69 11y agoIt's not about which script file is considered to be "cleaner", aesthetic preferences don't matter here. The Makefile here almost certainly has some unexpected side-effects when used in a way that the original author didn't intend to. E.g. accidentally removing your PID files (e.g. with git clean) and then you have more than one dev server running. Make isn't intended for starting/stopping services or doing non-build tasks. It really sucks for that kind of tasks. It might work ok for the handful of workflows the author intended it for, but then spectacularly break down when someone else tries to do something outside of that or when new features get added. Sometimes I see people use Make for situations where some build platform (e.g. Windows or an embedded toolchain) doesn't have a proper shell at hand. But it's still not a great idea to use Makefiles as a replacement for shell scripts. There are much better alternatives for doing non-build tasks.
- to3m 11y agoWhat problems would there be doing things from GNU make, that there wouldn't be when doing the same thing from a shell script? My experience has been that you can totally use GNU make as a replacement for shell scripts, and it works fine. Why wouldn't it? It's just sequences of shell commands, where each sequence has a name. And in fact for this sort of situation, where you've got one of a pre-canned set of sequences to run, it works very well - because GNU make will handle the command line for you, and most shells will give you some kind of basic (but usable) tab completion for the sequences available, without any effort on your part. You do need to use phony targets, though. (https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html https://www.gnu.org/software/make/manual/html_node/Phony-Tar...) This might seem like a ridiculous requirement, but I've seen plenty of bash scripts that just kept on going when a shell command failed; it's not like GNU make is unique in requiring a small amount of boilerplate to make things work nicely.
- xaduha 11y agoI was replying to this line > This is a lot cleaner. The PID stuff can be done with bash too. In any case, until there is a tool which is as ubiquitous and as declarative as make you're going to have hard time convincing those of use who use it this way to stop.
- jlg23 11y agoThis is only cleaner in your simple case. Make's power lies in dependency tracking and its declarative approach to defining those dependencies. When you use make anyway, adding those targets there is the logical thing to do. One interface instead of two. It's even less lines of code than your proposed solution (which btw does not fail hard like make does, so a recipe for desaster). Finally: Pretty please, sh, not bash. Almost none of the bash-scripts out there use actual bash-features and those that do can usually easily be rewritten to just rely on a plain posix shell.
- kps 11y agoFor makefiles, even GNU make executes commands using /bin/sh (unless you set $(SHELL) explicitly); trouble is, many Linux systems use bash for /bin/sh, and its sh emulation is lacking.
- chubot 11y agoMy point is precisely that the script is not using "Make's power in dependency tracking". It's just running commands. If you need Make, use Make; otherwise use shell. It's far from unusual to have a Makefile and some shell scripts at the top level of a project. Make's semantics are to invoke the shell at EVERY LINE. This is slow and makes quoting a nightmare (try quoting find or sed in bash in Make correctly; you cannot directly invoke them from Make). Conversely, bash's semantics do not involve make whatsoever :) Shell also has local variables for modularity, and better constructs for conditionals and iterations. And functions. Make has a poor man's implementation of Turing-complete constructs compared to shell (which is a little ironic since shell is already sort of a poor man's procedural language). 'set -o errexit' makes bash fail on errors. Also, as mentioned, the Makefile isn't using phony targets. Neither shell or Make is perfect, but shell is the more appropriate tool when you're not making use of Make's incremental build features. Another pattern I find useful is to have the actions take more arguments, like: ./run.sh dev-frontend --flag-for-testing which is implemented just like this: dev-front-end() { ./frontend.py --port 8080 --other-default-flag "$@" } "$@" The arguments to Make are actually TARGETS/files and not functions, so I don't think you can do this.
- 11y ago
- dergachev 11y agoBefore fig, Docker build repositories often have awkward arguments to build or run a container, and that's where I first saw people using a Makefile as basically a bash script file. I copied it and since then I've used it like 100 times since, it feels a lot more easier than the above bash script approach, though for reasons I can't quite put into words right now. It also turns out that dependencies creep up pretty often, so shortly after we started abusing the Makefile, we also started using it "right" too. Examples: * https://github.com/dergachev/screengif/blob/master/Makefile https://github.com/dergachev/screengif/blob/master/Makefile * https://github.com/dergachev/drupal-docker-marriage/blob/master/Makefile https://github.com/dergachev/drupal-docker-marriage/blob/mas...
- s_kilk 11y agoBit of a tangent, but in a fit of snark a few years ago I wrote a bash "task runner" in the vein of Grunt and Make: http://manuel.00null.net/ http://manuel.00null.net/ Not very useful, but it kept me amused for a weekend at least.