I would like to apply the 'notdir'-function to a list of files I obtain from a wildcard match. While '$(notdir $(wildcard dir/*.tst))' works, I do not manage to first store the list in a variable ('FILES' in the Makefile below) that then is processed by $(notdir ...). Using the variable directly ('$(notdir $(FILES))') results in the wildcard being returned, using value ('$(notdir $(value $(FILES)))') yields an empty result.
.PHONY: show
FILES := dir/*.tst
FILES2 := dir/a.tst dir/b.tst
#NAMES := $(notdir $(FILES))
NAMES1 := $(notdir $(value $(FILES)))
NAMES2 := $(notdir $(FILES2))
NAMES3 := $(notdir $(wildcard dir/*.tst))
show:
#echo "FILES: " $(FILES)
#echo "NAMES1: " $(NAMES1)
#echo "NAMES2: " $(NAMES2)
#echo "NAMES3: " $(NAMES3)
I also tried $(notdir $(eval $$(FILES))), but this results in a "missing separator" error.
What am I missing here? I'd have expected that value would do the job...
Try the following:
FILES := $(wildcard dir/*.tst)
NAMES := $(notdir ${FILES})
Related
I have a makefile that gives me the source files in a hierarchy.
SRCS := $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/*/*.c)
gives me
./src/main.c ./src/add/add.c ./src/sub/sub.c
I want to flatten the object files into a single "obj" directory.
Of course
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.obj)
gives me
./obj/main.obj ./obj/add/add.obj ./obj/sub/sub.obj
instead of desired
./obj/main.obj ./obj/add.obj ./obj/sub.obj
Question: How do I get rid of additional source directory levels?
Never had to use complex substitution so far. My intuitive try with additional "/%" in pattern
# won't work as expected:
OBJS := $(SRCS:$(SRC_DIR)/%/%.c=$(OBJ_DIR)/%.obj)
produces no meaningful result (${OBJS} becomes same as ${SRCS}).
All examples I found so far only have single occurance of "%" in match pattern.
MAK_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
SRC_DIR = $(MAK_DIR)./src
OBJ_DIR = $(MAK_DIR)./obj
# gives: ./src/main.c ./src/add/add.c ./src/sub/sub.c
SRCS := $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/*/*.c)
# gives: ./obj/main.obj ./obj/add/add.obj ./obj/sub/sub.obj
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.obj)
.PHONY : all
all :
#echo $(SRCS)
#echo $(OBJS)
Just use the notdir function, and also patsubst, more powerful (and that I find easier to understand than the shorthand):
OBJS := $(patsubst %.c,$(OBJ_DIR)/%.obj,$(notdir $(SRCS)))
But it is not the whole story because later on you will probably want to do something like:
$(OBJ_DIR)/%.obj: $(SRC_DIR)/%.c
which will not work any more. Not mentioning the fact that you could have several source files with the same name in different directories. Assuming you do not have such names conflicts you can generate all your dependencies using foreach-eval-call:
MAK_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
SRC_DIR := $(MAK_DIR)./src
OBJ_DIR := $(MAK_DIR)./obj
SRCS := $(shell find $(MAK_DIR) -type f -name '*.c')
OBJS := $(patsubst %.c,$(OBJ_DIR)/%.obj,$(notdir $(SRCS)))
.PHONY: objs
objs: $(OBJS)
# $(1): source file
define DEP_rule
$(1)-obj := $$(patsubst %.c,$$(OBJ_DIR)/%.obj,$$(notdir $(1)))
$(1)-dep := $$(patsubst %.c,$$(OBJ_DIR)/%.d,$$(notdir $(1)))
$$($(1)-obj): $(1) $$($(1)-dep)
endef
$(foreach src,$(SRCS),$(eval $(call DEP_rule,$(src))))
Just remember that the DEP_rule macro gets expanded twice, thus the $$.
I have, in the main repository some subdirectories called assignment_1, assignment_2, ..., assignment_n.
I'm tring to write a Makefile that compiles the all TeX files inside those subdirectories.
This is what I have so far, but it doesn't work:
.PHONY: papers clean
PUBLISH_DIR := publish
TEX_DIR := .tex
SRC_DIR := assignment_$(wildcard *)
SRC_FILES := $(wildcard $(SRC_DIR)/*.tex)
CC := xelatex
FLAGS := -shell-escape -output-directory=$(TEX_DIR)
all: $(patsubst $(SRC_DIR)/%.tex, $(PUBLISH_DIR)/%.pdf, $(SRC_FILES))
$(PUBLISH_DIR)/%.pdf: $(SRC_DIR)/%.tex
mkdir -p $(TEX_DIR)
$(CC) $(FLAGS) $<
$(CC) $(FLAGS) $<
mkdir -p $(PUBLISH_DIR)
mv $(TEX_DIR)/*.pdf $(PUBLISH_DIR)/
clean:
rm -rf $(PUBLISH_DIR) $(TEX_DIR)
If I change this line
SRC_DIR := assignment_$(wildcard *)
with
SRC_DIR := assignment_1
it works beautifully but (obviously) only with the TeX file inside assignment_1.
Beside traversing the subdirectories, is there anything else I can improove in this Makefile?
I think you should modify your wildcard:
SRC_DIR := assignment_$(wildcard *)
to
SRC_DIR := $(wildcard assignment_*)
If $(wildcard *) expands to 1 2 3 then assignment_$(wildcard *) will expand to assignment_1 2 3 which is clearly not what you want.
Try this:
SRC_DIR := $(addprefix assignment_,$(wildcard *))
to add the assignment_ prefix to the start of each word.
In the following example Makefile:
EXTENS := .c .C .cc .c++ .cpp .cxx
SOURCES := 1.c 2.C 3.cc 4.c++ 5.cpp 6.cxx
OBJECTS := $(SOURCES)
REPLACE_EXTENS = $(foreach f,$(EXTENS),$(eval $(1) := $(patsubst %$(f),%.o,$($(1)))))
$(call REPLACE_EXTENS, OBJECTS)
all:
#echo $(SOURCES)
#echo $(OBJECTS)
I expect the line #echo $(OBJECTS) to output:
1.o 2.o 3.o 4.o 5.o 6.o
However it outputs nothing. What I am doing wrong and what would be the correct way to do it?
Change $(call REPLACE_EXTENS, OBJECTS) into $(call REPLACE_EXTENS,OBJECTS). No whitespace between arguments for call.
The right way to to do this is to throw out the EXTENS and REPLACE_EXTENS call completely, and write:
SOURCES := 1.c 2.C 3.cc 4.c++ 5.cpp 6.cxx
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))
all:
#echo $(SOURCES)
#echo $(OBJECTS)
I am using gnu make.
I have version like this:
MYLIST := $(filter-out $(if $(filter 1,$(exclude_file1)), file1.c),$(wildcard *.c))
It works well: when I what to filter out "file1.c", I set the environment variable, exclude_file1.
Now I want the opposite: when an environment variable is not set, I want to exclude file1.c.
Could you point me what should be the change?
MYLIST := $(filter-out $(if $(filter undefined,$(origin exclude_file1)),,file1.c),$(wildcard *.c))
or
MYLIST := $(filter-out $(if $(filter-out undefined,$(origin exclude_file1)),file1.c),$(wildcard *.c))
or
MYLIST := $(filter-out $(if ${exclude_file1},,file1.c),$(wildcard *.c))
etc.
One advantage of the first two formulations is that they don't generate a message when the very useful --warn-undefined-variables is in effect.
I have a make variable containing a list of files with one file per line and I'd like to join all of them into a single-line space-separated list.
The following excerpt was a naive attempt to do that, without success.
define FILELIST
src/foo.c
src/bar.c
src/frobnicator.c
endef
empty :=
space := $(empty) $(empty)
$(subst \n,$(space),$(FILELIST))
define FILELIST
src/foo.c
src/bar.c
src/frobnicator.c
endef
$(info FILELIST=$(FILELIST))
F1 := $(foreach w, $(FILELIST), $(strip $(w)))
$(info F1=$(F1))
FILELIST := $(strip $(F1))
$(info FILELIST=$(FILELIST))
result:
FILELIST= src/foo.c
src/bar.c
src/frobnicator.c
F1= src/foo.c src/bar.c src/frobnicator.c
FILELIST=src/foo.c src/bar.c src/frobnicator.c