How to replace .c and .cpp file together? - makefile

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)

Related

Substitute the value of a Make variables with multiple alterations?

#
# 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)

multiple Makefile for a single project

I am trying build a project with several modules included. the file tree looks like this:
the individual Makefiles for lib_one, lib_two and Main.cpp works fine, generating the 2 DLL and the EXE for the project, but requires enter at each directory and execute the command 'make' for each module.
I want now a Makefile in the top level directory ('/project') which triggers the building for all the other modules (DLLs and EXE) once. Based on some search results I got something like that:
lib_one := ./src/lib_one
lib_two := ./src/lib_two
libraries := $(lib_one) $(lib_two)
player := ./src
.PHONY: all $(player) $(libraries)
all: $(player)
$(player) $(libraries):
$(MAKE) --directory=$#
$(player): $(libraries)
when I execute the command 'make' I got this error:
Makefile:10: ***. Stop.
(the line 10 is this one: $(MAKE) --directory=$#). Besides a way to fix this error, I am looking to a way to accomplish this 3 things:
1)
the object files (*.o) from all the modules (DLLs and EXE) should be stores on a directory build in the same place from the directory src.
2)
the final files (*.dll and *.exe) should be placed in a directory reelease alongside the directories src and build.
3) if item 2 was possible, would be nice if each type of file being placed in a specific directory inside release (bin for *.exe, lib for *.dll and shared for other types). also, even with the exe and dlls in different directories, would be possible run the executable from this directory (making it search for the necessary libraries in ../lib alongside the other usual places?).
#Maxim is likely right for the cause of the error -- spaces vs tabs. As far as a your other questions go, without using non-recursive make, you could do something like:
Makefile:
export base_dir := ${CURDIR}
export obj_dir := ${base_dir}/build
export release_dir := ${base_dir}/release
lib_one := ${base_dir}/src/lib_one
lib_two := ${base_dir}/src/lib_two
libraries := $(lib_one) $(lib_two)
player := ${base_dir}/src
.PHONY: all $(player) $(libraries)
all: $(player)
$(player) $(libraries): | ${obj_dir} ${release_dir}
$(MAKE) --directory=$#
$(player): $(libraries)
${obj_dir} ${release_dir} :
#mkdir -f $#
The sub-makefiles would have access to any exported variable from the parent (see here), so in these you could do stuff like:
${obj_dir}/%.o : %.c
#echo compiling "$^ ==> $#"
$(CC) -c -o $# $^ $(CFLAGS)
which would compile the objects to the right directory.
Beware though -- if you have two components that produce an object file with the same name, because they're being produced in the same directory, you will end up with a potentially hard to debug race condition. Typically each component produces object files in its own unique directory to avoid this very thing.

How to remove multiple source files after wildcard Makefile

The question is:
I have a makefile called A.mk (a general makefile for all projects). Over there, I have added all source files in folder src1 using
Var += $(wildcard src1/*.c)
Then, for a specific application I have a makefile (called B.mk), which includes A.mk in itself. Now, I want to substitute the source file foo1.c from folder src1 with a new one foo2.c from folder src2. How can I do that?
How can I do that if I want to substitute (or even delete) multiple files from Var in B.mk.
Thanks for your help in advance.
Make has a number of string functions, filter-out looks like it would apply here
# All .c files
Var := $(filter-out %.c,$(Var))
# A specific file
Var := $(filter-out src/foo.c,$(Var))

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)))

Resources