Variable arguments list to a Makefile - makefile

I would like do something like following. I would like to have a variable argument list for a Makefile.
make VAR_ARG_LIST=src1,src2,src3,src4
Can I do like this? If I can, how do I extract src1,src2 or src3 from the variable VAR_ARG_LIST inside the Makefile?
Thanks,

If you want a list of targets in a macro for make to use, use blanks to separate them (and quotes to enclose them) on the command line:
make VAR_ARG_LIST="src1 src2 src3 src4"
This can be used inside the makefile without much trouble at all:
PROGRAMS = ${VAR_ARG_LIST}
all: ${PROGRAMS}
and it will go off and create the programs src1, ... src4 from the rest of the rules in the makefile.
If that isn't roughly what you're after, then you need to clarify your question.

You really haven't provided enough information for a solution. Why do you want to extract those values? What do you want to do with them?
However, I can answer the question you asked and hope it is useful. If you're using GNU make you can do this:
COMMA := ,
VAR_ARG_LIST_A := $(subst $(COMMA), ,$(VAR_ARG_LIST))
VAR_ARG_LIST_1 := $(word 1,$(VAR_ARG_LIST_A))
VAR_ARG_LIST_2 := $(word 2,$(VAR_ARG_LIST_A))
etc.

Related

How can I add a directory to the search path of GNU Make?

I have a makefile that looks something like this:
include anotherFile.mk
all:
someStuff
The file anotherFile.mk is like this:
include yetAnotherFile.mk
export SOME_VAR = 93
The problem is that anotherFile.mk and yetAnotherFile.mk are in a different directory from my Makefile. So my makefile can't just be changed to this:
include $(OTHER_PROJECT_PATH)/anotherFile.mk
all:
someStuff
The problem with this approach is that the include statement in anotherFile.mk will fail because it will be searching in the current directory.
A partial solution that I found is to pass the --include-dir=$OTHER_PROJECT_PATH flag to the invocation of make, but that's a bit user-unfriendly.
So my question is: Is there something I can put inside my makefile that will add to the directories that make searches for when executing an include? Something like MAKE_INCLUDE_DIRS += $(OTHER_PROJECT_PATH)
Surprisingly there doesn't seem to be a good answer to that question. Forcing .INCLUDE_DIR doesn't help and there doesn't seem to be any way around invoking make with --include-dir=$OTHER_PROJECT_PATH.
It is however possible to put the appropriate recursive make invocation inside the makefile but, in order to get it to work for all reasonable cases it quickly becomes too complicated to be worth it. In summary it requires:
a top level condition to check if the OTHER_PROJECT_PATH is in .INCLUDE_DIR
the appropriate target with the recipe invoking make recursively
possibly additional targets if there are multiple command goals
the real make file enclosed in the else part of the conditional
You Makefile would look like this:
OTHER_PROJECT_PATH := other
ifeq (,$(filter $(OTHER_PROJECT_PATH), $(.INCLUDE_DIRS)))
# this is the mechanism to add the include dir in a recursive make
$(or $(firstword $(MAKECMDGOALS)),all):
$(MAKE) -I$(OTHER_PROJECT_PATH) $(MAKECMDGOALS)
# add empty targets for additional goals if needed
ifneq (,$(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)))
$(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)):
endif
else
# this is where the real makefile starts
all more:
echo $#: $< $^
include a.mak
endif
It still does not seem possible from a makefile, but if you have a script that sets up environment variables, you can use MAKEFLAGS (e.g. export MAKEFLAGS=I/your/path ordentlich on Linux, or SET on Windows)

How to check whether a file exists inside of a "foreach" in Makefile?

So I have a variable with file names, however I am not sure whether these file names exist. I want to put the ones that exist into some other variable.
All this is happening in a Makefile.
Here is one of my many tries to accomplish it:
FILES is the preset variable containing the set of the files.
OUTPUT += $(foreach file, $(FILES), \
ifneq (,$(wildcard $(file))
$(file)
endif
Obviously it doesn't work for many reasons, just trying to make clear what I want to achieve.
Also I would like to avoid using $(shell *) if possible.
Thanks!
The wildcard function takes multiple targets, and unlike shell globs non-matching patterns are omitted from the output, so I would expect this to work:
OUTPUT = $(wildcard $(FILES))

How to define a variable which is every file except this one

I am using gnu make.
I have a rule like this:
SOURCES=*.in
output:$(SOURCES)
$(PROCESSOR) -i $(SOURCES)
This works well. Now I need to exclude one file, test.in, from SOURCES, how should I update the rule above?
[UPDATE]
Actually the problem changes a bit, I need to read an environment variable, based on its value, I either take all files with ".in" as postfix or exclude test.in.
Could you show me how to do this?
Using some of the built-in functions:
SOURCES := $(filter-out $(if $(filter val,$(env_var)),test.in),$(wildcard *.in))
If you only want this to apply to that single rule:
output: $(filter-out $(if $(filter val,$(env_var)),test.in),$(SOURCES))
where env_var is the environment value to check, and val the value. If you want a partial match then replace filter with findstr. You can split the definition into multiple statements and / or ifeq if the one-liner is too cryptic.

Filtering using multiple wildcards

I've git a project where, at some point in its Makefile, I'm filtering out stuff from a certain directory:
relevant = $(filter-out irrelevant/%,$^)
Now I want to use this in a VPATH-enabled environment. So the paths of my dependencies in $^ might not start with irrelevant any more, but instead something like ../src/irrelevant or similar.
Is there a way to filter-out anything that contains irrelevant, in any position? I.e. something like the following?
relevant = $(filter-out %irrelevant/%,$^)
This doesn't work, since apparently patterns for filter-out can contain only a single % wildcard. I know I could possibly achieve this via a shell invocation, grep or whatever, but I was hoping for some combinations of functions inside the Makefile.
Try
relevant = $(foreach a,$^,$(if $(findstring irrelevant,$a),,$a))

multiple makefiles same variable names

im trying to write a non recursive make build system.
what im trying to accomplish is that each makefile will define its own variables and "feel" like he is the only one in the system.
for example:
Project layout:
-Makefile
-src1
----Makefile
----example1.c
-src2
----Makfile
----example2.c
the main Makefile looks like this:
include src1/Makefile
include src2/Makefile
all: $(TARGETS)
each of src1/src2 makefile looks like this:
SRC:=...
OBJ:=...
TARGETS+=bin1 #in src2 its bin2
bin1: $(OBJ)
----gcc ....
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c
----gcc ....
but this design pattern does not work as the evaluation of recipe in the targets is deferred.
this means all the variables with the same name in src1 gets the value of src2 variables(the last assignment). i tried to replace the include with $(eval include ...) but no luck.
please note that all the variables assignment is done with :=
is there a way to accomplish that each makefile can define what he wants or each variable should be unique?
thanks,
tal
It's difficult to do that. When I've done this in one or two places I've started with make snippets in each directory that can be included from the master make file, and ended up with a scripted approach which scans the make snippets and generates something else. And I had a VPATH in there as well.
There's an example of how this might be achieved in the 'recursive make considered harmful' paper which might be of help.

Resources