google / shaderc-rs

Rust bindings for the shaderc library.
https://docs.rs/shaderc
Apache License 2.0
260 stars 64 forks source link

Linking error when building with target-feature=+crt-static #103

Open AngelicosPhosphoros opened 3 years ago

AngelicosPhosphoros commented 3 years ago

This feature makes Visual C++ runtime to be linked output binaries statically. I found a workaround but maybe there is some better way?

I build on Windows with: MS Visual Studio 2019 Vulkan SDK 1.2.162.1 rustc 1.48.0 (7eac88abb 2020-11-16)

Code (build.rs):

use anyhow::*;
use glob::glob;
use std::path::PathBuf;

struct ShaderData {
    src: String,
    src_path: PathBuf,
    spv_path: PathBuf,
    kind: shaderc::ShaderKind,
}

impl ShaderData {
    pub fn load(src_path: PathBuf) -> Result<Self> {
        let extension = src_path
            .extension()
            .context("File has no extension")?
            .to_str()
            .context("Extension cannot be converted to &str")?;
        let kind = match extension {
            "vert" => shaderc::ShaderKind::Vertex,
            "frag" => shaderc::ShaderKind::Fragment,
            "comp" => shaderc::ShaderKind::Compute,
            _ => bail!("Unsupported shader: {}", src_path.display()),
        };

        let src = std::fs::read_to_string(src_path.clone())?;
        let spv_path = src_path.with_extension(format!("{}.spv", extension));

        Ok(Self {
            src,
            src_path,
            spv_path,
            kind,
        })
    }
}

fn main() -> Result<()> {
    // Collect all shaders recursively within /src/
    let mut shader_paths = [
        glob("./src/**/*.vert")?,
        glob("./src/**/*.frag")?,
        glob("./src/**/*.comp")?,
    ];

    let shaders: Result<Vec<_>> = shader_paths
        .iter_mut()
        .flatten()
        .map(|glob_res| -> Result<ShaderData> { ShaderData::load(glob_res?) })
        .collect();
    let shaders = shaders?;
    let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?;

    for shader in shaders {
        println!(
            "cargo:rerun-if-changed={}",
            shader
                .src_path
                .as_os_str()
                .to_str()
                .expect("Failed to get string name for shader")
        );
        let compiled = compiler.compile_into_spirv(
            &shader.src,
            shader.kind,
            shader.src_path.to_str().unwrap(),
            "main",
            None,
        )?;
        std::fs::write(shader.spv_path, compiled.as_binary_u8())?;
    }
    Ok(())
}

Cargo.toml:

[build-dependencies]
anyhow = "1.0"
glob = "0.3"
shaderc = "0.7"

I run build in Powershell with commands:

$env:RUSTFLAGS="-C target-feature=+crt-static"
cargo build

I expect build to compile but got this (this is only a part, a lot of omitted):

LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(validate_scopes.obj)'
          LINK : warning LNK4217: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(loop_dependence_helpers.obj)' in function '"protected: virtual class std::fpos<struct _Mbstatet> __cdecl std::basic_stringbuf<char,struct std::char_traits<char>,class std::allocator<char> >::seekoff(__int64,int,int)" (?seekoff@?$basic_stringbuf@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@MEAA?AV?$fpos@U_Mbstatet@@@2@_JHH@Z)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(PpTokens.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(basic_block.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(construct.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(instruction.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(loop_utils.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(loop_fusion.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(scalar_analysis_simplification.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(bit_vector.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(instrument_pass.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(register_pressure.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(scalar_analysis.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(loop_dependence.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(dominator_analysis.obj)'
          LINK : warning LNK4217: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(struct_cfg_analysis.obj)' in function '"private: void __cdecl spvtools::opt::StructuredCFGAnalysis::AddBlocksInFunction(class spvtools::opt::Function *)" (?AddBlocksInFunction@StructuredCFGAnalysis@opt@spvtools@@AEAAXPEAVFunction@23@@Z)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(value_number_table.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(inline_pass.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(folding_rules.obj)'
          LINK : warning LNK4217: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(fold.obj)' in function '"public: class std::_Tree_iterator<class std::_Tree_val<struct std::_Tree_simple_types<struct std::pair<class spvtools::opt::analysis::Constant const * const,unsigned int> > > > __cdecl std::_Tree<class std::_Tmap_traits<class spvtools::opt::analysis::Constant const *,unsigned int,struct std::less<class spvtools::opt::analysis::Constant const *>,class std::allocator<struct std::pair<class spvtools::opt::analysis::Constant const * const,unsigned int> >,1> >::erase(class std::_Tree_const_iterator<class std::_Tree_val<struct std::_Tree_simple_types<struct std::pair<class spvtools::opt::analysis::Constant const * const,unsigned int> > > >,class std::_Tree_const_iterator<class std::_Tree_val<struct std::_Tree_simple_types<struct std::pair<class spvtools::opt::analysis::Constant const * const,unsigned int> > > >)" (?erase@?$_Tree@V?$_Tmap_traits@PEBVConstant@analysis@opt@spvtools@@IU?$less@PEBVConstant@analysis@opt@spvtools@@@std@@V?$allocator@U?$pair@QEBVConstant@analysis@opt@spvtools@@I@std@@@6@$00@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@U?$_Tree_simple_types@U?$pair@QEBVConstant@analysis@opt@spvtools@@I@std@@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@U?$_Tree_simple_types@U?$pair@QEBVConstant@analysis@opt@spvtools@@I@std@@@std@@@std@@@2@0@Z)'
          LINK : warning LNK4217: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(block_merge_util.obj)' in function '"bool __cdecl spvtools::opt::blockmergeutil::CanMergeWithSuccessor(class spvtools::opt::IRContext *,class spvtools::opt::BasicBlock *)" (?CanMergeWithSuccessor@blockmergeutil@opt@spvtools@@YA_NPEAVIRContext@23@PEAVBasicBlock@23@@Z)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(propagator.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(decoration_manager.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(debug_info_manager.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(eliminate_dead_functions_util.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(const_folding_rules.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(ir_context.obj)'
          LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(type_manager.obj)'
          LINK : warning LNK4217: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'libshaderc_sys-cae357ba032ea1ca.rlib(ir_loader.obj)' in function '"protected: void __cdecl std::vector<class std::unique_ptr<class spvtools::opt::BasicBlock,struct std::default_delete<class spvtools::opt::BasicBlock> >,class std::allocator<class std::unique_ptr<class spvtools::opt::BasicBlock,struct std::default_delete<class spvtools::opt::BasicBlock> > > >::_Reallocate(unsigned __int64)" (?_Reallocate@?$vector@V?$unique_ptr@VBasicBlock@opt@spvtools@@U?$default_delete@VBasicBlock@opt@spvtools@@@std@@@std@@V?$allocator@V?$unique_ptr@VBasicBlock@opt@spvtools@@U?$default_delete@VBasicBlock@opt@spvtools@@@std@@@std@@@2@@std@@IEAAX_K@Z)'

I currently use a hack with specifying target explicitely. It makes cargo send custom compiler flags only to the final binary compilations and ignore build scripts:

cargo run --target x86_64-pc-windows-msvc
guilhermewerner commented 3 years ago

Instead of passing the --target to cargo you can put this in your .cargo/config.toml:

[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
AngelicosPhosphoros commented 2 years ago

@GuilhermeWerner rustflags in config.toml have same effect as setting RUSTFLAGS environment variable so it is unrelated.