Talk:Makefile

From OSDev Wiki
Jump to: navigation, search

Contents

rm

if [ -f $$file ]; then rm $$file; fi;

what about using rm -f, or $(RM) which is by default defined as rm -f ?

Also, are you very sure you can mark an explanation of your own makefile as a tutorial for makefiles? It seems quite arrogant.

-- Candy

The "mark an explanation of your own makefile as a tutorial for makefiles" does seem a little weird. Maybe you just got that strange naming convention and programmers block I get sometimes. .. maybe all the time. Look I am doing it now. "Makefile: Tips And Tricks". <Have mercy on me..>
-- kmcguire 10:40 AM CST 11 March 2007
Everything is relative, so is arrogance. A practical example may be a good starting point, even if it is your own code. As long as it serves its purpose and people learn from it, why should we care?. You have an alternative? ;) - Combuster 03:05, 12 March 2007 (CDT)

Sorry for taking so long to reply, I'm not a "regular" to the new Wiki (yet?). Candy, you are of course right about the $(RM) implicit variable. The "if"-wrapper is being done to keep the Makefile quiet even if a file from the list does not exist (which is not, in fact, an error, and thus shouldn't bother the user). I know I had problems with "only" rm -f to this end, but would have to do some testing to give an exact explanation. As for the "arrogance" part... you can't write "the" tutorial about makefiles, because make is far too diverse. You can use them to run everything and the kitchen sink. I thought the PDCLib Makefile - being AFAIK correct, non-trivial, and yet not overly long / complex - would be a good example for others to learn a few tricks about Makefiles, especially the dependency handling and non-recursiveness. I shall make the wording a bit more general, and add a note that this is meant as a starting-point, with feedback / requests for extensions being very welcome. Sorry if it sounded too arrogant. Solar 03:02, 28 March 2007 (CDT)

Sorry but right now I can't be bothered to do this. I have more or less dropped osdev.org completely, and am spending my time on other projects. I might return later, but for now feel free to rewrite this any way you like. Solar 23:31, 22 April 2007 (CDT)

Looks better to me. I especially liked the fact that I found a neat section on extracting the TODO:s from a source tree which I just never have thought about doing.

--Kevin 18:22, 29 April 2007 (CDT)

I did a rework today, including some explanation on why I used the actual PDCLib Makefile instead of giving general tipps. I hope you like it. Solar 04:20, 21 January 2008 (CST)

$(RM) wildcarding

-@for file in $(OBJFILES) $(DEPFILES) $(TSTFILES) $(REGFILES) pdclib.a pdclib.tgz; do if [ -f $$file ]; then rm $$file; fi; done

Wow, that is ugly, and IMO needlessly complicated. A much better rule would be:

@$(RM) $(wildcard $(OBJFILES) $(DEPFILES) $(TSTFILES) $(REGFILES) pdclib.a pdclib.tgz)

The wildcard function returns a list of only the files that exist, so the if statement and for loop are no longer necessary. Likewise, the - to ignore failures from $(RM) is unneccessary because all files are guaranteed to exist. Although if you don't have permission to delete them, then a failure will stop any other rules that may be in that target from being run, but that's correct bahavior anyway. --quok 07:05, 26 August 2008 (UTC)

Very nice. -- Solar 08:43, 26 August 2008 (UTC)

Recursive Make

I'm not an expert in makefiles and I do understand the overhead inolved in recursive invocations of "make". However, parallel builds are impossible without recursivity as far as I can tell. Feel free to correct me.--Love4boobies 00:44, 10 April 2010 (UTC)

Make will build anything in parallel, as long as you use -j[N]. Nedbrek 10:47, 12 April 2010 (UTC)

And it's actually the other way around - recursive Makefiles are always in danger of not representing the whole dependency graph, and the more processes you run in parallel, the higher the chances to break something. Monolithic Makefiles don't suffer from this problem.
The parallelity doesn't come from multiple Makefiles being executed in parallel, but in multiple rules being run. (You have 100 .c files to be turned into .o files, so you can run 100 compiler processes if you feel like it.) -- Solar 14:26, 13 April 2010 (UTC)
You are right, of course. Thank you for clearing up how parallel building actually works, Solar.--Love4boobies 09:22, 14 April 2010 (UTC)

Extended todolist...

I disagree with Virtlink's edit [1]. Indeed in the PDCLib makefile that was the "template" for this article, I have two different targets, one for TODO: comments and one for FIXME: comments, as the two represent very different levels of urgency; I only presented one of the two as I felt it would be trivial to adapt this to personal choice. You usually don't want TODOs in a FIXME-list, and vice versa. The -F option may make the grep faster, but I feel it's a bit non-KISS. And while we're at it printing file names, why not line numbers to go? Suggestion:

