4

Ability to specify the output name for a bin target different from the crate nam...

 2 years ago
source link: https://github.com/rust-lang/cargo/issues/1706
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Copy link

crumblingstatue commented on Jun 11, 2015

edited by rustbot

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.

Copy link

Lakier15 commented on Feb 1, 2017

edited

+1 for this feature

Yes, please :)

Copy link

Member

matklad commented on May 6, 2018

@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.)

Copy link

tzaeru commented on May 16, 2018

edited

I wouldn't want to change my pretty

[[bin]]
name = "server"
path = "src/server/main.rs"
[[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:

  • Deserialization happens via this struct, which would need to grow a new optional field for this key.
  • Cargo's internal data structure is here. The TOML configuration would need to make its way to this internal data structure.
  • This will want to start off as an unstable feature. There's some documentation about adding features here to Cargo, and the call to require would happen wherever the internal Target is configured if the TOML key is Some
  • The actual -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.
  • We'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
  • After that, a few simple tests for this new feature should suffice!

Copy link

Member

m-ou-se commented on Nov 29, 2018

We'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?

Copy link

Member

m-ou-se commented on Oct 7, 2019

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.

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.

Copy link

aliu commented on Nov 15, 2019

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.

build.gradle#L45

@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?

Copy link

Member

matklad commented on Dec 18, 2020

edited

@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: rust-lang/rust#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.

Copy link

Wafelack commented on Feb 2

Sounds like a good idea, it would be very convenient when the crate name is quite long.

Copy link

dcow commented on Feb 2

Would love to see the ability to specify the name of the inferred main.rs binary target. Just a note, you can:

mkdir src/bin
mv src/main.rs src/bin/foo.rs

and the main bin will not longer be auto-discovered and cargo run will run the sole foo bin target without any other config. Would be nice to be able to do something like:

[bin.main]
name = "foo"

for aesthetics.

Copy link

dragonmaus commented on Feb 2

While I agree that it would be nice for aesthetics and/or convenience, personally I want this feature so that I can produce executables that have names not allowed by the current scheme (e.g. en% and de%).

Copy link

dcow commented on Feb 2

edited

Just tested and you can also:

[[bin]]
name = "foo"
path = "src/main.rs"

The name applies to the auto-discovered main target (no duplicate binary target is created).

Copy link

kotx commented on Feb 14

edited

Just tested and you can also:

[[bin]]
name = "foo"
path = "src/main.rs"

The name applies to the auto-discovered main target (no duplicate binary target is created).

Unfortunately if the name isn't in snake case (or kebab case) you'll get a warning (crate `X` should have a snake case name), but I want to name my executable file in pascal case. Hoping for a workaround other than disabling the warning or changing the name.

Copy link

SoniEx2 commented on Feb 21

We used to have application binaries called foo.cli and foo.gui and unfortunately we can't switch to rust because this issue breaks backwards compatibility. All in all it's kinda silly that applications have a crate name tho, it's not like that's ever gonna be exposed anywhere, and it's not like there are macros to get the crate name at compile-time or anything.

Why not just set the crate name the same for all applications, and/or remove the concept of crate name from rust applications?

Copy link

Wafelack commented on Feb 23

edited

You can actually get the crate name at compile time. And crate names for application aren't « silly » as you say, they are necessary for crates.io (for both installation and searching.).

Copy link

SirWindfield commented on Mar 7

edited

Unfortunately if the name isn't in snake case you'll get a warning (crate `X` should have a snake case name), but I want to name my executable file in pascal case. Hoping for a workaround other than disabling the warning or changing the name.

This isn't true (entirely), I have the following and I do not get any errors when calling cargo run:

[package]
name = "krate_name"

[[bin]]
name = "krate-name"
path = "src/bin/krate_name.rs"

It seems to also support kebab-case.

Copy link

kotx commented on Mar 7

Unfortunately if the name isn't in snake case you'll get a warning (crate `X` should have a snake case name), but I want to name my executable file in pascal case. Hoping for a workaround other than disabling the warning or changing the name.

This isn't true (entirely), I have the following and I do not get any errors when calling cargo run:

[package]
name = "krate_name"

[[bin]]
name = "krate-name"
path = "src/bin/krate_name.rs"

It seems to also support kebab-case.

Yeah I forgot about that, edited. The warning explicitly says snake case, so I guess that's an oversight. Snake case is preferred over kebab case IIRC.

Copy link

whereistejas commented 5 days ago

edited

Hi everyone,
If possible I would like to take up this issue. Based on the discussion above, we can summarise the requirements as follows:

  1. output name of the binary should not have the restrictions of a crate name.
  2. add a second key in [[bin]] section along with name called filename.
    1. name will allow us to set the name of the crate.
    2. filename will allow us to set the name of the binary.
  3. only allow this config options in [[bin]] and [[example]].

@alexcrichton @ehuss please correct me if I'm wrong about the above requirements.

@rustbot claim


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK