Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Cargo #10

Open
dbrgn opened this issue Jan 27, 2016 · 38 comments
Open

Add support for Cargo #10

dbrgn opened this issue Jan 27, 2016 · 38 comments

Comments

@dbrgn
Copy link

dbrgn commented Jan 27, 2016

Cargo is the Rust package manager. It handles metadata, compilation and dependencies.

If we want to properly integrate with the Rust library ecosystem, we should support Cargo.

This would replace #7 and #8.

@tjpeden
Copy link

tjpeden commented Jan 28, 2016

I actually took a stab at this the other day. I am really close but ran into an issue. I am happy to dig into it more tonight and this weekend.

@tjpeden
Copy link

tjpeden commented Jan 28, 2016

Here's my progress so far: tjpeden@38529b1

There are some formatting changes in application.rs that aren't really important, but what is important is that I changed the delay parameters down to 100ms but my photon is still blinking as if it were 500ms (from when I flashed the original code). The DFU shows successful in the output of make PLATFORM=photon all program-dfu in main/ So, that is what I will figure out next.

Let me know if you want/need me to change anything I've done. I'm compiling a few other libraries from rust but I'm not 100% sure if we need/want them?

@tjpeden
Copy link

tjpeden commented Jan 28, 2016

I'm now sure how to tell Cargo to let the makefiles dictate the target dirs. Thoughts?

@japaric
Copy link

japaric commented Jan 28, 2016

@tjpeden Did you forget to commit the Cargo.toml file? AFAIK, you can't call cargo without a Cargo.toml file and a project directory. See http://doc.crates.io/guide.html

I'm compiling a few other libraries from rust but I'm not 100% sure if we need/want them?

We only need the core crate in this case.

I'm now sure how to tell Cargo to let the makefiles dictate the target dirs. Thoughts?

If you mean telling cargo to use a custom target directory, then you can use a configuration file with the following key:

# .cargo/config
[build]
target-dir = "custom/target/directory"

Then cargo will output the binary/docs to "custom/target/directory" instead of the default "target" directory.

@japaric
Copy link

japaric commented Jan 28, 2016

Other thoughts:

With cargo support we wouldn't need the build_core.sh script. There is cargo crate: rust-libcore that builds the core crate when used as a dependency.

Ideally, I'd like to only use cargo to build particle applications. I'm envisioning something like this:

$ cargo new --bin app
$ cd app

# depend on particle libraries
$ vim Cargo.toml
$ cat Cargo.toml
[package]
name = "app"
version = "0.1.0"
authors = ["me"]

[dependencies]
particle = "0.1.0"

# write app
$ vim src/main.rs

# builds the core crate, particle's C dependencies, and the app
$ cargo build --target=photon

# This installs the cargo-flash and cargo-debug binaries used below
$ cargo install particle-tools

# Custom cargo subcommand that flashes the application
# This subcommand can just shell out to `particle flash ...`
$ cargo flash

# Or, start a remote gdb session
$ cargo debug

I'm sure this is feasible because I have done the cargo build part here. Check the "apps" and the travis output, specially the *-size and *-objdump calls. But, I'm not sure how to expand this to produce a binary or ELF file that's usable by particle's bootloader because I'm not familiar with bootloaders in general as I always flash programs directly at the start of the flash memory (0x08000000).

Can anyone point me to information about particle's bootloader or bootloaders in general. Does the bootloader expect an ELF file that starts at some specific address, other than 0x08000000? Does the particle's bootloader expect the ELF file to contain some specific symbols?

@dbrgn
Copy link
Author

dbrgn commented Jan 28, 2016

@japaric woah, that would be pretty awesome :)

@tjpeden
Copy link

tjpeden commented Jan 29, 2016

@japaric, you're right, I did. Fixed. Also just committed my attempt at using .cargo/config. The problem is I think that the path is based on a couple make variables (if I understand the make spaghetti correctly lol). Either way, it doesn't place the output files where make expects them, even if I specify the directory that the .o is normally placed, cargo will still use it's own directory structure from there. Not to mention I currently have it outputting a .a file.

All of that aside, everything I've seen online has cautioned against using that crate, but maybe that's wrong? I like the idea of using only cargo for building and programming the rust code.

What crate should we use to test being able to use extern crate to make sure it works?

Unfortunately, my fiance won't let me work on it anymore today. lol

@tjpeden
Copy link

tjpeden commented Jan 29, 2016

@japaric, I really like that project you linked. I think that would be an awesome way to model the Particle Rust support

