I'm running a makefile using GNU Make 4.1 on windows. I've seen a lot of SO links about this topic, but they all seem to be for C or c++. I'm not sure if the same rules apply, and since I'm using windows, syntax seems to be a bit different too.
Here's my make file:
FC = gfortran
FCFLAGS = -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all
# FCFLAGS = -O2
MODDIR = "bin"
FCFLAGS += -J$(MODDIR) -fopenmp -fimplicit-none -Wuninitialized
SRCS_C =\
gridFun.f90 \
test.f90
OBJS_C = $(SRCS_C:.c=.o)
TARGET = test
all: $(TARGET)
$(TARGET): $(OBJS_C)
$(FC) -o $# $(FCFLAGS) $(OBJS_C)
$(OBJS_C): $(SRCS_C)
$(FC) $(FCFLAGS) -c $(SRCS_C)
cleanMod:
del *.mod
cleanObj:
del *.o
I run my make file with
gmake
and I've noticed that
mingw32-make
seems to produce the same result. The error I'm getting is:
gmake: Circular gridFun.f90 <- gridFun.f90 dependency dropped.
gmake: Circular test.f90 <- gridFun.f90 dependency dropped.
gmake: Circular test.f90 <- test.f90 dependency dropped.
gfortran -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all -J"bin" -fopenmp -fimpl
icit-none -Wuninitialized -c gridFun.f90 test.f90
gfortran -o test -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all -J"bin" -fopenm
p -fimplicit-none -Wuninitialized gridFun.f90 test.f90
Any help about how to fix this, and maybe an explanation would be greatly appreciated!
You don't have c sources so the _C suffix on variables is inaccurate (harmless but confusing).
The real issue is with this OBJS_C = $(SRCS_C:.c=.o) substitution ref.
That's expecting to change .c files into .o files but you don't have any .c files.
Change that to OBJS_C = $(SRCS_C:.f90=.o) and it should work for you.
Related
I have been trying to create a neatly-organized makefile project template utilizing the ARM mbed library. I have already solved a few of the problems (see this post) related to header file paths. However, now I am having problems with the linker. My goal is to have sources and headers in src, object files in obj, and the final binaries in either debug or release.
Here is the error I am getting...
make
arm-none-eabi-g++ -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 -std=c++98 -fno-rtti -I lib/ -I lib/mbed/ -I lib/mbed/TARGET_NUCLEO_F446RE/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ -I lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ -o obj/main.o src/main.cc
/usr/lib/gcc/arm-none-eabi/6.1.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
make: *** [makefile:54: obj/main.o] Error 1
This is my makefile. I have denoted where the problem(s) might be, but I am not sure.
#Project parameters
PROJECT = Nucleo_blink
OBJECTS = obj/main.o
DEST = debug
VPATH = src lib $DEST
TARGET = NUCLEO_F446RE
#Compilation options
DEBUG = 1
#Tools
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CXX = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
include $(TARGET).mk
CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0
else
CFLAGS += -DNDEBUG -Os
endif
#MY PROBLEM MAY BE HERE
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
#`-u _printf_float -u _scanf_float` after -specs for floating point I/O
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
LIBRARIES = -lmbed
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f debug/* obj/* asm/* $(DEPS)
obj/%.o: %.c
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.asm
$(CC) $(CPU) -c -x assembler-with-cpp -o asm/$# $<
#OR HERE
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$# $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $#
$(PROJECT).hex: $(PROJECT).elf
#$(OBJCOPY) -O ihex $< $#
$(PROJECT).lst: $(PROJECT).elf
#$(OBJDUMP) -Sdh $< > $#
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
Before you ask, I have already tried changing --specs=nano.specs to --specs=nosys.specs. It does nothing. The strange part is that the linker settings above work fine for the automatically generated mbed makefile.
Here is the working makefile. It compiles without errors...
# This file was automagically generated by mbed.org. For more information,
# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
GCC_BIN =
PROJECT = Nucleo_blink
OBJECTS = ./source/main.o
SYS_OBJECTS = #Long list of object files
INCLUDE_PATHS = -I. -I./source -I./mbed -I./mbed/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4 -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARY_PATHS = -L./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARIES = -lmbed
LINKER_SCRIPT = ./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
###############################################################################
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CPP = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
CC_SYMBOLS = -DTARGET_M4 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DMBED_BUILD_TIMESTAMP=1468213384.59 -DTARGET_STM32F446RE -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4
#My makefile above copies these two lines
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
ifeq ($(DEBUG), 1)
CC_FLAGS += -DDEBUG -O0
else
CC_FLAGS += -DNDEBUG -Os
endif
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex size
clean:
rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
.asm.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.s.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.S.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.c.o:
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $# $<
.cpp.o:
$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $# $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $#
$(PROJECT).hex: $(PROJECT).elf
#$(OBJCOPY) -O ihex $< $#
$(PROJECT).lst: $(PROJECT).elf
#$(OBJDUMP) -Sdh $< > $#
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
I think my problem is some sort of path error...
- The _exit symbol may be defined, but inaccessible by main.o
- There may be some major error in the makefile I'm missing
- Something totally different?
Feel free to comment any suggested changes to this question.
EDIT: All I had to do to fix the error was change CFLAGS to CCFLAGS. The answer I marked as the solution explained what was happening, and a potential way to fix it. Although I didn't need to use the suggested solution, the explanation of why it wasn't working is useful, and the information provided by both answers is useful.
Adding --specs=nosys.specs to your linker options may also solve this issue.
You can see exactly what this does by looking at the nosys.specs file which will be somewhere in your compiler directory.
See also: exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc
_exit is a system call, as well as some other functions you probably will need later. When you compile a binary for (for example) Linux, these calls are serviced by the operating system. In bare-metal embedded project you need to define these functions by yourself. The common way is to create a file called syscalls.c or something like that and put all needed system calls there. Take a look at example of such file, rapidly found by google: https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c
As a bonus, if you properly implement _read and _write to work with UART, you will get a serial console capable to do formatted IO via printf and scanf .
The _exit symbol may be defined, but inaccessible by main.o - There may be some major error in the makefile I'm missing - Something totally different?
This happens when a call to a standard library method indirectly has a dependency on exit(). Often from automatically generated exception unwind code that's supposed to abort your process on exit, which obviously has different semantics in a bare metal application. The division-by-zero floating point exception is one such example. -fno-exceptions does not help with this.
You can of course supply a do-nothing exit() handler but your code would be smaller if the exception unwind code didn't get inserted in the first place.
I discovered by examining the generated assembler that you can replace the exception handlers with do-nothing versions like this in a compilation unit:
extern "C" void __wrap___aeabi_unwind_cpp_pr0() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr1() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr2() {}
and then link those in as replacements at link time with these additional linker arguments.
-Wl,-wrap,__aeabi_unwind_cpp_pr0,
-Wl,-wrap,__aeabi_unwind_cpp_pr1
-Wl,-wrap,__aeabi_unwind_cpp_pr2
Another benefit is that your code should shrink as a result. You may even want to insert your own implementations that reset the MCU.
For me it took both -fno-exceptions and --specs=nosys.specs in compiler flags.
It seems like you use stdlib. System cal exit(int) calls in-system function _exit(int).
For me decision was applying -nostdlib option because I wasn't going to use stdlib.
Thanks, UserHuman, https://stackoverflow.com/a/51657692/8313090
I'm trying to compile and link several files in different folders using gfortran, and GNU Make 3.81 on a windows machine. I learned how to use wildcards from this reference:
gmake compile all files in a directory
And I want to do something similar to this reference:
Makefiles with source files in different directories
But the difference is that I want to build only one executable in my root directory from the source files in several other directories. I tried reading the make manual:
http://www.gnu.org/software/make/manual/make.html
But it seems primarily directed towards c/c++ programming and non-windows syntax.
My current makefile looks like this:
FC = gfortran
MOD_DIR = "bin"
FCFLAGS = -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized
TARGET = test
SRCS_C = $(wildcard *.f90) $(TARGET).f90
OBJS_C = $(patsubst %.f90,%.o,$(SRCS_C))
all: $(TARGET)
$(TARGET): $(OBJS_C)
$(FC) -o $# $(FCFLAGS) $(OBJS_C)
$(OBJS_C): $(SRCS_C)
$(FC) $(FCFLAGS) -c $(SRCS_C)
clean:
del *.o $(MOD_DIR)\*.mod
Which works fine when all of my source files are in the root directory. And so I thought this would work:
FC = gfortran
MOD_DIR = "bin"
FCFLAGS = -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all
# FCFLAGS += -J$(MOD_DIR) -I$(INCLUDE_DIR) -fopenmp -fimplicit-none -Wuninitialized
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized
TARGET = test
SRCS_C =\
"solvers/"$(wildcard *.f90) \
"user/"$(wildcard *.f90) \
$(wildcard *.f90) $(TARGET).f90
OBJS_C = $(patsubst %.f90,%.o,$(SRCS_C))
all: $(TARGET)
$(TARGET): $(OBJS_C)
$(FC) -o $# $(FCFLAGS) $(OBJS_C)
$(OBJS_C): $(SRCS_C)
$(FC) $(FCFLAGS) -c $(SRCS_C)
clean:
del *.o $(MOD_DIR)\*.mod
Where I don't mind just entering the names of the folders where a list of source files can be taken from. I've also tried using -I$(INCLUDE_DIR), but this didn't work either. The error from what I have above is:
gmake: *** No rule to make target `"user/"gridFun.f90', needed by `"user/"gridFu
n.o'. Stop.
Any help is greatly appreciated!
To accomplish what you want with SRCS_C, consider using:
SRCS_C =\
$(wildcard solvers/*.f90) \
$(wildcard user/*.f90) \
$(wildcard *.f90) $(TARGET).f90
Also note that (TARGET).f90 will also be matched by $(wildcard *.f90), in your cases causing test.f90 to be included twice in SRCS_C. You can safely omit $(TARGET).f90 in this example.
I'm running a makefile using mingw on windows. I've seen a lot of SO links about this topic, but they all seem to be for C or c++. I'm not sure if the same rules apply, and since I'm using windows, syntax seems to be a bit different too. Here are some of the other references:
How to place object files in separate subdirectory (most promising, I think)
Using a make file to compile files in separate directories
Flat object file directory structure output with GNU Make
What I currently have is (verbatim)
VPATH =\
user \
static \
computations \
solvers\\steadyState \
solvers\\transient \
solvers\\transient\\momentum \
solvers\\transient\\induction
FC = gfortran
TOP_DIR = .
MOD_DIR = $(TOP_DIR)\\mod
OBJ_DIR = $(TOP_DIR)\\obj
FCFLAGS = -g
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized
TARGET = parametricStudy
SRCS_F =\
user\\constants.f90 \
static\\myExceptions.f90 \
static\\myDebug.f90 \
static\\scalarField.f90 \
static\\vectorField.f90 \
static\\myIO.f90 \
user\\simParams.f90 \
static\\solverSettings.f90 \
static\\myTime.f90 \
computations\\myError.f90 \
static\\coordinates.f90 \
user\\griddata.f90 \
static\\myAllocate.f90 \
static\\BCs.f90 \
user\\rundata.f90 \
computations\\myDel.f90 \
computations\\vectorOps.f90 \
static\\myExport.f90 \
computations\\applyBCs.f90 \
solvers\\steadyState\\mySOR.f90 \
solvers\\steadyState\\myPoisson.f90 \
solvers\\transient\\induction\\initializeBBCs.f90 \
solvers\\transient\\induction\\initializeBfield.f90 \
solvers\\transient\\induction\\initializeSigmaMu.f90 \
solvers\\transient\\momentum\\initializeUBCs.f90 \
solvers\\transient\\momentum\\initializeUfield.f90 \
solvers\\transient\\inductionSolver.f90 \
solvers\\transient\\momentumSolver.f90 \
solvers\\transient\\MHDSolver.f90 \
user\\MOONS.f90 \
parametricStudy.f90
OBJS_F = $(patsubst %.f90,$(OBJ_DIR)\\%.o,$(notdir $(SRCS_F)))
all: $(TARGET)
$(TARGET): $(OBJS_F)
$(FC) -o $# $(FCFLAGS) $(OBJS_F)
$(OBJ_DIR)\\%.o: %.f90
$(FC) $(FCFLAGS) -c -o $# $<
clean:
del $(OBJ_DIR)\\*.o $(MOD_DIR)\\*.mod parametricStudy.exe
list:; #echo " "
#echo " "
#echo "Source files:"
#echo $(SRCS_F)
#echo " "
#echo "Object files:"
#echo $(OBJS_F)
#echo " "
#echo "Compiler : $(FC)"
#echo "Include directory : $(INC_DIR)"
#echo "Root directory : $(ROOT_DIR)"
#echo "Bin directory : $(BIN_DIR)"
#echo "Modules directory : $(MOD_DIR)"
#echo "Modules directory : $(MOD_DIR)"
#echo "Object directory : $(OBJ_DIR)"
#echo " "
Using this, I can execute the following (again, verbatim)
C:\Users\Charlie\Desktop\development\FORTRAN_LIB>gmake
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\const
ants.o user/constants.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myExc
eptions.o static/myExceptions.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myDeb
ug.o static/myDebug.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\scala
rField.o static/scalarField.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\vecto
rField.o static/vectorField.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myIO.
o static/myIO.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\simPa
rams.o user/simParams.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\solve
rSettings.o static/solverSettings.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myTim
e.o static/myTime.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myErr
or.o computations/myError.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\coord
inates.o static/coordinates.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\gridd
ata.o user/griddata.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myAll
ocate.o static/myAllocate.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\BCs.o
static/BCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\runda
ta.o user/rundata.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myDel
.o computations/myDel.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\vecto
rOps.o computations/vectorOps.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myExp
ort.o static/myExport.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\apply
BCs.o computations/applyBCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\mySOR
.o solvers\\steadyState/mySOR.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myPoi
sson.o solvers\\steadyState/myPoisson.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeBBCs.o solvers\\transient\\induction/initializeBBCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeBfield.o solvers\\transient\\induction/initializeBfield.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeSigmaMu.o solvers\\transient\\induction/initializeSigmaMu.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeUBCs.o solvers\\transient\\momentum/initializeUBCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeUfield.o solvers\\transient\\momentum/initializeUfield.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\induc
tionSolver.o solvers\\transient\\induction/inductionSolver.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\momen
tumSolver.o solvers\\transient\\momentum/momentumSolver.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\MHDSo
lver.o solvers\\transient/MHDSolver.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\MOONS
.o user/MOONS.f90
gmake: *** No rule to make target `.\\obj\parametricStudy.o', needed by `paramet
ricStudy'. Stop.
C:\Users\Charlie\Desktop\development\FORTRAN_LIB>gfortran -g -J.\\mod -fopenmp -
c -o .\\obj\parametricStudy.o parametricStudy.f90
C:\Users\Charlie\Desktop\development\FORTRAN_LIB>gmake
gfortran -o parametricStudy -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized
.\\obj\constants.o .\\obj\myExceptions.o .\\obj\myDebug.o .\\obj\scalarField.o
.\\obj\vectorField.o .\\obj\myIO.o .\\obj\simParams.o .\\obj\solverSettings.o .\
\obj\myTime.o .\\obj\myError.o .\\obj\coordinates.o .\\obj\griddata.o .\\obj\myA
llocate.o .\\obj\BCs.o .\\obj\rundata.o .\\obj\myDel.o .\\obj\vectorOps.o .\\obj
\myExport.o .\\obj\applyBCs.o .\\obj\mySOR.o .\\obj\myPoisson.o .\\obj\initializ
eBBCs.o .\\obj\initializeBfield.o .\\obj\initializeSigmaMu.o .\\obj\initializeUB
Cs.o .\\obj\initializeUfield.o .\\obj\inductionSolver.o .\\obj\momentumSolver.o
.\\obj\MHDSolver.o .\\obj\MOONS.o .\\obj\parametricStudy.o
Note that after I receive the error, I can explicitly compile the parametricStudy.f90 after the error with:
gfortran -g -J.\\mod -fopenmp -c -o .\\obj\parametricStudy.o parametricStudy.f90
and then type
gmake
Again, which results in no errors. I'm very puzzled.
Here is a screenshot of my directory:
Maybe it has something to do with TARGET? It seems like the path of the last file is somehow wrong. Any help is greatly appreciated!
I think the following style of makefile solves the problems. I tested it with a specimen C
project, not fortran, but that is immaterial to the make problem and solution.
# VPATH: Tell `make` to look for in `user` for prerequisites it can't find here
VPATH = user
# If e.g. you also want `make` to look for for prerequisites in `../include`, then:
# VPATH = user:../include
FC = gfortran
TOP_DIR = .
MOD_DIR = $(TOP_DIR)\\mod
OBJ_DIR = $(TOP_DIR)\\obj
FCFLAGS = -g
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized
TARGET = parametricStudy
SRCS_F =\
user\\constants.f90 \
...
parametricStudy.f90
OBJS_T1 = $(patsubst %.f90,%.o,$(SRCS_F))
OBJS_T2 = $(notdir $(OBJS_T1))
# The object files are all to be obj\<name>.o
OBJS_F = $(patsubst %.o,$(OBJ_DIR)\\%.o,$(OBJS_T2))
all: $(TARGET)
$(TARGET): $(OBJS_F)
$(FC) -o $# $(FCFLAGS) $(OBJS_F)
# How to make an obj\*.o from the matching *.f90. `make` considers the VPATH
$(OBJ_DIR)\\%.o: %.f90
$(FC) $(FCFLAGS) -c -o $# $<
clean:
del $(OBJ_DIR)\\*.o $(MOD_DIR)\\*.mod parametricStudy.exe
Using a relative path TOP_DIR = . rather than an absolute ROOT_DIR is good advice already offered
by #Wintermute.
To enable the required pattern rule:
$(OBJ_DIR)\\%.o: %.f90
to kick in, you must make it appear to make that any prerequisite *.f90 is right here, as per the pattern,
not in some other directory like, e.g. user\constants.f90 That is what the VPATH
achieves.
Continued for later developments
Not yet having seen a listing of the directory where the makefile resides I
can only venture a hypothesis, but the hypothesis suggested by what I do see is:
The directory does not actually contain a file called parametricStudy.f90,
but a file called parametricStudy.F90, and if it is renamed to parametricStudy.f90,
then the makefile will find and compile it.
Is that right?
How this explains the facts: The pattern rule:
$(OBJ_DIR)\\%.o: %.f90
is failing to match any parametricStudy.f90, so there is no such file. You say however that:
gfortran -g -J.\\mod -fopenmp -c -o .\\obj\parametricStudy.o parametricStudy.f90
successfully compiles.
You are building on Windows, so the toolchain subscribes to Windows' file-handling protocols.
Filenames are case-insentive: parametricStudy.f90 will identify parametricStudy.F90, if it exists,
and .F90 will be interpreted by gfortran (on Windows or anywhere else) as denoting a
Fortran 90 source file. Thus the successful commandline compile.
But the pattern rule is indifferent to file-handling protocols. It is just a pattern
matching rule, and the invariant .f90 is not matched by .F90.
The problem you're facing is that with
ROOT_DIR = "C:\Users\Charlie\"
OBJ_DIR = $(ROOT_DIR)\obj
the rule
$(OBJ_DIR)/%.o: %.f90
expands to
"C:\Users\Charlie\"obj/%.o: %.f90
which is parsed as the static pattern rule
"C: \Users\Charlie\"obj/%.o: %.f90
That is to say, with target "C, target pattern \Users\Charlie\"obj/%.o and prerequisite pattern %.f90. make complains that "C does not match the pattern \Users\Charlie\"obj/%.o.
There is some hacky code in GNU make (at least in MinGW; I think Cygwin behaves differently because it expects you to work with its unix-ish directory structure) to recognize absolute Windows paths, but it does not handle quoting. As long as your OBJ_DIR does not contain spaces, using
ROOT_DIR = C:\Users\Charlie\
should make the Windows path recognition kick in.
However...it is rather unusual to see absolute paths in handcrafted Makefiles. Are you sure you want to do it this way? A more common approach would be to work with relative paths so that the Makefile does not have to be changed if the source code is copied to a different directory. Assuming the Makefile is in the root directory, that would be
ROOT_DIR = .
or just nixing the ROOT_DIR variable altogether and saying
MOD_DIR = mod
OBJ_DIR = obj
Oh, and to answer the next question that's going to crop up: In order to make make use the
$(OBJ_DIR)/%.o: %.f90
rule, you'll need to make $(TARGET) have prerequisites that match the $(OBJ_DIR)/%.o pattern. That could be
OBJS_F = $(patsubst %.f90,$(OBJ_DIR)/%.o,$(notdir $(SRCS_F)))
I am trying to create a very basic hand crafted Makefile to create a shared library to illustrate a point.
This is what I have so far:
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99 -Iinclude
CFLAGS = -fPIC -pedantic -Wall -Wextra -march=native -ggdb3
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(shell echo src/*.c)
HEADERS = $(shell echo include/*.h)
OBJECTS = $(SOURCES:.c=.o)
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
When I run make, it attempts to build an application - and ld fails because it can't resolve main().
Problem seems to be with CFLAGS - I have specified -fPIC but that is not working - what am I doing wrong?
Edit
I added the -shared flag as suggested, when I run make, I got this error:
gcc -std=gnu99 -Iinclude -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3 -O0 -D _DEBUG -o example.so src/example.o
/usr/bin/ld: src/example.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
src/example.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [example.so] Error 1
Which seems to be suggesting to revert back to -fPIC only.
BTW, my new CFLAGS setting is:
CFLAGS = -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3
I am running gcc v4.4.3 on Ubuntu 10.0.4.
The solution was to modify the XXFLAGS as follows:
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
Compile with -shared:
gcc -o libfoo.so module1.o module2.o -shared
(This also works on MingW under Windows to produce DLLs.)
Example for C++ files. I've also included a clean target.
.PHONY : clean
CPPFLAGS= -fPIC -g
LDFLAGS= -shared
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS=$(SOURCES:.cpp=.o)
FIKSENGINE_LIBDIR=../../../../lib
FIKSENGINE_INCDIR=../../../../include
TARGET=$(FIKSENGINE_LIBDIR)/tinyxml.so
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(TARGET)
$(TARGET) : $(OBJECTS)
$(CC) $(CPPFLAGS) $(OBJECTS) -o $# $(LDFLAGS)
Since you try to build so file, you probably need -shared.
this is my goto makefile rule for so files:
%.so: %.o ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
can be used like so
CFLAGS+=-fPIC
libmyfoo.so: # create from libmyfoo.o
# or
libmyfoo.so: myfoo.o # create from myfoo.o
I downloaded someone's source code for a program and i needed to make some changes.
Now i want to compile it but it doesn't seem to work.
PROGS = isotociso
COMMON = tools.o bn.o ec.o wiidisc.o rijndael.o
DEFINES = -DLARGE_FILES -D_FILE_OFFSET_BITS=64
LIBS = C:/Dev-Cpp/lib/libwsock32.a C:/Dev-Cpp/lib/libcrypto.a C:/Dev-Cpp/lib/libcomdlg32.a
CC = gcc
#CFLAGS = -Wall -W -Os -Ilibwbfs -I.
CFLAGS = -Wall -m32 -W -ggdb -Ilibwbfs -I.
LDFLAGS = -m32 -static
VPATH+=libwbfs
OBJS = $(patsubst %,%.o,$(PROGS)) $(COMMON)
all: $(PROGS)
$(PROGS): %: %.o $(COMMON) Makefile
$(CC) $(CFLAGS) $(LDFLAGS) $< $(COMMON) $(LIBS) -o $#
$(OBJS): %.o: %.c tools.h Makefile
$(CC) $(CFLAGS) $(DEFINES) -c $< -o $#
clean:
-rm -f $(OBJS) $(PROGS)
Output
C:\Users\Panda\Desktop\uloader_v4.1\src\isotociso\src>make
gcc -Wall -m32 -W -ggdb -Ilibwbfs -I. -DLARGE_FILES -D_FILE_OFFSET_BITS=64 -c i
sotociso.c -o isotociso.o
process_begin: CreateProcess((null), gcc -Wall -m32 -W -ggdb -Ilibwbfs -I. -DLAR
GE_FILES -D_FILE_OFFSET_BITS=64 -c isotociso.c -o isotociso.o, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [isotociso.o] Error 2
What would be the problem?
Looks to me as if gcc is not in your PATH.
It also looks like you need MinGW to get the libraries.
I am no expert in C(++) development under Windows, but my interpretation would be that it can't find the compiler itself. What development environment are you using?
It looks like it can't find a file. Are you sure you have all the required source files?