Makefile with multiple targets - linux

Hopefully this is a very simple question. I have a makefile pattern rule that looks like this:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
I want the makefile to build a number of .so files, so I tried to get it to build two files (radgrd_py.so and lodiso_py.so) by doing this:
radgrd_py.so lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
and then tried this:
radgrd_py.so:
lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
But in each case, it only builds the first target that I specify. If I run 'make radgrd_py.so' it works fine, I'm just not sure how to specify a list of files that need to be built so I can just run 'make'.

The usual trick is to add a 'dummy' target as the first that depends on all targets you want to build when running a plain make:
all: radgrd_py.so lodiso_py.so
It is a convention to call this target 'all' or 'default'. For extra correctness, let make know that this is not a real file by adding this line to your Makefile:
.PHONY: all

Best way is to add:
.PHONY: all
.DEFAULT: all
all: radgrd_py.so lodiso_py.so
Explanations:
make uses the first target appearing when no .DEFAULT is specified.
.PHONY informs make that the targets (a coma-separated list, in fact) don't create any file or folder.
all: as proposed by schot

Related

Getting dependencies of a shared library that could be located at any folder

I'm creating a Rules.make file, similar to Linux's 2.0 version, which contains all kinds of targets - including .so files. My goal is to then only need to make minimalistic Makefiles like so:
include $(DIR_TOP)/Rules.make
in the directories that contain any source files I need compiled. The rules also enable me to create targets like so in the "main" Makefile:
something: something_else lib.so
, so that something_else is done first, and then lib.so is built.
Everything has been going smoothly, until I decided to add dependencies to the aforementioned shared library target. I figured something like the following would do the trick:
${DIR_OUT}/%.so: $(shell find $(dir $#) -name *.o)
$(CC) $(CFLAGS) -o $# $(CLIBS) -shared $^
However, to my demise, $(dir $#) apparently expands to $(dir ${DIR_OUT}/%.so), which then results in simply ${DIR_OUT}, which is exactly not what I need. DIR_OUT is simply the top-level directory string, but the target may be invoked from any sub-directories, or simply like target: $(DIR_OUT)/path/to/lib.so. I was hoping that % could match not only file names, but also any directories (which it does), and then have that expanded to $# once it's already decided what the full path is. Doesn't work like that. With this solution, not only the object files I need are included in the building process, but also any other object files that are there in the output folder, and that then produces errors of kind multiple definition of x y z etc.
Is there any other way to get the list of dependencies for the shared library I want to build? Ideally a purely Makefile based solution, but if there isn't one, I'm fond of some bash scripting too.
The solution turns out to be secondary expansion:
.SECONDEXPANSION:
${DIR_OUT}/%.so: $$(shell find $$(dir $$#) -name *.o)
$(CC) $(CFLAGS) -o $# $(CLIBS) -shared $^

Primitive makefile failure for compiling

I am trying to learn makefile, but I fail badly.
One example (which is very primitive) but I should understand it to go ahead is this one
f90_simple: f1.o
gfortran f1.o
mv a.out f90_simple
f90_simple.o: f1.f90
gfortran -c f1.f90
it does not work, and I get this error
I get this error
make: *** No rule to make target `f1.o', needed by `f90_simple'. Stop.
could you please advise me?
thanks
Your first rule says that before f90_simple can be built, the target f1.o must be built.
But there's no rule in your makefile that tells make how to build the target f1.o, and make can't find any built-in rule that can build it (based on the source files make has available), so it prints that error.
You do have a rule that tells make how to build a target f90_simple.o... but that's not the target make is looking for. Most likely you want your makefile to either be:
f90_simple: f1.o
gfortran $^
mv a.out $#
f1.o: f1.f90
gfortran -o $# -c $<
or else:
f90_simple: f90_simple.o
gfortran $^
mv a.out $#
f90_simple.o: f1.f90
gfortran -o $# -c $<
but you can't mix and match them, or make doesn't know what to do.
I think you would really benefit from reading at least the introductory chapters in The GNU Make Manual.

Make could not see commands (recipes) except gcc

My system is windows 8.1. I'm working on cygwin 32 bit version (first i set up 64 bit version and could not uninstall completely , later set up 32 bit version).I simply want to use 'make' utility. All my makefiles' extensions are 'makefile'.
When i try this below (to see them work , I only use simple makefiles)
make kernel.o (in shell)
kernel.o : kernel.c
<tab>gcc - ffreestanding -c $< -o $#
it works , and compiles.
But these ones below do not work. And for testing purposes and keeping things simple, each source and corresponding makefiles are in own directory. And all make commands've been made in the current directory where source and corresponding makefiles are located.
All executables (nasm ,ld ,objcopy ,cat) that cygwin needs to run the recipes are in the same directory (that is c:\cygwin\bin\)
If i command the recipes from shell, they work.
I also changed source files to see what would happen.
I also thought that maybe the problem is from cygwin itself , and i set up linux ubuntu desktop version to my machine. But they are (recipes below) not working too.(and also If i command the recipes from shell, they work.)
make kernel_entry.o (in shell)
make: *** No rule to make target 'kernel_entry.o'.
Rule:
kernel_entry.o : kernel_entry.asm
<tab>nasm $< -o $# -f coff (coff for windows)
//--------------------------------
make os-image.bin (in shell)
make: *** No rule to make target 'os-image.bin'.
Rule:
os-image.bin: boot.bin kernel.bin
<tab>cat $< > $#
//--------------------------------
make boot.bin
make: *** No rule to make target 'boot.bin'.
Rule :
boot.bin : boot.asm
<tab> nasm $< -f bin -o $#
*recipes with ld and objcopy also does not work.*
Thank you in advance...
These are my files and directory appearance :
C:\cygwin\bin --> where gcc.stays
C:\cygwin\bin --> where make.exe stays
C:\cygwin\bin --> where objcopy stays
C:\cygwin\bin --> where nasm.exe stays
C:\cygwin\bin --> where ld stays
C:\cygwin\home\me\OS\boot --> where boot.makefile stays and also boot.asm source code
C:\cygwin\home\me\OS\kernel --> where kern.makefile stays ( working sample ) and also kernel.c source code
And this is cygwin shell appearance:
me#Me ~/os/kernel
$ dir
kern.makefile kernel.c kernel_entry.asm
**in my kern.makefile the existing rule is as follows
kernel_entry.o : kernel_entry.asm
nasm $< -o $# -f coff
and boot directory
me#Me ~/os/boot
$ dir
boot.asm disk_load.asm print_hex.asm print_string_pm.asm
boot.makefile gdt.asm print_string.asm switch_to_pm.asm
**in my boot.makefile the existing rule is as follows
boot.bin : boot.asm
nasm $< -f bin -o $#
Make does not see your makefiles.
From the GNU make manual:
If no -f option is present, make will look for the makefiles GNUmakefile, makefile, and Makefile, in that order.
From what I see, your makefiles (kern.makefile, boot.makefile) are simply not found by your call to make (which does not have a -f option). This makes make rely on its internal rules, which do not include any %.o: %.asm dependency or somesuch (for make, assembly ends in .s, assembly with preprocessing to be done in .S).
This can become bloody confusing when your *.c and *.S files are compiled into *.o files, because make does have internal rules for those -- which, of course, stubbornly refuse to take any compiler options into account that you might have defined in that makefile of yours that make doesn't actually read. ;-)
So either call
make -f kern.makefile kernel.o
or (and this is my recommendation), rename <whatever>.makefile to Makefile (which is the canonical way of naming those).

How to ouput the static library into other directory than current?

Following is my directory structure
calculator
|
|---src
(multiply.cpp sum.cpp)
|---lib
I am building a static library calc.a using following
ar -rcs calc.a multiply.o sum.o
calc.a is builded in current directory.
I trying calc.a to be put into lib folder not in current directory (i.e. src)
I searched in internet and man page but couldn't find anything.
Any idea?
Since you are using the command line, the easiest way to write the library into the lib directory is to do it explicitly:
ar -rcs lib/libcalc.a multiply.o sum.o
Using a Makefile you can do more sophisticated things, but even then, it boils down to the same thing, e.g. adding the path to the front of the library name.
Since you asked for additional info on your comment, I add here a simple Makefile, which may be helpful to get you started:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=src/main.cpp src/sum.cpp src/multiply.cpp
OBJECTS=$(SOURCES:.cpp=.o)
LIBRARY=lib/libcalc.a
EXECUTABLE=main
all: $(SOURCES) $(LIBRARY) $(EXECUTABLE)
$(LIBRARY): $(OBJECTS)
<tab>mkdir -p lib
<tab>ar -rcs $# $<
$(EXECUTABLE): $(OBJECTS)
<tab>$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
<tab>$(CC) $(CFLAGS) $< -o $#
clean:
<tab>rm -rf main lib/ src/*.o
Important: All <tab>s must be replaced with real tabs, as required by the Makefile syntax!
Makefiles are very very flexible, so they can be very simple and specific to your problem, or as general and/or complex to build many libraries and binaries, based on millions and millions of source code. I suggest you to search for Makefile documentation for more information.
As a final note, I also suggest you to rename your library as 'libcalc.a', since the 'lib' prefix is standard in Unix. Other similar standards apply for other environments.

makefile with multiple dependencies for a single file

I have a makefile similar to the following:
SRCS = a.c b.cpp
OBJS = objs/a.o objs/b.o
all: $(OBJS)
objs/%.o: %.c
gcc -c $< -o $#
objs/%.o: %.cpp
gcc -c $< -o $#
It seems to work. But I don't really understand why.
Why doesn't it try to generate a.cpp and b.c?
as I read it : a.cpp is a prerequisite for objs/a.o and it should try to generate it. And because it doesn't find a matching rule for it - it should fail
Where am I wrong?
P.S - I execute my makefile using -r -R to avoid builtin rules
Make does not combine the prerequisite lists of different pattern rules.
When Make is looking for a way to build objs/a.o, it finds that the first pattern rule matches the target, and the prerequisite (a.c) exists. The second pattern rule matches the target, but the prerequisite (a.cpp) does not exist and cannot be built, so Make uses the first rule. Likewise, Make chooses the second rule over the first when looking for a way to build objs/b.o.
Make would try to generate a.cpp and b.c if these files depended on something else. However it is not the case here, these two files are leaves in the dependency tree, so Make has no reason to try to generate them.

Resources