How can I write a Makefile to make a list of .so targets that each have different .o dependencies without writing out each .so rule individually?
What I basically have write now is every rule written out individually:
BUILD_SO=$(CC) -shared $(CPPFLAGS) -o $# $? $(LDLIBS)
liba.so: foo.o bar.o epicfoo.o
$(BUILD_SO)
libb.so: foo.o epicbar.o
$(BUILD_SO)
libc.so: foobar.o
$(BUILD_SO)
What I would like is to maybe be able to define variables at the top of the file like:
LIBA = liba.so
LIBA_DEPENDS = foo.o bar.o epicfoo.o
LIBB = libb.so
LIBB_DEPENDS = foo.o epicbar.o
LIBC = libc.so
LIBC_DEPENDS = foobar.o
ALL_LIBS = $(LIBA) $(LIBB) $(LIBC)
and somehow run them all through a generic rule that builds the targets similar to a %.o:%.c pattern rule, but instead more like
%.so: <some list of .o names>
Then have a .PHONY rule called libs so that I can call:
make libs
and have all the libs built.
You could try this:
libadeps = foo.o bar.o
libbdeps = bar.o bar2.o
libcdeps = foo2.o foo.o
lib%.so: $(lib%deps)
$(BUILD_SO)
I haven't tryed yet (I will because this will be helpfull to me too), but I think it will work.
Related
I'm trying to do a Makefile for my project in Fortran and make it reusable for now projects. The Mkefile I have come up with after many tries is the following. The thing is that it works OK in few scenarios but right now I have this files:
main.f90, initial.f90, parameters.f90, functions.f90
The first one has my program and the others are modules where I have subroutines. The thing is that initial needs parameters to work but the Makefile decides to try compiling initial before parameters. Is there a way I can make it to choose them in the right order?
vpath %.o obj
vpath %.mod mod
TOP_DIR = .
MOD_DIR = $(TOP_DIR)/mod
OBJ_DIR = $(TOP_DIR)/obj
SOURCES = $(wildcard *.f90)
OBJECTS := $(patsubst %.f90, $(OBJ_DIR)/%.o, $(SOURCES))
ALL_MODULES = $(patsubst %.f90, %.mod, $(SOURCES))
MODULES = $(filter-out main.mod, $(ALL_MODULES))
FFLAGS = -O3 -J$(MOD_DIR) -march=native -fimplicit-none -Wall -Wline-truncation -fwhole-file
.PHONY: main clean
main: main.out
./main.out
main.out: $(MODULES) $(OBJECTS)
gfortran $(FFLAGS) $(OBJECTS) -o main.out
$(OBJ_DIR)/%.o : %.f90
gfortran $(FFLAGS) $^ -c $#
%.mod: %.f90
gfortran $(FFLAGS) -c $^
clean:
rm -f $(OBJ_DIR)/*.o *.out $(MOD_DIR)/*.mod
List the source files in the dependency order instead of automatically: SOURCES = parameters.f90 initial.f90 functions.f90.
Separate the source for the modules and for the program: main.f90 does not, in general, generate .mod files and that will break the simplistic Makefile you have.
I also advise to use another build system (cmake, for instance) but for small projects you can get by with a Makefile if you prefer to.
With modern Fortran compilation order is very important. When using makefiles, for anything non-trivial it's too tedious to keep track of the dependencies manually. Enter various tools to generate these dependency lists. I have successfully used makedepf90 which is available as a package in EPEL (for RHEL/CentOS) and Debian/Ubuntu.
You can even make a makefile rule for regenerating the dependency list, if you keep the list in a separate file, like:
include depend.mk
# Dependencies generated by "makedepf90" tool.
depend depend.mk:
cd $(srcdir) && makedepf90 $(yourprogramname_SOURCES) >depend.mk
The above BTW works both with plain makefiles and automake (in which case you put the above snippet to your Makefile.am)
I have two sets of source files in my project from which I need to generate object files.
SET_ONE = foo.o bar.o
SET_TWO = zerz.o zork.o
I want to pass add an extra option to CFLAGS when building the files in SET_ONE but not for those in SET_TWO. For example, I want:
> make -n
cc -c -DEXTRA_FLAG foo.c
cc -c -DEXTRA_FLAG bar.c
cc -c zerz.c
cc -c zork.c
...
Since the files have the same extension, the same rule applies to all of them, and I don't see a straightforward way to tweak CFLAGS for just the ones in one of the sets.
I could make custom rules for the files in SET_ONE:
foo.o : foo.c
$(CC) $(CFLAGS) -DEXTRA_FLAG foo.c
bar.o : bar.c
$(CC) $(CFLAGS) -DEXTRA_FLAG bar.c
but that leads to repetition, which will be harder to maintain. Is there a cleaner way to do this? It's probably been a decade since I hacked on a makefile.
There are a number of ways to do it. The most straightforward uses target-specific variables; add to your makefile:
$(SET_ONE): CFLAGS += -DEXTRA_FLAG
In a makefile, suppose I have two corresponding dependency and target lists, like this:
SRC = x.c y.c z.c
OBJS = x.o y.o z.o
Of course, my example is more complicated than this, but I want to know if it is possible to automatically create targets x.o, y.o, z.o depending on x.c, y.c, z.c respectively, like this:
x.o: x.c
y.o: y.c
z.o: z.c
I think the question was how to create rules for each of these targets, not how to create OBJS from SRC (although it's good to do that!).
The simplest way is to use the already-built-in rule in make that knows how to do it; you don't need to write your own. Just use:
all: $(OBJS)
and they'll all be created. You can control the compiler by setting the CC variable, the preprocessor flags by setting the CPPFLAGS variable, and the other compiler flags by setting the CFLAGS variable.
If you DO really want to write your own rule, then pattern rules will do that for you easily:
%.o : %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
You can use substitution references:
OBJS = $(SRC:.c=.o)
or patsubst:
OBJS = $(patsubst %.c,%.o,$(SRC))
I am talking about this question where the person has updated his final solution with a makefile for the task. I am having a hard time understanding how it's done.
There is a rule:
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
which I am unable to understand, but by intuition I know what it will be doing. Almost everything else is pretty much clear. Thanks!
This is a static pattern rule. The first field is a list of targets, the second is a target pattern which Make uses to isolate a target's "stem", the third is the prerequisite pattern which Make uses to construct the list of prerequisites.
Suppose you have
SRCDIR = src
OBJDIR = obj
OBJECTS = obj/foo.o obj/bar.o obj/baz.o
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
If you make obj/foo.o, Make first identifies this rule as the one to use (since obj/foo.o is in the target list $(OBJECTS)), matches it against the target pattern obj/%.o and finds that the stem (the part matched by the wildcard %) is foo, then plugs that into the prereq pattern src/%.c and finds that the prerequisite is src/foo.c.
If you've also defined the variables
CC = gcc
CFLAGS = -thisflag -thatflag=something
Then the command in the rule becomes
#gcc -thisflag -thatflag=something -c src/foo.c -o obj/foo.o
(Note that $< is the first prerequisite and $# is the target name.)
In answer to your other question: Yes, a makefile can handle a dependency on a header file (x.h) so that if the header has been modified, Make will rebuild the target. No, this makefile doesn't do that. You can modify the makefile by hand, adding rules like
a.o: x.h
assuming you know what the inclusions actually are, or you can have the makefile do it automatically, which is an advanced technique you probably shouldn't attempt yet.
This line is explaining how to obtain the object files (.o) from the source (.c), it avoids having to repeat the line for each .c file.
The objects will be in OBJDIR and the sources in SRCDIR
$(CC) will contain the compiler, CFLAGS will contain the options for the compiler and -c tells gcc to compile the source into objects.
For example:
CC = gcc
CFLAGS = -g -Wall
can be converted into
gcc -g -Wall -c test.c -o test.o
I want to write a lot of tiny example programmes for one same library, each needs gcc $(OtherOpt) -o xxx -lthelibname xxx.c.
How to write a Makefile without dozens of tagret lines ?
Pattern rules are your friend for these situations. As long as your targets all match a predictable pattern -- and they do in this case, as they are all of the form "create foo from foo.c" -- you can write a single pattern rule that will be used for all of the targets:
OtherOpt=-Wall -g
all: $(patsubst %.c,%,$(wildcard *.c))
%: %.c
gcc $(OtherOpt) -o $# -lthelibname $<
Now you can either run simply make to build all your apps, or make appname to build a specific app. Here I've created a single pattern rule that will be used anytime you want to create something from something.c. I used the $# automatic variable, which will expand to the name of the output, and the $< variable, which will expand to the name of the first prerequisite, so that the command-line is correct regardless of the specific app being built. Technically you don't need the all line, but I figured you probably didn't want to always have to type in the name(s) of the apps you want to build.
Also, technically you can probably get away without having any of this makefile, because GNU make already has a built-in pattern rule for the %: %.c relationship! I mention this option only for completeness; personally, I prefer doing things the way I've shown here because it's a little bit more explicit what's going on.
%.o: %.c
gcc $(OtherOpt) -c -o $# -lthelibname $<
That compiles all .c files to their .o files (object code) of the same base name. Then in your actual target(s), you would include all necessary .o files as dependencies and use gcc $(OtherOpt) -o $# $^ -lthelibname, assuming I'm not misunderstanding how your build is set up.
Some versions of make also support the suffix rule .c.o to be ALMOST the same thing as %.o: %.c, but the suffix rules can't have any dependencies. Writing .c.o: foo.h tells make to compile "foo.h" to "foo.c.o" rather than requiring "foo.h" as a dependency of any file with a .c suffix as %.o: %.c foo.h would correctly do.
I learnd from http://sourceforge.net/projects/gcmakefile/
LDLIB = -lpthread
LDFLAGS = -Wl,-O1 -Wl,--sort-common -Wl,--enable-new-dtags -Wl,--hash-style=both $(LDLIB)
SRCDIRS =
SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp
CFLAGS = -pipe -march=core2 -mtune=generic -Wfloat-equal \
#-Wall -pedantic
ifeq ($(SRCDIRS),)
SRCDIRS = .
endif
SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
TARGET = $(addprefix bin/,$(basename $(SOURCES)))
all: $(TARGET)
ls -l $(TARGET)
bin/%: %.c dir
gcc $(CFLAGS) $(LDFLAGS) -o $# $<
dir:
#-mkdir bin
.PHONY : clean
clean:
-rm $(TARGET)
-rmdir bin