4 ms·
Trying to do anything non-trivial in GNU make macros is the most bewilderingly awful programming experience it is possible to have. They are horribly broken in
by david-given 11y ago
Trying to do anything non-trivial in GNU make macros is the most bewilderingly awful programming experience it is possible to have. They are horribly broken in every respect, from little stuff like awful syntax (whitespace is insignificant except where it's significant!) and poor error checking (detecting undefined variables? Who cares?) to the really big stuff (can't do arithmetic, despite having core functions which take numbers as arguments!).
A while back I wrote a compiler which targeted GNU Make and made it run Conway's Game of Life (complete with hand-tooled arbitrary precision maths library written in make). I learnt more about this stuff than is healthy to know. The compiler output is... special.
http://cowlark.com/2013-10-19-insane-make http://cowlark.com/2013-10-19-insane-make
- scrollaway 11y agoFun story, I have a set of scripts that extract, decompile and process various sets of files, outputting them into a build directory. At first I wrote shell scripts to automatically do all this, then I figured this is the sort of thing Make was built for (right?). This is what I ended up with after days of work: https://github.com/HearthSim/extract-scripts/blob/master/Makefile https://github.com/HearthSim/extract-scripts/blob/master/Mak... Turns out, Make kind of just assumes you're building a C project and makes a lot of further assumptions which made writing this Makefile a living hell. In the end, I didn't even manage to do proper checks for built files. Make seems like a really poorly execution of a good concept. I think a large part of why autotools suck also comes from that.
- david-given 11y agoOne thing that make appears completely unable to do cleanly is to build things twice, with different flags. You know, like 'build a release version and a debug version'. I've ended up having to write self-writing makefiles to do that. It's not as nasty as it sounds (but still pretty nasty): https://github.com/davidgiven/wordgrinder/blob/master/Makefile https://github.com/davidgiven/wordgrinder/blob/master/Makefi... Plus, 'set a flag for just this file' is another thing that's appallingly broken. GNU Make has an extension to do that --- but if you use it, it makes your builds non-deterministic. (Flags propagate down the build chain; builds are not in a defined order; each file is built once regardless of the flags for that file; so if a file is reachable via more than one rule with different flags settings, it's pure luck which setting wins...)
- the_why_of_y 11y agoIf you write make files to build everything in twice, release and debug, you're doing it wrong. The proper way to do this is to write make files so you can do "out-of-tree" builds, i.e. your build directory is outside your source directory and each build directory has its own configuration. This has the significant advantage that you can not just build 2 or 3 or however many different configurations you would think important enough to hard code in the build system from one source tree, but as many as anyone who builds it happens to need. Incidentally this is one thing that GNU autotools get right. It is true that if you use target specific variables you have to ensure yourself that you set them in such a way that no non-deterministic behavior can occur; it would be great if make reported a warning in such cases. Another problem with them is that you can't invoke make with a single object file target any more if that requires a variable set on and inherited from the corresponding link target to compile.
- david-given 11y agoSorry, I don't follow. I am doing out-of-tree builds? The problem is that there is no way to generate multiple files from one rule. If you write: $(OBJDIR)/foo.o: src/foo.c ...you get one rule, which will build one object file. If you want to generate two object files with two different settings, you have to have two rules. $(OBJDIR1)/foo.o: src/foo.c $(OBJDIR2)/foo.o: src/foo.c There is no way round this. Target-specific variables look like they solve this, but they basically don't work for anything useful. There are only three options here: (1) hardcode multiple rules; (2) use make macros to generate multiple rules; (3) invoke the makefile multiple times with different settings. All of these options are horrible.
- enqk 11y agoYour flags should be encoded in the OBJDIR name indeed. It is most likely more correct anyway, as you can't always assume you can mix two objects which were compiled with different flags. An example is C++, where often standard libraries don't allow mixing debug and release code.
- the_why_of_y 11y ago
- MichaelMoser123 11y agoI don't know, Make is difficult because we are used to think in procedures and not in rules; and the rule and macro syntax is a bit weird; it takes time to master it. i have a makefile/make system that uses gnu make macros; (here http://mosermichael.github.io/cstuff/all/projects/2011/06/17.. http://mosermichael.github.io/cstuff/all/projects/2011/06/17.... ) this saves you from repeating the same make constructs many times over, in the following example you do a static library and executable. 1: TOPDIR=../.. 2: 3: # - declare build targets. (built with make) 4: TARGETS:=shlib slibuser 5: 6: # - slib target is a static library - 7: shlib_TYPE=lib 8: shlib_SRC=slib.c 9: 10: 11: # - slibuser target is a executable using slib - 12: slibuser_TYPE=exe 13: slibuser_SRC=slibuser.c slibuser2.c slibuser3.c 14: slibuser_LIBS=shlib 15: 16: include $(TOPDIR)/rules.make At a previous job they had an even more convoluted make system - it was simulating macros: the makefile was including another generic make file; this included make file was writing hidden files that contained the make rules ; then as the last step these generated files were included.
- J_Darnley 11y agoYour link is wrong and returns 404. Even https://mosermichael.github.io/ https://mosermichael.github.io/ returns 404. Can you prove the correct link?
- MichaelMoser123 11y agoThanks here is the correct link (can no longer edit the parent post). http://mosermichael.github.io/cstuff/ http://mosermichael.github.io/cstuff/ http://mosermichael.github.io/cstuff/all/projects/2011/06/17/make-system.html http://mosermichael.github.io/cstuff/all/projects/2011/06/17...
- J_Darnley 11y agotyvm
- krylon 11y ago> A while back I wrote a compiler which targeted GNU Make and made it run Conway's Game of Life (complete with hand-tooled arbitrary precision maths library written in make). I learnt more about this stuff than is healthy to know. The compiler output is... special. One part of me wants to buy you a drink. The other part wants to scratch my eyes out with a rusty fork. Since I have no rusty forks at hand, and we probably won't ever meet, I'm just going to enjoy this as new record in "because-I-can"-land.