Problems with substitution - makefile

I'm having trouble getting path substitution working correctly. I have a bunch of source files in SOURCES:
#echo $(SOURCES)
foo.c bar.cpp bah.cxx
And I want a list of object files:
# Imaginary only because nothing works
#echo $(OBJECTS)
foo.o bar.o bah.o
I'm trying to build the list of OBJECTS with patsubst. First, this produces a list of source files and object files. Besides being wrong, it causes a duplicate of _main which fails a link.
OBJECTS = $(patsubst %.c, %.o, ${SOURCES}) $(patsubst %.cc, %.o, ${SOURCES}) \
$(patsubst %.cpp, %.o, ${SOURCES}) $(patsubst %.cxx, %.o, ${SOURCES})
Second, this performs no substitutions. Not only is it wrong, I get back the original list in SOURCES.
OBJECTS = $(patsubst %.c %.cc %.cpp %.cxx, %.o, ${SOURCES})
Third, this produces the original list of source files:
OBJECTS = $(patsubst %.*, %.o, ${SOURCES})
I also tried using the following, which seems to multiply the files like rabbits:
OBJECTS = $(SOURCES:.c=.o) $(SOURCES:.cc=.o) \
$(SOURCES:.cpp=.o) $(SOURCES:.cxx=.o)
How does one perform a simple substitution of extensions when using a portable make?