@towynlin
Copy link

@japaric This is looking great. Thank you!

Photon firmware consists of several dynamically linked modules. If you run make in the modules folder 3 of the modules will be built if you want to see some examples.

  • 0x08000000 Bootloader
  • 0x08020000 System part 1
  • 0x08060000 System part 2
  • 0x080a0000 User application

The addresses and number of modules may be different on different platforms. I often reference this file in the CLI: https://github.com/spark/particle-cli/blob/master/lib/deviceSpecs/specifications.js

Additionally, there are several pieces of data prepended and appended to our modules using linker scripts. Here's a tool for reading them: https://github.com/spark/binary-version-reader

Hope that helps!

@japaric
Copy link

japaric commented Jan 29, 2016

@tjpeden

@japaric, you're right, I did. Fixed. Also just committed my attempt at using .cargo/config. The problem is I think that the path is based on a couple make variables (if I understand the make spaghetti correctly lol). Either way, it doesn't place the output files where make expects them, even if I specify the directory that the .o is normally placed, cargo will still use it's own directory structure from there. Not to mention I currently have it outputting a .a file.

I guess you can let cargo output its files in the default target directory, and add some cp commands to the Makefile to move the files when the rest of the build system expects them.

About the *.a file, you should be able to use something like cargo rustc -- --emit=obj to make cargo output *.o files.

All of that aside, everything I've seen online has cautioned against using that crate, but maybe that's wrong? I like the idea of using only cargo for building and programming the rust code.

You mean the rust-libcore crate? What's the argument against it? The zinc project also uses that crate to build the core crate.

What crate should we use to test being able to use extern crate to make sure it works?

You can test with the spin crate, that crate works with just the core crate.


@towynlin That's pretty helpful. I took a quick look and I'm starting to understand how the pieces fall together. Looks like the setup and loop symbols are mandatory, right? During the weekend, I'll take a closer look to the linker scripts and see if I can hack my copper cargo project to generate an ELF file that matches the layout of the user-part example you pointed out. I don't have hardware yet so that's as far I can go right now.

@tjpeden
Copy link

tjpeden commented Jan 29, 2016

Added the spin crate and got the following error running make PLATFORM=photon all program-dfu from main/:

...
cargo rustc --target thumbv7m-none-eabi -- -O -Z no-landing-pads -g -L ../build/arm/rust
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling spin v0.3.5
/home/tjp/.multirust/toolchains/nightly/cargo/registry/src/github.com-88ac128001ac3a9a/spin-0.3.5/src/lib.rs:1:1: 1:1 error: can't find crate for `core` [E0463]

This is how I have the Cargo.toml configured:

[package]
name = "application"
version = "0.1.0"
authors = ["TJ Peden <tj@tjcoding.com>"]

[lib]
crate-type = ["staticlib"]

[dependencies]
rust-libcore = "0.0.3"
spin = "0.3.5"

I'm not sure how to fix that.

@japaric
Copy link

japaric commented Jan 29, 2016

@tjpeden Ah right, spin can't be cross compiled like this because it (spin) would need to depend on rust-libcore but it doesn't. One "solution" would be install the libcore.rlib that cargo build --target= generated in your rust installation directory. But I don't like this solution because it pollutes your Rust install. Let me discuss this with other Rust devs to see if there's a cleaner solution.

@tjpeden
Copy link

tjpeden commented Jan 30, 2016

IRC?

@japaric
Copy link

japaric commented Jan 30, 2016

IRC?

Yeah, I asked one of the core devs that's working on Rust cross compilation story. Cargo doesn't support this use case out the box, but there's an RFC with a possible solution for this but requires adding new features to cargo.

I also received an idea on how to support this use case without needing new cargo features but hasn't been explored/implemented yet. The idea is that you create a "sysroot" (a directory tree) that contains the cross compiled core crate, and then configure cargo to use rustc --sysroot ... instead of just rustc, that way cargo looks for "standard" dependencies (like libcore) in the sysroot you created rather than in the rust installation directory. I'm going to explore this idea and report back my findings.

@tjpeden
Copy link

tjpeden commented Jan 30, 2016

Awesome! Thanks @japaric

@zsup
Copy link
Owner

zsup commented Feb 1, 2016

@japaric love your goal of a cargo build process, would love to see the build process work like that.

@japaric
Copy link

japaric commented Feb 1, 2016

I created a cargo sysroot subcommand that implements the solution I mentioned above. More details in the README. This subcommand depends on this cargo PR, which hasn't landed yet, so it's not currently usable with the latest cargo nightly.

@tjpeden You may want to test that ^. You'll need to compile cargo checked out at that PR though.

@tjpeden
Copy link

tjpeden commented Feb 2, 2016

I will indeed

@tjpeden
Copy link

tjpeden commented Feb 3, 2016

@japaric I am having trouble building Cargo on that branch. Is there something special one has to do other than the instructions in the readme?

@japaric
Copy link

japaric commented Feb 3, 2016

@japaric I am having trouble building Cargo on that branch. Is there something special one has to do other than the instructions in the readme?

Cargo is a Cargo project, so I just did cd cargo && cargo build. The new cargo binary will be in target/debug/cargo. I haven't use the make instructions in the readme in a long time.

@tjpeden
Copy link

tjpeden commented Feb 3, 2016

That works a lot better, thanks!

@tjpeden
Copy link

tjpeden commented Feb 3, 2016

This is what I got:

$ ~/code/cargo/target/debug/cargo sysroot --target ../build/arm/rust/thumbv7m-none-eabi.json target/sysroot
INFO: source up to date
INFO: symlinking host crates
INFO: building the core crate
An unknown error occurred

To learn more, run the command again with --verbose.
thread '<main>' panicked at 'assertion failed: try!(Command:: new ( "cargo" ) . args ( & [ "build" , "--target" ] ) . arg (
     ctx . target ) . arg ( if ctx . release { "--release" } else { "--lib" }
     ) . current_dir ( src_dir ) . env ( "CARGO_TARGET_DIR" , temp_dir ) .
     status (  )).success()', /home/tjp/.cargo/git/checkouts/cargo-sysroot-c5462c8bc31a2590/master/src/main.rs:204
An unknown error occurred

To learn more, run the command again with --verbose.

@japaric
Copy link

japaric commented Feb 3, 2016

@tjpeden Ah, yes. cargo-sysroot doesn't support taking a file path as target right now (I'll fix that later). For now, you'll need to have the json file in the same directory where cargo sysroot is called, and you'll have to call cargo sysroot --target thumbv7m-none-eabi (without the json extension).

@tjpeden
Copy link

tjpeden commented Feb 3, 2016

I'm getting the same thing :-/

@tjpeden
Copy link

tjpeden commented Feb 3, 2016

Could you add --verbose and pass it along?

@japaric
Copy link

japaric commented Feb 3, 2016

Could you add --verbose and pass it along?

done

@tjpeden
Copy link

tjpeden commented Feb 4, 2016

Okay, I think I have this setup wrong.

$ ~/code/cargo/target/debug/cargo sysroot --target thumb7m-none-eabi target/sysroot --verbose
INFO: source up to date
INFO: symlinking host crates
INFO: building the core crate
Process didn't exit successfully: `rustc - --crate-name _ --crate-type dylib --crate-type staticlib --crate-type bin --print=file-names --target thumb7m-none-eabi` (exit code: 101)
--- stderr
error: Error loading target specification: Could not find specification for target "thumb7m-none-eabi"

thread '<main>' panicked at 'assertion failed: try!(cmd . current_dir ( src_dir ) . env ( "CARGO_TARGET_DIR" , temp_dir ) .
    status (  )).success()', .cargo/git/checkouts/cargo-sysroot-c5462c8bc31a2590/master/src/main.rs:238
An unknown error occurred

To learn more, run the command again with --verbose.
$ ll
total 48K
drwxrwxr-x 11 tjp tjp 4.0K Jan 19 23:45 applications/
-rw-rw-r--  1 tjp tjp 1.6K Jan 19 23:46 build.mk
-rw-r--r--  1 tjp tjp 3.6K Feb  3 23:14 Cargo.lock
-rw-rw-r--  1 tjp tjp  163 Feb  4 08:14 Cargo.toml
-rw-rw-r--  1 tjp tjp  839 Jan 19 23:29 import.mk
drwxrwxr-x  2 tjp tjp 4.0K Jan 19 23:45 inc/
drwxrwxr-x  7 tjp tjp 4.0K Jan 19 23:29 libraries/
-rw-rw-r--  1 tjp tjp  701 Jan 19 23:45 makefile
drwxrwxr-x  3 tjp tjp 4.0K Jan 29 17:43 src/
drwxrwxr-x  3 tjp tjp 4.0K Feb  3 10:31 target/
drwxrwxr-x  8 tjp tjp 4.0K Jan 19 23:45 tests/
-rw-r--r--  1 tjp tjp  381 Feb  3 12:02 thumbv7m-none-eabi.json

Do I have thumb7m-none-eabi.json in the right place? Also, thanks for adding that verbose flag, worked like a charm!

@japaric
Copy link

japaric commented Feb 4, 2016

@tjpeden

There's a typo in this command

$ ~/code/cargo/target/debug/cargo sysroot --target thumb7m-none-eabi target/sysroot --verbose

The target is missing a "v": thumbv7m-none-eabi, because that's the name of the spec file: thumbv7m-none-eabi.json.

Once you fix the typo you should see this line in the log:

INFO: copy target specification file

This could have been detected and the tool could have informed you about this, but I haven't implemented nice error reporting (yet).

P.S. If you are using zinc's target specification files then delete the "data-layout" field from the file or you'll hit this issue.

@tjpeden
Copy link

tjpeden commented Feb 4, 2016

I apologize, I should have caught that. I'm using the target file from build/arm/rust so I don't think it's an issue?

However, the fs::copy line failed:

~/code/cargo/target/debug/cargo sysroot --target thumbv7m-none-eabi target/sysroot --verbose
INFO: source up to date
INFO: symlinking host crates
INFO: building the core crate
       Fresh core v0.0.0 (<redacted>)
INFO: copy the core crate to the sysroot
thread '<main>' panicked at 'fs::copy(src, dst)', .cargo/git/checkouts/cargo-sysroot-c5462c8bc31a2590/master/src/main.rs:257
An unknown error occurred

To learn more, run the command again with --verbose.

It's not an access issue (I'm on Ubuntu) so I'm not sure what would cause it to fail. Thoughts?

@japaric
Copy link

japaric commented Feb 4, 2016

I'm using the target file from build/arm/rust so I don't think it's an issue?

If you get a LLVM assertion while building the core crate, remove the "data-layout" field from the json file should fix. It's problem that appeared in recent nightlies.

It's not an access issue (I'm on Ubuntu) so I'm not sure what would cause it to fail. Thoughts?

No idea with just that information. But I pushed a debug branch to cargo-sysroot, it'll print the src and dst arguments of the failing fs::copy and will also preserve the temporary directory so you can inspect it. You can install that branch with cargo install --git https://github.com/japaric/cargo-sysroot/ --branch debug.

Also, could we take this discussion somewhere else? Either the cargo-sysroot bug tracker or to IRC (I'm japaric on freenode, I'm on #rust, #cargo, #particle, etc)

@dbrgn
Copy link
Author

dbrgn commented Mar 11, 2016

What's the status here? I'm waiting for advances in Cargo support in order to continue working on library features :)

@dbrgn
Copy link
Author

dbrgn commented Mar 24, 2016

Any news, @tjpeden?

@japaric
Copy link

japaric commented Apr 7, 2016

I received my Photon this past Monday and got a LED blinking using the particle-cli tool. So, I'm going to look into this soon. I'm going to try two approaches: (a) have the Makefile build system use Cargo and (b) have Cargo call the Makefile system. I'll report back as soon as I get any of them working.

P.S. I was hoping to use the particle-cli tool as a reference on how the binaries are assembled but the particle compile command uses a web service to compile the program. Is the backend code published somewhere?

@bvosk
Copy link

bvosk commented Apr 7, 2016

@japaric Instructions on how to compile the firmware locally can be found here. All the firmware and a ton of information can be found in that repo. There's also this write up which contains more details about the build setup.

Thanks for helping out, I'm looking forward to using Cargo with the Photon!

@japaric
Copy link

japaric commented Apr 10, 2016

I took the route (b) I mentioned before and I got a working Cargo project that builds photon apps.
Check https://github.com/japaric/photon for details. We can use it as a starting point to prototype
rustic bindings around the HAL. I'll look into that next; getting bindgen to emit low level
bindings to the HAL would be a great start. I'd also like to build a cargo subcommand that flashes
the ELF generated by Cargo into the photon because it requires computing a CRC.

@zsup
Copy link
Owner

zsup commented Apr 11, 2016

@japaric that's awesome, could you contribute that as a PR?

@zsup
Copy link
Owner

zsup commented Apr 11, 2016

actually, now that I'm looking at your repo, I suppose that doesn't make a ton of sense, since it's a rebuild and not a fork

@dbrgn
Copy link
Author

dbrgn commented Apr 11, 2016

Awesome! This week I'm quite busy but I'll take a closer look next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants