r-windows / rtools-packages

Toolchains and libraries for R-4.0 to R-4.2 (legacy)
https://cran.r-project.org/bin/windows/Rtools/rtools40.html
BSD 3-Clause "New" or "Revised" License
54 stars 36 forks source link

Implement libgcc_eh "hack" for mingw64 #185

Closed Ilia-Kosenkov closed 3 years ago

Ilia-Kosenkov commented 3 years ago

We attempt to bridge R and rust and use rtools for building rust code. However, we encountered a linker error reporting there is no libgcc_eh when targeting x86_64.

Preliminary googling suggested that if gcc is built with --disabled-shared, libgcc_eh is not emitted. https://github.com/r-windows/rtools-packages/blob/df6b4363b0422db30abf7dd78378022666a24ab4/mingw-w64-gcc/PKGBUILD#L167

We found that mingw32 version of gcc contains libgcc_eh, which is an exact copy of libgcc, and rust libraries targeting i686 can be successfully built with the help of rtools.

PKGBUILD of gcc contains a "hack" implemented for mingw32 (comment suggests it is needed for rust compiler), but no such hack is present for mingw64. https://github.com/r-windows/rtools-packages/blob/df6b4363b0422db30abf7dd78378022666a24ab4/mingw-w64-gcc/PKGBUILD#L305-L309

We confirm that our linking issues are resolved by duplicating libgcc as libgcc_eh in mingw64 gcc folder. Therefore, we would like to have this "hack" implemented for mingw64 as well.

A possible implementation based on existing mingw32 code:

  if [ "${MINGW_CHOST}" = "x86_64-w64-mingw32" ]; then
    cp ${pkgdir}${MINGW_PREFIX}/lib/gcc/${MINGW_CHOST}/${pkgver}/libgcc.a ${pkgdir}${MINGW_PREFIX}/lib/gcc/${MINGW_CHOST}/${pkgver}/libgcc_eh.a
  fi
}

Alternatively, if condition can be removed so the cp command is executed for both architectures.

Relevant discussions can be found in https://github.com/extendr/rextendr/issues/19.

jeroen commented 3 years ago

Hmmm last time i checked this was not needed on x64. See also https://github.com/r-rust/hellorust which passes CI using rtools40. Where are you getting this error ?

Op zo 17 jan. 2021 20:12 schreef Ilia notifications@github.com:

We attempt to bridge R and rust and use rtools for building rust code. However, we encountered a linker error reporting there is no libgcc_eh when targeting x86_64.

Preliminary googling suggested that if gcc is built with --disabled-shared, libgcc_eh is not emitted.

https://github.com/r-windows/rtools-packages/blob/df6b4363b0422db30abf7dd78378022666a24ab4/mingw-w64-gcc/PKGBUILD#L167

We found that mingw32 version of gcc contains libgcc_eh, which is an exact copy of libgcc, and rust libraries targeting i686 can be successfully built with the help of rtools.

PKGBUILD of gcc contains a "hack" implemented for mingw32 (comment suggests it is needed for rust compiler), but no such hack is present for mingw64.

https://github.com/r-windows/rtools-packages/blob/df6b4363b0422db30abf7dd78378022666a24ab4/mingw-w64-gcc/PKGBUILD#L305-L309

We confirm that our linking issues are resolved by duplicating libgcc as libgcc_eh in mingw64 gcc folder. Therefore, we would like to have this "hack" implemented for mingw64 as well.

A possible implementation based on existing mingw32 code:

if [ "${MINGW_CHOST}" = "x86_64-w64-mingw32" ]; then cp ${pkgdir}${MINGW_PREFIX}/lib/gcc/${MINGW_CHOST}/${pkgver}/libgcc.a ${pkgdir}${MINGW_PREFIX}/lib/gcc/${MINGW_CHOST}/${pkgver}/libgcc_eh.a fi }

Alternatively, if condition can be removed so the cp command is executed for both architectures.

Relevant discussions can be found in extendr/rextendr#19 https://github.com/extendr/rextendr/issues/19.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/r-windows/rtools-packages/issues/185, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABUZ7YTLQEC2HLT7FZDPU3S2MZBHANCNFSM4WGKSARA .

