I want to recompile an old Fortran 77 code (having a lot of subroutines) via gfortran in MingW bash platform in windows 10. There is a makefile among the old code files which is attached here:
Version = 2.10
FOR = df
FFLAGS = /optimize:5
INSTALL = move
DELETE = del
COPY = copy
# these libraries must already exist somewhere
# where ld can find them
LIBS = \rfem\lib\GAF77.lib \rfem\lib\VFEM.lib DFPORT.lib
# where the final program is to be placed
BINDIR = \rfem\bin
# where the cat man pages are to go
CATDIR = \rfem\doc
# here are the files needed to construct Rslope2D
FILES = mrslope2d.f \
chknxe.f dismsh.f echosd.f fem2det.f fem2rf.f \
fem2sd.f feminit.f mesh.f openin.f opensd.f \
pltfld.f readsd.f rect.f setsd2.f sim2sd.f \
statsd.f szchk.f vecmsh.f
OBJS = mrslope2d.obj \
chknxe.obj dismsh.obj echosd.obj fem2det.obj fem2rf.obj \
fem2sd.obj feminit.obj mesh.obj openin.obj opensd.obj \
pltfld.obj readsd.obj rect.obj setsd2.obj sim2sd.obj \
statsd.obj szchk.obj vecmsh.obj
rslope2d.exe: $(OBJS)
link /out:rslope2d.exe $(OBJS) $(LIBS)
$(DELETE) $(BINDIR)\rslope2d.exe
$(INSTALL) rslope2d.exe $(BINDIR)
$(COPY) rslope2d.1 $(CATDIR)
clean:
$(DELETE) *.obj
After navigating to the directory where this makefile is located and typing make in the MingW window (to recompile the main code),
I encounter the following error:
No rule to make target 'mrslope2d.obj', needed by 'rslope2d.exe'. Stop.
I am a beginner in Fortran, so apologies if the question is simple.
Looking forward to your suggestions and guidance as I do not know how to resolve this.
Thanks
Related
I am having issues with a Makefile on certain systems
SRC = $(wildcard $(SRCDIR)/*.c)
SRCS = $(wildcard $(SRCDIR)/*.s)
works when compiling in Azure Devops, but not when compiling on my local Windows 10 computer.
Changing the source to
SRC = \
$(SRCDIR)/browser.c \
$(SRCDIR)/main.c \
SRCS = $(SRCDIR)/data's
allows compilation without issue in both instances. I am wondering if it could be a dependency not being met, or VPATH getting in the way (although it is not used in my Makefile...
The issue was to do with a patch being applied to make. Removing the patch allowed wildcard to work as expected.
I am completely new to using autotools so it might be a dumb question but I'll try anyway. I have two pieces of Makefile.am. Except one is working fine and the other is not.
This works fine.
sbin_PROGRAMS = kernel
kernel_SOURCES = \
src/arch/$(host_cpu)/arch_sysdefs.h \
src/arch/$(host_cpu)/boot.asm \
src/arch/$(host_cpu)/cpu.asm \
src/arch/$(host_cpu)/isr.asm \
src/kmain.cpp
But this doesn't. .asm files are completely ignored by generated Makefile.
if HOST_CPU_X86
ASM_EXT = .asm
else
ASM_EXT = .S
endif
sbin_PROGRAMS = kernel
kernel_SOURCES = \
src/arch/$(host_cpu)/arch_sysdefs.h \
src/arch/$(host_cpu)/boot$(ASM_EXT) \
src/arch/$(host_cpu)/cpu$(ASM_EXT) \
src/arch/$(host_cpu)/isr$(ASM_EXT) \
src/kmain.cpp
What I am trying to do is that I want to use different suffixes for assembly files for some CPUs my project is going to support.
I've also added necessary rule to transform .asm to object files.
.asm.o:
yasm -f $(YASM_OUT_FMT) $< -o $#
EDIT: Temporarily overriding .cpp.o rule with echo $(kernel_SOURCES) reveals that $(ASM_EXT) in kernel_SOURCES is substituted correctly. For example src/arch/$(host_cpu)/boot$(ASM_EXT) becomes src/arch/x86_64/boot.asm for x86-64 CPU and src/arch/arm/boot.S for ARM, etc. Also, setting ASM_EXT variable from autoconf.ac doesn't make any difference.
I'm trying to create a makefile for a suite of programs that I am working on. The programs are all written in fortran and the source files are contained in different directories. I can't seem how to figure out how to get things to work. My current sumfile is
#Compiler and compiler flag variables
FCOMP=/usr/local/bin/gfortran
F_FLAGS=-O2 -fbounds-check -Wall
F_FLAGSDB=-g -fbounds-check -Wall
#paths to libraries
COMMON_LIB=/usr/local/lib/libspc_common.a
SPICE_LIB=/usr/local/lib/spicelib.a
# Paths to directories
BIN_DIR=BIN
# Get file names of component source files
#get names of files in src1
FORT_FILES=$(wildcard ./SRC1/*.f)
#get names of files in src2
FORTFILES+=$(wildcard ./SRC2/*.f)
#get names of files in src3
FORTFILES+=$(wildcard ./SRC3/*.f)
#get file names for output
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
# make commands
# Set the default option to compile the library with optimization
default: all
# create all command
all: $(EXE_FILES)
#echo toolkit has been built with optimization
#If compiling for debugging replace the compiler flags to remove optimization and add debugging
debug: F_FLAGS=$(F_FLAGSDB)
#Run compiler with debugging flags
debug: $(EXE_FILES)
#echo toolkit has been built with debugging
# Compile all of the source files into executables
$(EXE_FILES): % : %.f
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$#
# install the library in /usr/local/lib
install:
cp -p $(BIN_DIR)* /usr/local/bin/toolkit/
# remove executable files for a clean build
clean:
rm $(BIN_DIR)*
The problem I am running into is that I get the following error when I try to run make:
make: *** No rule to make target `Display.f', needed by `Display'. Stop.
which I am assuming is because I have lost the directory that the source file comes from. Can someone help me here? I am totally stuck and don't know how to proceed.
In addition (this is more a general question about make), is there a way to tell make to recompile everything if the COMMON_LIB changes?
Thanks for your help!
Suppose your source files are
SRC1/alpha.f
SRC1/beta.f
SRC2/gamma.f
SRC3/delta.f
1) There is a flaw here:
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
This will produce
BINalpha BINbeta BINgamma BINdelta
when I think you intended
BIN/alpha BIN/beta BIN/gamma BIN/delta
A simple fix:
EXE_FILES=$(addprefix $(BIN_DIR)/,$(notdir $(patsubst %.f, % , $(FORTFILES))))
2) Now look at the static pattern rule:
$(EXE_FILES): % : %.f
...
So to build BIN/alpha, Make must first find BIN/alpha.f, which doesn't exist. To make it look for alpha.f, do this:
$(EXE_FILES): $(BIN_DIR)/% : %.f
...
3) How to find the sources?
You could do some delicate coding to help Make remember where it found alpha.f, but there's no need when we can use the vpath directive:
vpath %.f SRC1 SRC2 SRC3
4) One last look at that rule:
This command:
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$#
Will produce e.g. BIN/BIN/alpha, which is silly. A non-PHONY Make rule should produce a file whose name is the target of the rule. It prevents a lot of trouble.
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $#
A few further refinements may be possible, once you have this working perfectly.
Following is the directory structure of my project:
expt-main
---------
Makefile_main
/ \
subdir-1 subdir-2
-------- --------
Makefile_1 Makefile_2
mod_codeA.f90 mod_code1.f90
mod_codeB.f90 mod_code2.f90
mod_codeC.f90 mod_code3.f90
Makefile_main:
export
SHELL = /bin/sh
F90 = mpxlf95
SRCDIRS = $(subdir-1) $(subdir-2)
all:
#for DIR in ${SRCDIRS} ;
do \
back=`pwd`; \
cd $$DIR ;\
$(MAKE) ; status=$$? ; \
if [ $$status != 0 ] ; then \
echo "Exit status fro make was $$status" ; exit $$status ; \
fi ; \
cd $$back ; \
done
-------------------------------------------------------------------------------
Makefile-1:
%.o: %.f90
$(F90) $(F90FLAGS) -I$(subdir-2) -c $<
mod_codeA.o: mod_codeC.o $(subdir-2)/mod_code2.o
-------------------------------------------------------------------------------
Makefile-2:
PROG = $(exec)
subdir-1_objs = $(subdir-1)/mod_codeA.o mod_codeB.o mod_codeC.o
all: $(PROG)
$(PROG): $(subdir-2_objs) $(subdir-1_objs) -o $# $(subdir-2_objs) $(subdir-1_objs)
---------------------------------------------------------------------------------
-
I've written the Makefile_main such that it compiles the codes (modules) in subdir-1 first and then the ones in subdir-2 and finally makes the executable. The issue: modules in subdir-1 uses modules from subdir-2 and in similar fashion, modules in subdir-2 uses those in subdir-1. My make is getting failed because the modules being used is in other directory. How to write a makefile which will take care of this issue that is, while compiling modules in subdir-1, whenever it encounters the need for an object file from subdir-2, it should switch to subdir-2 compile the necessary modules and return back to subdir-1 for further action?
If modules in different subdirectories need each other as you say, then this is not a good use of recursive Make.
Do away with Makefile-1 and Makefile-2, and let Makefile_main do all the work. (I can't tell you specifically how to change Makefile-main, since I don't do Fortran, I don't understand Makefile-2, and I don't see any dependency of modules in subdir-2 upon those in subdir-1).
If you want to stick to this directory layout and still keep three separated Makefiles, then you can use compiler flags to instruct the FORTRAN compiler to put module files into a common directory of your choice.
For instance using:
$ gfortran --version
GNU Fortran (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
you can use -I and -J flags to instruct the compiler on:
where to search for module files (.mod)
where to put generated module files
That said I think that the suggestion given by Beta to join the Makefiles makes a lot of sense. To know some of the reasons why you should do that you can read this paper.
Finally, as your project seems not to be very large at this stage, I also suggest to take into consideration CMake as a build system, as it possibly provides a more convenient way of specifying dependencies between targets (as well as many other things).
I don't really know anything about make or makefile scripts, so I'm hoping someone can tell me what I need to change. There is a common makefile script included in all of the others, and this specific piece of the code seems to be responsible for processing the list of source files (DLL_OBJS) and setting up the target to compile them:
ifdef DLL_TARGET
DLL_REAL_OBJS=$(addprefix $(OBJDIR)/, $(DLL_OBJS:=.$(OBJ))) $(DLL_VERSION_OBJS)
DLL_OUTPUT_FILE=$(OBJDIR)/$(LIBPREFIX)$(DLL_TARGET).$(DYNAMIC_LIB_SUFFIX)
$(DLL_OUTPUT_FILE): $(DLL_REAL_OBJS) $(DLL_NONPARSED_OBJS)
$(CC) $(CC_SHARED_LIB_FLAGS) $(LD_DYNAMIC) \
\
$(LD_DASH_O)$(DLL_OUTPUT_FILE) \
\
$(DLL_REAL_OBJS) $(DLL_NONPARSED_OBJS) \
$(DLL_EXTRA) $(PRELIB) $(LD_FLAGS) \
$(DLL_REAL_LIBS) $(DLL_NONPARSED_LIBS) $(LD_LIBS) $(DLL_OPTION)
ifdef EMBED_MANIFEST
ifndef SUPPRESS_MANIFEST_DLL
$(PREMANIFEST) $(MT) \
\
$(MANIFESTFLAGS) /outputresource:"$(DLL_OUTPUT_FILE);#2" /manifest $(DLL_OUTPUT_FILE).manifest
endif
endif
endif # DLL_TARGET
The problem is if I do this:
DLL_OBJS=subdir/main
Then it will try to write the main.obj file to WINNT5.0_DBG.OBJ/subdir/main.obj, whereas I want it to go to WINNT5.0_DBG.OBJ/main.obj. How can I modify the code above to exclude the subdirectory portion of the source file from the object file output path? I suspect the changes will need to happen to the DLL_REAL_OBJS variable.
Note that DLL_OBJS could be a list of items, like:
DLL_OBJS=\
subdir/main\
subdir/foo\
bar\
another_source
Let me know if any important information is missing and I will do my best to update my question with it.
If you're using GNUMake, just modify the second line:
DLL_REAL_OBJS=$(addprefix $(OBJDIR)/, $(notdir $(DLL_OBJS:=.$(OBJ)))) $(DLL_VERSION_OBJS)