profile
viewpoint

Ask questionsunder latest MinGW, cannot link with C code using stdout

I'm having an issue under MinGW and I'm not sure if it's a MinGW issue or a rustc issue. On the one hand the bug crops up after an update to two MinGW packages, but on the other hand I cannot reproduce with only C, and I don't know if rustc is using MinGW in some undocumented unsupported way.

say_hi.c:

#include <stdio.h>
void say_hi(void) {
    fprintf(stdout, "hi!\n");
}

c_main.c

void say_hi(void);
int main(void) {
    say_hi();
    return 0;
}

r_main.rs:

extern "C" {
    fn say_hi();
}
fn main() {
    unsafe {
        say_hi();
    }
}

Under the latest MinGW, specifically with packages

  • mingw-w64-x86_64-crt-git-6.0.0.5066.61efe559-1 and
  • mingw-w64-x86_64-headers-git-6.0.0.5066.61efe559-1,

using only gcc like this works:

$ gcc -c say_hi.c
$ ar cr libsay_hi.a say_hi.o
$ gcc c_main.c -L. -lsay_hi -o c_main.exe && ./c_main.exe
hi!

But it doesn't work with rustc:

$ gcc -c say_hi.c
$ ar cr libsay_hi.a say_hi.o
$ rustc r_main.rs -L. -lsay_hi -o r_main.exe && ./r_main.exe
error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-m64" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\crt2.o" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "r_main.r_main0.rust-cgu.o" "-o" "r_main.exe" "r_main.crate.allocator.rust-cgu.o" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "." "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-l" "say_hi" "-Wl,-Bstatic" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd-60d4a252bdda9250.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc_system-a05404e5e059417a.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librand-81cbf6f1d5a19206.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libpanic_unwind-0b63e20460046692.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc-f824a78e715239af.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd_unicode-2abaea46f194a6e1.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libunwind-7daa32005d584d8a.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liblibc-49ff25caaa6e945f.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcore-f2bd2d524c6ace24.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcompiler_builtins-c6139fac5e899293.rlib" "-Wl,-Bdynamic" "-l" "advapi32" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-Wl,-Bstatic" "-l" "gcc_eh" "-l" "pthread" "-Wl,-Bdynamic" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\Trevor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsend.o"
  = note: ./libsay_hi.a(say_hi.o):say_hi.c:(.text+0x10): undefined reference to `__imp___acrt_iob_func'
          

error: aborting due to previous error

If I downgrade those two packages to

  • mingw-w64-x86_64-crt-git-5.0.0.5002.34a7c1c0-1 and
  • mingw-w64-x86_64-headers-git-5.0.0.5002.34a7c1c0-1,

it works with rustc too:

$ gcc -c say_hi.c
$ ar cr libsay_hi.a say_hi.o
$ rustc r_main.rs -L. -lsay_hi -o r_main.exe && ./r_main.exe
hi!

One last thing, if I compile the library using the old packages, and then upgrade the packages, both gcc c_main.c ... and rustc r_main.rs ... work. If I compile the library using the new packages, and then downgrade the packages, both gcc c_main.c ... and rustc r_main.rs ... fail.

rust-lang/rust

Answer questions daniel-shimon

For whoever is getting here with the original problem, the following worked for me:

(undefined reference to '__imp___acrt_iob_func')

1. Create workaround.c with the following

(thanks @tspiteri for the workaround code)
/* workaround.c */
#define _CRTBLD
#include <stdio.h>

FILE *__cdecl __acrt_iob_func(unsigned index)
{
    return &(__iob_func()[index]);
}

typedef FILE *__cdecl (*_f__acrt_iob_func)(unsigned index);
_f__acrt_iob_func __MINGW_IMP_SYMBOL(__acrt_iob_func) = __acrt_iob_func;

2. Compile and create the library

gcc -fPIC -O2 -c workaround.c
ar cr libworkaround_47048.a workaround.o

3. Move the library to rust's lib folder

mv libworkaround_47048.a ~/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib
/x86_64-pc-windows-gnu/lib/

rm workaround.c workaround.o

4. Add the following to ~/.cargo/config:

[target.x86_64-pc-windows-gnu]
rustflags=["-Clink-args=-lworkaround_47048"]

Enjoy 😄

useful!

Related questions

Spurious NaNs produced by trig functions with valid inputs on Windows GNU toolchains hot 2
using 'cargo install xsv' on windows 10 triggers rustc internal error hot 1
chain() make collect very slow hot 1
if/while Some(n) = &mut foo sugar will leak a temporary mutable borrow to current scope in particular situation hot 1
build an empty project failed (undefined reference to `__onexitbegin') hot 1
Invalid collision with TryFrom implementation? hot 1
Crater runs for Rust 1.38.0 hot 1
Spurious NaNs produced by trig functions with valid inputs on Windows GNU toolchains hot 1
Archive all nightlies hot 1
Building LLVM with Clang fails hot 1
Internal compiler error: can't buffer lints after HIR lowering hot 1
Tracking issue for `Option::contains` and `Result::contains` hot 1
async fn + rustfmt don't "just work" inside of RLS hot 1
Some closures are not inlined in release mode hot 1
nightly version fails: invalid version 3 on git_proxy_options; class=Invalid (3) hot 1
Github User Rank List