Fortran: declare function and subroutine in "header module" - module

How can I declare function and subroutine in separate module and initialize it in the appropriate non-header module?
I am using make for compilation:
# All modules
OBJS := $(BINDIR)/physics.o $(BINDIR)/particles.o
# Build rules
$(BINDIR)/%.o: $(VPATH)/%.f | $(BINDIR)
$(FC) $(FFLAGS) -c $^ -o $#
$(BINDIR)/%.mod:
runner: $(OBJS)
.. and problem is that physics.f depends on subroutine in particles.f and vice-versa. So I can't just change order of compilation for these files.
I get such error:
src/physics.f:105.23:
use particles
1
Fatal Error: Can't open module file 'particles.mod' for reading at (1): No such file or directory
make: *** [bin/physics.o] Error 1

While it is not totally clear what you intent to do it appears to me, that you are looking for submodules.
Unfortunately they are currently not widely supported by compilers.

Related

Build and link a fortran dll to a fortran code with gfortran in cygwin

I built a fortran dll and I try now to use it in a fortran main. The problem is I cannot link correctly the main to the dll.
I am on WIndows10 and I use gfortran from cygwin (the 32 bit version of cygwin, gfortran comes from the suite i686-w64-mingw32).
Here is the dll:
$ more helloworld.f90
function hello()
integer hello
hello=1
return
end
I complile and generate the dll like this:
gfortran -fno-underscoring -c helloworld.f90
gfortran -shared -o helloworld.dll helloworld.o
Here is the main
$ more usehello.f90
program usehello
integer, external :: hello
integer :: i
i=1
write(*,*) hello(i)
stop
end
compilation is OK:
i686-w64-mingw32-gfortran.exe -c -fno-underscoring usehello.f90
link fails:
i686-w64-mingw32-gfortran.exe usehello.o helloworld.dll -o usehello
error while loading shared libraries: libgfortran-5.dll: cannot open shared object file: No such file or directory
Yet, I do have this file:
$ ls -l /usr/i686-w64-mingw32/sys-root/mingw/bin/libgfortran-5.dll
-rwxr-xr-x 1 UT013536+l-pg164999 UT013536+Aucun 2460672 4 mars 04:46 /usr/i686-w64-mingw32/sys-root/mingw/bin/libgfortran-5.dll
I have tried to add --static-libgfortran (I wasn't not convinced of using something 'static' for a dll but so...):
It links apparently correctly but the executable fails:
$ i686-w64-mingw32-gfortran.exe usehello.o helloworld.dll -static-libgfortran -o usehello
$ ./usehello
usehello.exe: error while loading shared libraries: libquadmath-0.dll: cannot open shared object file: No such file or directory
Sounds like if an environnement variable was missing but I cannot find any post reporting on this kind of fail. Thanks in case some one can help...
Actually, the idea to use the command i686-w64-mingw32-gfortran.exe is not good...if we simply use gfortran it works fine...

Can't compile Fortran modules: Undefined symbol _main

I've been trying lately to use libraries in Fotran, but I kept on getting this error message
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
which I cound't find any specific solution to it. In this case, I was working with some libraries that I built myself (this problem happened with static and shared libraries) from simples modules I wrote for purposses of tests.
I decided to try only the modules then, and I kept getting the same error message regardes of the module I used. I would like to know if someone can help me on telling if I am using incorrect syntax. Here is the module
module modulo1
IMPLICIT NONE
real, parameter:: pi=3.1415
end module modulo1
This is the main
program teste
use modulo1
IMPLICIT NONE
real :: r = 2
write (*,*) 'Área: ', pi*r**2
end program teste
These were the commands I used for compiling
gfortran -c modulo1.f90
gfortran -c teste.f90
gfortran -o teste.o modulo1.o
Your compilation is broken. The command
gfortran -o teste.o modulo1.o
tells gfortran to create an executable called teste.o from the object file called modulo1.o. Since that module file doesn't contain a program the compiler can't find an entry point for the executable it is trying to build. The argument to the -o option is the name of the executable to build.
You probably ought to replace that statement with something like
gfortran -o test teste.o modulo1.o
which will build an executable called test.
In the longer run learn how to use make or another build system.

Scons "Dir" command doesn't work?

I've got a sub directory called "myc" containing 2 ".c" files:
$ ls myc
1.c f.c
And my current directory has a SConstruct:
$ cat SConstruct
myc=Dir('myc')
print myc
Program('test2',myc)
Run scons, it prints a bunch of errors:
$ scons
scons: Reading SConscript files ...
myc
scons: done reading SConscript files.
scons: Building targets ...
gcc -o test2 myc
/usr/bin/ld: cannot find myc: File format not recognized
collect2: error: ld returned 1 exit status
scons: *** [test2] Error 1
scons: building terminated because of errors.
What is weird: I expect the "print myc" will list "1.c" and "f.c", to my disappointment it prints "myc", not the varible value, and the compiling also fails.
How to correct it?
Not sure why you believe that specifying a directory as the source(s) for a directory would work?
Is there something in the docs which makes you believe this should work?
If so, please point it out so it can be improved.
If you did:
gcc -o blah some_dir_name
That wouldn't work right?
This should do what you're asking for.
myc=Glob('myc/*.c')
print myc
Program('test2',myc)

gfortran cannot read its own creation

I am trying to compile a code with gfortran. One of the first things that happens in the compilation is the creation of constants.mod. Soon after that gfortran tells me:
Fatal Error: Cannot read module file ‘constants.mod’ opened at (1), because it was created by a different version of GNU Fortran
Now here's the thing: This module file is created by the same gfortran that it's trying to read it. gfortran creates the thing itself and then 1 second later thinks the file was created by some other version! Any idea what's going on here?
You'll probably want to see the compile command:
mpif90 -c -O3 -ISDF/FORTRAN/include -I/usr/include -Iobj -Jobj -o obj/shared_data.o src/core/shared_data.F90
shared_data.F90 contains the module constants at the top of the file.
EDIT: Here's the compile command followed by the full error message:
$> mpif90 -c -O3 -ISDF/FORTRAN/include -I/usr/include -Iobj -Jobj -o obj/shared_data.o src/core/shared_data.F90
src/core/shared_data.F90:67:6:
USE constants
1
Fatal Error: Cannot read module file ‘constants.mod’ opened at (1), because it was created by a different version of GNU Fortran
compilation terminated.
UPDATE: I hope you'll agree this is weird. The file that is failing is in src/core. If I cd to src/core and issue this command:
mpif90 -c -O3 -I../../SDF/FORTRAN/include -I../../obj -J../../obj -o ../../obj/shared_data.o shared_data.F90
it compiles just fine! But then I clean everything out of the obj directory and I cd two levels up and issue:
mpif90 -c -O3 -ISDF/FORTRAN/include -Iobj -Jobj -o shared_data.o src/core/shared_data.F90
and it fails with the error I showed above! What is the difference??? Thanks.

C++ linking issue: multiple definition

Unfortunately I cannot post all of the source code here. I can describe the structure though. All header files have #ifndef/#define/#endif guards. The structure is as follows:
node.h - included by tree.h
tree.h - included by tree.cpp and main.cpp
tree.cpp
main.cpp
In node.h in the global namespace, I declare the following free standing function:
bool char_sort_func(Path first, Path second)
{
return (first->label() < second->label());
}
(Note: as shown bellow, a Path is just a shared_ptr) When I try to build, I get a multiple definition error saying that the function is present in both tree.o and main.o:
> make
g++ -c -g -Wall main.cpp -I /usr/include
g++ -c -g -Wall tree.cpp -I /usr/include
g++ -Wall -o tool tree.o main.o -L /usr/lib -l boost_program_options
main.o: In function `char_sort_func(boost::shared_ptr<Edge>, boost::shared_ptr<Edge>)':
node.h:70: multiple definition of `char_sort_func(boost::shared_ptr<Edge>, boost::shared_ptr<Edge>)'
tree.o:node.h:70: first defined here
collect2: ld returned 1 exit status
make: *** [all] Error 1
I tried searching all of the source files to see if that was true, however, I don't see it in any wrong places:
> grep char_sort_func *
Binary file main.o matches
node.h:bool char_sort_func(Path first, Path second)
node.h: std::sort(edges_.begin(), edges_.end(), char_sort_func);
Binary file trie.o matches
Sure enough though, it is in the binary files. How can I restructure my code to prevent this linking issue?
This will happen if you declare normal functions in a .h file, because they will be generated in every file that #includes it. Perhaps you meant to declare it inline or static?