todolist:
-@for file in $(ALLFILES); do grep -Hn TODO $$file; done; true

This will print a list of all TODO comments from my files, complete with file name and line number. Nice to be remembered what's still missing before you do a release.


'fgrep' seems simple enough, and has advantages, especially when you have a big project to build. On the other hand, '-Hn' (or '-H' for that matter) seems also a bit non-KISS to me, however it may be useful. And it is not that trivial to add another keyword, because you need the '-e' switch for that. To me (any possibly to you too), FIXME's are more urgent than TODO's (in the spirit of 'what's missing before you do a release') so maybe we should use those in the example instead. I suggest the following (or with 'fixme' replaced by 'todo'): Virtlink 16:03, 20 August 2008 (UTC)
fixmelist:
    -@for file in $(ALLFILES); do fgrep -Hn -e FIXME $$file; done; true
This will grep all those FIXME comments from the files and display them in the terminal. It's nice to be remembered of what's still missing before you do a release. To add another keyword, just add another -e keyword. Don't forget to add fixmelist to your .PHONY list.

Bug in Dependencies, pt. 3?

Should

   %.o: %.c Makefile
           @$(CC) $(CFLAGS) -DNDEBUG -MMD -MP -MT "$*.d $*.t" -g -std=c99 -I./includes -I./internals -c $< -o $@

not be

   %.o: %.c Makefile
           @$(CC) $(CFLAGS) -DNDEBUG -MMD -MP -MT "$*.o $*.t" -g -std=c99 -I./includes -I./internals -c $< -o $@

instead? --Mikeroz 01:13, 1 August 2009 (UTC)

Not quite. The $*.d is needed to recreate the dependency file itself. But you are absolutely right that the $*.o was missing. Funny that no-one else pointed this out (and a shame that I didn't figure this one out earlier, especially since I've got a corresponding bug sitting in my PDCLib tracker for ages...). -- Solar 14:27, 19 June 2010 (UTC)

Added "What Is A" and a basic example to aid complete beginners to makefiles

I have added two sections into this article and felt they required a brief spot of justification. Whilst the prerequisites for this wiki include an in-depth knowledge of C, not all flavours of C (maily the Microsoft flavours) use makefiles and some people (like myself) can have survived their whole life of C experience never even having laid eyes on a Makefile. The first section, "What is a Makefile?", is my attempt to bridge this gap and hopefully convey some of the benefits of having one of these. Moving on, I have added the most basic of basic examples that I could think of to address the fact that the first actual look at a makefile appears more than half way down this fairly sizable beginner tutorial document. I hope I'm not treading on anyone's toes here, the tutorial is very good, but speaking from the starting point of my experience it needed this little intro. Feel free to edit or remove.--Kenny 19:12, 19 July 2010 (UTC)

Which make to target?

Should this article target GNU make or POSIX make? I think it wouldn't be bad idea to rewrite this article to conform POSIX, because those features can be trusted to be available unlike some GNU extensions (try to look for pattern rules in pmake, for example), and if someone wants to know if his/her specific make know some fancier tricks, the manual is available. Maybe some tricks could be even shortly listed in the end of the article. After quick skimming I noticed two things which would need changing, pattern rules and usage of := to create macros. IMO at least it should be noted that this article talks about GNU make.

And by the way, usage of = to create macros can also be sign of trying to be portable instead of an error... Fronty 20:58, 6 April 2011 (UTC)

It does say it is targeting GNU make, right in the intro of the Tutorial section. There are several reasons I wrote it like this.
First, I did not write this tutorial in limbo; the example Makefile presented closely reflects the Makefile I use for PDCLib. Any error I find there gets corrected here, too, which likely wouldn't happen if this tutorial were not connected to a "live" Makefile like that. (And there have been a couple of errors over time, like a complete screw-up of dependency handling I would never have discovered if it had been tutorial code only.)
All platforms I have access to, both privately and professionally, have a GNU make installation on them, or could be fitted with one in no time (make being one of the few tools having zero dependencies and making true of the ./configure && make install promise). And figuring out one make manual was quite enough for me. Two reasons I don't feel like digging through other make's manuals to find out the common denominator...
Then there's the thing with common denominators... = may be more portable, but it is also highly inefficient (as the expression gets re-evaluated every time it appears in a rule). There is no such thing as the .PHONY target in POSIX make (I just checked), so you're open for faulty behaviour on that flank.
That's not touching on where I simply prefer the GNU notation (e.g. "%.o: %c") over the POSIX one (".c.o:") for expressiveness.
Bottom line, if you insist on re-structuring this tutorial to target POSIX instead of GNU make, I won't be starting an edit war over it, :but I think GNU make has some distinct advantages. -- Solar 13:15, 7 April 2011 (UTC)
I kind of like the idea of portable makefiles but to be fair, it's better to be practical sometimes. The POSIX make is sort of rudimentary; I don't even know any projects actually trying to achieve make compatibility. Furthermore, most people are turning away from make (IMHO, for good reason). --Love4boobies 15:59, 7 April 2011 (UTC)
"Most people are turning away from make"? Not in the C/C++ world, they don't. (CMake, Automake, they all use make in the end, and I haven't heard of any non-make alternative making the mainstream.) -- Solar 05:15, 8 April 2011 (UTC)
Fair enough but in the same sense that CMake uses make, C compilers usually use assembly. What I meant was that makefiles tend to become very cumbersome for larger projects and that makes people want to learn something else instead. --Love4boobies 08:22, 8 April 2011 (UTC)
I don't understand how I could miss that GNU make really is mentioned. Maybe I really should grep more thoroughly before complaining. :-)
Yes, I missed .PHONY target. That isn't very big problem, though. The trick is to add a dummy dependency which does nothing to a phony target. Maybe it isn't beautiful, but .PHONY IMO is quite ugly too.
I checked out PDCLib to see how much worse would the build time be if all the := would be changed to = when built with GNU make on Ubuntu 10.04 live cd (my FreeBSD installation has some attitude problems right now). Worst differences were about 0.5s, best differences under 0.1s. I got similar results with version Ubuntu stock make (version 3.81) and 3.75 built from source, so I think this isn't due to some relatively new optimization. I don't think that is highly inefficient.
So... Looks like we're going to live rest of our lives happily with our opinions on efficiency and aesthetics and compatibility and hope we don't stomp on other's feet. Fronty 16:50, 9 April 2011 (UTC)
This whole page is for people who want to make a good Makefile, not for comparing build systems in general. Make is quite up to the task, it's just that few people ever bothered to actually learn how to use make efficiently. Oh, and your "trick" for .PHONY doesn't work, if you think about it for a second. (What happens when a file with the name of the dependency exists?) And you can hardly argue with "getting cumbersome for large projects" on the one hand and the comparatively simple PDCLib not making much of a difference on the other hand. Hey, just buy a computer that's twice as fast, and you can get away with crappy algorithms? I don't think so. -- Solar 08:14, 11 April 2011 (UTC)
This whole page is about that, and this whole discussion is about what does a good Makefile mean, and I think we have found out what is public's opinion on that.
Yes, I know the .PHONY "trick" isn't completely foolproof, but IMO double check is good enough in this kind of situation. What the heck are some extra files doing in the source/build directory anyway? This can be always argued, though.
Yes, I understand that PDClib is quite simple project. However, that shows well enough that the impact of the type of macro doesn't have that big impact on build speed that I would care. I don't care if my nightly builds are ready a little earlier or later. Full build won't be once-in-an-hour event while developing, and I'll be making tea or something while my computer is installing something and I don't think someone who has already chosen the slow path will want to stare the compilation the whole time. You won't have anything magical in the macros, maybe to the macros containing list of source and object files will be a bit fancier, but they aren't used very much.
Can I get away with crappy algorithms with faster computer? No. Can I use maybe a little slower algorithm with some good characteristics if the speed difference won't make any difference in that situation and I fancy the good characteristics? Yes. Fronty 13:56, 11 April 2011 (UTC)