Ilia-Kosenkov commented 3 years ago

@jeroen, In all cases where we build targeting x86_64-pc-windows-gnu. Take for instance https://github.com/extendr/libR-sys With default rust toolchain (stable-msvc)

$env:PATH = "$env:RTOOLS40_home\bin\mingw64;$env:PATH"
(cargo test --target x86-64-pc-windows-gnu -- --nocapture) *> log_64.dat
log_64.dat ``` Compiling winapi-build v0.1.1 Compiling winapi v0.3.9 Compiling winapi v0.2.8 Compiling kernel32-sys v0.2.2 Compiling libR-sys v0.2.1 (C:\Users\[redacted]\OneDrive\Development\OSS\libR-sys) error: linking with `x86_64-w64-mingw32-gcc` failed: exit code: 1 | = note: "x86_64-w64-mingw32-gcc" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-m64" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.13e24wakruqa2ah7.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.13wfxsp1qqybu2z3.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.1917yhdxyoq3tgnj.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.1exzbqhkz8pqpzp9.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.1hucimhq9xcsuht.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.1meg8mpsu90xrg5s.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.1pgxej3t2o08lmbm.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.1xdsu19ahgz52rjl.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.202e2r3iouenuv5n.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.24fnxbqbha6qkn3o.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.29jewaiuu86e4lef.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.29lp6rpzk599u24v.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.2e4jvc5epi1nyqrw.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.2kenc4gj764msilk.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.2mhd5nq6pptleasa.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.2o3e244xjct43rxd.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.2z1x0ke236824jx2.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.30vp44d4xgphbn39.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.3aiyal9l89aphhtj.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.3q3kmobogxat5avl.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.4d39vmh8fvaybfb6.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.4gus57dnrogmdq7x.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.4u0tozr3cfy9n9b.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.4umfseixxzc8m7e0.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.4zlmpni3919vdda8.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.al4a540l4jd761a.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.jw1zg484vhbr6hv.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.ochc4vxxm8qq2fj.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.p6nsbb2qyur5elh.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.w2cqinzert970ru.rcgu.o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.xrr4e9p5a2pgkq.rcgu.o" "-o" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.exe" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps\\libR_sys-0b7fd5a192a38508.2p820bsrdy2fc2kq.rcgu.o" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\x86_64-pc-windows-gnu\\debug\\deps" "-L" "C:\\Users\\[redacted]\\OneDrive\\Development\\OSS\\libR-sys\\target\\debug\\deps" "-L" "C:\\Program Files\\R\\R-4.0.3\\bin\\x64" "-L" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-lR" "-Wl,-Bstatic" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libtest-6b691ae2f7a468dd.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libterm-31c4b14ee45d62c5.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libgetopts-fc86de0fe7be563d.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libunicode_width-eee464f106bb1692.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librustc_std_workspace_std-a13e0c0cecc328ed.rlib" "-Wl,--start-group" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd-8394c9398cbadee5.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libpanic_unwind-886e4f572a6d227c.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libobject-17cf826d0f7d2ed3.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libaddr2line-0dad5a98c26b9739.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libgimli-dfab679e0565d217.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librustc_demangle-9f6866b4336a1d1c.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libhashbrown-81ade66b9e4c9cd5.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librustc_std_workspace_alloc-4149a301273ebf0c.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libunwind-738a3de7ad0cd3a3.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcfg_if-06d418ce9254f841.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liblibc-7c3291a8d67347b3.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc-9f2b7229edc9025e.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librustc_std_workspace_core-4ae0cac901a4e3c1.rlib" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcore-9e39cfd0b85a4b6e.rlib" "-Wl,--end-group" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcompiler_builtins-de70f57e5c136950.rlib" "-Wl,-Bdynamic" "-lkernel32" "-ladvapi32" "-lws2_32" "-luserenv" "-lgcc_eh" "-l:libpthread.a" "-lmsvcrt" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\[redacted]\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsend.o" = note: C:/rtools40/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lgcc_eh collect2.exe: error: ld returned 1 exit status error: aborting due to previous error error: could not compile `libR-sys` To learn more, run the command again with --verbose. ```

