{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/1766","repository_url":"https://api.github.com/repos/rust-lang/rfcs","labels_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1766/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1766/comments","events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1766/events","html_url":"https://github.com/rust-lang/rfcs/issues/1766","id":181289701,"number":1766,"title":"[Cargo] let build scripts pass (arbitrary) linker arguments to `rustc`","user":{"login":"japaric","id":5018213,"avatar_url":"https://avatars.githubusercontent.com/u/5018213?v=3","gravatar_id":"","url":"https://api.github.com/users/japaric","html_url":"https://github.com/japaric","followers_url":"https://api.github.com/users/japaric/followers","following_url":"https://api.github.com/users/japaric/following{/other_user}","gists_url":"https://api.github.com/users/japaric/gists{/gist_id}","starred_url":"https://api.github.com/users/japaric/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/japaric/subscriptions","organizations_url":"https://api.github.com/users/japaric/orgs","repos_url":"https://api.github.com/users/japaric/repos","events_url":"https://api.github.com/users/japaric/events{/privacy}","received_events_url":"https://api.github.com/users/japaric/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rust-lang/rfcs/labels/T-tools","name":"T-tools","color":"bfd4f2"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2016-10-05T23:20:12Z","updated_at":"2016-10-07T00:56:29Z","closed_at":null,"body":"## Use cases\r\n\r\n### Bare metal embedded development\r\n\r\nLinking Rust programs for bare metal targets always (unless there some C in the mix) require passing a linker script to the linker. This linker script specifies the memory layout of the target device and, if omitted, the resulting binary will not work on the target device (the device will not boot or crash during the boot process).\r\n\r\nThe current way to pass these flags to the linker (using rustc as a proxy) is via the `build.rustflags` or `target.$triple.rustflags` key in .cargo/config:\r\n\r\n``` toml\r\n# .cargo/config\r\n[target.thumbv7em-none-eabihf]\r\nrustflags = [\r\n  \"-C\", \"link-arg=-nostartfiles\",\r\n  \"-C\", \"link-arg=-Tlayout.ld\",\r\n]\r\n```\r\n\r\nThis is troublesome because:\r\n\r\n- A library can't pass a `.cargo/config` to its dependent crates. Every user of the library will have to manually copy the library `.cargo/config` in their binary project.\r\n  \r\n### Other use cases\r\n\r\n*There are probably other use cases that I don't know about*\r\n\r\n## Straw man proposal\r\n\r\nCargo will learn about a new \"build script key\": `rustc-link-arg`. Cargo will collect all the values under that key and pass those to all its `rustc` invocations via the `-C link-arg` flag. For example, this build script output:\r\n\r\n```\r\ncargo:rustc-link-arg=-Tlayout.ld\r\ncargo:rustc-link-arg=-nostartfiles\r\n```\r\n\r\nMakes Cargo pass the `-C link-arg=-Tlayout.ld -C link-arg=-nostartfiles` to all its `rustc` invocations.\r\n\r\nAs with other `cargo:$key`s, Cargo will collect these values from all the dependencies.\r\n\r\n## Potential problems\r\n\r\n- Reduces composability of crates. For instance, what happens if two crates want to inject their own linker scripts? iirc, @nagisa mentioned that this form of \"non-composability\" is already present today in some other feature hmm ... was it symbol names (`#[export_name]`, `#[no_mangle]`)?\r\n\r\n- Linker arguments are ... linker dependent. So if a crate hard codes some linker arguments for a specific linker then that crate can't be used with any other linker. This doesn't seem like a problem for ELF files because `rustc` only supports `gcc`-style linkers. And if a crate needs to support two or more targets that use different linkers then the build.rs can simply pick different linker arguments based on the value of the `$TARGET` env variable.\r\n  \r\n- Linker arguments are order sensitive. Depending on A and B might not be the same as depending on B and A because one combination will generate linker arguments in a different order than the other. We can't do much in this regard other than encourage users to only use order independent flags (the flags needed in the use case presented above *are* order independent). FWIW, today, build scripts can pass `-l`-style arguments to the linker and those *are* order sensitive.\r\n\r\ncc @nagisa @alexcrichton \r\n@jamesmunns and @cbiffle may be interested as well\r\n"},"comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments/252128359","html_url":"https://github.com/rust-lang/rfcs/issues/1766#issuecomment-252128359","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1766","id":252128359,"user":{"login":"japaric","id":5018213,"avatar_url":"https://avatars.githubusercontent.com/u/5018213?v=3","gravatar_id":"","url":"https://api.github.com/users/japaric","html_url":"https://github.com/japaric","followers_url":"https://api.github.com/users/japaric/followers","following_url":"https://api.github.com/users/japaric/following{/other_user}","gists_url":"https://api.github.com/users/japaric/gists{/gist_id}","starred_url":"https://api.github.com/users/japaric/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/japaric/subscriptions","organizations_url":"https://api.github.com/users/japaric/orgs","repos_url":"https://api.github.com/users/japaric/repos","events_url":"https://api.github.com/users/japaric/events{/privacy}","received_events_url":"https://api.github.com/users/japaric/received_events","type":"User","site_admin":false},"created_at":"2016-10-07T00:56:29Z","updated_at":"2016-10-07T00:56:29Z","body":"> I also personally feel that many linker arguments are best expressed via this style of crate attribute where possible.\r\n\r\nOK. so **I** can compromise with a more constrained form of injection of linker arguments. Allowing crates and/or build script to inject linker arguments of the form `-T$linkerScript` would solve half (\\*) of my use case (Pure Rust bare metal programs) problem. But people using Rust within C embedded frameworks seem to require a different level of custom linker flags. For example, this is what the `teensy3-rs` crate is using at the moment:\r\n\r\n``` js\r\n{\r\n    // ..\r\n    \"pre-link-args\": [\r\n        \"-mcpu=cortex-m4\",\r\n        \"-mthumb\",\r\n        \"-Tteensy3-sys/teensy3-core/mk20dx256.ld\",\r\n        \"-Os\",\r\n        \"-Wl,--gc-sections,--defsym=__rtc_localtime=0\",\r\n        \"--specs=nano.specs\"\r\n    ],\r\n    \"post-link-args\": [\r\n        \"-lm\", \"-Wl,--start-group\", \"-lnosys\", \"-lc\", \"-lgcc\", \"-Wl,--end-group\"\r\n    ]\r\n    // ..\r\n}\r\n```\r\n\r\n(Although, I think some of those flags, like `-mcpu`, `-mthumb`, etc., are not really needed)\r\n\r\nSo, there's that to consider.\r\n\r\n(\\*) The other half of my problem is that I want to pass `-nostartfiles` to the linker because I don't use newlib startup objects (I've implemented crt0 in Rust) but creating a crate attribute just for that flag seems overkill. And there's also the fact that `lld` doesn't implicitly link startup object so the `-nostartfiles` flag doesn't exist over there.\r\n"}}
{"actor":{"display_login":"japaric"}}