How to specify custom output library file name with hyphens in cargo?

Hello.

My overall goal is to create a Windows native DLL library with a name that contains hyphens.
The name is not just a file name, but the name of the DLL is also written by the linker in the PE file in IMAGE_EXPORT_DIRECTORY.

It seems like the linker does not provide a separate flag for specifying the dllname in PE (unlike tools like dllwrap and dlltool), and instead uses the file name as dllname.

So I wanted to change the file name, and I managed to do that with -o flag specified in rustc, and everything worked, I got the desired result. Command was: rustc src/lib.rs --crate-type cdylib -o "my-file.dll" --target x86_64-pc-windows-gnu

I don't want to run rustc manually, so I'd like the same result, but with cargo.
However, specifying the same flag via cargo config build.rustflag:

[build]
rustflags = [
    "-o",
    "my-file.dll"
]

Results in a build error:

error: output of --print=file-names missing when learning about target-specific information from rustc
command was: `rustc - --crate-name ___ --print=file-names -o my-file.dll --target x86_64-pc-windows-gnu --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=split-debuginfo --print=crate-name --print=cfg`

--- stdout
my-file.exe
lib___.rlib
___.dll
___.dll
lib___.a
___.dll
/home/user/.rustup/toolchains/nightly-2023-10-02-x86_64-unknown-linux-gnu
off
___
debug_assertions
overflow_checks
panic="unwind"
proc_macro
relocation_model="pic"
target_abi=""
target_arch="x86_64"
target_endian="little"
target_env="gnu"
target_family="windows"
target_feature="fxsr"
target_feature="sse"
target_feature="sse2"
target_has_atomic
target_has_atomic="16"
target_has_atomic="32"
target_has_atomic="64"
target_has_atomic="8"
target_has_atomic="ptr"
target_has_atomic_equal_alignment="16"
target_has_atomic_equal_alignment="32"
target_has_atomic_equal_alignment="64"
target_has_atomic_equal_alignment="8"
target_has_atomic_equal_alignment="ptr"
target_has_atomic_load_store
target_has_atomic_load_store="16"
target_has_atomic_load_store="32"
target_has_atomic_load_store="64"
target_has_atomic_load_store="8"
target_has_atomic_load_store="ptr"
target_os="windows"
target_pointer_width="64"
target_vendor="pc"
windows

I get the same error even if do not use cross compilation, compile for linux, or compile a bin target instead of lib. It seems like specifying "-o" flag when building with cargo always results in this error.

I also tried to change the name in Cargo.toml:

[lib]
name = "my-file"
crate-type = ["cdylib"]

But it failed with error:

error: failed to parse manifest at `Cargo.toml`

Caused by:
  library target names cannot contain hyphens: my-file

Changing project name to a name with hyphens produces a file with hyphens replaced with underscores.

What can I do to make cargo to custom output file name with hyphens to rustc?
Thanks!

if you look at the error message closely, you might get a clue why it's failing:

the problem with rustflags is that cargo invokes rustc multiple times for all kinds of work, not just to build the target artifact. in this case, the -o flag conflicts (and will mess up the output of) various --print flags, e.g. --print=file-names, --print=crate-name etc.

and I don't think there's any way to specify rustc flags only for the final building step in cargo.

I would suggest you either:

a) just use underscore for your library name, or:

b) use another tool to build the library other than cargo

  • at least for the final dll artifact (you can still use cargo to build the crate as rust library, then link dll outside of cargo)
  • or:

c) bypass the build.rustflags configuration and add the -o flags through other means, e.g. use a custom rustc-wrapper

1 Like