Same thing, but for i686:

$env:PATH = "$env:RTOOLS40_home\bin\mingw32;$env:PATH"
(cargo test --target i686-pc-windows-gnu -- --nocapture) *> log_32.dat
log_32.dat ``` Compiling winapi-build v0.1.1 Compiling winapi v0.3.9 Compiling winapi v0.2.8 Compiling kernel32-sys v0.2.2 Compiling libR-sys v0.2.1 (C:\Users\[redacted]\OneDrive\Development\OSS\libR-sys) Finished test [unoptimized + debuginfo] target(s) in 1m 03s Running target\i686-pc-windows-gnu\debug\deps\libR_sys-e275bd16a562c3bb.exe running 17 tests test bindgen_test_layout_R_CMethodDef ... ok test bindgen_test_layout_R_CallMethodDef ... ok test bindgen_test_layout_R_inpstream_st ... ok test bindgen_test_layout_R_outpstream_st ... ok test bindgen_test_layout_Rcomplex ... ok test bindgen_test_layout___mingw_dbl_type_t ... ok test bindgen_test_layout___mingw_flt_type_t ... ok test bindgen_test_layout___mingw_dbl_type_t__bindgen_ty_1 ... ok test bindgen_test_layout___mingw_ldbl_type_t__bindgen_ty_1 ... ok test bindgen_test_layout__complex ... ok test bindgen_test_layout__exception ... ok test bindgen_test_layout__iobuf ... ok test bindgen_test_layout_localeinfo_struct ... ok test bindgen_test_layout_tagLC_ID ... ok test bindgen_test_layout_threadlocaleinfostruct ... ok test bindgen_test_layout_threadlocaleinfostruct__bindgen_ty_1 ... ok test tests::test_eval ... ok test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out [1] 1 ```

