GNU Make 4.0 Released
lists.gnu.org
lists.gnu.org
I still use Make occasionally, but redo (https://github.com/apenwarr/redo) just fits my mind better - it's simple, consistent, doesn't require keeping another language with its dark corners (it's just shell scripts), and works well.
It also solves the bootstrap problem - there's a short script called "do", which always rebuilds everything, all of 177 of non-minified bash script. If you need to distribute anything, you should distribute it with "do" inside - and guarantee that your users can build without relying on an installed package (or a specific version of GNU Make).
p.s: OS/X, Linux and BSD supported. Supposedly, windows through cygwin or busybox - but I've never tried.
To rebuild everything with Make, you can use the -B switch:
-B, --always-make
Unconditionally make all targets.It doesn't take care of the problem, it mitigates it. It tries to find the most POSIX-like shell. You still don't know which shell that will be. And then, even if you did, you are still relying on external programs, which may all work differently than the ones on your box. Writing portable shell scripts is hard.
This bug is the reason why make 3.82, released in 2011, still sits in Debian experimental and hasn't yet graduated to unstable where it might form part of a release. Make 4.0 seems likely to suffer the same fate.
What could be done with GNU Make to help encourage a transition forward?
With massive, carefully coordinated transitions, and features provided to help with backward compatibility (e.g. OS X provided PowerPC emulation for ~5 years).
> What could be done with GNU Make to help encourage a transition forward?
First, documenting exactly why the previous behavior (mixing implicit/pattern rules and normal rules) is problematic to support going forward and is worth the pain of a backward-incompatible transition.
Second, adding a backward-compatibility option to enable the old behavior, or ideally allowing it by default, perhaps with a warning if transitioning away from it is that important.
And third, keeping that option available for many years as existing software projects making use of that behavior filter out of usefulness (until, for example, all of the enterprise Linux distributions have moved to versions of the Linux kernel that don't depend on the old behavior).
FWIW: Other issues with 3.82 broke things in Android and openembedded too. It wasn't their finest release.
Doesn't look like it; I checked the Fedora sources for their make package, at http://pkgs.fedoraproject.org/cgit/make.git/tree/ , and none of the patches appears to affect that backward-incompatibility.
If anyone knows of a patch, in a Linux distribution or otherwise, which fixes this backward incompatibility, I'd love to hear about it.
A huge amount of complexity in using and deploying software comes about because of very narrow version requirements, where due to combinations of backwards incompatibility and necessary new features, there are very narrow windows of software which is actually usable. Add in dozens of different packages, and you are frequently left with a situation in which there is no single set that will all interoperate.
The Linux kernel has a very reasonable attitude: you don't break userspace. You just don't do it. I wish more tools would adopt this attitude. You just don't break your API, ever. No backwards-incompatible revisions, ever. If it's backwards incompatible, it's a new piece of software, not an update.
I realize that this is fairly idealistic, but having experienced so much breakage with non-backwards compatible software, and had so much better experience any time people make an actual honest effort to preserve backwards compatibility, I really hope that more developers start to consider backwards compatibility one of their primary goals, only to be broken if absolutely necessary, and only with a major version change or entire renaming of the package.
In general yes it'd be good if developers paid more attention to backwards compatibility.
My point is that even undocumented features are an important part of backwards compatibility. If there is software out there relying on it, breaking it and saying "well, they were relying on an undocumented feature" doesn't actually help your users at all. Is your goal to ensure that developers do everything the way you tell them to all the time, and punish them if they don't? Or is your goal to provide software that your users can use to do their jobs?
It is how the world works, when you use undocumented features in every aspect of life (e.g. not following the rules) it is great when you get away with that, but don't expect the world to bend their rules to accommodate you, that only happens when a majority goes that path, and often it doesn't even happen then.
Microsoft gets this. Linus gets this. FSF and GNU, while I love their ideals, are apparently a bit too ivory tower to actually get it on things like this.
There were several outright bugs; without a patch (that most distros apply), it would SIGABRT during the Android build, perhaps this is what a few people are referring to (I am unaware if this was the only problem with building Android on 3.82)
The most significant backwards-incompatible change was changing how pattern rules are selected if there are multiple matches, but this is documented.
Perhaps you are thinking of wildcard expansion, which has the undocumented feature of returning a sorted list? That wasn't actually changed, it was marked as a "Future backward incompatibility" that would be changed in the next release.
However, breaking compatibility from 3.x to 4.x is perfectly fine and won't cause any surprisings. After all, that's what major version number are good for.
(... at least in their original meaning, before various free software projects started some strange kind of race with their major version numbers)
Because if there's one thing the GNU software-building toolchain needs, it's more languages! How many are we up to now?
Grouping output by target for parallel builds sounds very useful though \o/
But GNU Make seems to be the first major one.
One of the features it doesn't have, though, is a first class language for doing non-trivial extensions. Some systems (the kernel Makefiles and Android's build system are really good examples) have stretched make's built-in environmnent past the limit already and might have benefitted from something like this.
Being realistic, I look forward to adding Scheme to the cruft.
http://www.gnu.org/software/make/manual/html_node/Functions....
(note "foreach", "call", "eval") and:
http://www.gnu.org/software/make/manual/html_node/Multi_002d...
For instance, from the "call" documentation --
"The call function is unique in that it can be used to create new parameterized functions."
Sometimes these types of functions are really important, and you have to be creative to use the builtins to set up the dependencies you want. For instance, by combining "foreach" with "call" or "eval", you can dynamically create sets of rules. This can be quite powerful.
And you don't have to use make only for software compilation. You can use it to create more general-purpose data transformations. When you get a batch of new images, for example, you type "make", and it just recomputes all the derived data (but only what depends on the new stuff). I have done this, and it was very slick, but it tends to stress the existing function set.
So I often asked myself why they don't use Lisp directly. Now they almost do, which I find very consequent.
[1] http://mxe.cc/
I so prefer reading makefiles to a sea of XML gibberish.
mytarget: source1 source2
do-something -o mytarget source1 source2
so much easier to read than Ant tasks. (and, yes, there are ways to get the file lists into symbols without explicitly enumerating them)Ant, and by extension, Maven, was a huge step backward. Sure, have a way to make portable commands, BUT, was XML really needed??? And, does every task have to be built such that the task checks dependency timestamps, rather than the framework that calls the task???
Ant and Maven both have plenty of issues, but being dissimilar from make is not one of them. At the end of the day 'file based' tools like Make are not really suitable for Java which is more concerned with source directories - rightly so in my opinion. There is no program that cannot be written because of a consistent source layout.
There are ways to enumerate files, but nothing good (in my experience) and by the time you are using them the make files are no longer easy to read (never mind debug).
Make also has this Faustian pact thing going on. Access to the shell and all of its power and familiarity, but at the (significant) expense of portability.
Add that to your CFLAGS and include the generated dependency files by adding something like
-include $(OBJECTS:%.o=%.d)
to the Makefile.[1] http://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
If your rule that builds .o files from .c/.cpp files uses the one of the dependency-generating flags to GCC (options beginning with -M), GCC will create an alternate or additional (depending on the flag) make-compatible file that describes what files were included during the build. If you then include these files in your Makefile with the 'include' directive, then you'll get the behavior you're looking for.
Implementing it correctly can be a little tricky, but once you understand how to do it it's not too bad. As I recall there used to be some subtle issues that required some post-processing of the GCC-generated dependency files to avoid a problem when header files were renamed or removed (foo.c included foo.h, so a dependency was generated; later foo.c was modified to not require foo.h, and foo.h was removed, but the build still thinks it's required to build) -- it looks like GCC now has a -MP option to add phony empty rules for all dependencies, allowing make to power through these.
https://github.com/chkoreff/Fexl/blob/master/build
Configurable with a small src/config file:
https://github.com/chkoreff/Fexl/blob/master/src/config
It automatically greps header dependencies, caching them in obj/*.i files.
.i is the extension for pre-processed C source. If you re-use it for something else build-related, I guarantee you'll regret it.
$ gcc -M src/value.c
value.o: src/value.c src/memory.h src/value.h
The result of my grep/sed gives me just the header dependencies alone, which is really all I need: $ cat obj/value.i
src/memory.h src/value.h
So I might consider replacing the grep/sed with gcc -M, and strip off the first two entries, which would give me the equivalent result, but it doesn't strike me as a "must do" right now. Again, I don't use make, just /bin/sh, so I don't need a make rule per se.Thanks for the advice about the ".i" suffix. I don't think there's a conflict though, because all my intermediate files go into a completely separate "obj" directory, and no pre-processed source will be going there. However, I will consider choosing a different suffix just for the heck of it. I'm sure anything I choose (such as ".dep" or ".inc") will mean something to somebody somewhere, but since I'm in the entirely orthogonal context of the "obj" directory I don't think it matters.
https://github.com/mcinglis/c-style#use-gccs-and-clangs--m-t...
Generally it's my style to prefer I/O redirection in the shell to programs taking output parameters and managing their own files. Thus, using `> $@` rather than `-MF` or `-MD`.
For C/C++, I have to subvert GNU make's attempts to rebuild .d files by using $(wildcard) on them and inserting a /./ in the middle of the path.
Note that there are other cases where I do have a rule for building .d files and have them rebuilt. In particular for Fortran 90 modules. This occurs wherever you need to build the .d files first for the initial first build to be in the correct order. This is only an issue for C/C++ if you are invoking a program to generate C sources (e.g. rpcgen). In practice, that is often best handled with a few dependencies listed explicitly in your Makefile.
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
(which predates GPLv3)That is a pretty presumptuous thing to say.
EDIT: To answer your question more directly: when you have a large project, or a project that needs to build on many platforms. Probably a whole load of other situations as well, but those are the two that stick out.
TL;DR faster turn around times using make.