Substitute the value of a Make variables with multiple alterations? - makefile

#
# Sources are .c and .s files
#
# Append .o to both .c and .s:
PRJ_OBJ := $(addprefix $(BUILD_PATH)/,$(addsuffix .o, $(PRJ_SRC)))
# Create .c.d from .c.o and .s.d from s.o:
PRJ_DEP_TEMP := $(PRJ_OBJ:.c.o=.c.d)
PRJ_DEP += $(PRJ_DEP_TEMP:.s.o=.s.d)
How could I do both replacements .c.o=.c.d and .s.o=.s.d in one line instead of two?
Doc: GNU Make Substitution References.

If your intent is to only get .d files for .c.o and .s.o files, then you would have to do something like this:
PRJ_DEP = $(patsubst %.o,%.d,$(filter %.c.o %.s.o,$(PRJ_OBJ)))
The $(filter ... would get rid of any files you don't want to create corresponding .d files for and then you simply replace the .o with a .d using $(patsubst...
If, on the otherhand you know that PRJ_OBJ only contains .c.o and .s.o files, then you can go with #Vroomfondel or #urcodebetterznow's suggestions and simply do:
PRJ_DEP += $(PRJ_OBJ:%.o=%.d)

Related

How to replace .c and .cpp file together?

I am currently have an Android.mk file. For some requirement I need to write a standard GNU make file to build the same program.
As you know in Android native build, we simply put all source files together like
LOCAL_SRC_FILES := a.c b.c d.cpp e.cpp
Now I want to do something in Makefile like:
OBJ = $(LOCAL_SRC_FILES: .c=.o)
This will only transform .c files with .o object targets. How can I combine the condition ".c or .cpp" together?
I think I am too busy to forget that I can just achieve this target by execute this function twice.
TMP_OBJ = $(LOCAL_SRC_FILES: .c=.o)
OBJ = $(TMP_OBJ: .cpp=.o)
Sorry for this silly question.
You could use basename:
OBJ := $(addsuffix .o,$(basename $(LOCAL_SRC_FILES)))
(strips off the suffix of each file in LOCAL_SRC_FILES then adds .o to the end)
Doing it in two steps:
SRC := main.c hello.cpp
OBJ := $(SRC:.c=.o)
OBJ := $(OBJ:.cpp=.o)

makefiles compiling files to library

I'm new to makefiles , recently I was looking at a makefile and could not understand what this means
OBJS := $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
where
PROJECT_ROOT=.
EXTERNAL_ROOT=$(PROJECT_ROOT)/external
SRCDIR = $(PROJECT_ROOT)/src
OBJDIR = $(PROJECT_ROOT)/myobjs
BINDIR = $(PROJECT_ROOT)/mybins
DOCDIR = $(PROJECT_ROOT)/doc
what does it represent? Also i wish to make static library consistly of all files in in the myobjs folder or $(OBJS) except main.o a file in it how to write the command
ar -cvq mylibs/libCS296test.a $(OBJS); for such a case?
Please create different SO requests for very different questions.
For your first question, that is equivalent to this function:
$(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SOURCES))
which basically says "look through the value of the $(SOURCES) variable and for every word matching the pattern $(SRCDIR)/%.cpp, replace it with the pattern $(OBJDIR)/%.o. So, if SOURCES contained a word ./external/src/foo/bar/biz.cpp that would be replaced with ./external/myobjs/foo/bar/biz.o.

Substitute file name in Makefile

I usually use this line OBJECTS = $(SOURCES:.cpp=.o) to substitute the .cpp extension of files in SOURCES to .o extension.
My project now has files with .c extension together with .cpp. How do I modify that line to make it substitute all .c and .cpp extensions to .o?
I would not prefer a two lines solution like below:
OBJECTS_TMP = $(SOURCES:.cpp=.o)
OBJECTS = $(OBJECT_TMP:.c=.o)
I would like something like
OBJECTS = $(SOURCES:(.cpp|.c)=.o)
or even
OBJECTS = $(SOURCES:.*=.o)
Is that possible and how? Thanks!
You can't do it only with the shorthand. You'll have to use the patsubst function:
OBJECTS = $(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SOURCES)))
Or you can use one of each:
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES:.c=.o))
Or, you can do it like this:
OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))

makefile problems (gnuplot)

I'm trying to produce some graphs using GNUplot with a makefile. I would like for every *.plt file in the directory to be run through GNUplot, however I can't see to get it to work.
Here's my makefile so far:
all: %.tex
%.tex: %.plt
<tab> gnuplot < $<
The recipe is working fine if I specify a .plt file individually but I want it to pick up my new plots as I produce them.
EDIT:
I think I've got it working now:
# plots all files in the folder with .plt extensions
SOURCES = $(wildcard *.plt)
TARGETS = $(SOURCES:.plt=.tex)
all: $(TARGETS)
%.tex: %.plt
gnuplot < $<
Can someone confirm whether my reasoning (as follows) is correct?
Previously I hadn't specified any files for all (I'm a little confused by %). Now assigning the variable SOURCES by picking up any .plt files using the wildcard (why doesn't it work when using .plt instead of *.plt?). Having assigned SOURCE, the TARGETS variable is then set, now all: has files specified to build. and the matching rule is now run.
all : %.tex won't work because there is no percent in the target name, in other words, it is not a patter rule.
Use wildcard function to get the list of all .plt files and add an all dependence on these files with the extension replaced by .tex:
PLT_FILES := $(wildcard *.plt)
TARGETS := $(PLT_FILES:%.plt=%.tex)
all: $(TARGET)
%.tex: %.plt
gnuplot < $<

GNU make substitution command for automatic list of object files

A common type of makefile has a line like this:
OBJS=something.o other.o third.o progname.o
progname: $(OBJS)
Then you would run make progname. But GNU Make can also generate the list of o-files itself from all the c-files it sees in the current directory. How is this done?
Basically, I want to be able to add C files to the directory without having to change the makefile.
(Is it for instance through some shell-magic, or is there is a built-in function for this?)
It can also be done like this:
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
progname: $(OBJS)
Which works just fine if the object file with main() in it is "progname.o".
To view all the defined rules (include the implicit ones), issue make -p.
However the fact that make knows how to generate object files from source files, does not mean that it should do this. Make will try to do the bare minimum in order to satisfy the target you ask it to build.
If you want make to compile all the sources into object in the current directory you will need a rule that will depend on all the objects, e.g.:
all: $(patsubst %.c,%.o,$(wildcard *.c))
You can expand a shell command to give you a list of files. You can also use implicit rules.
It can be done like this:
$(ODIR)/%.o: %.cpp
$(CC) -c $(CFLAGS) -o $# $<
make generates .o file names from .cpp file names it found in the current directory.

Resources