As far as I know, the only way to name the output of a bin target is through the name attribute of a bin section.
This, however, sets both the crate name and the output name.
It seems too restricting that the output name of an executable should be a valid crate name.
For example, it cannot contain spaces. Cargo also warns if it's uppercase, because crate names are lowercase by convention.
Rustc with the -o FILENAME option allows to set any arbitrary filename for the output.
If there is already a way to do this with cargo, it should be better documented, as I couldn't find it.
I think this can be solved with cargo rustc (a relatively new subcommand), so I'm going to classify this as a docs bug.
How does cargo rustc solve this problem?
What I'm thinking of is the ability to specify the output name of the executable in Cargo.toml, so everyone who compiles it gets that executable name.
Yes cargo rustc would not allow you to encode the value in Cargo.toml, cargo does not currently allow that level of configuration.
I would like to express interest in this feature as well.
yes, +1 for this feature
One whole year and still nothing...
+1 for this feature.
+1 for this feature
Yes, please :)
@brettcannon binary can have a name different from the name of he package, you can see it in Cargo toml in a [[bin]] section with the name key
@matklad yep, and I deleted my comment as it was incorrect; sorry about the noise; misunderstanding on my part when looking for a solution for my problem. (And feel free to hide this comment.)
+1.
I wouldn't want to change my pretty
[[bin]]
name = "server"
path = "src/server/main.rs"
to
[[bin]]
name = "SoundAnalyzerServer.exe"
path = "src/server/main.rs"
+1 for this too
This should in theory be a pretty easy issue to knock out if anyone's interested in implementing it! I'll try to leave some instructions here and if anyone has any questions please feel free to just let me know!
I think a basic design for this will probably look like a new key in the [[bin]] section:
[[bin]]
name = "some-valid-crate-name"
filestem = "invalid.crate.name but valid-ish file $name"
Basically the filestem key (or something similarly named) would control the file that rustc actually literally emits, but is probably orthogonal from the crate name. As mentioned in the OP we'd implement this with the -o flag passed to rustc.
Some things to note for the implementation here:
require would happen wherever the internal Target is configured if the TOML key is Some-o flag would go somewhere around here where unit.target is the Target structure for Cargo, and cx.files().out_dir(unit) is the folder where the output file should go. [[bin]] and [[example]] targets to start off. Configuring the file stem of a [lib] target should likely be an errorWe'll probably want to only allow this on
[[bin]]and[[example]]targets to start off. Configuring the file stem of a[lib]target should likely be an error
I need this feature for a [lib]. My use case: I write plugins for other software in Rust, which are technically shared libraries (crate-type = ["dylib"]: .so files, as I'm workig on Linux), but should be named something.plugin instead of libsomething.so.
Hello @alexcrichton. I want to make certain I understand what you have in mind. Your suggestion, filestem, would not change the target's extension. Which means @m-ou-se would not be helped. Correct?
I need this feature for a
[lib]. My use case: I write plugins for other software in Rust, which are technically shared libraries (crate-type = ["dylib"]:.sofiles, as I'm workig on Linux), but should be namedsomething.plugininstead oflibsomething.so.
One could argue that these plugins should not be [lib]s, but [[bin]]s instead, as there's no need to restrict them to one per package. Just like normal binaries, it'd be fine if one package produces multiple different plugins (possibly all using the same [lib] crate of the package). Even though they are technically 'libraries', they will not be used as libraries by other Rust crates. Maybe [[bin]] just needs to allow crate-type = "dylib" or something like that?
Note that I was also just spitballing, we could also switch it to using filename = "..." which include the extension to cover @m-ou-se's use case as well
I would also like to +1 this with the possibility of allowing feature based filenames. So something like cargo build --feature foo would produce appname-foo.exe, based on a defined pattern in cargo.toml.
I spent some time working on @alexcrichton's suggestions and implemented most of the data plumbing, but I ran into some issues. Basically, the -o flag doesn't combine very well with rest of the arguments supplied to rustc. For example, if the output directory doesn't exist, --out-dir will create it, but passing the output directory as part of -o panics with an internal compiler error. I'm not sure if this is a bug with rustc and should be fixed there, or if we should work around it in cargo by creating the directory first (however this doesn't seem ideal).
Nowadays it's probably best to use the --emit flag, so I think instead of -o you can use:
rustc --emit link=path/to/output foo.rs
I think that'll work better in conjunction with all the other outputs we're getting from rustc right now.
@crumblingstatue
Maybe it can work, but not under test.
RUSTFLAGS="-C link-arg=-o -C link-arg=libabc.so" cargo build
# or specify the path
RUSTFLAGS="-C link-arg=-o -C link-arg=<your_pc_path>/libabc.so" cargo build
# or
RUSTFLAGS="-C link-arg=-o -C link-arg=libabc.so" cargo build —target=aarch64-linux-android
In additional, it also works on android gradle script:
build.gradle
// …..
// Build with cargo
tasks.create(name: "cargo-build-${arch}-${buildType}", type: Exec, description: "Building core for ${arch}", dependsOn: "cargo-output-dir-${arch}-${buildType}") {
doFirst { println("\n============================== Start Compile Native Lib ==============================\n") }
workingDir rustBasePath
environment("RUSTFLAGS", "-C link-arg=-o -C link-arg=${project.ext.cargo_target_directory}/${target}/${buildType}/libabc.so")
if (buildType.equalsIgnoreCase("release")) {
commandLine 'cargo', 'build', "--color=always", "--target=${target}", '--release'
} else {
commandLine 'cargo', 'build', "--color=always", "--target=${target}"
}
doLast { println("\n============================== Finish Compile Native Lib ==============================\n") }
}
// …..
And you can just change libName to xyz for test.
@alexcrichton Maybe filestem (bikeshed: basename?) and filename could both be supported options. The former allows you to write an OS-neutral filename and let Cargo do the work of determining the OS-conventional extension, and the latter allows you to override the OS-conventional extension.
Sounds like a great idea to me!
@matklad I noticed in #5203 you explained that --out-dir only allows specifying a directory because a single target may produce multiple artifacts. Can you explain how that can happen? Does that complicate the goal of this issue, if "the output name" may not be a unique thing?
@dherman the most common case for that is that debuginfo on mac and windows is in a separate file. So you get foo and foo.dSYM. IIRC, there's split-dwarf for linux as well, at least in theory: https://github.com/rust-lang/rust/issues/34651
I also have vague recollections that emscripting used to spit out .wasm and .js files together.
I don't have exact details about how that works? Ie, how rustc's -o flag interracts with multi-file outputs.
This makes me wonder if letting users override the full filename might be a bad idea, since there may not be a single file. It might be that @alexcrichton's idea of filestem is as far as the extensibility should go, so the target backend can determine the full set of files it needs to create, and what extensions they need.
(For my use case, it's got me leaning towards doing the final copying for myself, and just wrapping cargo build with --message-format=json to find out where the generated DLL is so I can copy into the final destination.)
I personally feel that both make sense. I think that if you asked for a specific filename on Emscripten and rustc doesn't support that then it should error, but naming a shared library on Linux something arbitrary I don't think should be blocked because Windows has PDB files that need to be named something (for example). Basically I still fill that both are probably warranted.
Most helpful comment
I need this feature for a
[lib]. My use case: I write plugins for other software in Rust, which are technically shared libraries (crate-type = ["dylib"]:.sofiles, as I'm workig on Linux), but should be namedsomething.plugininstead oflibsomething.so.