Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't statically link on Windows when building for debug #109

Closed
robmikh opened this issue Aug 7, 2019 · 5 comments
Closed

Can't statically link on Windows when building for debug #109

robmikh opened this issue Aug 7, 2019 · 5 comments

Comments

@robmikh
Copy link

robmikh commented Aug 7, 2019

Hello, I'm trying to put together an application that uses both C++ and rust. What I've done is create a static lib in rust that I then link into a C++ executable.

The problem I'm running into is that appears that spirv-cross is being built for Release on Windows no matter what. I've put together a small repro with build instructions here if you're interested.

This only reproduces when building in Debug mode on Windows. In Release mode it seems to work fine, and other platforms (Linux and macOS) seem to be fine in either Debug or Release modes.

Here's the linker error that I run into:

rust_lib.lib(wrapper.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(wrapper.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_cross.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_cross.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_cross_util.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_cross_util.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_glsl.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_glsl.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_hlsl.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_hlsl.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_msl.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_msl.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_cfg.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_cfg.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_cross_parsed_ir.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_cross_parsed_ir.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
rust_lib.lib(spirv_parser.o) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
rust_lib.lib(spirv_parser.o) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
cpp-exe\cpp-exe.exe : fatal error LNK1319: 18 mismatches detected
ninja: build stopped: subcommand failed.

I'm a bit new to using Rust in this way, but is there a way to configure the build? As you can see in the repro, I'm not consuming spirv-cross directly, but instead consuming it through wpgu.

I'd be willing to submit a PR if required. I just need to know what direction to look in/what to look for.

Thanks for your project!

@grovesNL
Copy link
Owner

grovesNL commented Aug 7, 2019

Interesting, thanks for reporting the issue!

The idea is that this crate builds the C++ library SPIRV-Cross as part if it's build. In order to do this it uses cc-rs in spirv_cross's build.rs.

I believe the default behavior when static linking on Windows would mean that /MT would be provided while building SPIRV-Cross, which statically links a particular version of the runtime library.

Could static linking be avoided in this case? (You should be able to use Rust and C++ together fine without static linking, but maybe you're considering distribution of the executable or something else)

Was the C++ executable built with /MT? I would try changing it on that side first if possible and seeing if it helps. Otherwise we can try adjusting the build.rs to pass different flags for the SPIRV-Cross (C++) portion while still building the spirv_cross (Rust) portion as a static library.

@robmikh
Copy link
Author

robmikh commented Aug 7, 2019

The original project that ran into this is meant to be a dll instead of an executable, and distributed by itself. In the future I'd like the the dll to be entirely Rust, but until then it has some C++ portions. For the time being I need to statically link the two together.

By default, Debug mode will compile using /MDd. Overriding that by compiling with /MD does resolve the linker issues, but this does put me halfway to building as Release. I also tried /MT for fun and got more linker errors than before.

I might try to play with the build.rs to build with /MDd (or possibly building as debug, I guess building as release with /MDd is just as arbitrary). How does this usually work in the Rust ecosystem? Is there a way to inform indirect dependencies of desired build configurations? I've only ever seen people read environment variables from their build.rs, but I also haven't seen too many of them.

Thank you so much for the quick reply! I can't believe I didn't think about the runtime library flags...

@robmikh
Copy link
Author

robmikh commented Aug 7, 2019

Hmmm... after some quick experimenting it's not as simple as compiling SPIRV-Cross with /MDd. Unfortunately, I've had my fill of linker errors for the past couple of days and will probably just put up with building my dll with /MD for now. I may come back to this later.

Thanks for your help! Feel free to close this issue if you don't think it's necessary.

@retep998
Copy link

retep998 commented Aug 7, 2019

Rust currently always uses the release CRT. It does not have the option to use the debug CRT. Every crate that builds C code therefore builds it with the release CRT and so trying to link the resulting staticlib into a C project using the debug CRT will cause a CRT mismatch.

@robmikh
Copy link
Author

robmikh commented Aug 7, 2019

Ah, that's good to know! In that case I'll close the issue.

Thanks, @retep998!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants