Skip to content

Commit db3c09c

Browse files
klendathu2kCopilotCopilotplexoos
authored
Star f90 build support (star-bnl#784)
UrQMD 4.0 requires FORtran 90 support. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Dmitri Smirnov <dmixsmi@gmail.com>
1 parent 6e14386 commit db3c09c

5 files changed

Lines changed: 177 additions & 1 deletion

File tree

docs/fortran90-support.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Fortran 90 Compiler Support
2+
3+
This document describes the Fortran 90 compiler support added to the cons build system.
4+
5+
## Overview
6+
7+
The cons build system in the `mgr/` directory now supports compilation and linking of Fortran 90 source files (.f90 and .F90). This extends the existing Fortran 77 support (.f and .F).
8+
9+
## Compiler Configuration
10+
11+
The Fortran 90 compiler uses the same compiler binary as the Fortran 77 compiler (typically `gfortran`), which supports both Fortran 77 and Fortran 90 standards.
12+
13+
### Build Variables
14+
15+
The following build variables have been added to `ConsDefs.pm`:
16+
17+
- **F90**: The Fortran 90 compiler command (defaults to the value of FC, typically gfortran)
18+
- **F90FLAGS**: Compiler flags for Fortran 90 compilation
19+
- **F90DEBUG**: Debug flags for Fortran 90 (defaults to FDEBUG value)
20+
- **F90PATH**: Include paths for Fortran 90 modules
21+
- **EXTRA_F90PATH**: Additional include paths for Fortran 90 modules
22+
- **F90PPFLAGS**: Preprocessor flags for Fortran 90
23+
- **EXTRA_F90PPFLAGS**: Additional preprocessor flags for Fortran 90
24+
- **F90COM**: The complete compilation command for Fortran 90 files
25+
26+
### Default Compiler Flags
27+
28+
The default F90FLAGS are compatible with Fortran 77 flags and include:
29+
- `-fd-lines-as-comments` or `-fd-lines-as-code`: Handle debug lines (depending on NODEBUG setting)
30+
- `-fno-second-underscore`: Disable second underscore for symbol names
31+
- `-fno-automatic`: Variables are static by default
32+
- `-Wall -W -Wsurprising`: Enable comprehensive warnings
33+
- `-fPIC`: Generate position-independent code for shared libraries
34+
35+
Note: The `-std=legacy` flag used for Fortran 77 is intentionally excluded as it's F77-specific.
36+
37+
## File Extensions
38+
39+
The build system now recognizes the following Fortran 90 file extensions:
40+
41+
- **.f90**: Free-form Fortran 90 source files
42+
- **.F90**: Free-form Fortran 90 source files with preprocessing
43+
44+
Both extensions are mapped to the `build::command::f90` builder in the cons system.
45+
46+
## Usage
47+
48+
To use Fortran 90 in your project:
49+
50+
1. Create your Fortran 90 source files with `.f90` or `.F90` extensions in your source directory
51+
2. The cons build system will automatically discover these files when scanning the directory
52+
3. The build system will automatically use the Fortran 90 compiler for these files
53+
54+
**Note**: The build system uses the `find_sources` function to automatically discover source files. The following Fortran file extensions are recognized for automatic discovery:
55+
- `.F` - Fortran 77 fixed-form with preprocessing
56+
- `.f90` - Fortran 90 free-form
57+
- `.F90` - Fortran 90 free-form with preprocessing
58+
59+
**Important**: `.f` files (Fortran 77 fixed-form without preprocessing) use a separate preprocessing compilation mechanism and are not included in automatic source file discovery. They are handled through a different build path.
60+
61+
Example directory structure:
62+
```
63+
MyPackage/
64+
├── mycode.cxx
65+
├── myfortran.F # Fortran 77 with preprocessing (auto-discovered)
66+
├── myfortran90.f90 # Fortran 90 (auto-discovered)
67+
└── preprocessed.F90 # Fortran 90 with preprocessing (auto-discovered)
68+
```
69+
70+
The build system will automatically find all these files and compile them appropriately.
71+
72+
## Differences from Fortran 77
73+
74+
The key differences in how Fortran 90 files are handled:
75+
76+
1. **Free-form source**: Fortran 90 uses free-form source format by default (no column restrictions)
77+
2. **Module support**: The compiler will generate .mod files for Fortran 90 modules
78+
3. **Include paths**: Use F90PATH instead of FCPATH for Fortran 90-specific include directories
79+
80+
## Notes
81+
82+
- The same linker and libraries are used for both Fortran 77 and Fortran 90 code
83+
- Fortran 90 modules can be used (via `USE`) from other Fortran 90 code; Fortran 77 code can call procedures compiled from Fortran 90 sources when interfaces are compatible, but cannot `USE` modules directly
84+
- The gfortran compiler supports mixing Fortran 77 and Fortran 90 code in the same project

mgr/ConsDefs.pm

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,26 @@
187187
$FFLAGS = $G77FLAGS;
188188
$FEXTEND = $G77EXTEND;
189189

190+
# Fortran 90 compiler settings (use same compiler as FC, typically gfortran)
191+
$F90 = $FC;
192+
# F90FLAGS compatible with F77 flags but without -std=legacy (F77-specific)
193+
if ( defined( $ARG{NODEBUG} ) || $NODEBUG ) {
194+
$F90FLAGS = "$XMACHOPT -fd-lines-as-comments ";
195+
} else {
196+
$F90FLAGS = "$XMACHOPT -fd-lines-as-code ";
197+
}
198+
$F90FLAGS .= " -fno-second-underscore -fno-automatic -Wall -W -Wsurprising -fPIC";
199+
*F90DEBUG = *FDEBUG;
200+
$F90PATH = "";
201+
$EXTRA_F90PATH = "";
202+
$F90PPFLAGS = "";
203+
$EXTRA_F90PPFLAGS = "";
204+
# gfortran: -J <dir> writes .mod files to <dir> and adds <dir> to the
205+
# module search path. Both effects are needed: output goes to the build
206+
# OBJ directory (not the repo root) and subsequent compilations in the
207+
# same package can find those modules.
208+
$F90MODOUT = "-J ";
209+
190210
$CPPCERN = " -DCERNLIB_TYPE -DCERNLIB_DOUBLE -DCERNLIB_NOQUAD -DCERNLIB_LINUX ";
191211
$FPPFLAGS = $CPPCERN;
192212
$EXTRA_FPPFLAGS= "";
@@ -310,6 +330,9 @@
310330
$AGETOFCOM .= "%FC %FPPFLAGS %FFLAGS %EXTRA_FPPFLAGS %FDEBUG %_IFLAGS %EXTRA_FCPATH -c";
311331
$AGETOFCOM .= " %>:b.F %Fout%>";
312332

333+
$F90COM =
334+
"%F90 %F90PPFLAGS %F90FLAGS %EXTRA_F90PPFLAGS %F90DEBUG %_IFLAGS %EXTRA_F90PATH %F90MODOUT%>:d -c %< %Fout%>";
335+
313336
$INCLUDE_PATH = $INCLUDE;
314337
$Salt = undef;
315338
$NoKeep = undef;
@@ -1061,6 +1084,15 @@
10611084
'AGETOFLAGS' => $AGETOFLAGS,
10621085
'AGETOFCOM' => $AGETOFCOM,
10631086
'FCviaAGETOFCOM' => $FCviaAGETOFCOM,
1087+
'F90' => $F90,
1088+
'F90FLAGS' => $F90FLAGS,
1089+
'F90DEBUG' => $F90DEBUG,
1090+
'F90PATH' => $F90PATH,
1091+
'EXTRA_F90PATH' => $EXTRA_F90PATH,
1092+
'F90PPFLAGS' => $F90PPFLAGS,
1093+
'EXTRA_F90PPFLAGS' => $EXTRA_F90PPFLAGS,
1094+
'F90MODOUT' => $F90MODOUT,
1095+
'F90COM' => $F90COM,
10641096
'CC' => $CC,
10651097
'CFLAGS' => $CFLAGS,
10661098
'EXTRA_CFLAGS' => $EXTRA_CFLAGS,
@@ -1117,6 +1149,8 @@
11171149
'.age' => 'build::command::agetof',
11181150
'.f' => 'build::command::fc',
11191151
'.F' => 'build::command::fc',
1152+
'.f90' => 'build::command::f90',
1153+
'.F90' => 'build::command::f90',
11201154
'.C' => 'build::command::cxx',
11211155
'.s' => 'build::command::cc',
11221156
'.S' => 'build::command::cc',

mgr/Conscript-standard

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ my $FCPATH = $env1->{FCPATH};
8585
my $FEXTEND = $env1->{FEXTEND};
8686
my $FPPFLAGS= $env1->{FPPFLAGS};
8787
my $FCCOM = $env1->{FCCOM};
88+
my $F90 = $env1->{F90};
89+
my $F90FLAGS= $env1->{F90FLAGS};
90+
my $F90PATH = $env1->{F90PATH};
91+
my $F90COM = $env1->{F90COM};
8892
my $LIBS = $env1->{LIBS};
8993
my $SOFLAGS = $env1->{SOFLAGS};
9094
my $LIBPATH = $env1->{LIBPATH};
@@ -120,6 +124,14 @@ print "idlL = @idlL\n" if $param::debug;
120124
my (@src, @h_files, @idlM);
121125
my $CPPPATH = $env1->{CPPPATH};
122126

127+
# Initialize F90PATH with current directory for include files
128+
# Package-specific conditions below may override this
129+
if ($F90PATH) {
130+
$F90PATH = "#" . $Dir . $main::PATH_SEPARATOR . $F90PATH;
131+
} else {
132+
$F90PATH = "#" . $Dir;
133+
}
134+
123135
if ($pkg eq "RTS") {
124136
if ($STAR_SYS =~ /^x86_darwin/) {}
125137
else {
@@ -600,6 +612,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
600612
my $py8ver = "Pythia8_1_86";
601613

602614
$FCPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg";
615+
$F90PATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg";
603616
$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg";
604617
$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/HepMC2_06_09";
605618
$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/${py8ver}/include";
@@ -621,6 +634,13 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
621634

622635
#print "DEBUG ".join(" ",@srcL)."\n";
623636

637+
} elsif ( $pkg =~ m/^UrQMD/ and $Dir =~ m/StarGenerator/ ){
638+
639+
$FCPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg";
640+
$F90PATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg";
641+
$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg";
642+
643+
$FEXTEND = "-ffixed-line-length-72";
624644

625645
} elsif ( $pkg =~ m/^HepMC/ and $Dir =~ m/StarGenerator/ ){
626646
# Append HepMC include path and define version
@@ -671,6 +691,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
671691
$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/HepMC2_06_09";
672692
$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/Tauola1_1_5/include/Tauola";
673693
$FCPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg/tauola-fortran/tauola-modified/new-currents/RChL-currents/rcht_3pi";
694+
$F90PATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg/tauola-fortran/tauola-modified/new-currents/RChL-currents/rcht_3pi";
674695
#$CPPPATH .= $main::PATH_SEPARATOR . "#StRoot/StarGenerator/$pkg/tauola-fortran/tauola-modified/new-currents/RChL-currents/rcht_3pi";
675696
$CXXFLAGS .= " -DTauola_version=\\\"$pkg\\\" ";
676697
$CPPFLAGS .= " -x c++";
@@ -776,6 +797,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
776797
$main::PATH_SEPARATOR . "#" . $Dir . "/../starsim/include" .
777798
$main::PATH_SEPARATOR . "#" . $Dir . "/../gcalor/include" .
778799
$main::PATH_SEPARATOR . $env1->{FCPATH};
800+
$F90PATH = $FCPATH;
779801
$FPPFLAGS = " -DATLAS_UNIX -DCOMMONS_CONFIG_H -DCERNLIB_LINUX -DCPP_VERS=\"'W'\"";
780802
# $FPPFLAGS = $env1->{Packages}->{CERNLIB}->{FPPFLAGS} . " -DCOMMONS_CONFIG_H -DCERNLIB_LINUX -DCPP_VERS=\"'W'\"";
781803
# $CPPFLAGS .= " " . $env1->{Packages}->{CERNLIB}->{CPPFLAGS};
@@ -786,6 +808,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
786808
$FCPATH .= $main::PATH_SEPARATOR . "#asps/Simulation/starsim/include";
787809
$FCPATH .= $main::PATH_SEPARATOR . "#asps/Simulation/geant321/include";
788810
$FCPATH .= $main::PATH_SEPARATOR . $env1->{ENV}->{CERN_ROOT} . "/include";
811+
$F90PATH = $FCPATH;
789812
# $FCPATH .= $main::PATH_SEPARATOR . $env1->{Packages}->{CERNLIB}->{INCDIR};
790813

791814
} elsif ( $pkg =~ /^xgeometry/ ){
@@ -799,6 +822,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
799822
$FPPFLAGS .= " " . $env1->{Packages}->{CERNLIB}->{FPPFLAGS};
800823
$CPPFLAGS .= " " . $env1->{Packages}->{CERNLIB}->{CPPFLAGS};
801824
$FCPATH = "#StarVMC/minicern" . $main::PATH_SEPARATOR . $INCLUDE;
825+
$F90PATH = $FCPATH;
802826
$CPPPATH .= $main::PATH_SEPARATOR . "#StarVMC/minicern";
803827
my @srcC = ();
804828
foreach my $s (@src) {
@@ -828,6 +852,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
828852
$CPPFLAGS .= " " . $env1->{Packages}->{CERNLIB}->{CPPFLAGS};
829853
$FCPATH = "#StarVMC/geant3" . $main::PATH_SEPARATOR . "#StarVMC/geant3/minicern" . $main::PATH_SEPARATOR . $INCLUDE .
830854
$main::PATH_SEPARATOR . $env1->{Packages}->{CERNLIB}->{INCDIR};
855+
$F90PATH = $FCPATH;
831856
$CPPPATH .= $main::PATH_SEPARATOR . $env1->{Packages}->{CERNLIB}->{INCDIR};
832857
my @dirs = qw (added gbase gcons geocad ggeom gheisha ghits ghrout ghutils
833858
giface giopa gkine gparal gphys gscan gstrag gtrak matx55 miface
@@ -990,6 +1015,10 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) {
9901015
'FPPFLAGS' => $FPPFLAGS,
9911016
'CPPFLAGS' => $CPPFLAGS,
9921017
'FCCOM' => $FCCOM,
1018+
'F90' => $F90,
1019+
'F90FLAGS' => $F90FLAGS,
1020+
'F90PATH' => $F90PATH,
1021+
'F90COM' => $F90COM,
9931022
'LIBS' => $LIBS,
9941023
'SOFLAGS' => $SOFLAGS,
9951024
'LIBPATH' => $libpath,

mgr/Construct

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ if ( !$param::quiet ) {
133133
CC DEBUG CFLAGS EXTRA_CFLAGS br
134134
FC FDEBUG FPPFLAGS FEXTEND FFLAGS br
135135
FCPATH EXTRA_FCPATH br
136+
F90 F90DEBUG F90PPFLAGS F90FLAGS br
137+
F90PATH EXTRA_F90PATH br
136138
F77LD F77LDFLAGS br
137139
CERNLIBS br
138140
FLIBS CLIBS SYSLIBS LIBG2C br

mgr/cons

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,9 @@ sub wanted {
12631263
/^\w.*\.cxx$/ ||
12641264
/^\w.*\.cpp$/ ||
12651265
/^\w.*\.g$/ ||
1266-
/^\w.*\.age$/ || #for STAR /^\w.*\.f$/ ||
1266+
/^\w.*\.age$/ ||
1267+
/^\w.*\.f90$/ ||
1268+
/^\w.*\.F90$/ ||
12671269
/^\w.*\.cdf$/ ||
12681270
/^\w.*\.F$/) {# print " $File::Find::name\n";
12691271
push @main::search_files, $File::Find::name;
@@ -2218,6 +2220,31 @@ sub includes {
22182220
$self->{scanner}->includes($tgt, $tgt->{sources}[0]);
22192221
}
22202222
#________________________________________________________________________________
2223+
# Builder for Fortran 90 files
2224+
package build::command::f90;
2225+
2226+
use vars qw( @ISA );
2227+
2228+
BEGIN { @ISA = qw(build::command) }
2229+
2230+
#________________________________________
2231+
sub find {
2232+
$_[1]->{_f90} || do {
2233+
my($class, $env) = @_;
2234+
my($cscanner) = find scan::cpp($env->{_cwd}, $env->{F90PATH});
2235+
$env->{_IFLAGS} = "%(" . $cscanner->iflags($env) . "%)";
2236+
my($self) = find build::command($env, $env->{F90COM});
2237+
$self->{scanner} = $cscanner;
2238+
bless $env->{_f90} = $self;
2239+
}
2240+
}
2241+
#________________________________________
2242+
# Invoke the associated scanner to get signature of included files.
2243+
sub includes {
2244+
my($self, $tgt) = @_;
2245+
$self->{scanner}->includes($tgt, $tgt->{sources}[0]);
2246+
}
2247+
#________________________________________________________________________________
22212248
# Builder for a geant3 module
22222249
package build::command::geant3;
22232250

0 commit comments

Comments
 (0)