I am compiling code with this makefile
SHELL = /bin/tcsh
include ../make.inc
FC = gfortran
#--------------------------------------------------------------------
# Compiler flags
#--------------------------------------------------------------------
# none
#FFLAGS =
# Optimize
#FFLAGS = -O
# debug
#FFLAGS = -g
# Large memory needed (ifort)
FFLAGS = -O
#--------------------------------------------------------------------
# Location of files
#--------------------------------------------------------------------
DIR = ./
PLSRC = ./src/
PLPROG = ./programs/
#--------------------------------------------------------------------
# Module flag
#--------------------------------------------------------------------
# Sun Compiler
#MFLAG = -M
# Nag Compiler
#MFLAG = -i
#MFLAG = -I
# Absoft Compiler
#MFLAG = -p
# Intel or g95 compiler
MFLAG = -I
MODULE = $(MFLAG)$(MOD)
#--------------------------------------------------------------------
# Fortran Files
#--------------------------------------------------------------------
PLFILES = gplot.f90 gnuplot.f90
PLPRFILES = xyplot.f90
#--------------------------------------------------------------------
# Objects Files
#--------------------------------------------------------------------
PLOBJS = $(PLFILES:.f90=.o)
#--------------------------------------------------------------------
# Compile libraries
#--------------------------------------------------------------------
# $# means the target name
# $? means all dependencies (OBJS) that are new.
# $< similar to $? but just on dependency rules (%.o : %.f90)
all : libgplot.a organize pl_progs
libgplot.a : $(PLOBJS)
ar cr $# $(PLOBJS)
ranlib $#
rm *.o
%.o : $(PLSRC)%.f90
$(FC) $(FFLAGS) -c $< -o $#
organize : libgplot.a
mv *.mod $(MOD)
mv *.a $(LIB)
#--------------------------------------------------------------------
# Compile programs
#--------------------------------------------------------------------
pl_progs : xyplot test_plot
%: $(PLPROG)%.f90 $(LIB)libgplot.a
$(FC) $(FFLAGS) $(MODULE) $< $(LIB)libgplot.a -o $(PROG)$#
mv *.mod $(MOD)
#--------------------------------------------------------------------
# Clean
#--------------------------------------------------------------------
clean:
rm $(LIB)libgplot.a
I got this
root#milenko-HP-Compaq-6830s:/home/milenko/gprieto/gplot# make
gfortran -O -c src/gplot.f90 -o gplot.o
gfortran -O -c src/gnuplot.f90 -o gnuplot.o
ar cr libgplot.a gplot.o gnuplot.o
ranlib libgplot.a
rm *.o
mv *.mod /usr/local/
mv *.a /usr/local/lib/
gfortran -O -I/usr/local/ programs/xyplot.f90 /usr/local/lib/libgplot.a -o /usr/local/bin/xyplot
mv *.mod /usr/local/
gfortran -O -I/usr/local/ programs/test_plot.f90 /usr/local/lib/libgplot.a -o /usr/local/bin/test_plot
mv *.mod /usr/local/
mv: No match.
Makefile:123: recipe for target 'test_plot' failed
make: *** [test_plot] Error 1
I do not understand why the recipe failed in this case and worked with xyplot.
The fail happens at
mv *.mod /usr/local/
mv: No match.
There are no *.mod files mv could move so it triggers an error.
The most probable cause is that test_plot.f90 contains just the main program and no module. There is no place for the mv *.mod /usr/local/ command then for this file.
Related
This has been asked many times but from none of the answers can I figure out how to do it.
Simply put, I have directory structure: SRC/ for all *.for and *.f90 files, BLD/ for all files needed for building (that is *.o and *.mod) and lib/ for necessary libraries that need to be linked.
I want to build all source files in the SRC/ directory and put *.o and *.mod to the BLD/ directory while keeping the executable in the root where makefile is. I don't want to have multiple makefiles. The current makefile that does not work is below. I think that one issue there are lines that refere e.g. $(BLD)/$(objects) which probably expands to BLD/nrtype.o nrutil.o nr.o mtypes.o polint.o polyin2.o a.o but I am not really sure, and I am just trying and erroring since I do not have enough knowledge and the manuals are not clear for me to be able to figure it out. In one of the trials, *.mod some got to BLD/ some stayed in the root, it seems that the rules do not work I think they do.
# Compilation related variables
SRC = src
BLD = build
LIB = lib
FC = gfortran
LDFLAGS = $(LIB)/asm_functions.o
FFLAGS = -O0
# the name of the output executable
target = a
# all objects to generate
objects = nrtype.o nrutil.o nr.o mtypes.o polint.o polyin2.o a.o
#
modules = nrtype.mod nrutil.mod nr.mod mtypes.mod
# set module dependencies
nrtype_mod = polint.o polyin2.o
nrutil_mod = polint.o polyin2.o
nr_mod = polin2.o
mtypes_mod = a.o
# set default target
default: $(target)
# add dependencies to the targets
$(nrtype_mod): nrtype.mod
$(nrutil_mod): nrutil.mod
$(nr_mod): nr.mod
$(mtypes_mod): mtypes.mod
# compile modules
$(BLD)/%.mod: $(SRC)/%.f90 $(BLD)/%.o
$(FC) -c $(FFLAGS) -o $# $<
# compile old fortran files
$(BLD)/%.o: $(SRC)/%.for
$(FC) -c $(FFLAGS) -o $# $<
# compile new fortran files
$(BLD)/%.o: $(SRC)/%.f90
$(FC) -c $(FFLAGS) -o $(BLD)$# $<
# link everything
$(target): $BLD/$(objects)
$(FC) -o $# $(FFLAGS) $^ $(LDFLAGS)
# cleaning up
clean:
rm -f $(BLD)/$(objects) $(BLD)/$(modules)
clobber: clean
rm -f $(BLD)/$(target)
.PHONY: default clean clobber
Update
I edited the makefile to the form:
# Compilation related variables
SRC = src
BLD = build
LIB = lib
FC = gfortran
LDFLAGS = $(LIB)/asm_functions.o
FFLAGS = -O0
# the name of the output executable
target = a
# all objects to generate
objects = $(BLD)/nrtype.o $(BLD)/nrutil.o $(BLD)/nr.o $(BLD)/mtypes.o $(BLD)/polint.o $(BLD)/polyin2.o $(BLD)/a.o
#
modules = $(BLD)/nrtype.mod $(BLD)/nrutil.mod $(BLD)/nr.mod $(BLD)/mtypes.mod
# set module dependencies
nrtype_mod = polint.o polyin2.o
nrutil_mod = polint.o polyin2.o
nr_mod = polin2.o
mtypes_mod = a.o
# set default target
default: $(target)
# add dependencies to the targets
$(nrtype_mod): nrtype.mod
$(nrutil_mod): nrutil.mod
$(nr_mod): nr.mod
$(mtypes_mod): mtypes.mod
# compile modules
$(BLD)/%.mod: $(SRC)/%.f90 $(BLD)/%.o
$(FC) -c $(FFLAGS) -o $# $<
# compile old fortran files
$(BLD)/%.o: $(SRC)/%.for
$(FC) -c $(FFLAGS) -o $# $<
# compile new fortran files
$(BLD)/%.o: $(SRC)/%.f90
$(FC) -c $(FFLAGS) -o $# $<
# link everything
$(target): $(objects)
$(FC) -o $# $(FFLAGS) $^ $(LDFLAGS)
# cleaning up
clean:
rm -f $(BLD)/$(objects) $(BLD)/$(modules)
clobber: clean
rm -f $(BLD)/$(target)
.PHONY: default clean clobber
While with this modification the build is successful, it is still not obeying orders. Specifically, *.mod files are being generated where the makefile is but I found in the meantime that it is gfortran who is disobedient and for mod files the output directory is controlled by some other switch. Nevertheless:
Other things that are not clear:
Should the lines look like:
$(BLD)/%.o: $(SRC)/%.for
$(FC) -c $(FFLAGS) -o $# $<
Or
%.o: %.f90
$(FC) -c $(FFLAGS) -o $(BLD)/$# $(SRC)/$<
or is it the same (i prefer the second one for readability).
Why the line such as
nrtype_mod = polint.o polyin2.o
do not need to be prepended by the paths? Or do they have to be (but it built correctly). This is where it is very confusing.
The maual would really benefit from some basic examples of a full makefile.
I think that one issue there are lines that refere e.g. $(BLD)/$(objects) which probably expands to BLD/nrtype.o nrutil.o nr.o mtypes.o polint.o polyin2.o a.o
You are exactly correct in your assessment here.
You can use a GNU make function like addprefix to fix this.
It would be useful to understand what part of the manual you had trouble understanding, so it can be improved.
I am getting vk: command not found when running vk, and getting bash: ./vk: No such file or directory when executing ./vk.
I did some research and the cause is usually that it isa 32bit exe on a 64bit machine
make builds the output to vk/_target. I cd to _target
When I run file vk I get this back.
vk: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld6, not stripped
I have tried executing chmod +x vk and chmod u+x vk. I have tried every combination of typing ./vk and vk with chmod. I'm at a loss here. I have passed -m64 as an option to gcc, but that seems to be the default.
Here is my makefile
CFLAGS = -m64 -Wall -O3
CC = gcc
LINKER = ld -lc --entry main
DUMP = objdump
COPY = objcopy
TARGET_DIR = _target
SRCS := $(shell find ./ -name \*.c)
VPATH := $(sort $(dir $(SRCS)))
OBJS := $(patsubst %.c,$(TARGET_DIR)/%.o,$(notdir $(SRCS)))
$(TARGET_DIR)/vk : $(OBJS)
$(LINKER) $^ -o $#
$(DUMP) -D $# > $(#:=.list)
$(TARGET_DIR)/%.o : %.c folders
#echo "compiling $<"
$(CC) $(CFLAGS) -c $< -o $#
#echo "assembly dump $#"
$(DUMP) -D $# > $#.list
.PHONY: folders
folders:
mkdir -p $(TARGET_DIR)
.PHONY: clean
clean:
rm -rf $(TARGET_DIR)
So I have been trying to use the answers and the idea of this published question: Makefile: Compiling from directory to another directory
In the following excerpt code, you can see the definition of the directories, for sources and compilation objects.
all : Mpois Mkvz MBJ Mlid
# Definitions
COMPILER := gfortran -O3
LIBS := -g -fbounds-check -ffast-math -lm
# Directories of object code
OBJDIR = objects
SRCDIR = src
SOURCES := $(SRCDIR)/lbm_const.f90 $(SRCDIR)/BORDERS.f90 $(SRCDIR)/CONVERGENCE.f90 $(SRCDIR)/FILESIO.f90 $(SRCDIR)/LBM.f90
OBJECTS := $(OBJDIR)/lbm_const.o $(OBJDIR)/BORDERS.o $(OBJDIR)/CONVERGENCE.o $(OBJDIR)/FILESIO.o $(OBJDIR)/LBM.o
SOURCES_pois := $(SRCDIR)/Main_pois.f90
OBJECTS_pois := $(OBJDIR)/Main_pois.o
# Linking
Mpois: $(OBJECTS) $(OBJECTS_pois)
$(COMPILER) $^ -o $# $(LIBS)
# Compiling
$(OBJECTS): $(OBJDIR)/%.o: %.f90
$(COMPILER) -c $< -o $#
# Compiling
$(OBJECTS_pois): $(OBJDIR)/%.o: %.f90
$(COMPILER) -c $< -o $#
clean:
rm -f $(OBJDIR)/*.o
rm -f $(OBJDIR)/*.mod
rm -f $(SRCDIR)/*.mod
When running the makefile script I get the following error:
make: *** No rule to make target 'lbm_const.f90', needed by 'objects/lbm_const.o'. Stop.
Interesting is to note that when SRCDIR = src changes to SRCDIR = . the makefile compiles even having files in folder src.
I have following folder structure
--Makefile
--source/
--boot.s
--kernel.c
--linker.ld
--build/
and I compile my sources using following Makefile
###############################################################################
#
# A makefile script for generation of raspberry pi kernel images.
#
###############################################################################
# The toolchain to use. arm-none-eabi works, but there does exist
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
CFLAGS = -march=armv8-a+crc \
-mcpu=cortex-a53 \
-mtune=cortex-a53 \
-mfpu=crypto-neon-fp-armv8 \
-mfloat-abi=hard \
-ftree-vectorize \
-funsafe-math-optimizations \
-O2 -pipe -ffreestanding
LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib
# The name of the output file to generate.
TARGET = kernel.img
.PHONY: all clean run
# Rule to make everything.
all: $(TARGET)
# Rule to remake everything. Does not include clean.
rebuild: clean all
#Rule to invoke qemu
run:
qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf
$(TARGET): kernel.elf
arm-none-eabi-objcopy $(BUILD)kernel.elf -O binary $(BUILD)kernel.img
kernel.elf: boot.o kernel.o
$(LD) $(LDFLAGS) -o $(BUILD)kernel.elf $(BUILD)boot.o $(BUILD)kernel.o
boot.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o
kernel.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)kernel.c -o $(BUILD)kernel.o
# Rule to clean files.
clean :
-rm -f $(BUILD)*
-rm -f *.o
-rm -f *.elf
-rm -f *.img
How to write pattern based rules ? I tried many stack overflow answers but couldn't make it work.
First I listed my source using wild cards but couldn't write proper target as sources list had [source/boot.s source/kernel.c] and it would create object files in source folder it self.
I was facing difficulty while keeping sources and build directory different. Any help is appreciated.
----------Complete solution as per #MadScientist -----------
###############################################################################
#
# A makefile script for generation of raspberry pi kernel images.
#
###############################################################################
# The toolchain to use. arm-none-eabi works, but there does exist
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
CFLAGS = -march=armv8-a+crc \
-mcpu=cortex-a53 \
-mtune=cortex-a53 \
-mfpu=crypto-neon-fp-armv8 \
-mfloat-abi=hard \
-ftree-vectorize \
-funsafe-math-optimizations \
-O2 -pipe -ffreestanding
LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib
SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))
# The name of the output file to generate.
TARGET = kernel.img
.PHONY: all clean run
# Rule to make everything.
all: $(BUILD)$(TARGET)
# Rule to remake everything. Does not include clean.
rebuild: clean all
#Rule to invoke qemu
run:
qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf
$(BUILD)%.o : $(SOURCE)%.s
$(CC) $(CFLAGS) -c $< -o $#
$(BUILD)%.o : $(SOURCE)%.c
$(CC) $(CFLAGS) -c $< -o $#
$(BUILD)$(TARGET): $(BUILD)kernel.elf
arm-none-eabi-objcopy $< -O binary $#
$(BUILD)kernel.elf: $(OBJECTS)
$(LD) $(LDFLAGS) -o $# $^
# Rule to clean files.
clean :
-rm -f $(BUILD)*
-rm -f *.o
-rm -f *.elf
-rm -f *.img
This is wrong:
boot.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o
You are telling make that your recipe will build a file named boot.o, but it doesn't: it creates a file named $(BUILD)boot.o, which is completely different. Same with your rules to build kernel.img and kernel.elf.
If you want to write a pattern rule the % can match only identical parts. Since SOURCE and BUILD are not identical, they won't match the % part. So you have to write this:
$(BUILD)%.o : $(SOURCE)%.s
$(CC) $(CFLAGS) -c $< -o $#
Since you're building $(BUILD)xxx.o you have to use that as a prerequisite as well, so you have to write:
$(BUILD)$(TARGET): $(BUILD)kernel.elf
arm-none-eabi-objcopy $< -O binary $#
$(BUILD)kernel.elf: $(BUILD)boot.o $(BUILD)kernel.o
$(LD) $(LDFLAGS) -o $# $^
ETA
If you want to get the source files via wildcard you can, but you have to substitute the directory as well not just the suffix, like this:
SOURCES := $(wildcard $(SOURCE)*.s)
OBJECTS := $(patsubst $(SOURCE)%.s,$(BUILD)%.o,$(SOURCES))
If you have both assembly and C source files (you didn't show any C source files in your example makefile) you can use this:
SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))
I'm trying to create a generic makefile to build static libraries that my project uses. I've used the expertise on this site, as well as the GNU Make manual to help write the following makefile. It is working well apart from one annoying problem.
# Generic makefile to build/install a static library (zlib example)
ARCH = linux
CFLAGS = -O3 -Wall
# List of source code directories
SOURCES = src test utils
# List of header files to install
INCLUDES = src/zlib.h src/zconf.h
# Library to create
LIBNAME = libz.a
############################################################
BUILD_DIR = build/$(ARCH)
# Full path to the built library
TARGET = $(BUILD_DIR)/$(LIBNAME)
prefix = ../..
exec_prefix = prefix
libdir = $(prefix)/lib/$(ARCH)
includedir = $(prefix)/include
INSTALL_PROGRAM = install -D
INSTALL_DATA = $(INSTALL_PROGRAM) -m 644
CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c))
OBJECTS := $(addprefix $(BUILD_DIR)/,$(CFILES:.c=.o))
DEPENDS := $(OBJECTS:.o=.d)
.PHONY: all installdirs install uninstall clean
# Default
all: $(DEPENDS) $(TARGET)
# Build the dependency files
# (GNU Make Manual 4.14 Generating Prerequisites Automatically)
$(BUILD_DIR)/%.d: $(BUILD_DIR)
#echo "build dep for $*.c as $#"
#$(CC) -M $(CFLAGS) $*.c > $#.tmp
#sed s~.*:~"$(BUILD_DIR)/$*.o $#:"~ $#.tmp > $#
#rm $#.tmp
# Link all changed object files into static library
$(TARGET): $(OBJECTS)
$(AR) -rc $(TARGET) $?
# Compile C source to object code
$(BUILD_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
# Create the necessary directory tree for the build
$(BUILD_DIR):
#for p in $(SOURCES); do mkdir -p $(BUILD_DIR)/$$p; done
# Create the necessary directory tree for installation
installdirs:
#mkdir -p $(libdir)
#mkdir -p $(includedir)
# Install the library and headers
install: all installdirs
$(INSTALL_DATA) $(TARGET) $(libdir)
for p in $(INCLUDES); do $(INSTALL_DATA) $$p $(includedir); done
# Remove the library and headers
uninstall:
rm -f $(libdir)/$(LIBNAME)
for p in $(notdir $(INCLUDES)); do rm -f $(includedir)/$$p; done
# Remove all build files
clean:
rm -fr $(BUILD_DIR)
# Pull in the dependencies if they exist
# http://scottmcpeak.com/autodepend/autodepend.html
-include $(DEPENDS)
The problem is that the dependency files are built when they don't need to be. e.g. make install shown below rebuilds the .d files before installing.
$make --version
GNU Make 3.81
$make
build dep for utils/utils.c as build/linux/utils/utils.d
build dep for test/test.c as build/linux/test/test.d
build dep for src/zutil.c as build/linux/src/zutil.d
...
{ continues on making the other .d files, then the .o files }
...
cc -O3 -Wall -c src/zutil.c -o build/linux/src/zutil.o
cc -O3 -Wall -c test/test.c -o build/linux/test/test.o
cc -O3 -Wall -c utils/utils.c -o build/linux/utils/utils.o
ar rc { ... .o files ... }
All good up to this point! But a 'make install' now will rebuild the .d files
$make install
build dep for utils/utils.c as build/linux/utils/utils.d
build dep for test/test.c as build/linux/test/test.d
build dep for src/zutil.c as build/linux/src/zutil.d
{ ... }
install -D -m 644 build/linux/libz.a ../../lib/linux
for p in src/zlib.h src/zconf.h; do install -D -m 644 $p ../../include; done
I tried to 'touch' the .d files when the objects are built, so the update time is newer than the .o files, but that had no effect. What's wrong with my makefile?
The problem is that you include the dependency files (whatever.d), and you also have a rule for building these files. So every time you use this makefile, no matter what target you specify, it will rebuild them, include them, and execute again.
Try this for an approach to dependency handling that solves this problem. Basically, you don't need a separate rule for foo.d, just make it a side effect of the foo.o rule (it takes some thought to realize that this will work).