Skip to content

[rustbuild] cannot link to printf with MSVC on AppVeyor #42830

Closed

Description

@kennytm

Spun off from #42777 (comment). The test case for error code E0060 contains an invocation to the C function printf. On MSVC, performing doctest on this test case failed with

  = note: rust_out.0.o : error LNK2019: unresolved external symbol printf referenced in function _ZN8rust_out4main17ha22022d8940e3e88E

Currently I'm checking if there is any missing linker args should be added to make the pass without #[cfg]ing it out.


Minimal test case

Code (copy of E0060), see https://github.com/kennytm/test-term-coloring/tree/43a23596b

/**
```
# use std::os::raw::{c_char, c_int};
# extern "C" { fn printf(_: *const c_char, ...) -> c_int; }
unsafe {
    use std::ffi::CString;
    let fmt = CString::new("test\n").unwrap();
    printf(fmt.as_ptr());
    let fmt = CString::new("number = %d\n").unwrap();
    printf(fmt.as_ptr(), 3);
    let fmt = CString::new("%d, %d\n").unwrap();
    printf(fmt.as_ptr(), 10, 5);
}
```
*/
pub fn wut() {}

Test result, see https://ci.appveyor.com/project/kennytm/test-term-coloring/build/1.0.2

   Doc-tests test-term-coloring
running 1 test
error: linking with `link.exe` failed: exit code: 1120
  |
  = note: "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe" "/NOLOGO" "/NXCOMPAT" "/LIBPATH:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib" "C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\rustdoctest.xIdH18C27InS\\rust_out.0.o" "/OUT:C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\rustdoctest.xIdH18C27InS\\rust_out.exe" "/OPT:REF,NOICF" "/DEBUG" "/LIBPATH:C:\\projects\\test-term-coloring\\target\\x86_64-pc-windows-msvc\\debug\\deps" "/LIBPATH:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib" "/LIBPATH:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib" "std-7c926edf41e020d3.dll.lib" "C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libcompiler_builtins-ce3e1312c7c980ee.rlib" "advapi32.lib" "ws2_32.lib" "userenv.lib" "shell32.lib" "msvcrt.lib"
  = note: rust_out.0.o : error LNK2019: unresolved external symbol printf referenced in function _ZN8rust_out4main17ha22022d8940e3e88E
          C:\Users\appveyor\AppData\Local\Temp\1\rustdoctest.xIdH18C27InS\rust_out.exe : fatal error LNK1120: 1 unresolved externals
          
error: aborting due to previous error(s)
thread 'rustc' panicked at 'Box<Any>', src\librustc_errors\lib.rs:512
note: Run with `RUST_BACKTRACE=1` for a backtrace.
thread 'rustc' panicked at 'couldn't compile the test', src\librustdoc\test.rs:278
test src\lib.rs - wut (line 1) ... FAILED
failures:
failures:
    src\lib.rs - wut (line 1)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

Activity

  1. retep998 commented on Jun 22, 2017

    @retep998
    Contributor

    With the new Universal CRT, msvc has switched to all the printf functions being inline wrapper functions. This is a known issue that has been hit before in Rust If you really want printf the solution is to link against legacy_stdio_definitions.lib which provides the printf wrapper functions as normal symbols to link against, but only when using a newer msvc that uses the Universal CRT. For older versions (such as VS 2013) that library does not exist and you can use printf normally.

  2. kennytm commented on Jun 22, 2017

    @kennytm
    MemberAuthor

    Looks like adding

    #[cfg_attr(all(windows, target_env="msvc"), link(name="legacy_stdio_definitions", kind="static"))]

    to the extern block works.

    It is not possible to cfg the linker version in the doctest. As we are just using the default VS version on AppVeyor i.e. VS2015, I'll just add the attribute and ignore VS2013.

  3. retep998 commented on Jun 22, 2017

    @retep998
    Contributor

    Please don't use kind="static". Either use dylib or static-nobundle. static should only be used when the bundling behavior is necessary.

  4. kennytm commented on Jun 22, 2017

    @kennytm
    MemberAuthor

    @retep998 Thanks. static-nobundle should be the only option then? legacy_stdio_definitions does not seem to be a dynamic library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    O-windows-msvcToolchain: MSVC, Operating system: Windows

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions