Wildcard in make dependency list - makefile

Hey I'm trying to build some files at the same time with different suffixes. Somehow it seems imposible to do this in one line. My makefile looks as follows:
ARCH=ar
ARCHFLAGS=r
F90=gfortran
F90FLAGS=-O2 -Wall
LDFLAGS=-llapack -lblas
SRCF=/Users/pm/bin/src
OBJF=/Users/pm/bin/objs
MODF=/Users/pm/bin/mods
LIBF=/Users/pm/bin/include
SOURCES=a.f b.f90 c.f90
OBJECTS=$(addprefix $(OBJF)/,$(addsuffix .o,$(basename $(SOURCES))))
MODULES=$(addprefix $(MODF)/,*.mod)
TARGET=lib_pm_math_lib.a
$(LIBF)/$(TARGET): $(OBJECTS)
$(ARCH) $(ARCHFLAGS) $# $(OBJECTS) $(MODULES)
obmod.clean :
rm $(OBJECTS) $(MODULES)
clean :
rm $(OBJECTS) $(MODULES) $(LIBF)/$(TARGET)
$(OBJECTS): $(OBJF)/%.o : $(addprefix $(SRCF)/,$(join %.,$(suffix $(SOURCES))))
$(F90) $(F90FLAGS) $(LDFLAGS) -c $< -o$# -J$(MODF)
#$(OBJECTS): $(OBJF)/%.o : $(subst .x, ,$(addprefix $(SRCF)/,$(addsuffix .x$(suffix $(SOURCES)),%)))
# $(F90) $(F90FLAGS) $(LDFLAGS) -c $< -o$# -J$(MODF)
#$(OBJECTS): $(OBJF)/%.o : $(SRCF)/%.f90
# $(F90) $(F90FLAGS) $(LDFLAGS) -c $< -o $# -J$(MODF)
As you can see, I already managed to define my OBJECTS. But I'm not able to creat a construct that does the same for the building part of the object. Of course my first try was to use the join without the extra dot, but this results in only the suffix, for whatever reasons. Substituting the two dots with one dot does this as well. So I'm lost. The lines that I commanded out are another interesting try, and a working version for only .f90 suffixes. Actually I was hoping for something like the following to be working:
$(OBJECTS): $(OBJF)/%.o : $(SRCF)/%.*
$(F90) $(F90FLAGS) $(LDFLAGS) -c $< -o $# -J$(MODF)
I hope it's not too messy. I posted the whole file since I bet you guy's see other problems which I didn't even think of so far. Thanks in advance!

If I'm understanding you correctly, you're wanting a suffix-based wildcard rule that you can run on multiple file suffixes. You can only have one wildcard per recipe, so there's no way to do it directly. You'll need separate rules for each suffix.
The easy solution is to copy-paste one rule and change the suffix. This can become unmanageable when you start to have a lot of suffixes. Another option is to create a rule template and use that to dynamically generate your rules for you:
# Template for build rules
# Pass a file extension for an argument
define build_rule
$(OBJF)/%.o: $(SRCF)/%.$(1)
$(F90) $(F90FLAGS) $(LDFLAGS) -c $$< -o$$# -J$(MODF)
endef
# Generate rules for each selected file extension
FILE_EXTS = f f90
$(foreach ext,$(FILE_EXTS),$(eval $(call build_rule,$(ext))))
This will dynamically generate a rule that differs only by the file extension used on the input file. To support a new file extension, simply add it to the FILE_EXTS list.
Note that when make initially parses the recipe template (inside call), it will expand variables. You have to double-up the $ in the template for anything that you don't want make to expand until the recipe is actually executed (like $# or $<).
You shouldn't need to do anything special to ensure that only the objects in the OBJECTS list are compiled. Since your default make target only lists $(OBJECTS) as a dependency, the files in $(OBJECTS) will be the only ones that get built.

In this case I'd probably just use two rules:
$(OBJF)/%.o: $(SRCF)/%.f
$(F90) $(F90FLAGS) $(LDFLAGS) -c $< -o$# -J$(MODF)
$(OBJF)/%.o: $(SRCF)/%.f90
$(F90) $(F90FLAGS) $(LDFLAGS) -c $< -o$# -J$(MODF)
You could combine them into one, but it's not really worth the effort.

Related

Makefile: source files in a particular directory

What do I need to do if I want to compile several files (e.g. a.f90, b.f90, c.f90) in a given directory (say, MYDIR)?
My Makefile code is something like:
CC=gfortran
CFLAG=-g
HOME=MYDIR
SRC=$(HOME)/(a.f90,b.f90,c.f90)
OBJ=$(SRC:,=.o)
EXE=test.x
%.o: %.f90
$(CC) $(CFLAG) -c -o $# $<
$(EXE): $(OBJ)
$(CC) -o $# $^ $(CFLAG)
clean:
rm -f *.o
I think, the 4-th line is not correct. So what could be the replacement?
Another thought: Can I use a wildcard if I want to compile all .f90 file inside MYDIR?
There are lots of ways to do it. You can do something like:
SRC = $(addprefix $(HOME)/,a.f90 b.f90 c.f90)
Also your assignment of OBJ is wrong; there's no comma needed after the colon.
Yes you can use wildcard if you want.

Use general rule as part of a specific target in Gnu Make

I am curious if it is possible to use a general rule as part of a more specific rule in Gnu Make. This is easier to explain with an example:
%.o:
$(FC) $(FLAGS) -o $# -c $<
some_file.o:
DO SOMETHING EXTRA
PASS ON TO GENERAL FOR %.o
That is, I want the target for some_file.o to first do something extra, and then do what is specified for %.o. Of course, I could just be redundant and write
some_file.o:
DO SOMETHING EXTRA
$(FC) $(FLAGS) -o $# -c $<
But that is not as convenient.
Add an extra rule that does not create the file itself:
%.o:
$(FC) $(FLAGS) -o $# -c $<
some_file.o: thing
thing:
DO SOMETHING EXTRA BUT DON'T CREATE some_file.o
Note that if thing is not created, this will cause some_file.o to be built every time.
No, that's not possible in any reasonable way. The best you can do is put the command into a variable, then reuse the variable:
FCCOMMAND = $(FC) $(FLAGS) -o $# -c $<
%.o :
$(FCCOMMAND)
some_file.o:
DO SOMETHING EXTRA
$(FCCOMMAND)

Makefile - Pattern Rule as a dependency

