Passing target name in dependencies which can be formatted in a makefile - makefile

What I would like to do is to get the target name in the dependency and be able to format it.
For example if the target is Objs/foo.o I would like to make the dependency to Sources1/foo.c, I tried doing this
$(filter %.o,$(OBJS)): $(filter %/$(patsubst %.o,%,$(notdir $#)).cpp, $(SRCS))
but none of them works. Where OBJS is a list of object files ex. Objs/foo.o Objs/moo.o etc..
Any help would be greatly appreciated. And SRCS is a list of different directories were sources can be located. Example Sources1/ and Sources2/ where I need to search in both those directories to find where the source is.

Using the vpath directive could take care of your issue. Here's an example:
OBJS:=Objs/foo.o Objs/bar.o
all: $(OBJS)
# This tells make to search for %.c files in Sources1 and Sources2.
vpath %.c Sources1 Sources2
$(filter %.o,$(OBJS)): Objs/%.o : %.c
#echo $# $^
When I run it here with foo.c in Sources1 and bar.c in Sources2, I get the following output:
Objs/foo.o Sources1/foo.c
Objs/bar.o Sources2/bar.c

Related

Makefile - build from multiple directories

I am new to Makefile.
I have a string of multiple directories and I want to compile all the .c files in them.
The number of paths in that string can change (it is received as an argument from a script).
For example:
DIRS = path1 path2...
I will be happy to receive help with building a mechanism that can go over DIRS and compile each and every .c file in each path.
I am not sure if this is the right way, but I got this so far:
DIRS = path1 path2
define generateRules
SOURCES := $(wildcard $(path)/*.c)
%.o: $(SOURCES)
echo "path is $(path)";
$(CC) $(CFLAGS) ${INCS} ${DEFS} -c $< -o ${BUILD}/$#
endef
$(foreach path,$(DIRS),$(info $(generateRules)))
Thank you
Let's start with generating a list of the source files.
DIRS = path1 path2
SOURCES := $(wildcard $(addsuffix /*.c,$(DIRS)))
From this we can generate a list of targets:
TARGETS = $(patsubst %.c,$(BUILD)/%.o,$(notdir $(SOURCES)))
The simplest way to get the effect you want is by use of the vpath directive and a static pattern rule:
vpath %.c $(DIRS)
$(TARGETS): $(BUILD)/%.o: %.c
#echo building $# from $<
$(CC) $(CFLAGS) ${INCS} ${DEFS} -c $< -o $#
If you want to generate a rule for each source directory -- or each source file -- you can, but that requires a few more advanced techniques. I advise you to get the simple approach working first.

Makefile pattern matching not working as I expected

I'm trying to setup a simple Makefile for building a simple project that's not too hard to maintain.
I want to make use of pattern matching rules e.g. %.o : %.c ; g++ ... where I have all the object files I would want to compile deduced from wildcard matched source files.
The directory structure is
./src
./include
./build/bin
./build/objs
Right now my problem looks something like this.
INCL_DIR = ./include
SRC_DIR = ./src
BUILD_DIR = ./build
BIN_DIR = $(BUILD_DIR)/bin
OBJ_DIR = $(BUILD_DIR)/objs
SRCS = $(notdir $(wildcard $(SRC_DIR)/*.cc))
OBJS = $(addprefix $(OBJ_DIR)/, $(SRCS:%.cc=%.o))
$(BIN_DIR)/program : $(OBJS)
$(CXX) $(CXXFLAGS) -I $(INCL_DIR) $^ -o $#
$(OBJS):%.o : %.cc
$(CXX) $(CXXFLAGS) -I $(INCL_DIR) -c $< -o $#
In the line $(OBJS):%.o : %.cc an example expansion would be from target rule ./build/objs/a.o that depends on ./build/objs/a.cc but the source file is in ./src/a.cc.
So I figured I could strip away the dependency format to try and match ./src/a.cc but the utilies for text manipulations don't seem to work on the dependency side of a rule.
I tried something like
$(OBJS):%.o : $(SRC_DIR)/$(notdir %.cc)
or
$(OBJS):%.o : $(SRC_DIR)/$(*F).cc
where $(*F) would expand to a in the earlier example case but it doesn't expand to anything when listed as a dependency.
I'm not experienced with Makefiles and not sure why my attempts arent working and would very much like to hear a solution that might solve my issue.
Thanks.
The solution is already in #John's comment. I will try to explain it in bit more detail. I will use an example with hello.cc in folder src.
pattern rules hold the pattern in % symbol. If there is in the makefile a pattern rule: build/objs/%.o : src/%.cc and you request to build file build/objs/hello.o, % will carry value hello. But if your pattern rule would be $(OBJS):%.o : %.cc, the pattern % will be build/objs/hello and the dependency file build/objs/hello.cc is missing (because it is saved in src, not in build/objs).
So solution for you would be:
$(OBJS):$(OBJ_DIR)%.o : $(SRC_DIR)%.cc
$(CXX) $(CXXFLAGS) -I $(INCL_DIR) -c $< -o $#
If you want to make sure how patterns work, you can print pattern content by adding line #echo $* to recipe.

Generic target/rule to build all source files from a list, outputting objects to one directory

I am trying to make one generic target in my makefile that will builds sources from mixed directories and output the object files to on single directory.
We have a source structure that is mixed in various directories (like said above, below is just an example)
SRCS = ../a/b/source1.c \
b/source2.c \
../c/source3.c
But I would like all of the object files to output to the directory ./objs (same directory level as 'b')
To do this I was trying the following
OBJS = $(addprefix objs/, $(notdir $(SRCS:.c=.o)))
$(OBJS): %.o : $(filter %/$(basename $(notdir %)).c, $(SRCS))
echo "dependencies: $^" # shows up empty
$(CC) $(filter %/$(basename $(notdir $#)).c, $(SRCS)) -o $# # This works and finds the proper source file
$(CC) $^, $(SRCS)) -o $# # I would like to use this, but as I said the dependencies show up blank
There is a weird problem with this however, and I don't understand where the problem is.
In the dependency it doesn't match anything, but in the recipe it does match properly.
Now the weird part (for me atleast). If I try and test out by hard coding one of the paths then it match for ALL files in that path
$(OBJS): %.o : $(filter ../a/b/$(basename $(notdir %)).c, $(SRCS)) # matches for all files in "../a/b" directory
But using SECONDEXPANSION and hardcoding the directory it works
.SECONDEXPANSION:
$(OBJS): %.o : $$(filter ../a/b/$$(basename $$(notdir %)).c, $(SRCS))
And also not using SECONDEXPANSION and hardcoding the source file name works
$(OBJS): %.o : $(filter %source1.c, $(SRCS)) # Hardcoding source1.c works for source1.c
But it seems like I can't combine to two do what I want for some reason. I have tried secondexpansion stuff (thoguht I'm not really sure why I would need it in this case) and could never get anything working that way either.
I am trying to avoid manually declaring targets for each file individually i.e.
objs/source1.o : ../a/b/source1.c
Because our real world example has tons of files and it would be nice to have less to maintain. I feel like I am very close to getting it.
I am using Cygwin with GNU Make 4.0.
After googling a few more times I finally came across the fix here:
http://lists.gnu.org/archive/html/help-make/2010-09/msg00062.html
I still don't know exactly why I needed to use the SECONDEXPANSION ($$-ness) at all but in practice it doesn't work without it. But basically I needed to create a variable for the '%' sign. Doing the following works for me.
SRCS = ../a/b/source1.c \
b/source2.c \
../c/source3.c
OBJS = $(addprefix objs/, $(notdir $(SRCS:.c=.o)))
.SECONDEXPANSION:
PERCENT = %
$(OBJS): %.o : $$(filter $$(PERCENT)/$$(notdir %).c, $(SRCS))
$(CC) $< -o $#
This now builds source1.c, source2.c, and source3.c and outputs the object files into the objs/ directory.
What I didn't mention in my question but I knew all along was that this will only work if you have unique file names for all source files. But we are okay with that limitation (obviously).

Generating a makefile target dependency from the filename in a stem

Hi I have a makefile I am creating where each .o is represented as a relative path to another directory and has a dependency on a .cpp file in the local directory. My understanding of the problem is that I can't use functions in a rule definition so the rule:
%.o: %.cpp
results in a prerequisite .cpp that is in the same directory as the .o which is not where the cpp is actually located. For example:
../../Tmp/MyClass.o: ../../Tmp/MyClass.cpp <--- WRONG, result of %.o: %.cpp
../../Tmp/MyClass.o: MyClass.cpp <--- RIGHT, how do I do this in an automatic way?
Lastly the output, which is in yet another directory, has a dependency on the .o's so they must all have full relative path information from the beginning:
OBJS := $(addprefix ../../../Tmp/XCode/${PLATFORM}/${CONFIGURATION}/, $(addsuffix .o, $(basename ${SRCS})))
${OUTPUT}: ${OBJS} ; ${AR} $# ${OBJS}
Thanks!
I think kristi's solution will work, but here's another way to do the same thing:
# Here's how you do it:
OBJS := $(addprefix ../../../Tmp/XCode/${PLATFORM}/${CONFIGURATION}/, $(addsuffix .o, $(basename ${SRCS})))
# Here's a slightly cleaner way:
BASEPATH = ../../../Tmp/XCode/$(PLATFORM)/$(CONFIGURATION)
OBJS := $(patsubst %.cc,$(BASEPATH)/%.o,$(SRCS))
# And here's the rule:
$(OBJS): $(BASEPATH)/%.o: %.cc
whatever...
This should work
../../Tmp/%.o: %.cpp
Or use a variable
builddir := ../../Tmp
$(builddir)/%.o: %.cpp

Makefile, Pattern-Rules and Directories

I want to write a (gmake) makefile for a compiler that - unlike gcc - puts all output files into a specific directory. Unfortunately this behavior cannot be changed.
My sources are in multiple directories. How do I write a pattern-rule that lets me compile the sources.
Okay, that's a bit unclear. Here is an example. My sources look may like this:
./folder1/foo.c
./folder2/bar.c
and the output files will end up like this:
./obj/foo.obj
./obj/bar.obj
How should my rule to compile my sources look like?
%.obj : %.c
$(COMPILER) -c $<
will not work.
Any ideas? I'd like to avoid an implicit rule for each source file...
Extracted from some Makefile of mine:
OBJS := $(sort $(patsubst %.cpp,$(OBJECT_DIRECTORY)/%.o,$(patsubst %.c,$(OBJECT_DIRECTORY)/%.o,$(notdir $(SRCS)))))
Where OBJECT_DIRECTORY points to the object directory and SRCS is the list of source files (which you can even populate using $(wildcard)).
Then in the Makefile, I have:
define define_compile_rules
$(OBJECT_DIRECTORY)/%.o: $(1)%.c
#echo " + Compiling '$$<'"
#mkdir -p $$(#D)
$(CC) $$(CFLAGS) -o $$# -c $$<
endef
$(foreach directory,$(sort $(dir $(SRCS))),$(eval $(call define_compile_rules,$(directory))))
See the $(eval) function.

Resources