Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Make global variables updated in sub-makes

I need some help with my Makefile for a project. The source directory looks something like this.

|-- Makefile
|-- drivers
|   |-- Makefile
|   |-- tty
|       |-- Makefile
|       |-- console.c
|       |-- keyboard.c
|-- kernel
|   |-- Makefile
|   |-- kmain.c

In the top Makefile, I have exported a variable OBJECTS that I want to populate with object files so I can build and link them together in the top Makefile.

I want to update OBJECTS in, say, drivers/tty/Makefile by doing something like this:

OBJECTS += $(CURDIR)console.o
OBJECTS += $(CURDIR)keyboard.o

But the change to OBJECTS does not bubble up to the top Makefile. I've been looking at the Makefiles in the Linux source tree, and they seem to be doing something similar. However, I can't get it to work. Am I missing something here?

like image 264
tobier Avatar asked Sep 13 '25 10:09

tobier


2 Answers

You appear to be using Make recursively, something like

# Makefile:

export OBJECTS :=
all:
    $(MAKE) -C drivers/tty
    @echo OBJECTS is $(OBJECTS)

# drivers/tty/Makefile:

OBJECTS += $(CURDIR)console.o
all:
    whatever

This doesn't work, because each Make has its own OBJECTS; the child Make can't modify variables in the parent Make. It's export, not import/export or share (there's no such thing as import/export or share, I'm just trying to illustrate).

You can get the effect you want by including the other makefiles instead of invoking them:

# Makefile:

OBJECTS :=
all: DRIVERS_TTY
    @echo OBJECTS is $(OBJECTS)

include drivers/tty/Makefile

# drivers/tty/Makefile:

OBJECTS += drivers/tty/console.o

DRIVERS_TTY:
    whatever

You'll notice there is some unpleasant location-dependency there; drivers/tty/Makefile has "drivers/tty" spelled out inside it, which makes maintenance a pain. There are ways to fix that, once you have this basic include trick working.

like image 137
Beta Avatar answered Sep 17 '25 19:09

Beta


When you recursively run make it opens a new subshell for each subsequent call to make so you can't go back up the chain with your exports. One method would be for each call to a submake to append to an object list file and then possibly include that file. A better solution is to probably do something along the lines of having your main makefile include each of these submake files directly instead of calling make on them. This method allows the OBJECTS variable to be built up using the each of the submake files with your OBJECTS += statements. Another added benefit is that you are running just one instance of make instead of multiple submakes which allows make to do better dependency generation. Take a look at "Recursive make considered harmful" http://aegis.sourceforge.net/auug97.pdf

One cool makefile build system that was posted up here before by user Dan Moulding https://stackoverflow.com/users/95706/dan-moulding really showed off a lot of the cool stuff you can do with submake files all while having just one master makefile. Dan's boilermake project is here: https://github.com/dmoulding/boilermake

like image 23
ThePosey Avatar answered Sep 17 '25 19:09

ThePosey