Same x86_64 setup, but using `libgcc_eh" hack:

cp $env:RTOOLS40_HOME\mingw64\lib\gcc\x86_64-w64-mingw32\8.3.0\libgcc.a $env:RTOOLS40_HOME\mingw64\lib\gcc\x86_64-w64-mingw32\8.3.0\libgcc_eh.a
$env:PATH = "$env:RTOOLS40_home\bin\mingw64;$env:PATH"
(cargo test --target x86-64-pc-windows-gnu -- --nocapture) *> log_64_hack.dat
log_64_hack.dat ``` Compiling winapi-build v0.1.1 Compiling winapi v0.3.9 Compiling winapi v0.2.8 Compiling kernel32-sys v0.2.2 Compiling libR-sys v0.2.1 (C:\Users\[redacted]\OneDrive\Development\OSS\libR-sys) Finished test [unoptimized + debuginfo] target(s) in 1m 00s Running target\x86_64-pc-windows-gnu\debug\deps\libR_sys-0b7fd5a192a38508.exe running 19 tests test bindgen_test_layout_R_CMethodDef ... ok test bindgen_test_layout_R_CallMethodDef ... ok test bindgen_test_layout_R_inpstream_st ... ok test bindgen_test_layout_R_outpstream_st ... ok test bindgen_test_layout_Rcomplex ... ok test bindgen_test_layout___mingw_dbl_type_t ... ok test bindgen_test_layout___mingw_dbl_type_t__bindgen_ty_1 ... ok test bindgen_test_layout___mingw_flt_type_t ... ok test bindgen_test_layout___mingw_ldbl_type_t ... ok test bindgen_test_layout___mingw_ldbl_type_t__bindgen_ty_1 ... ok test bindgen_test_layout__complex ... ok test bindgen_test_layout__exception ... ok test bindgen_test_layout__iobuf ... ok test bindgen_test_layout_localeinfo_struct ... ok test bindgen_test_layout_max_align_t ... ok test bindgen_test_layout_tagLC_ID ... ok test bindgen_test_layout_threadlocaleinfostruct ... ok test bindgen_test_layout_threadlocaleinfostruct__bindgen_ty_1 ... ok test tests::test_eval ... ok test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out [1] 1 ```

What I observed is the need for libgcc_eh is not universal, perhaps in your r-rust/hellorust it is not invoked. Also, you are using stable-gnu as default toolchain, we rely on stable-msvc for a number of reasons. We also provide options to use different toolchains if a user so desires, so it is important for us that it works in such configuration. There is also a relevant discussion about rust gnu toolchains here https://github.com/rust-lang/cargo/issues/8990.

EDIT01: to test libR-sys, just install rustup, set default toolchain to stable-msvc and add x86_64-pc-windows-gnu and i686-pc-windows-gnu targets to said toolchain. You also need to have $R_HOME\bin\x64 or $R_HOME\bin\i386 on your path for tests to grab R.dll.

jeroen commented 3 years ago

Sorry i'm completely lost in all your topics what you're trying to do.

Rtools is a gcc/mingw-w64 toolchain for building R packages, I don't understand why/how you are using the MSVC version of rust with rtools.

Am I correct to understand the problem does not appear when you're using the the native gnu version of rust, but only when using MSVC to cross-compile for mingw-w64? And if you're already cross-compiling, why do you need rtools in the first place?

Ilia-Kosenkov commented 3 years ago

@jeroen, I am sorry for the messy explanation, let me try one more time. The rust code that goes into an R package makes use of a number of rust crates that provide convenient instruments for rust developers, like macros for automatic exporting and auto-generated bindings to R C API.

These crates are built targeting either x86_64-pc-windows-gnu or i686-pc-windows-gnu depending on the architecture. So, to target *-gnu we need mingw toolchains. rust stable-x86_64-pc-windows-gnu toolchain provides tools for building x86_64 target, however, we are unable to cross-compile to i686 using only rust toolchain (which, apparently, is possible in https://github.com/r-rust/hellorust). We can, in principle, use another toolchain, stable-i686-pc-windows-gnu, to compile for i686, but this means additional tweaking of cargo and asking users to install and configure two toolchains.

As an alternative, we can use mingw toolchain provided elsewhere for cross-compilation. One possibility is rtools, as it should be already available and configured on a Windows machine that attempts to build non-R code for packages. When using mingw toolchain from rtools, we found that the "hack" implemented for mingw32 is also required for mingw64 to enable simple cross-compilation. Therefore, we suggest to extend this "hack" to include both mingw64 and mingw32.

To illustrate the issue with the gnu cross-compilation, here is an example output of building our core rust package:

(cargo +stable-x86_64-pc-windows-gnu test --target i686-pc-windows-gnu -- --nocapture) *> log.dat
log.dat ``` Compiling winapi-x86_64-pc-windows-gnu v0.4.0 Compiling winapi-build v0.1.1 Compiling winapi v0.3.9 Compiling winapi v0.2.8 Compiling kernel32-sys v0.2.2 Compiling libR-sys v0.2.1 (C:\Users\[redacted]\OneDrive\Development\OSS\libR-sys) error: linker `i686-w64-mingw32-gcc` not found | = note: The system cannot find the file specified. (os error 2) error: aborting due to previous error error: could not compile `libR-sys` To learn more, run the command again with --verbose. ```

Because this package is referenced in rust-R packages, any build errors occuring at this step will propagate and ruin builds for any derived product.

yutannihilation commented 3 years ago

What I observed is the need for libgcc_eh is not universal, perhaps in your r-rust/hellorust it is not invoked.

I found this actually happen even on r-rust/hellorust if you run cargo test instead of cargo build. Comparing the actual rustc commands executed, it seems cargo test doesn't pass --crate-type lib to rustc. I don't know why this matters and this is beyond my knowledge, but you can confirm the same error happens here:

commit: https://github.com/yutannihilation/hellorust/commit/ce49dc598b519a57b363f18de43c72979797262d job run: https://github.com/yutannihilation/hellorust/runs/1721221185?check_suite_focus=true#step:8:212

diff (this one is of extendr/libR-sys, but it's probably mostly the same in the hellorust's case):

--- ".\\cargo_build.txt"        2021-01-18 21:22:57.629898200 +0900
+++ ".\\cargo_test.txt" 2021-01-18 21:21:02.806275900 +0900
@@ -3,12 +3,12 @@
     --edition=2018 src\lib.rs
     --error-format=json
     --json=diagnostic-rendered-ansi
-    --crate-type lib
-    --emit=dep-info,metadata,link
+    --emit=dep-info,link
     -C embed-bitcode=no
     -C debuginfo=2
-    -C metadata=6227798a48c8b7f3
-    -C extra-filename=-6227798a48c8b7f3
+    --test
+    -C metadata=1f3043e575d47cae
+    -C extra-filename=-1f3043e575d47cae
     --out-dir C:\path\to\libR-sys\target\i686-pc-windows-gnu\debug\deps
     --target i686-pc-windows-gnu
     -C incremental=C:\path\to\libR-sys\target\i686-pc-windows-gnu\debug\incremental

So, this probably means,

Am I correct to understand the problem does not appear when you're using the the native gnu version of rust,

you are correct as long as we only build staticlib, but we might run tests or dynamic library (as an intermediate artifact?) (Sorry, this seems my misunderstanding).

clauswilke commented 3 years ago

Just as an aside, the hellorust example also uses the msvc toolchain: https://github.com/r-rust/hellorust/runs/1482980650?check_suite_focus=true#step:4:15

clauswilke commented 3 years ago

To be clear, the extendr project has three distinct use cases with somewhat differing requirements:

  1. Build static library for packages, as in hellorust
  2. Build Rust standalone binary linking to R, for testing and to call R from Rust
  3. Build dynamic library for interactive use from R, e.g. rust_function()

In cases 2 and 3, linking is done by cargo, and it insists on injecting -lgcc_eh. Not entirely sure why, but I'll also note that we're just working around a gcc bug here, gcc should figure out that the symbols are already available in libgcc but it doesn't when cross-compiling.

Here's a post from 2003 where they discuss the gcc workaround for static builds and that it doesn't work for cross-compiles: https://sourceware.org/legacy-ml/libc-alpha/2003-09/msg00100.html

jeroen commented 3 years ago

But it sounds like you don't need rtools for 2 and 3 really? I mean I don't mind, but I'm afraid you're going to rely on a "hack" that won't work on other systems. Does this same problem appear when you use the upstream msys2 compilers (of which rtools40 is simply a variation)?

Ilia-Kosenkov commented 3 years ago

@jeroen, The latest version of msys2 has gcc 10.2.0 and it includes ligcc_eh.a both in mingw32 and mingw64. Up until now we were using msys2 successfully, but we want to switch to rtools to ditch msys2 dependency for endusers.

clauswilke commented 3 years ago

The reason Rtools needs this hack is because gcc is built with --disable-shared.

clauswilke commented 3 years ago

@Ilia-Kosenkov Just to be clear: It's not an issue of gcc 10.2 vs 8.3. It's --disable-shared vs --enable-shared. When you compile gcc with --disable-shared then the static compile chain breaks for certain use cases, ironically.

Ilia-Kosenkov commented 3 years ago

@clauswilke, Yes I know, I just replied to @jeroen stating that msys2 is configured in such a manner that gcc emits libgcc_eh and we experience no issues when using msys2, but not rtools.

clauswilke commented 3 years ago

@Ilia-Kosenkov Since @jeroen said he is fine in principle with the proposed solution, would you mind preparing a PR? I think a simple unconditional copy would be best. This will continue to work even if in the future there's a different Windows architecture that needs to be supported (e.g. ARM).

It would also be helpful to expand a bit on what's happening in the comment, so in the future people can understand why this was added and what exactly it does.

Ilia-Kosenkov commented 3 years ago

@clauswilke, @jeroen, I actually have a fork where I tested this thing (by building gcc and later installing it for rtools using pacman as per guidelines). https://github.com/Ilia-Kosenkov/rtools-packages/commit/e1fd3bece3abf218efe2b370fd666e99674d40f7

I will open a PR and the discussion can be moved there.