I've ha makefile with following entries. Will the first rule depend on the secon rule ? So that it builds all the .o files from second files ?
all:$(PROG)
$(PROG): *.o
$(LD) -o $(PROG) -c $< $(LFLAGS)
%.o : %.c
$(CC) $(CFLAGS) -o $# -c $<
To be specific if i invoke 'make all' will it invoke the second rule if no *.o files were found ?
All other Variables have usual meaning .
No, that will not work. When you run your makefile for the first time, are there any .o files? No. So the expression *.o will expand to nothing.
Of course, your recipe for $(PROG) doesn't actually use any of the object files anyway, as written.
You can do something like this (although personally I prefer to simply list the files out by hand; it's not very common to create all new files so it's not much effort, and it's safer than just trying to grab every file in the directory):
SOURCES := $(wildcard *.c)
OBJECTS := $(SOURCES:%.c=%.o)
$(PROG): $(OBJECTS)

Passing target name to a dependency in makefile

If I have the following rule in a makefile:
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -c -o $# $< $(CFLAGS)
Every file matching the prefix ./obj/ and sufix .o will have its stem passed to %, so I can provide some dependencies based on its name.
But, suppose I have this kind of rule, which I specify one by one the targets I want:
OBJECTS=abc.o bca.o cba.o
$(OBJECTS): $(SRC)/%.c
$(CC) -c -o $# $< $(CFLAGS)
How do I make the % stem actually work for the current target name make is executing? Just using % doesn't work, neither $#.
Note that I'm trying to write the actual target name to its own dependency. For example, when make is executing the rule for abc.o, it would include $(SRC)/abc.c and just it (something like $(patsubst %.o, $(SRC)/%.c, MAGIC_TARGET_NAME_VARIABLE)).
You can just replace this rule:
$(OBJECTS): $(SRC)/%.c
with:
$(OBJECTS) : %.o : $(SRC)/%.c
You will need to add the $(OBJ) to the -o part of the recipe if you still want them built there:
$(OBJECTS) : %.o : $(SRC)/%.c
$(CC) -c -o $(OBJ)/$# $< $(CFLAGS)
I’m not completely clear on what you’re asking, but I think this accomplishes what you’re trying to do:
OBJECTS=abc.o bca.o cba.o
.PHONY: all
all: $(OBJECTS:%=obj/%)
$(OBJ)/%.o: $(SRC)/%.c
echo $(CC) -c -o $# $< $(CFLAGS)
All .o files are built; each .o file is built using only the .c file corresponding to it; and if you want to refer to the list of all object files or source files in the command for compiling a .o file, then you can reference ${OBJECTS} directly.
If this isn’t what you’re trying to do, you’ll be able to get a better answer by listing the input files you have, the output files you want to make, the input dependencies of each output file, and what compilation command you want to execute for each output file.

In gnu make, can the prerequisites in a static pattern rule have different suffixes

Our make file compiles .c source files with a static pattern rule like this:
OBJECTS = foo.o bar.o baz.o
$(OBJECTS): %.o: %.c
$(CC) $< $(C_OPTIONS) -c -o $#
I need to change one of the .c files to an Objective-C .m file. Invoking the compiler is the same for both source types, so I'd like to use the same rule and just tweak it to be more flexible. I'd rather not change the OPTIONS variable because it's also used for the linking step, etc.
Is there a way to make the rule above more flexible to accommodate both .c and .m files?
Thanks
We can add this either-or behavior to the list of things Make should be able to do easily, but isn't. Here's a way to do it, using "eval" to create a seperate rule for each object.
define RULE_template
$(1): $(wildcard $(basename $(1)).[cm])
endef
OBJECTS = foo.o bar.o baz.o
$(foreach obj,$(OBJECTS),$(eval $(call RULE_template,$(obj))))
$(OBJECTS):
$(CC) $&lt $(C_OPTIONS) -c -o $#
Note that this depends on the source files already existing before you run Make (foo.c or foo.m, but not both). If you're generating those sources in the same step, this won't work.
Here's a less clever, more robust method.
CPP_OBJECTS = foo.o bar.o
OBJECTIVE_OBJECTS = baz.o
OBJECTS = $(CPP_OBJECTS) $(OBJECTIVE_OBJECTS)
$(CPP_OBJECTS): %.o: %.c
$(OBJECTIVE_OBJECTS): %.o: %.m
$(OBJECTS):
$(CC) $&lt $(C_OPTIONS) -c -o $#
EDIT: corrected OBJECTS assignment, thanks to Jonathan Leffler.
Not really just copy to
$(OBJECTS): %.o: %.m
$(CC) $< $(C_OPTIONS) -c -o $#
The call to the same compiler is just a happy occasion. Normally you do not compile objective-c code with $(CC). That just feels strange.
But since you go in a harsh way, I won't post do-it-right solution, where you separate objective-C targets from C targets into two different $(OBJECTS)-like variables and make two rules (which you should really do). Too boring. Instead, take a hack!
OBJC_FILES:=$(subst $(wildcard *.m))
real_name = `(test -h $(1) && readlink $(1) ) || echo $(1)`
$(OBJECTS): %.o: %.c
$(GCC) $< $(C_OPTIONS) -c -o $(call real_name,$#)
$(OBJC_FILES): %.c: %.m
ln -s $< $#
And God help those who maintains it!
Btw, this obviously won't work if your m-files are generated.

Resources