M1芯片Mac用gfortran编译NetCDF代码出现arm64未定义符号错误
问题:M1芯片Mac使用gfortran创建NetCDF文件时出现链接错误
我是搭载M1芯片的Mac用户,尝试使用gfortran创建NetCDF文件时出现错误。以下是编写的Fortran代码:
PROGRAM net2 use netcdf IMPLICIT NONE INTEGER :: status, ncid INTEGER :: nx, ny, ii, jj, x, y, xx, yy REAL, DIMENSION(239, 239) :: field REAL, DIMENSION(239, 239) :: eqa INTEGER :: dimid_lon, dimid_lat, dimid_time INTEGER :: varid_lat, varid_lon, varid_field, varid_eqa, varid_time REAL :: pi, lat_array(239), lon_array(239) PARAMETER (pi = 4.0 * atan(1.0)) status = nf90_create('new.nc', NF90_NETCDF4, ncid) call check(status, 'open') nx = 239 ny = 239 status = nf90_def_dim(ncid, 'longitude', nx, dimid_lon) status = nf90_def_dim(ncid, 'latitude', ny, dimid_lat) status = nf90_def_dim(ncid, 'time', nf90_unlimited, dimid_time) status = nf90_def_var(ncid, 'longitude', NF90_FLOAT, [dimid_lon], varid_lon) status = nf90_def_var(ncid, 'latitude', NF90_FLOAT, [dimid_lat], varid_lat) status = nf90_def_var(ncid, 'time', NF90_FLOAT, [dimid_time], varid_time) status = nf90_def_var(ncid, 'field', NF90_FLOAT, [dimid_lat, dimid_lon], varid_field) status = nf90_def_var(ncid, 'eqa', NF90_FLOAT, [dimid_lat, dimid_lon], varid_eqa) status = nf90_put_att(ncid, NF90_GLOBAL, 'note', 'Test of Created NetCDF file') status = nf90_put_att(ncid, NF90_GLOBAL, 'ISIC', 15) status = nf90_put_att(ncid, varid_lon, 'units', 'degree_east') status = nf90_put_att(ncid, varid_lat, 'units', 'degree_north') status = nf90_put_att(ncid, varid_field, '_FillValue', -2e8) status = nf90_put_att(ncid, varid_eqa, '_FillValue', -2e8) lat_array = [(jj * (360./ny), jj=0, ny-1)] lon_array = [((ii * (180./(nx-1)) - 90.), ii=0, nx-1)] do jj = 1, ny do ii = 1, nx field(ii, jj) = sin(lon_array(ii) * pi/180.) * cos(lat_array(jj) * pi/180.) end do end do do yy = 1, ny do xx = 1, nx eqa(xx, yy) = x**2 + y**2 end do end do status = nf90_put_var(ncid, varid_lon, lon_array) status = nf90_put_var(ncid, varid_lat, lat_array) status = nf90_put_var(ncid, varid_field, field) status = nf90_put_var(ncid, varid_eqa, eqa) status = nf90_close(ncid) call check(status, 'close') contains SUBROUTINE check(status, loc) INTEGER, INTENT(in) :: status CHARACTER, INTENT(in) :: loc if (status /= NF90_NOERR) then WRITE(*, *) "ERROR at", loc WRITE(*, *) NF90_STRERROR(status) end if END SUBROUTINE check END PROGRAM net2
编译该代码后出现如下错误:
Undefined symbols for architecture arm64: "___netcdf_MOD_nf90_close", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_create", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_def_dim", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_def_var_manydims", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_put_att_one_fourbyteint", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_put_att_one_fourbytereal", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_put_att_text", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_put_var_1d_fourbytereal", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_put_var_2d_fourbytereal", referenced from: _MAIN__ in ccHtjGFn.o "___netcdf_MOD_nf90_strerror", referenced from: _check.0 in ccHtjGFn.o ld: symbol(s) not found for architecture arm64 collect2: error: ld returned 1 exit status
我在Windows环境从未遇到过此类错误,不知该如何解决。
解决方法
这类错误是链接器找不到NetCDF Fortran库的符号导致的,本质是编译时没有正确链接NetCDF相关库文件,M1 Mac的arm64架构下需要确保库和编译器的架构匹配,同时正确指定链接参数。
步骤1:确认NetCDF库的安装情况
如果是用Homebrew安装的NetCDF和NetCDF-Fortran,执行以下命令确认安装路径:
brew list netcdf brew list netcdf-fortran
确保安装的是arm64架构的版本(Homebrew在M1 Mac默认安装arm64版本,若之前用Rosetta安装的x86版本,需要卸载后重新安装)。
步骤2:正确编译链接代码
编译时需要指定NetCDF-Fortran的库路径和链接库,使用nf-config工具获取正确的编译参数:
gfortran net2.f90 -o net2 $(nf-config --fflags --flibs)
如果nf-config不可用,可手动指定路径(以Homebrew默认安装路径为例):
gfortran net2.f90 -o net2 -I/opt/homebrew/include -L/opt/homebrew/lib -lnetcdff -lnetcdf
根据实际安装路径调整-I和-L后的路径。
步骤3:修复代码中的未定义变量问题
代码中eqa(xx, yy) = x**2 + y**2一行的x和y未定义,运行时会触发错误,建议修改为:
eqa(xx, yy) = real(xx)**2 + real(yy)**2
内容的提问来源于stack exchange,提问作者이수현
相关产品推荐
相关产品推荐

