Compiling Fortran 77 with an external library using a Makefile - makefile

I have main program Engine.f that calls functions/external in LIB.f.
Unlike C++ and Java there is no include in the main program so it will be possible to compile.
How does my Fortran comiler know that there is another library which I use?
I'm using photran from Eclipse.
The MAKE file:
.PHONY: all clean
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
all: src/Engine.f
$(FORTRAN_COMPILER) -O2 -g \
-o bin/Engine.exe \
src/Engine.f
clean:
rm -f bin/Engine.exe *.mod
errors that I get when I compile:
undefined reference to (name of function in **LIB.f**)

.PHONY: all clean
all: Engine.exe
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
FORTRAN_FLAGS=-O2 -g
%.o: src/%.f
$(FORTRAN_COMPILER) $(FORTRAN_FLAGS) -c $<
Engine.exe: Lib.o Engine.o
$(FORTRAN_COMPILER) $(FORTRAN_FLAGS) \
-o bin/Engine.exe \
Lib.o Engine.o
clean:
rm -f *.o *.mod
In FORTRAN 77, the compiler "just" needs the function to be supplied in a .o file at link time. You can test the Makefile below, it should do what you want.
Modern versions of Fortran use module files to structure libraries, if you ever upgrade to that.

Related

GCC ERROR: Cannot Execute Binary File [GCC Compiled from Source]

