I have a large fortran 77 code, "NSCool", distributed among many files which I compile into a python package using f2py. It used to work nicely with python 3.7, then it took me weeks to have it work with python 3.12, but now that I have updated numpy to version 2.3.2 it fails.
I am working on Macos Ventura, 13.7.6, with the last available version of the command line tools and gfortran14, python3.12 and needed python packages all installed with Macports.
I compile everything with a makefile with three options to generate three versions of the NSCool_Py*.so:
- A: linking directly all objects with the main subroutines in NSCool_2.f
- B: putting all *.o of DEPENDS into a static library libNSCool_lib_stat.a
- C: putting all *.o of DEPENDS into a dynamic library libNSCool_lib_dyn.so
Here is the makefile:
CODE_DIR = /Users/dany/Dropbox/Work/NStar/NSCool/Code
COMPILER = /opt/local/bin/gfortran-mp-14
COMPILER_LIB = /opt/local/lib/gcc14
OPTIONS = -O0 -fPIC -funderscoring
F2PY = python -m numpy.f2py
#--------------------------------------------------------------------------------
DEPENDS = NSCool_Read.o NSCool_Initialize.o NSCool_Help.o NSCool_Precool.o \
\
conductivity.o conductivity_core.o conductivity_crust.o \
opacity.o Envelope_Opacity.o \
neutrino.o neutrino_core.o neutrino_crust.o neutrino_pairing_control.o \
heating.o spec_heat.o boundary.o tc.o tc_Ioffe.o \
Envelope_NSCool.o Envelope_EOS.o Envelope_EOS_Fermi_Dirac.o Envelope_EOS_OCP.o \
eff_mass.o accretion.o magnetic.o Tools.o Dump.o \
\
OMP_Void.o \
Data_Crust.o Data_Crust_Plot_Void.o Weights.o \
\
ag_subroutines_A0.o ap_subroutines_A0.o pg_subroutines_A0.o wk_subroutines_A0.o \
rates_reader.o isos_subroutines.o pp_and_3a.o Screening.o eps_nuc_and_rhs.o \
Chemical_oz_time_dependent.o Tools_Maths.o
#--------------------------------------------------------------------------------
export MACOSX_DEPLOYMENT_TARGET=13.7
NSCool_Py_A: NSCool_2.f $(DEPENDS)
f2py -c -m NSCool_Py_A NSCool_2.f $(DEPENDS) \
--f77exec=$(COMPILER) \
--f77flags="$(OPTIONS)" \
--include-paths=$(CODE_DIR)
@echo "This is NSCool_Py_A"
NSCool_Py_B: NSCool_2.f NSCool_lib_stat
f2py -c -m NSCool_Py_B NSCool_2.f \
--include-paths=$(CODE_DIR) \
--f77exec=$(COMPILER) \
-L$(COMPILER_LIB) -lgfortran -L$(CODE_DIR) -lNSCool_lib_stat \
--f77flags="-L$(COMPILER_LIB) -lgfortran -L$(CODE_DIR) -lNSCool_lib " \
--link-flags="-bundle -undefined dynamic_lookup -Wl,-L$(CODE_DIR),-lNSCool_lib"
@echo "This is NSCool_Py_B"
NSCool_Py_C: NSCool_2.f NSCool_lib_dyn
f2py -c -m NSCool_Py_C NSCool_2.f \
--f77exec=$(COMPILER) \
--include-paths=$(CODE_DIR) \
-L$(CODE_DIR) -lNSCool_lib_dyn \
-Wl,-force_load,$(CODE_DIR)/libNSCool_lib_dyn.so \
--link-options="-bundle -undefined dynamic_lookup -Wl,-rpath,@loader_path"
@echo "This isNSCool_Py_C"
NSCool_lib_stat: $(DEPENDS)
libtool -static -o libNSCool_lib_stat.a $(DEPENDS)
NSCool_lib_dyn: $(DEPENDS)
$(COMPILER) $(OPTIONS) -dynamiclib -install_name @rpath/libNSCool_lib_dyn.so -o libNSCool_lib_dyn.so $(DEPENDS) -lgfortran
#--------------------------------------------------------------------------------
accretion.o: accretion.f
$(COMPILER) $(OPTIONS) -c accretion.f
...
where " ... " means many similar commands to generate all the other object files
If run three versions with python and get error messages (and I check if the missing symbols are really missing):
Version A:
%
% python -c "import NSCool_Py_A"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: dlopen(/Users/dany/Dropbox/Work/NStar/NSCool/Code/NSCool_Py_A.cpython-312-darwin.so, 0x0002): symbol not found in flat namespace 'accretion_rate'
%
% nm -gU NSCool_Py_A.cpython-312-darwin.so | grep accretion_rate
%
(accretion_rate is a subroutine that in the accretion.o object, itself listed in DEPENDS)
Version B:
%
% python -c "import NSCool_Py_B"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: dynamic module does not define module export function (PyInit_NSCool_Py_B)
%
% nm -gU NSCool_Py_B.cpython-312-darwin.so | grep PyInit_NSCool_Py_B
0000000000016350 T _PyInit_NSCool_Py_B
%
Version C:
%
% python -c "import NSCool_Py_C"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: dlopen(/Users/dany/Dropbox/Work/NStar/NSCool/Code/NSCool_Py_C.cpython-312-darwin.so, 0x0002): Symbol not found: accretion_rate
Referenced from: <38EA9BF8-7293-3099-B782-1E4E5583984C> /Users/dany/Dropbox/Work/NStar/NSCool/Code/NSCool_Py_C.cpython-312-darwin.so
Expected in: <6FEF4279-E414-3F36-98E5-526848F925F1> /Users/dany/Dropbox/Work/NStar/NSCool/Code/libNSCool_lib_dyn.so
%
% nm -gU libNSCool_lib_dyn.so | grep accretion_rate
000000000008cf73 T accretion_rate
000000000008b2cc T accretion_rate_swift_j1858
000000000008c3a0 T initialize_accretion_rate
%
Any idea how to fix this ? At least one of the three versions !