Windows 上带有 Fortran 模块的 R 包?对“__stack_chk_fail”的未定义引用

R package with Fortran module on Windows? undefined reference to `__stack_chk_fail'

我创建了一个使用 Fortran 模块的 R 库。在 linux 上一切都像魅力一样。

现在我正在尝试让它在 Windows 上运行。我在 windows 计算机上克隆了 my git repository,当我在 Rstudio 上按下 build and reload 按钮时,出现以下错误:

==> Rcmd.exe INSTALL --no-multiarch --with-keep.source MyPi

* installing to library 'C:/Users/IMartinez/Documents/R/R-3.2.1/library'
* installing *source* package 'MyPi' ...
** libs
gfortran -m64 -shared -s -static-libgcc -o MyPi.dll tmp.def Fpi.o -Ld:/RCompile/r-compiling/local/local320/lib/x64 -Ld:/RCompile/r-compiling/local/local320/lib -LC:/Users/IMARTI~1/DOCUME~1/R/R-32~1.1/bin/x64 -lR
Fpi.o: In function `__fortranpi_MOD_dboard':
Fpi.f90:(.text+0xd7): undefined reference to `__stack_chk_fail'
Fpi.o: In function `pi_':
Fpi.f90:(.text+0x249): undefined reference to `__stack_chk_fail'
collect2: ld returned 1 exit status
no DLL was created
ERROR: compilation failed for package 'MyPi'
* removing 'C:/Users/IMartinez/Documents/R/R-3.2.1/library/MyPi'

Exited with status 1.

我错过了什么?


Module Fortranpi
IMPLICIT NONE
contains
subroutine dboard(darts, dartsscore)
  integer, intent(in)                    :: darts
  double precision, intent(out)          :: dartsscore
  double precision                       :: x_coord, y_coord
  integer                                :: score, n

score = 0
do n = 1, darts
  call random_number(x_coord)
  call random_number(y_coord)

  if ((x_coord**2 + y_coord**2) <= 1.0d0) then
  score = score + 1
  end if
end do

dartsscore = 4.0d0*score/darts

end subroutine dboard

subroutine pi(avepi, DARTS, ROUNDS) bind(C, name="pi_")
  use, intrinsic                         :: iso_c_binding, only : c_double, c_int
  real(c_double), intent(out)            ::  avepi
  integer(c_int), intent(in)             ::  DARTS, ROUNDS
  integer                                ::  MASTER, rank, i, n
  integer, allocatable                   ::  seed(:)
  double precision                       ::  pi_est, homepi, pirecv, pisum

! we set it to zero in the sequential run
rank = 0
! initialize the random number generator
! we make sure the seed is different for each task
call random_seed()
call random_seed(size = n)
allocate(seed(n))
seed = 12 + rank*11
call random_seed(put=seed(1:n))
deallocate(seed)

avepi = 0
do i = 0, ROUNDS-1
  call dboard(darts, pi_est)
  ! calculate the average value of pi over all iterations
  avepi = ((avepi*i) + pi_est)/(i + 1)
end do
end subroutine pi

end module Fortranpi

按照 this post 中的建议,我添加了 -fno-stack-protector -lssp 但没有帮助。可能是我加错地方了?


我也尝试过手动操作,但出现了这些错误:

> system("R CMD SHLIB -fno-stack-protector -lssp ./src/Fpi.f90")
gfortran -m64 -shared -s -static-libgcc -o src/Fpi.dll tmp.def ./src/Fpi.o -fno-stack-protector -lssp -Ld:/RCompile/r-compiling/local/local320/lib/x64 -Ld:/RCompile/r-compiling/local/local320/lib -LC:/Users/IMARTI~1/DOCUME~1/R/R-32~1.1/bin/x64 -lR
> dyn.load("./src/Fpi.dll")
Error in inDL(x, as.logical(local), as.logical(now), ...) : 
  unable to load shared object 'C:/Users/IMartinez/Projects/MyPi/./src/Fpi.dll':
  LoadLibrary failure:  %1 is not a valid Win32 application. 'C:/Users/IMartinez/Projects/MyPi/./src/Fpi.dll':
  LoadLibrary failure:  %1 is not a valid Win32 application.


按照@cdeterman 的说明,我做了以下操作:

  1. 我在 src 中使用以下行创建了 Makevars.win

    PKG_FCFLAGS="-fno-stack-protector"

  2. 然后我也把NAMESPACE里面的useDynLin(Fpi)改成了useDynLib(MyPi)。

这是我得到的:

==> Rcmd.exe INSTALL --no-multiarch --with-keep.source MyPi

* installing to library 'C:/Users/IMartinez/Documents/R/R-3.2.1/library'
* installing *source* package 'MyPi' ...
** libs
gfortran -m64 -shared -s -static-libgcc -o MyPi.dll tmp.def Fpi.o -Ld:/RCompile/r-compiling/local/local320/lib/x64 -Ld:/RCompile/r-compiling/local/local320/lib -LC:/Users/IMARTI~1/DOCUME~1/R/R-32~1.1/bin/x64 -lR
Fpi.o: In function `__fortranpi_MOD_dboard':
Fpi.f90:(.text+0xd7): undefined reference to `__stack_chk_fail'
Fpi.o: In function `pi_':
Fpi.f90:(.text+0x249): undefined reference to `__stack_chk_fail'
collect2: ld returned 1 exit status
installing to C:/Users/IMartinez/Documents/R/R-3.2.1/library/MyPi/libs/x64
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
Error in library.dynam(lib, package, package.lib) : 
  DLL 'MyPi' not found: maybe not installed for this architecture?
Error: loading failed
Execution halted
ERROR: loading failed
* removing 'C:/Users/IMartinez/Documents/R/R-3.2.1/library/MyPi'
* restoring previous 'C:/Users/IMartinez/Documents/R/R-3.2.1/library/MyPi'

Exited with status 1.

使用以下行在您的 src 目录中创建一个 Makevars.win 文件。

PKG_FCFLAGS="-fno-stack-protector"

然后也将 NAMESPACE 中的 useDynLib(Fpi) 更改为 useDynLib(MyPi),因为这就是包名称。

尝试构建包。如果输出没有显示正在使用的标志,则环境变量当前可能不存在并且无法工作。不确定为什么会发生这种情况。如果是这种情况,只需简单地初始化环境变量即可。

Sys.setenv(PKG_FCFLAGS = "")

这会让你的包在我的 Windows 系统上构建。