Makefile Question

Programming, for all ages and all languages.
User avatar
MuchLearning
Member
Member
Posts: 26
Joined: Sun Feb 12, 2017 1:50 am

Makefile Question

Post by MuchLearning »

Looking through the MeatySkeleton example and noticed that the makefile for libc manually lists all the object files in sub directories like this

Code: Select all

FREEOBJS=\
$(ARCH_FREEOBJS) \
stdio/printf.o \
stdio/putchar.o \
stdio/puts.o \
stdlib/abort.o \
string/memcmp.o \
string/memcpy.o \
string/memmove.o \
string/memset.o \
string/strlen.o \

libk.a: $(LIBK_OBJS)
	$(AR) rcs $@ $(LIBK_OBJS)
As the project grows in size this will become more and more tedious to maintain. Surely there is a way to tell Make about a directory and have it grab all object files in said directory?

Any help is appreciated, thanks.
User avatar
MuchLearning
Member
Member
Posts: 26
Joined: Sun Feb 12, 2017 1:50 am

Re: Makefile Question

Post by MuchLearning »

Would something like this work?

Code: Select all

$(shell find . -name *.o)
Last edited by MuchLearning on Tue May 02, 2017 12:07 am, edited 2 times in total.
StudlyCaps
Member
Member
Posts: 232
Joined: Mon Jul 25, 2016 6:54 pm
Location: Adelaide, Australia

Re: Makefile Question

Post by StudlyCaps »

Your snippet won't work I think, because you're searching for existing .o files which won't have been generated yet (.o files are intermediate results of compilation). At least it won't work on a clean build.

Generally, most build systems require you to explicitly define all targets, getting clever with autodetecting tends to introduce hard to find bugs in the build process. A decent compromise though is to use the include directive in your Makefile to separate out your list of .o files from the main build directives.

In your example, you might put a file in each directory (for example "stdio/mkconfig", "stdlib/mkconfig", "string/mkconfig") in the mkconfig files you can append to the FREEOBJS variable (FREEOBJS += stdio/printf.o stdio/putchar.o stdio/puts.o) then in your main Makefile simple put one "include <dir>/mkconfig" for each sub-directory.

Then the file listing the .o files is kept with the source .c files, and each one has a smaller list which is easier to maintain.

As far as it getting tedious, it can be, but typically once you've established the structure of a project you spend much more time editing existing files than adding new ones and it only takes a second to add another line to define a new dependency.
User avatar
MuchLearning
Member
Member
Posts: 26
Joined: Sun Feb 12, 2017 1:50 am

Re: Makefile Question

Post by MuchLearning »

Thanks! This is probably what I will do.

Just for fun though, I think I found something that almost works for including all possible object files.

Code: Select all

$(patsubst %.c,%.o,$(wildcard *.c))

From GNU Make Docs, this should select all .c files using the wildcard function, then replace the .c file extensions with .o, thus generating a list of all obj files from c files?

Even if this works it isn't recursive though and each directory would have to be specified by hand. Unacceptable!
StudlyCaps
Member
Member
Posts: 232
Joined: Mon Jul 25, 2016 6:54 pm
Location: Adelaide, Australia

Re: Makefile Question

Post by StudlyCaps »

That is a cool function. I always meant to learn more about make's string manip. functions, but when I come to use them in actual projects though I almost always end up finding some special case that needs to be handled and I just give up and declare everything explicitly. :lol:
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Makefile Question

Post by Solar »

I have used find and wildcarding myself, so this is very much a case of "do as I say, not as I do".

But listing all source files *explicitly* has its advantages.

For one, you get notified if one of the source files has been moved, renamed, or deleted. That might have been unintentional, and could have subtle impacts on your product.

Second, you might be looking at temporary stuff, like generated sources, "testme.c" one-offs and similar, which you don't *want* to be caught by your generic Makefile rules.

I'm not saying that find / wildcard are bad, or shouldn't be used. Just be aware what you're doing.

(Today I am using JAWS / CMake, and *do* list each source file and header file individually.)
Every good solution is obvious once you've found it.
User avatar
Sik
Member
Member
Posts: 251
Joined: Wed Aug 17, 2016 4:55 am

Re: Makefile Question

Post by Sik »

There's also the part where you explicitly need to make rules for each .o file anyway just to indicate their own dependencies (usually its matching .c file and the non-system header files it includes), so it's not like you completely avoid the headache (not to mention having to keep them up to date in case the dependencies ever change, e.g. an #include was added to the source file). It'd be more useful to get a list of .o file with a rule (and even then it assumes you want to include every single .o file, which is probably not the case for anything with multiple targets).

At this point it's easier to just generate the makefile automatically to ensure everything is kept up to date (which is what all those building tools like cmake ultimately aim to do).
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

Re: Makefile Question

Post by obiwac »

This may be entirely subjective, but I personally prefer having control on what files I want linked. For example, if you have a file that is not finished, and you start work on something else, it's nice to not have it crash your os or something like that.
User avatar
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

Re: Makefile Question

Post by eryjus »

For me personally, I despise maintaining my makefiles with each file addition/deletion/movement. I'm far more apt to forget to make the additional changes than I am to have a problem with linking the incorrect object. Also, running `make xxxx` is very tightly integrated into my iterative development workflow, where I could easily run make a hundred times a day just as a spell-checker. Instead, I would rather spend my makefile time working on the rules for a distinct target and what that all entails, so that if I add a file in to a location, it just works; if I move a file, it just works. If I move a header, well I have to run `make clean` first to address the dependencies, but then it just works.

That does not imply that my makefile is simplistic -- quite the contrary. But, I do not have to maintain it with every change I make. I would like to believe that I have a pretty robust build system as a result. You can see it here: https://github.com/eryjus/century/blob/master/Makefile
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

Re: Makefile Question

Post by obiwac »

Good point. You made me rethink my workflow.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Makefile Question

Post by Solar »

Sik wrote:There's also the part where you explicitly need to make rules for each .o file anyway just to indicate their own dependencies (usually its matching .c file and the non-system header files it includes)...
You do know about things like GCC's -MMD -MP option giving you the header dependencies of a source file, as a side-effect of compilation? If you did not know, check the Makefile tutorial in the OSDev Wiki (Dependencies pt. 1 through pt. 3). There are reasons to have explicit rules for specific object files, but header dependencies shouldn't be among them. (And no-one is better at figuring them out than the compiler.)
Every good solution is obvious once you've found it.
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Makefile Question

Post by Octocontrabass »

Solar wrote:(And no-one is better at figuring them out than the compiler.)
Except maybe tup.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Makefile Question

Post by Solar »

Well, what the compiler is actually including is what counts regarding logical dependencies, and no-one -- not even tup -- knows better what the compiler includes than the compiler itself.
Every good solution is obvious once you've found it.
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: Makefile Question

Post by dozniak »

According to tip docs it instruments file opening and as such also knows all files open by the compiler, not only direct depwndencies but perhaps library files and other binaries.
Learn to read.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Makefile Question

Post by Solar »

And while a commendable effort, it is still being educated guesswork. The -M options are making the compiler tell what it's doing, with regards to header files. :wink:
Every good solution is obvious once you've found it.
Post Reply