Tom's answer is correct. Etan's will work too. A shorter solution would be:
$(addsuffix .o,$(basename $(SOURCES))

If you have a filter-like function you can use that. Otherwise you can do it in stages:
SOURCES := foo.c bar.cpp bah.cxx
O := $(SOURCES)
$(info $(O))
O := $(patsubst %.c,%.o,$(O))
$(info $(O))
O := $(patsubst %.cpp,%.o,$(O))
$(info $(O))
O := $(patsubst %.cxx,%.o,$(O))
$(info $(O))
The problem with your first (and third since that is effectively identical) attempt is that patsubst leaves untouched any words in the input that do not match the pattern. So when you built OBJECTS up from multiple calls to patsubst you were duplicating (in each piece) all the SOURCSE entries that didn't match that pattern.
The problem with the second is that patsubst doesn't take multiple patterns so nothing matches that erroneous pattern and so you get SOURCES back entirely unmodified.

First, I don't think patsubst is portable. It is a GNU make feature.
I think one answer to your question is nested subsitutions, like:
$(patsubst %c,%.o,$(patsubst %.cc,%.o,$(patsubst .....)))

Related

collect all .o in subdirectories - makefile

I have the following hierarchy:
+ makefile
|
+ TT_Project1
| obj/
| makefile
+ TT_Project2
| obj/
| makefile
+ TT_Project3
| obj/
| makefile
The top level makefile calls recursively all makefiles below it, each compiles the .cpp to .o and places it under /obj
I would like to collect all .o in the top level to create a static library. And failing as my output library is too small...
TT := libTT.a
SUBDIRS := $(wildcard */.)
OBJECTS := $(wildcard $(addsuffix *.o,$(SUBDIRS)/obj))
all: $(TT) $(OBJECTS)
$(TT) : $(OBJECTS)
ar rcs $(TT) $(OBJECTS)
$(SUBDIRS):
$(MAKE) -C $#
I can clearly see that it's running the makefiles beneath it, and they are placing the *.o under their /obj as expected. But I am failing to grab all the .o I guess... any help is appreciated.
First, this is wrong:
OBJECTS := $(wildcard $(addsuffix *.o,$(SUBDIRS)/obj))
Not only are you missing a / between the obj and *.o, but you need to put the /obj in the first argument to addsuffix. Suppose SUBDIRS ends up as foo/. bar/. baz/.. Then the addsuffix will expand to:
$(addsuffix *.o,foo/. bar/. baz/./obj)
which gives:
foo/.*o bar/.*.o baz/./obj*.o
which is clearly wrong. You want this:
OBJECTS := $(wildcard $(addsuffix /obj/*.o,$(SUBDIRS)))
However, that isn't what you want. It won't work because these variables are expanded when the makefile is read, before any actions have been taken. Before the makefile actually builds anything, there will be no .o files existing, which means the wildcard function will match nothing.
In your case that's a good thing, because if it did match anything you'll get errors because make doesn't know how to build those objects: they're built by the sub-makes.
But, since you have nothing that depends on the SUBDIRS target they won't get built anyway: those recipes will never run.
The easiest thing you can do is something like this:
TT := libTT.a
SUBDIRS := $(wildcard */.)
all: $(TT)
$(TT) : $(SUBDIRS)
ar rcs $(TT) $(addsuffix /obj/*.o,$(SUBDIRS))
$(SUBDIRS):
$(MAKE) -C $#
.PHONY: $(SUBDIRS)
The downside of this is that it will rebuild the library every time you run make even if no objects have been changed. To fix that you'll have to add some complexity.

Pass argument of call to another function in Makefile

I would like a way to take the argument to a call invocation in a Makefile rule and pass that to a builtin function, in this case wildcard.
This doesn't seem to work:
MODULE_OBJS = $(patsubst %.cc, %.o, $(wildcard $(1)/*.cc))
lib%.a: $(call MODULE_OBJS, %)
#echo $# : $^
In this case I would expect make libfoo.a to print a list of .o files corresponding to the .cc files found under foo/, but nothing is printed. The parameter is getting there because if I append $(1) to the end of MODULE_OBJS the value of % gets printed, but it seems to be lost when getting passed into wildcard.
You need to understand that make will execute $(call MODULE_OBJS, %) before it has even begun building the dependency tree, you cannot accomplish this with a pattern rule. You could use eval hackery but there's a case to made against trying to be too clever with make.
Something like the following is easy enough to maintain
MODULE_OBJS = $(patsubst %.cc, %.o, $(wildcard $(1)/*.cc))
libfoo.a: $(call MODULE_OBJS, foo)
lib%.a:
#echo $#: $^
but after wrestling with clever ways of generating library and binary dependencies I prefer simply listing them explicitly.
I got what I wanted with some hacking of the eval rule:
EXCLUDE_MODULES = obj
MODULES = $(filter-out $(EXCLUDE_MODULES), $(patsubst %/, %, $(wildcard */)))
define MODULE_RULE
lib$(MODULE).a: $(patsubst %.cc, obj/%.o, $(wildcard $(MODULE)/*.cc))
#echo $# : $^
endef
$(foreach MODULE, $(MODULES), $(eval $(MODULE_RULE)))
This allows you to call make libfoo.a and get out a list of all the .o's corresponding with the .cc's in that subdirectory.
For those curious, I uploaded a complete example here.
The Metaprogramming Make articles were a useful resource here.

Makefile. Special chars

I have a question to this expression:
%.out: %.cpp Makefile
g++ $< -o $# -std=c++0x
What does it mean? I know, that it is defined target for *.o files but what does it mean %.cpp Makefile and $< and $#?
And:
What is differenece between:
all: $(patsubst %.cpp, %.o, $(wildcard *.cpp))
and:
all:
$(patsubst %.cpp, %.o, $(wildcard *.cpp))
The second doesn't works.
For the first part of your question:
%.out: %.cpp Makefile
g++ $< -o $# -std=c++0x
This is a pattern rule, and means: "for all files with a .cpp extension, compile (if needed) a corresponding .out file using the command g++ $< -o $# -std=c++0x
In this line, $< is the prerequisite (the .cpp file) , $# is the name of the target (the .out file). See here.
The rule also adds the makefile itself as a prerequisite, which means that all the files will be rebuild (even if they are already compiled) when you issue a make target command, if you make changes to the makefile.
For the second part of the question, your are mixing two things. A make rule is made of three parts:
target: dependencies
commands
The second one you show cannot work because there is no command. The line just produces a bunch of filenames, that your shell cannot understand.
The first one adds to the list of dependencies all the object files, whose names are deduced from all the .ccp files. But you are missing a command, so nothing should happen (unless you didn't give us the whole rule ?)
Edit: ouch, missed something, this rule actually should work fine, as make will evaluate all the prerequisite targets, thus call the pattern rule described above. I got confused by the fact that this structure is usually written like this:
targetname: $(OUTFILES)
#echo "- Done target $#"
with the variable defined above as:
OUTFILES = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
or even as:
INFILES = $(wildcard *.cpp)
OUTFILES = $(patsubst %.cpp, %.o, $(INFILES))
I suggest you find a good make tutorial, or read the manual, you seem to have lots of concepts to learn...

How to have a sometimes empty dependency in makefiles?

I have the following rule:
EXECS = $(sort $(patsubst %.cpp,%$(EXESUFFIX), $(patsubst %.c,%$(EXESUFFIX), $(filter-out $(IGNORESRCS), $(EXECSRCS)))))
SRCS = $(sort $(filter-out $(EXECSRCS), $(filter-out $(IGNORESRCS), $(wildcard *.c) $(wildcard *.cpp) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.cpp) $(wildcard $(DIR)/*.c) ) )))
#OBJS = $(addprefix $(OBJDIR), $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS))))
OBJS = $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS)))
RESOURCE_SRCS= $(sort $(filter-out $(IGNORESRCS), $(wildcard *.rc) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.rc) ) ))
RESOURCES = $(patsubst %.rc,%$(OBJSUFFIX), $(RESOURCE_SRCS))
%$(EXESUFFIX) : %.cpp $(LIBS) $(RESOURCES)
$(CXX) $(DEFINES) $(CFLAGS) $(INCLUDES) $(LIBPATH) -o $(BINDIR)/$* $< $(RESOURCES) $(LIBINCLUDES)
The problem is that $(RESOURCES) doesnt exist for all platforms. The %$(EXESUFFIX) : %.cpp rule doesnt run, instead it tries to run g++ exec.cpp -o exec which as far as I can tell isnt a rule that I declared anywhere.
How do I get the rule to still build despite the fact that it is empty (and build the resources if it is not empty)?
If the variable is empty it has no effect on the rule. It should just work as written. What is the actual error you're seeing?
ETA:
Your question is very unclear in what, exactly, you mean by $(RESOURCES) doesn't exist. My answer was assuming you meant that the variable was empty. But given your comment below about how the makefile behaves, I now suspect what you mean is that the variable is still set to a list of files, but that those files are not present.
Because they're not there, and make doesn't know how to build them, make decides that this pattern rule cannot be used at all and it chooses a different rule.
If you want these files to only have any impact if they exist, then you can use the $(wildcard ...) function to expand only to those files that exist:
%$(EXESUFFIX) : %.cpp $(LIBS) $(wildcard $(RESOURCES))
$(CXX) ...
One critical point here: the contents of $(RESOURCES) MUST be source files. They cannot be derived files (files that are supposed to be created by make). If they are derived, the situation is far more complex.

makefile: search for files in subdirectories

So I have a GCC command for which I want to use a SIMPLE makefile. Never worked on makefile before and still having problems after referring the tutorial.
So the command on terminal is
link4#link4-VirtualBox:~/link4/G2/G2 module/src$ gcc -I.src/L4COMM -I.src/L4SERIAL -I.src/L4SYSTEM -I.src/main.c -I.src/L4COMM/l4comm.c -I.src/L4SERIAL/l4serial.c ./src/bypass.c ./src/input.c
This works fine, but when I create a makefile, I'm unable to make it search for the files 'l4comm.c and l4serial.c' which are in src/L4COMM and src/L4SERIAL respectively.
This is what my makefile looks like:
CC =gcc
INCLUDE = -I/src/L4COMM \
-I/src/L4SERIAL
VPATH = -I/src/L4COMM \
-I/src/L4SERIAL
cfiles := $(patsubst %.c, %.o, $(wildcard *.c))
hfiles := $(patsubst %.h, %.o, $(wildcard *.h))
g2make: $(cfiles)
$(CC) $(INCLUDE) -o main.c l4comm.c l4serial.c bypass.c input.c
Want the makefile to look for files in the sub directories
Just as I used the 'cfiles/hfiles' to check for changes, I want to wildcard to also check for the files in the sub directories.
Help appreciated! :)
You can use this g2make:
$(CC) $(INCLUDE) -o .src/main.c ./src/L4COMM/l4comm.c ./src/L4SERIAL/l4serial.c ./src/bypass.c ./src/input.c

Resources