mjy
mjy

Reputation: 2767

Any interesting uses of Makefiles to share?

"make" is not only useful for building your programming project, but it seems to be under-used in other areas.

For example, many shell scripts can be rewritten as Makefiles to allow independent parts to run in parallel (with "make -jXX") to keep all your CPU cores busy, with the explicitly declared dependencies as an added benefit in case you'd ever consider reordering some tasks with side effects in your shell script.

Do you have any interesting stories with unusual uses of make / Makefiles to share? Do you use some other utility as a cheap job scheduler?

Upvotes: 15

Views: 3656

Answers (7)

John Gowers
John Gowers

Reputation: 2736

Make can also be used as a sync utility. For example:

#!/usr/bin/make -f

FILES = *.html *.js *.css images/*.jpg subpage/*.html
LAST_SYNC = .last_sync
SCP = scp webserver.com:/home/john/public_html

.PHONY: sync

sync : $(LAST_SYNC)

$(LAST_SYNC) : $(FILES)
    $(SCP) $?
    touch $(LAST_SYNC)

This Makefile creates an empty file .last_sync that is used to record the last time that we synced the local repository with the remote one. Each time this script is run, Make will check whether any of the files listed in FILES have been modified since the last time we ran the sync, will copy them to the server and will then update the timestamp on .last_sync. The key is the automatic variable $?, which holds the list of all prerequisites that are newer than the target of the rule.

Upvotes: 3

Nitin4873
Nitin4873

Reputation: 17562

make are also used to drive process ........ i came to know of this recently , not just individual installation or managing build but the whole process. Previously i thought that make was to be used for compilation of projects only but where ever there is a possibility of a dependency or a chain of activity that needs to be performed , make can be used there ... i recently saw a code that manages everything for a process till delivery/deployment , including data processing-updation ( 24hrs +).... good thing :)

Upvotes: 0

jturner
jturner

Reputation: 226

Make's parallelism is particularly handy for shell scripting. Say you want to get the 'uptime' of a whole set of hosts (or basically perform any slow operation). You could do it in a loop:

cat hosts | while read host; do echo "$host: $(ssh $host uptime)"; done

This works, but is slow. You can parallelise this by spawning subshells:

cat hosts | while read host; do (echo "$host: $(ssh $host uptime)")&; done

But now you have no control over how many threads you spawn, and CTRL-C won't cleanly interrupt all threads.

Here is the Make solution: save this to a file (eg. showuptimes) and mark as executable:

#!/usr/bin/make -f

hosts:=$(shell cat)
all: ${hosts}

${hosts} %:
        @echo "$@: `ssh $@ uptime`"

.PHONY: ${hosts} all

Now running cat hosts | ./showuptimes will print the uptimes one by one. cat hosts | ./showuptimes -j will run them all in parallel. The caller has direct control over the degree of parallelisation (-j), or can specify it indirectly by system load (-l).

Upvotes: 21

user50049
user50049

Reputation:

Depending on the variety of 'make' , you can sail through dependencies of tasks by using executable makefiles vs shell scripts .. i.e. in a scenario where one init script needs to start 10 services ... one after the other (i.e service two needs service one to be up and alive prior to starting), its easily done via a makefile.

A lot of GNU/Linux packagers make use of this, i.e. debian/rules and others. So yeah, if done correctly, make is just as good at starting programs as it is as building them.

The problem is, not everyone has a build tool chain installed .. so shell scripts or batch files remain the portable (hence 'correct') approach.

Upvotes: 2

jtimberman
jtimberman

Reputation: 8258

Other than obvious uses in programming, I've seen Makefiles used to perform repetitive tasks on servers to manage system settings such as user/group creation, package upgrades/updates, and copying config files into place. I have also seen (and used) rake to do this in Ruby based environments.

The most complex example of this I have heard of is ISConf, a configuration management tool. I heard about it from Luke Kanies, the author of Puppet, on his blog.

Upvotes: 3

Joshua
Joshua

Reputation: 43270

My work uses a curious one: the dependencies don't exist so it always rebuilds everything.

Might as well have used a batch file.

Upvotes: 0

Jonathan Leffler
Jonathan Leffler

Reputation: 753990

It probably means my imagination is deficient, but it is hard to get sufficient flexibility into a makefile for such use. The 'obvious' way to achieve it is to specify macro values on the 'make' command line.

make -f script.mk MACRO="list of files on which to operate"

That is more verbose than a simple shell script - and you lose the easy ability to use shell file name expansion. The workaround for that is:

make -f script.mk MACRO="$(echo *[io]*)"

I'd offer this SO question about Why not use #!/bin/make at the top of makefiles as an odd use of (executable) makefiles, but the goal there was not to do unusual things (just boring old software builds); just to use an unusual invocation mechanism for make.

Using the technique, you could simplify the invocation to:

script.mk MACRO="$(echo *[io]*)"

That's still more verbose than:

script *[io]*

I suppose script could be written to do the invocation of make. It all depends. I'm not convinced that there's enough mileage to be gained out of it; YMMV.

Upvotes: 1

Related Questions