Proper use of CFLAGS

I know that using CFLAGS like I did is frowned upon, as it overwrites any environment variable the user might have set. Since I don't feel the pressure in PDCLib, and don't have any other C/C++ project using Makefiles at the moment... does anyone have a canon / working alternative? -- Solar 03:01, 25 May 2012 (CDT)

My personal solution is to have a different named set of flags and append CFLAGS as appropriate:
CPARAMS := "-m32 -DNEEDED_DEFINE -DOTHER_DEFINE -Wall -Wextra -fno-omit-frame-pointer"
(...)
%.o: %.c
    $(CC) $(CFLAGS) $(CPARAMS) -c -o $@ $<
Which under many circumstances has exactly the intended effect, but it does little to prevent conflicting params/flagsets other than hoping they override in order. - Combuster 15:00, 25 May 2012 (CDT)


Oops, somehow I made an earlier comment vanish O.o - Combuster 03:06, 26 May 2012 (CDT)

How about CFLAGS += ...? e.g.

CFLAGS += -g -Wall

make
gcc -g -Wall -o test test.c

CFLAGS=-O3 make
gcc -O3 -g -Wall -o test test.c
Obviously this can lead to errors if the user-specified flags conflict with those you specify. John 06:02, 25 May 2012 (CDT)

Commands Prefixed with @

Is it really a good idea to cause make(1) not to print out the executed commands?

When debugging it's probably better to know which command failed.

When not debugging you can pass the -s to make(1).

Glauxosdever 06:09, 5 September 2016 (CDT)

Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox