Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I have local variables in included makefiles?

I am looking after a system with many hundreds of c files in many folders, there are multiple targets so not all the c files are required in each build.

Because not all files are required I cannot use a pure recursive build. And I don't want to do that, because I would rather not have a slow serial build with mystic dependencies anyway.

What I have come up with broadly is a top level makefile where I pull in a list of folders and include a makefile from each of these folders.

SUB_MAKEFILES := $(foreach subdir,$(SUBDIRS), $(subdir)/subdir.mk)
-include $(SUB_MAKEFILES)

Some folders have specific files to compile so the included file is pretty simple;

srcs += path/a.c path/b.c
deps += path/a.d path/b.d
objs += op/path/a.o op/path/b.o

op/path/%.o: path/%.c path/subdir.mk
   compile ...

I do not want to do this dozens of times so I have a generic pattern I use for folders where everything is to be compiled;

PATH155 := src/f1/f2/f3/f4

srcs += $(shell $(FFshell) $(PATH155) -maxdepth 1 -name '*.c')
deps += $(addprefix ${OUT_DIR}, $(patsubst %.c,%.d,$(shell $(FFshell) $(PATH155) -maxdepth 1 -name '*.c')))
objs   += $(addprefix ${OUT_DIR}, $(patsubst %.c,%.o,$(shell $(FFshell) $(PATH155) -maxdepth 1 -name '*.c')))

$(OUT_O_DIR)$(PATH155)/%.o: $(PATH155)/%.c $(PATH155)/subdir.mk
    gcc -c $(CFLGS) -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"

This works, however I would like to avoid having to make up a random unique name for the path where the subdir.mk file resides.

Is there anyway to replace "PATH155673423 := hand/entered/path" with something like "local SUBDIRPWD = $(some function...)".

Then I could just drop in a generic makefile and include it, no error prone typing of paths nor worries that I will get a unique name clash.

It would be nice to have a few less directory scans too, same issue really, need a local variable.

Even some sort of macro for the repeated variable names etc would be better

Maybe there is a way to include the makefiles in a loop instead and set a path variable just before each is included?

Ta

Chris

like image 403
Chris Aaaaa Avatar asked Oct 02 '15 09:10

Chris Aaaaa


People also ask

What does Includes do in a makefile?

The include directive tells make to suspend reading the current makefile and read one or more other makefiles before continuing. The directive is a line in the makefile that looks like this: include filenames … filenames can contain shell file name patterns.

What does $@ mean in makefiles?

The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run. $%

How do I get environment variables in makefile?

If you've not exported the environment variable, it is not accessible until you do export it, or unless you pass it explicitly on the command line: make DEMOPATH="${demoPath}" … If you are using a C shell derivative, substitute setenv demoPath /usr/local/demo for the export command.


1 Answers

There is no such thing as variables scoped to a particular makefile, such as you're suggesting. However, you have a lot of options for making this work, from constructed variables to give scope, to using eval to generate functions. For example, something like this:

SUBDIRS := foo bar biz baz

define INCLUDE_FILE
path = $S
include $S
endef

$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))

You can find out more about these by looking through this set of blog posts and the associated sections of the GNU make manual.

like image 89
MadScientist Avatar answered Oct 10 '22 13:10

MadScientist