rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.2k stars 1.6k forks source link

Any way to temporarily change default target? #5904

Closed ndarilek closed 3 years ago

ndarilek commented 4 years ago

I debated posting this as a general support request in the forum, but I couldn't find an answer in the manual, and it seems common enough that if there is a solution then maybe it might be documented a bit more clearly. I have a crate with a native and wasm target. It'd be nice if I could run a "set default target" command and either enter wasm32-unknown-unknown, or leave blank for the default target. Then I could have autocompletion for whatever target I'm currently working on.

Right now, I'm manually running cargo check --target wasm32-unknown-unknown from a terminal, but this of course doesn't give me completion for target-specific APIs. I can probably place a config file in my workspace and re-open the folder, but this seems more error-prone. Likewise, it may be possible to find and edit the various command lines, but that's a lot of work to go through to temporarily work on a non-standard target.

Have I missed an approach? Thanks for all the hard work on this extension--it really is amazing!

lnicola commented 4 years ago

There's a rust-analyzer.cargo.target, but no corresponding rust-analyzer.checkOnSave.target. We might want to implement that.

ndarilek commented 4 years ago

Would it make sense to also offer a command to change both, once the check setting is implemented of course, maybe with autocompletion of installed targets? Can't imagine I'm the only one needing to temporarily switch targets to do some development work, and a command would make that more discoverable and approachable.

Thanks a bunch.

lnicola commented 4 years ago

It would be nice, but we don't have this for the related settings like rust-analyzer.cargo.features. But we could at least default rust-analyzer.checkOnSave.target to rust-analyzer.cargo.target.

I'm not sure if this is possible in LSP, if implemented it might be specific to the Code extension.

ndarilek commented 4 years ago

Fair enough. Would that keep up with changes to cargo.target, or would I have to change them both? I.e. is the default only set once?

I'm wondering if there'd ever be a scenario where someone wants to not check |rust-analyzer.cargo.target? I.e. where they're checking one target but defaulting another?|

I guess I'm a bit confused why another setting would be necessary. Can I just set rust-analyzer.cargo.target and have that be what gets checked? If so, that should work fine.
lnicola commented 4 years ago

Would that keep up with changes to cargo.target, or would I have to change them both?

You can set rust-analyzer.cargo.target and rust-analyzer.checkOnSave.target will default to the same value.

I guess I'm a bit confused why another setting would be necessary.

I don't have any strong opinions, it's just for symmetry with the other preferences; see https://github.com/rust-analyzer/rust-analyzer/pull/4704

crlf0710 commented 4 years ago

I hope rust-analyzer can respect .cargo/config target setting, if that is possible.

hrydgard commented 4 years ago

+1 for defaulting to (or having an option to) follow .cargo/config for target, that would solve some issues for us.

Nils-TUD commented 3 years ago

Is there a temporary workaround until .cargo/config or similar is used?

I've already tried to provide a rust-project.json:

{
    "crates": [
        {
            "display_name": "kernel",
            "root_module": "src/kernel/src/kernel.rs",
            "edition": "2018",
            "target": "riscv-unknown-hw-gnu",
            "deps": []
        }
    ]
}

But although this file is used by rust-analyzer, the target seems to be ignored (e.g., setting it to a non-existing target doesn't fail).

As far as I've understood it, it works in VSCode, so there has to be a way to get it working without it too, right? I'm for example using sublime text. Is there any way to specify the target?

flodiebold commented 3 years ago

I don't see any reason right now why .cargo/config wouldn't already have an effect -- we're just calling cargo check. Or do you mean also using the target from .cargo/config for analysis (i.e. rust-analyzer.cargo.target)? Maybe cargo metadata doesn't use that configuration, or we call it in a way that prevents that; that might be worth investigating. We probably don't want to parse .cargo/config ourselves though.

bjorn3 commented 3 years ago

Cargo reads .cargo/config based in the current directory, not the crate or workspace directory.

zimond commented 3 years ago

If I have two crates A and B in a workspace, A compiles to native and wasm32, B only compiles to wasm32. And A depends on B when compiled to wasm32. How could I tweak rust-analyzer to get correct targets for each crates? (say, I want analyzer to check for target wasm32 for B, and native for A)

Nils-TUD commented 3 years ago

Thanks a lot for this feature, this really helps with multi-target projects!

In case somebody else has custom target specifications: the trick to get it working is to specify the path to the JSON file via build.target in .cargo/config (instead of specifying the target triple) and set the env variable RUST_TARGET_PATH to the folder which contains the JSON file. It took me quite some time to figure that out :)

ndarilek commented 3 years ago

Sorry for the silly question, but I keep seeing occasional references to a JSON file when changing Rust targets is discussed. What file is this? Is it something more than VS Code user settings? All the docs I've read just mention .cargo/config, not another file.

And to understand further, is something more than setting a target in .cargo/config necessary? A recent project hard-coded the target in user settings I shipped with the code, but I'd rather avoid that if I can.

Thanks.

Nils-TUD commented 3 years ago

The JSON file describes the properties of a target like word size, endianess and the like. If you develop a "normal" application, this shouldn't be necessary, as Rust provides many builtin targets. But if you, for example, develop something for a non-supported target or build an OS kernel, you can write your own target spec via JSON.

As far as I have understood it, if you don't have your own target spec, but only build for a different target than your host (e.g., a supported embedded platform), you can set the target triple in the .cargo/config. If you build an application to run on your host, you don't need to do anything. However, this only sets the default target. When running cargo, you can overwrite it via command line argument.

jtmarmon commented 2 years ago

For others stumbling upon this trying to get a custom target to work in VSCode (in my case, avr-hal):

First, the basic .cargo/config.toml setup obviously didn't work

[build]
target = "avr-specs/avr-atmega328p.json"

Adding a RUST_TARGET_PATH as @Nils-TUD suggested didn't work for me for some reason:

# VSCode User settings.json
    "rust-analyzer.server.extraEnv": {
        "RUST_TARGET_PATH": "<absolute path to my project>/avr-specs",
    }

So I then added an explicit reference to the avr target triple which finally worked

# also in User settings.json
{
    "rust-analyzer.cargo.target": "avr-atmega328p",
}

(Also, as a complete aside, after all of the above the rust-analyzer extension works ish, but autocomplete is broken. turns out the #[arduino_hal::entry] macro is what breaks it so I've just been commenting it out while I dev)

tkkcc commented 1 year ago

Set target in .cargo/config.toml now works, but only on project files. After jumping to library code outside project, it's gone.

In neovim, rust-analyzer.cargo.target can be set based on workspace.

local rust_config = {checkOnSave = {enable = false}}
if vim.fn.getcwd() == "/home/bilabila/bin/eframe_template" then
  rust_config["cargo"] = {target = "wasm32-unknown-unknown"}
end
nvim_lsp.rust_analyzer.setup {
  capabilities = capabilities,
  on_attach = on_attach,
  flags = {debounce_text_changes = 150},
  settings = {["rust-analyzer"] = rust_config},
}