I am writing an Operating System. I am currently stuck at not being able to compile C code into output files, then further linking them with ld
When I run my make file, this error pops up:
/usr/local/i386elfgcc/bin/i386-elf-gcc -g -ffreestanding -c kernel/kernel.c -o kernel/kernel.o
/usr/local/i386elfgcc/bin/i386-elf-gcc: /usr/local/i386elfgcc/bin/i386-elf-gcc: cannot execute binary file
make: *** [kernel/kernel.o] Error 126
This is the makefile
C_SOURCES = $(wildcard kernel/*.c drivers/*.c)
HEADERS = $(wildcard kernel/*.h drivers/*.h)
# Nice syntax for file extension replacement
OBJ = ${C_SOURCES:.c=.o}
# Change this if your cross-compiler is somewhere else
CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb
LD = /usr/local/i386elfgcc/bin/i386-elf-ld
# -g: Use debugging symbols in gcc
CFLAGS = -g
# First rule is run by default
os-image.bin: boot/boot.bin kernel.bin
cat $^ > os-image.bin
# '--oformat binary' deletes all symbols as a collateral, so we don't need
# to 'strip' them manually on this case
kernel.bin: boot/kernelStart32.o ${OBJ}
${LD} -o $# -Ttext 0x1000 $^ --oformat binary
# Used for debugging purposes
kernel.elf: boot/boot_32bit_kernel_entry.o ${OBJ}
${LD} -o $# -Ttext 0x1000 $^
run: os-image.bin
qemu-system-i386 -fda os-image.bin
# Open the connection to qemu and load our kernel-object file with symbols
debug: os-image.bin kernel.elf
qemu-system-i386 -s -fda os-image.bin &
${GDB} -ex "target remote localhost:1234" -ex "symbol-file kernel.elf"
# Generic rules for wildcards
# To make an object, always compile from its .c
%.o: %.c ${HEADERS}
${CC} ${CFLAGS} -ffreestanding -c $< -o $#
%.o: %.asm
nasm $< -f elf -o $#
%.bin: %.asm
nasm $< -f bin -o $#
clean:
rm -rf *.bin *.dis *.o os-image.bin *.elf
rm -rf kernel/*.o boot/*.bin drivers/*.o boot/*.o
I have built GCC etc to the path: /usr/local/i386-elf-gcc
I am on macOS Monterey 12.4 (Intel - x86_64) and have all dependencies installed
I have tried looking everywhere for this problem, trying different flags and everything, however the problem still persisted
It means that the compiler you built doesn't run on the system you are running it on. You have to decide whether you want to do native compiling in which case you would build a compiler that runs on the target and also generates output for the target. This is how the compilers you usually use always work.
If you create that kind of compiler then you have to run make on the target since that's where you build the compiler to run.
Or, you can create a cross-compiler. A cross-compiler runs on your local system, but builds output that runs on the target system.
In your case, if you want to compile code on your MacOS system but generate binary files that run on a different system, you need a cross-compiler.

Makefile for AVR

I have folder "I2C AtMega32":
and I have my simply Makefile:
all: main.hex program clean
main.o: main.cpp BMP280_driver-master\bmp280.c
avr-gcc -Wall -Os -mmcu=atmega32 -c $< -o $#
main.elf: main.o
avr-gcc -Wall -Os -mmcu=atmega32 -o main.elf main.o
main.hex: main.elf
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size --format=avr --mcu=atmega32 main.elf
program:
#program uC
.PHONY: clean
clean:
rm main.o main.elf
During the makefile working there is some errors:
Why it is no working?
The main issue is it looks like you are trying to compile two different compilation units into one object file. I would be surprised if GCC supports that, since I've never seen it before. Compile an object with gcc for each C source file, then compile an object with g++ for each C++ source file, then link them all together.
Also note that $< is just the name of the first prerequisite (main.cpp) so you never even attempted to compile the bmp280 code. Pay attention carefully to the commands your Makefile is running when you want to debug your build.
By the way, the all target should just build your HEX file. You can run make program or make clean separately to perform those tasks, and the program target should of course depend on main.hex.

Can't compile simple code with SDCC for pic on debian

I'm trying to compile the following code with SDCC, in Debian using only VIM and a Makefile:
void main(void) {
}
Yes, that simple, it's not working yet. I'm using a Makefile like this :
# GNU/Linux specific Make directives.
# Declare tools.
SHELL = /bin/sh
CC = sdcc
LD = gplink
ECHO = #echo
MCU = 16f88
ARCH = pic14
CFLAGS = -m$(ARCH) -p$(MCU)
LDFLAGS = -c -r -w -m I /usr/share/sdcc/lib/$(ARCH)/
EXECUTABLE = t1
SOURCES = test2.c
OBJECTS = $(SOURCES:.c=.o)
CLEANFILES = test2.o test2.asm test2.map test2.lst
.SUFFIXES: .c .o
.PHONY: clean
# Compile
all: $(EXECUTABLE)
.c.o:
$(AT) $(CC) $(CFLAGS) -o $*.o -c $<
$(EXECUTABLE): $(OBJECTS)
$(AT) $(LD) $(LDFLAGS) $(OBJECTS) -o $(EXECUTABLE)
clean:
$(AT) rm -rf $(CLEANFILES)
After all of this the output after running the makefile is:
sdcc -mpic14 -p16f88 -o test2.o -c test2.c
gplink -c -r -w -m I /usr/share/sdcc/lib/pic14/ test2.o -o t1
make: *** [t1] Segmentation fault
I have tried more complex code with the same result,
I can't see what's wrong, anyone ?
I see several things that can be causing you problems:
When you compile for PICs using SDCC, you need the option --use-non-free because some PIC header files have a special Microchip Licence which is not GPL compatible. Furthermore, --use-non-free might not be available on Debian because of their freedom policy if you installed SDCC from repositories. You would need to install the latest SDCC from the official website.
On the linking stage, you should include the PIC libraries needed to run. Try executing sdcc -mpic14 -p16f88 --use-non-free -V test2.c. This way, SDCC links automatically and With -V (verbose) you can see the calls to assembler and linker and can see the libraries that are added on linkage.

make is calling g++ is always re-compiles even when I do not change the source code

I am using make which calls g++ always re-compiles the code, even when I do not change the source code. That happens for all my projects, even for simple ones such as:
[code]
all: main.cpp
g++ -std=c++11 -c main.cpp
[/code]
I believe it should compare the date/time on source and object code. Could some help me with this, I am running using GNU toolchain on Ubuntu 12.04
THX
Edit: sorry guys, I do use Makefile, I edited my question accordingly.
Simplest Makefile
It was already pointed out that your Makefile is probably wrong. The 'all' target is indeed always built (although it may result in a no-op if it has no commands and all dependencies are already satisfied). All you need in your makefile is this:
all: main
Object files
If you expect to have more source file in your build, you should consider creating intermediate object files:
all: main
main: main.o
Tweak the build
Make will automatically find the main.ccp file and turn it into main which is required per the directive above. You can use special make variables to further tweak the compilation, e.g. for debug information inclusion and for warning configuration:
CXXFLAGS = -g -Wall -Werror
all: main
main: main.o
Nitpicking
If you insist on building up the compile rule yourself, you can do it like this:
%.o: %.hpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
CXX: C++ compiler
CPPFLAGS: C preprocessor flags
CXXFLAGS: C++ compiler flags
$#: Target
$<: First dependency
If you don't want to use the standard variables nor pattern matching, you can build up the whole makefile explicitly:
all: main
main: main.o
gcc -o $# $^
main.o: main.c
gcc -g -Wall -Werror -o $# -c $<
$^: Use that one if you want to include all dependencies, for example if you have multiple *.o files to build one binary.
Note: It is a bad idea to write the file names directly into the command as you might forget to update them later.
all: main.cpp
g++ -std=c++11 -c main.cpp
This seems wrong. Why does the rule for all has main.cpp as its target? Shouldn't it be something.exe or something.o? Say
all: main.exe
main.exe: main.cpp
g++ -std=c++11 main.cpp -o main.exe
clean:
del main.exe
Targets are output files and cpp files are source code which should be input to the make system.
g++ would have to "recompile" in general (what happens if you change the header but not main.cpp?)
If you are concerned about long build times, you should use something like Make (which is designed specifically to avoid recompiling when the source hasn't changed)
The compiler will always compile the code. If you want to do conditional compilation (based on file times etc) you will need to use a make system such as Make, CMake, Ant, etc. For the simplest you can set up a small "Makefile" in the directory and use the command "make" to build.
Simple Makefile for compiling "myapp.exe" from "main.cpp", "file1.cpp" and "file2.cpp"
myapp.exe: main.o file1.o file2.o
g++ -o myapp.exe main.o file1.o file2.o
(make knows to use .cpp files to build .o files)
But if you also have header files, then you will need to build dependency chains, for which you may want to look into something more sophisticated like automake, cmake, ant, etc.
---- EDIT ----
Based on your updated post, the problem is that you aren't specifying a target, so Make has to assume it needs to recompile. See my example in the above answer.

Compile C++ with Cygwin

How do I compile my C++ programs in Cygwin. I have gcc installed. What command should I use? Also, how do I run my console application when it is in a .cpp extension. I am trying to learn C++ with some little programs, but in Visual C++, I don't want to have to create a seperate project for each little .cpp file.
You need to use a command like:
g++ -o prog prog.cpp
That's a simple form that will turn a one-file C++ project into an executable. If you have multiple C++ files, you can do:
g++ -o prog prog.cpp part2.cpp part3.cpp
but eventually, you'll want to introduce makefiles for convenience so that you only have to compile the bits that have changed. Then you'll end up with a Makefile like:
prog: prog.o part2.o part3.o
g++ -o prog prog.o part2.o part3.o
prog.o: prog.cpp
g++ -c -o prog.o prog.cpp
part2.o: part2.cpp
g++ -c -o part2.o part2.cpp
part3.o: part3.cpp
g++ -c -o part3.o part3.cpp
And then, you'll start figuring how to write your makefiles to make them more flexible (such as not needing a separate rule for each C++ file), but that can be left for another question.
Regarding having a separate project for each C++ file, that's not necessary at all. If you've got them all in one directory and there's a simple mapping of C++ files to executable files, you can use the following makefile:
SRCS=$(wildcard *.cpp)
EXES=$(SRCS:.cpp=.exe)
all: $(EXES)
%.exe: %.cpp
g++ -o $# $^
Then run the make command and it will (intelligently) create all your executables. $# is the target and $^ is the list of pre-requisites.
And, if you have more complicated rules, just tack them down at the bottom. Specific rules will be chosen in preference to the pattern rules:
SRCS=$(wildcard *.cpp)
EXES=$(SRCS:.cpp=.exe)
all: $(EXES)
%.exe: %.cpp
g++ -o $# $^
xx.exe: xx.cpp xx2.cpp xx3.cpp
g++ -o $# $^
echo Made with special rule.
You will need g++. Then try g++ file.cpp -o file.exe as a start. Later you can avoid much typing by learning about Makefiles.
if you want to use cygwin you should use the normal gcc syntax
g++ -o foobar foobar.cpp
but that doesn't really play well with Visual C++. I advise you to take a look into Eclipse CDT if you prefer using GCC over the visual C++ compiler.
What I do to compile a cpp program:
g++ -Wall Test.cpp -o Test
-Wall enables warning and error messages to be shown
-o Test creates an Test.exe after compilation
If you want to compile files separately:
g++ -Wall -c File1.cpp
g++ -Wall -c File2.cpp
Now create an executable with the combined object files as:
g++ -Wall File1.o File2.o -o File.exe
This way you can compile your header files and you can include in your application programs.

Resources