foreach in Makefile not finding all files - c++

I am trying to write a generic Makefile and trying to use "foreach" to search all files in my project. There are about 250 files in multiple directors but I can't seem to be able to get this right. Any ideas why it is not working?
SRCDIRS = ./Src
SRCEXTS = .c .cpp
HDREXTS = .h
SOURCES = $(foreach $(SRCDIRS),$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
HEADERS = $(foreach $(SRCDIRS),$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))
Thanks!

I think you want something like this:
SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*, $(SRCEXTS))))
HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*, $(HDREXTS))))

wildcard can't search file recursively. So the files in sub-directory can't be found.
CPP_SRCS = $(shell find . -iname "*.cpp")
works.

Related

How to use GNU Make filter-out a list of files from a directory?

I have a list of cpp files that I want to exclude from my Makefile. I can't apply a wildcard as in this question; instead, I want to exclude a list of specific file names. How do I do that?
This doesn't seem to work.
SRCDIR = ../src
EXCLUDE := file1.cpp,file2.cpp,file3.cpp
SRCS = $(shell find $(SRCDIR) -name '*.cpp')
SRCS := $(filter-out $(SRCDIR)/$(EXCLUDE) , $(SRCS))
Looking at the documentation, multiple files can be filtered as:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects))
So my question pretty much becomes whether there is a way to exclude ../src/file1.cpp, ../src/file2.cpp, ../src/file3.cpp by loading value from the variable SRCDIR?
You probably want something like:
SRCS := $(filter-out $(EXCLUDE:%=$(SRCDIR)/%),$(SRCS))

c++ makefile using gcc - generate source file list from a list of subfolders

