I have several library source code files organized as follows in a separate directory (out of my project src):
/path/to/libsrc/file_clock.c
/path/to/libsrc/file_spi.c
/path/to/libsrc/file_dma.c
/path/to/libsrc/file_i2c.c
etc. and I don't need all of them. For example, I could need only file_clock.c and file_spi.c.
Is it possible to use a list to use only the source code file I need ?
For example, what I would like to is something like:
MODULES = spi clock
C_SRC += $(wildcard /path/to/libsrc/*$(MODULES)*.c)
but this doesnt work since MODULE is a space separated word list.
How can I achieve this if possible ?
Running $(wildcard ...) multiple times is an awful idea. Instead, it could be something like this:
MODULES := spi clock
C_SRC += $(filter $(patsubst %,\%/file_%.c,$(MODULES)),$(wildcard /path/to/libsrc/*.c))
SOLVED:
MODULES = spi clock
C_SRC += $(foreach var, $(MODULES), $(wildcard /path/to/libsrc/*$(var)*.c))
MODULES = spi clock
C_SRC += $(foreach var, $(MODULES), $(wildcard /path/to/libsrc/*$(var)*.c))
This would be the most recommended approach instead of filtering
What about:
C_SRC += $(wildcard $(patsubst %,/path/to/libsrc/file_%.c,$(MODULES)))
Related
I am trying to write a makefile to selectively include a certain file.
I have manage to get it working with the following:
OBJS := $(filter-out ./build/./src/class_1.cpp.o, $(OBJS))
OBJS := $(filter-out ./build/./src/class_2.cpp.o, $(OBJS))
OBJS_1 :=./build/./src/class_1.cpp.o $(OBJS)
OBJS_2 := ./build/./src/class_2.cpp.o $(OBJS)
But I would like to make it more generic and use a wildcard.
My understanding is that the following should work:
OBJS := $(filter-out $(wildcard ./build/./src/*), $(OBJS))
I also tried
OBJS := $(filter-out $(wildcard \./build/\./src/*), $(OBJS))
but not sure if the problem is with the special symbols or just a basic understanding.
however it then complains about having too many main functions (class 1 and class 2).
Is there something that I am missing with my understanding of wildcard and filters in make?
If I print out the value of $(OBJS) with the two different approaches, the values are identical, so I am not sure why one solution could work while the other one fails.
However, for some reason OBJS_1 doesn't seem to get the filter that was applied to $(OBJS)
$(wildcard ...) function finds which files actually exist in the filesystem (and some or all .o files might be created during make's execution, thus the result will be different depending on the last command). This is most certainly not what you want.
In your case you need only to perform the string substitution, and the 'match-all' pattern for strings in make is a percent-sign. So it should be:
OBJS:=$(filter-out ./build/./src/%,$(OBJS))
Also note that spaces in the makefile may have significance. For example, $(filter a, b) means that the second argument is " b", not just "b". Even though it wouldn't matter in your case, you should be more cautious with spaces.
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
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.
I have a bunch of libraries that I want to build as dependencies:
LIBS = libs/foo libs/bar
Each library has an object that I need to compile against, all in a predictable spot. They are:
libs/foo/lib/libfoo-O3.a
libs/bar/lib/libbar-O3.a
I would like to effectively transform my LIBS string into these rules:
build : libs/foo/lib/libfoo-O3.a libs/bar/lib/libbar-O3.a
libs/foo/lib/libfoo-O3.a:
$(MAKE) -C libs/foo
libs/bar/lib/libbar-O3.a:
$(MAKE) -C libs/bar
I know you can't use % twice, so unfortunately libs/%/lib/lib%-O3.a is a non-starter as a target. Is there another way to do this? Something with a define template?
If you can change the LIBS variable to just contain the name, you can do it easily:
LIBS = foo bar
LIBPATHS := $(foreach L,$(LIBS),libs/$L/lib/lib$L-O3.a)
If you can't you can still do this, only slightly less readable:
LIBS = libs/foo libs/bar
LIBPATHS := $(foreach L,$(LIBS),$L/lib/lib$(notdir $L)-O3.a)
Then just add something like:
$(LIBPATHS):
$(MAKE) -C $(firstword $(subst /lib/, ,$#))
My makefile looks something like this:
FOO_OBJECT_FILES := $(OBJDIR)/Foo.cpp.o
BAR_OBJECT_FILES := $(OBJDIR)/Bar.cpp.o $(OBJDIR)Bar.c.o
ALL_OBJECT_FILES := $(FOO_OBJECT_FILES) $(BAR_OBJECT_FILES)
$(BINDIR)/Foo.a: $(FOO_OBJECT_FILES)
# Rules for making a static library out of Foo's object files go here.
$(BINDIR)/Bar.a: $(BAR_OBJECT_FILES)
# This uses the exact same command sequence as the previous rule.
$(BINDIR)/All.a: $(ALL_OBJECT_FILES)
# Ditto.
# ...
When (not if) more targets are added to the project, the developer will have to update at least three things:
The list of the new target's object files
The list of all object files
Targets for making the new target, even if it uses the same rules as the others
Is there a way to simplify this process, or am I stuck with it?
I tried using wildcard rules, but it doesn't look like they work with macros.
$(BINDIR)/%.a: $(%_OBJECT_FILES)
# ...
You could treat the lists of object files as rules, but then the final target rules can't access them directly.
OBJECT_FILES_Foo: $(OBJDIR)/Foo.cpp.o
OBJECT_FILES_Bar: $(OBJDIR)/Bar.cpp.o $(OBJDIR)Bar.c.o
OBJECT_FILES_All: FOO_OBJECT_FILES BAR_OBJECT_FILES
$(BINDIR)/%.a: OBJECT_FILES_%
# This rule can't see into the object file lists to use them to build.
Is there no better way?
There are probably plenty of ways to do this. One such way is the following. All that needs to be done for a new target is add its name to the list of modules, and give the list of dependencies for it.
BINDIR := bin
OBJDIR := obj
MODULES := Foo Bar
Foo_OBJS := $(OBJDIR)/Foo.cpp.o
Bar_OBJS := $(OBJDIR)/Bar.cpp.o $(OBJDIR)/Bar.c.o
#####################################################
# #
# Nothing below here should need to be altered. #
# #
#####################################################
All_OBJS := $(foreach mod, $(MODULES),$($(mod)_OBJS))
define rule
$(BINDIR)/$(1).a: $($(1)_OBJS)
#echo
#echo 'Target: $$#'
#echo 'Deps : $$^'
endef
$(foreach lib, All $(MODULES), $(eval $(call rule,$(lib))))
###########################################
# #
# The next part is just here for testing. #
# #
###########################################
.PHONY: all
all: $(foreach lib, All $(MODULES),$(BINDIR)/$(lib).a)
%.o:
#echo Making $#
You can't do much about 1 and 2, those are arbitrary things that Make cannot possibly deduce. You can improve 3 slightly:
$(BINDIR)/%.a:
# commands for making a static library
# adding a new target:
QUARTZ_OBJECT_FILES := $(OBJDIR)/Quartz.cpp.o $(OBJDIR)Arbitrary.o
ALL_OBJECT_FILES += $(QUARTZ_OBJECT_FILES)
$(BINDIR)/Quartz.a: $(QUARTZ_OBJECT_FILES)
You could use a template to reduce those three lines to one:
$(eval $(call template, QUARTZ_OBJECT_FILES, $(OBJDIR)/Quartz.cpp.o $(OBJDIR)Arbitrary.o))
but is it really worth it?
While the other answers have provided good solutions for manual makefile writing, you could simply use automake to ease the build process.
I have a C++ library built using a Makefile. Until recently, all the sources were in a single directory, and the Makefile did something like this
SOURCES = $(wildcard *.cpp)
which worked fine.
Now I've added some sources that are in a subdirectory, say subdir. I know I can do this
SOURCES = $(wildcard *.cpp) $(wildcard subdir/*.cpp)
but I'm looking for a way to avoid specifying subdir manually, that is, make wildcard look into subdirectories, or generating a list of subdirectories somehow and expanding it with several wildcard functions. At this point, having a non-recursive solution (that is, expanding only the first level) would be fine.
I haven't found anything - my best guess is using find -type d to list the subdirectories, but it feels like a hack. Is there any built-in way to do this?
This should do it:
SOURCES = $(wildcard *.cpp) $(wildcard */*.cpp)
If you change you mind and want a recursive solution (i.e. to any depth), it can be done but it involves some of the more powerful Make functions. You know, the ones that allow you to do things you really shouldn't.
EDIT:
Jack Kelly points out that $(wildcard **/*.cpp) works to any depth, at least on some platforms, using GNUMake 3.81. (How he figured that out, I have no idea.)
Recursive wildcards can be done purely in Make, without calling the shell or the find command. Doing the search using only Make means that this solution works on Windows as well, not just *nix.
# Make does not offer a recursive wildcard function, so here's one:
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
# How to recursively find all files with the same name in a given folder
ALL_INDEX_HTMLS := $(call rwildcard,foo/,index.html)
# How to recursively find all files that match a pattern
ALL_HTMLS := $(call rwildcard,foo/,*.html)
The trailing slash in the folder name is required. This rwildcard function does not support multiple wildcards the way that Make's built-in wildcard function does, but adding that support would be straightforward with a couple more uses of foreach.
If you don't want to use recursive makefiles, this might give you some ideas:
subdirs := $(wildcard */)
sources := $(wildcard $(addsuffix *.cpp,$(subdirs)))
objects := $(patsubst %.cpp,%.o,$(sources))
$(objects) : %.o : %.cpp
You can use several rules in wildcard:
SOURCES := $(wildcard *.cpp */*.cpp)
if you need more depth:
SOURCES := $(wildcard *.cpp */*.cpp */*/*.cpp */*/*/*.cpp)
Unfortunately, and unlike what we sometimes read, glob (**) is not supported by makefile and will be interpreted as normal wildcard (*).
For example **/*.cpp match dir/file.cpp but neither file.cpp nor dir/sub/file.cpp.
If you need infinite depth use shell and find:
SOURCES := $(shell find . -name "*.cpp")
Common practice is to put a Makefile in each subdir with sources, then
all: recursive
$(MAKE) -C componentX
# stuff for current dir
or
all: recursive
cd componentX && $(MAKE)
# stuff for current dir
recursive: true
It may be wise to put settings for each Makefile in a Makefile.inc in the root source directory. The recursive target forces make to go into the subdirectories. Make sure that it doesn't recompile anything in a target requiring recursive.
If you can use find shell command, you may define a function to use it.
recurfind = $(shell find $(1) -name '$(2)')
SRCS := $(call recurfind,subdir1,*.c) $(call recurfind,subdir2,*.cc) $(call recurfind,subdir2,*.cu) \
...