So I have some rules that work:
# Folders
SRCDIR = src
SUBFOLDERS = test test/test2
OBJDIR = obj
# Just for me so I can read my own makefile :o
_TARGET = $#
_DEPEND = $<
# Get sources from /src and /src/test/ and /src/test/test2/
SOURCES = $(wildcard $(SRCDIR)/*.cpp ))
SOURCES = $(wildcard $(SRCDIR)/test/*.cpp ))
SOURCES = $(wildcard $(SRCDIR)/test/test2/*.cpp ))
OBJECTS = $(addprefix $(OBJDIR)/, $(patsubst src/%, %, $(SOURCES:.cpp=.o))
# Main target 'make debug'
debug: debugging $(OBJECTS)
#echo building: gcc $(OBJECTS) -o out.exe
# Compiling each file
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
g++ -c $(_DEPEND) -o $(_TARGET)
debugging:
#echo $(SOURCES)
#echo $(OBJECTS)
Note: I had to hand-copy this code so there may be some errors, but hopefully its clear what I am trying to do.
Lets say I want to add some more source file sub folders: src/another, src/andanother. Now I have to add more SOURCES = ... lines to do this. Is there a way to do this in a rule. I have been tinkering with it but I can't come up with rules that work yet. What I want is that I add a new folder to SUBFOLDERS list and my code picks up the .cpp files automatically.
note I don't want to use things like $(shell find ... ) because windows find sucks and I want this to be as portable as possiblt windows/Linux.
You can use make's foreach.
like:
SOURCES = $(foreach dir,${SUBFOLDERS},$(wildcard ${dir}/*.cpp))
more info:
https://www.gnu.org/software/make/manual/html_node/Foreach-Function.html

Makefile to build C and CPP files

I have been looking for a Makefile to compile a huge project which contains lots of C and C++ files. I have used Eclipse to compile it successfully but I want to go to a standalone Makefile.
I found this generic Makefile that works really well with my project except it can only compile C or C++ files but not both in one run...so it fails at Linking time.
The bits of original Makefile that compile for CPP or C:
SRC_EXT = cpp
OURCES = $(shell find $(SRC_PATH)/ -name '*.$(SRC_EXT)' -printf '%T#\t%p\n' \
SOURCES = $(shell find $(SRC_PATH)/ -name '*.$(CPP_EXT)' -o -name '*.$(C_EXT)' -printf '%T#\t%p\n' \
| sort -k 1nr | cut -f2-)
# fallback in case the above fails
rwildcard = $(foreach d, $(wildcard $1*), $(call rwildcard,$d/,$2) \
$(filter $(subst *,%,$2), $d))
ifeq ($(SOURCES),)
SOURCES := $(call rwildcard, $(SRC_PATH)/, *.$(SRC_EXT))
endif
OBJECTS = $(SOURCES:$(SRC_PATH)/%.$(SRC_EXT)=$(BUILD_PATH)/%.o)
DEPS = $(OBJECTS:.o=.d)
I tried to modify it to be:
SRC_EXT = cpp c
SOURCES = $(shell find $(SRC_PATH)/ -name '*.$(CPP_EXT)' -o -name '*.$(C_EXT)' -printf '%T#\t%p\n' \
| sort -k 1nr | cut -f2-)
# fallback in case the above fails
rwildcard = $(foreach d, $(wildcard $1*), $(call rwildcard,$d/,$2) \
$(filter $(subst *,%,$2), $d))
ifeq ($(SOURCES),)
SOURCES := $(call rwildcard, $(SRC_PATH)/, *.$(SRC_EXT))
endif
But i'm not sure what to do with the OBJECTS directive to make it work with the multiple extensions:
OBJECTS = $(SOURCES:$(SRC_PATH)/%.$(SRC_EXT)=$(BUILD_PATH)/%.o)
Can anybody help with this please?
Thanks
First, replace .cpp by .o, then replace the remaining .c by .o.

Unable to include library in make file

I have the following 3 makefiles which have been generated by some other programmer. I have included my code in between which I have marked with a begin and end. The code intends to include the libspatial index library. The other programmer has the hierarchy root directory---->tools--->r
MakeFile1 corresponds to r, MakeFile2 corresponds to tools and MakeFile3 corresponds to root
Now when I include the library I get the error that
make all
make: *** No rule to make target `bin//home/NP/rtree/spatialindex-src-1.8.0/src/storagemanager/DiskStorageManager.cc', needed by `bin/rdf3xload'. Stop.
I am unable to understand as to what mistake did I make. Can someone be kind enough to help me out.
MakeFile 1
src_tools_r:= \
tools/r/r.cpp \
tools/r/Sorter.cpp \
tools/r/StringLookup.cpp \
tools/r/TempFile.cpp \
/home/NP/rtree/spatialindex-src-1.8.0/src/storagemanager/DiskStorageManager.cc
#Code which I wrote in order to include my library --begin
# for CS machines
COURSE_DIR = /home/NP/rtree/spatialindex-src-1.8.0/.libs
LIB_DIR = /usr/local/lib
CPPFLAGS = -I. \
-I$(COURSE_DIR)
LDFLAGS = -L. \
-L$(COURSE_DIR) \
-R $(LIB_DIR):$(COURSE_DIR)
LDLIBS = -lspatialindex
#Code which I wrote in order to include my library --end
$(PREFIX)r$(EXEEXT): $(addprefix $(PREFIX),$(src_tools_r:.cpp=$(OBJEXT)) $(src_infra:.cpp=$(OBJEXT)) $(src_rts:.cpp=$(OBJEXT)) $(src_cts:.cpp=$(OBJEXT)))
$(buildexe)
MakeFile2
include tools/r/MakeFile1
src_tools:= \
$(src_tools_r) \
#Code which I wrote in order to include my library --begin
# for CS machines
COURSE_DIR = /home/NP/rtree/spatialindex-src-1.8.0/.libs
LIB_DIR = /usr/local/lib
CPPFLAGS = -I. \
-I$(COURSE_DIR)
LDFLAGS = -L. \
-L$(COURSE_DIR) \
-R $(LIB_DIR):$(COURSE_DIR)
LDLIBS = -lspatialindex
#Code which I wrote in order to include my library --end
**MakeFile3
# Include platform dependent makefiles
ifeq ($(OS),Windows_NT)
include Makefile.nt
else
include Makefile.unix
endif
PREFIX:=bin/
#############################################################################
# Default target
all: $(PREFIX)rd$(EXEEXT) $(PREFIX)r$(EXEEXT) $(PREFIX)rq$(EXEEXT) $(PREFIX)ru$(EXEEXT) $(PREFIX)re$(EXEEXT) $(PREFIX)ro$(EXEEXT)
#############################################################################
# Collect all sources
ifeq ($(LINEEDITOR),1)
src_lineeditor:=lineeditor/LineInput.cpp lineeditor/LineEditor.cpp lineeditor/Terminal.cpp lineeditor/Display.cpp lineeditor/Buffer.cpp
endif
include tools/Make2
source:=$(src_cts) $(src_infra) $(src_rts) $(src_tools) $(src_lineeditor)
#############################################################################
# Dependencies
generatedependencies=$(call nativefile,$(PREFIX)makeutil/getdep) -o$(basename $#).d $(IFLAGS) $< $(basename $#)$(OBJEXT) $(genheaders) $(GENERATED-$<)
ifneq ($(IGNORE_DEPENDENCIES),1)
-include $(addprefix $(PREFIX),$(source:.cpp=.d)) $(addsuffix .d,$(basename $(wildcard $(generatedsource))))
endif
#############################################################################
# Compiling
#Code which I wrote in order to include my library --begin
# for CS machines
COURSE_DIR = /home/NP/rtree/spatialindex-src-1.8.0/.libs
LIB_DIR = /usr/local/lib
CPPFLAGS = -I. \
-I$(COURSE_DIR)
LDFLAGS = -L. \
-L$(COURSE_DIR) \
-R $(LIB_DIR):$(COURSE_DIR)
LDLIBS = -lspatialindex
compile=$(CXX) -c $(TARGET)$(call nativefile,$#) $(CXXFLAGS) $(CXXFLAGS-$(firstword $(subst /, ,$<))) $(IFLAGS) $(IFLAGS-$(firstword $(subst /, ,$<))) $(call nativefile,$<)
$(PREFIX)%$(OBJEXT): %.cpp $(PREFIX)makeutil/getdep$(EXEEXT)
$(checkdir)
$(generatedependencies)
$(compile)
#############################################################################
# Cleanup
clean:
find bin -name '*.d' -delete -o -name '*.o' -delete -o '(' -perm -u=x '!' -type d ')' -delete
#############################################################################
# Executable
$(PREFIX)query: $(addprefix $(PREFIX),$(source:.cpp=$(OBJEXT)))
#Code which I wrote in order to include my library --end
If this is an independent library, it should have its own Makefile and should build alone as well.
If you want to integrate your source into the main build process, you must conform to their structure.
You have
different c++ source suffix .cc vs .cpp
This is easily resolvable by renaming your source files to .cpp.
absolute path /home/NP/rtree/... vs relative path tools/r/...
This would involve moving the entire tree into the main build tree, because the rules expect the directories to be accessible from there.
But I think the best is to have a library Makefile and integrate that into the main build.
Unfortunately, there is no easy answer like change variable X and move line Y. I recommend, sit down with your colleague and resolve this Makefile issue together.

Separate file name from its path

I have a number of files from this expression:
ui_files := $(wildcard $(SUBDIRS:%=%/*.ui)).
Now I need the list of the same file paths, but with "ui_" prefix in file name and another extension (.h). How can I do that?
You can iterate over the list using foreach and transform each element:
h_files := $(foreach ui,$(ui_files),$(dir $(ui))ui_$(notdir $(ui:.ui=.h)))
Or, first transform the whole list and then use join:
h_files := $(join $(dir $(ui_files)),$(patsubst %.ui,ui_%.h,$(notdir $(ui_files))))
Both solutions use dir and notdir functions.