-
Notifications
You must be signed in to change notification settings - Fork 125
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
Build extra components specified in manifest metadata #114
Conversation
Because #[path = "..."] approach sets different file paths for the same module, this causes issues with the normal module structure.
Add dependency `envy` to deserialize struct from env variables. Refactor `common::InstallDir` using the strum crate. Add `build_driver::TOOLS_DIR`. Cargo fmt `build/pio.rs`. Split build configuration into separate modules and structs `BuildConfig`, `NativeConfig`.
This change allows the build configuration to be specified in the `package.metadata.esp-idf-sys` table of the root crate's manifest (Cargo.toml). If no root crate exists in the workspace the crate with the name equal to the `ESP_IDF_SYS_ROOT_CRATE` environment variable is used. All configuration specified via environment variables will override the corresponding options of the cargo metadata. If `cargo metadata` fails for some reason, this will only generate a warning in the build output and not cause the build to fail. Add build dependency `cargo_metadata`.
Makes it possible to specify extra components in the `package.metadata.esp-idf-sys.extra_components` array in the root crate's manifest as well as all direct dependencies. This change also instructs cmake to build all extra components, but without generating any bindings.
Because cmake already knows all the compiled components, it is just a matter of forwarding that information to the build script. This removes the need to recurse into every subfolder of the esp-idf's components folder.
There are two ways the bindings are generated. The first is when `bindings_module` is not set. In that case the header of the extra component will just be added to the normal esp-idf bindings generation. All additional bindings will also be in the root of `esp-idf-sys`. The second: when `bindings_module` is set. For every unique `bindings_module` bindgen will be invoked to generate the bindings, which will then be appended as a new module to the `bindings.rs` file. Note though that since this is a new bindgen invocation duplicate symbols of the normal esp-idf bindings may be generated.
Okay, this should be pretty close to the finish line now. The only thing missing is more documentation (i.e. README, maybe book) and an Generally, this PR does two things. First, refactor the configuration to use Second, it allows to specify extra esp-idf components (even multiple) in the [[package.metadata.esp-idf-sys.extra_components]]
# A single path or a list of paths to a component directory, or directory containing components.
#
# Each path can be absolute or relative. Relative paths will be relative to the
# folder containing the defining `Cargo.toml`.
component_dirs = ["dir1", "dirs2"] # or
component_dirs = "one_dir"
# The path to the C header to generate the bindings with. If this option is absent,
# **no** bindings will be generated.
#
# The path can be absolute or relative. A relative path will be relative to the
# folder containing the defining `Cargo.toml`.
#
# Optional
bindings_header = "bindings.h"
# If this option is present, the component bindings will be generated separately from
# the `esp-idf` bindings and put into their own module inside the `esp-idf-sys` crate.
# Otherwise, if absent, the component bindings will be added to the existing
# `esp-idf` bindings (which are available in the crate root).
#
# To put the bindings into its own module, a separate bindgen instance will generate
# the bindings. Note that this will result in duplicate `esp-idf` bindings if the
# same `esp-idf` headers that were already processed for the `esp-idf` bindings are
# included by the component(s).
#
# Optional
bindings_module = "name" Note, the two [package.metadata.esp-idf-sys]
extra_components = [
{ component_dirs = [ "dir1", "dirs2" ], bindings_header = "bindings.h", bindings_module = "name" }
] Reviews are welcome. |
Thanks for tackling this @N3xed! Attempting to try it out now, running into a few build errors though: error[E0432]: unresolved import `embuild::bindgen::BindgenExt`
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:11:5
|
11 | use embuild::bindgen::BindgenExt;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `BindgenExt` in `bindgen`
error[E0425]: cannot find function `default_bindings_file` in module `bindgen_utils`
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:126:40
|
126 | let bindings_file = bindgen_utils::default_bindings_file()?;
| ^^^^^^^^^^^^^^^^^^^^^ not found in `bindgen_utils`
error[E0425]: cannot find function `cargo_fmt_file` in module `bindgen_utils`
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:178:20
|
178 | bindgen_utils::cargo_fmt_file(&bindings_file);
| ^^^^^^^^^^^^^^ not found in `bindgen_utils`
error[E0425]: cannot find value `ENV_PATH_VAR` in module `embuild::build`
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:197:45
|
197 | cargo::set_metadata(embuild::build::ENV_PATH_VAR, env_path);
| ^^^^^^^^^^^^ not found in `embuild::build`
error[E0425]: cannot find value `ESP_IDF_PATH_VAR` in module `embuild::build`
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:202:25
|
202 | embuild::build::ESP_IDF_PATH_VAR,
| ^^^^^^^^^^^^^^^^ not found in `embuild::build`
error[E0599]: no method named `headers` found for struct `bindgen::Builder` in the current scope
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:147:10
|
147 | .headers(headers)?
| ^^^^^^^ help: there is an associated function with a similar name: `header`
error[E0599]: no method named `headers` found for struct `bindgen::Builder` in the current scope
--> /home/mabez/.cargo/git/checkouts/esp-idf-sys-d4c2e811b42d99d6/db3254a/build/build.rs:161:18
|
161 | .headers(headers.into_iter().inspect(|h| cargo::track_file(h)))?
| ^^^^^^^ help: there is an associated function with a similar name: `header`
Some errors have detailed explanations: E0425, E0432, E0599.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `esp-idf-sys` due to 7 previous errors
warning: build failed, waiting for other jobs to finish... |
@MabezDev I didn't want to make a new |
Thanks for the hint about embuild. |
Ugh ignore me, I missed an end quote on an include in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is working brilliantly, thanks for working on this! LGTM!
I got this warning when I played around with this branch:
I tried to add |
I've also seen that in the CI output, and it seems to me this is because of rust-lang/cargo#10801 (related rust-lang/cargo#10352). My assumption was that when running So, I'll remove these flags for now. |
cargo metadata resolves all dependencies even ones that are disabled (known as weak dependencies) which cargo build doesn't do (see issue rust-lang/cargo#10801). These unresolved dependencies require network access to load their package metadata. As the `--frozen` flag itself blocks network access (in addition to blocking changes to the Cargo.lock) too, we need to remove both the `--frozen` and `--offline` flags. Doing this allows cargo the change the `Cargo.lock` though, which is undesirable (as we're in the process of building the same dependencies that rely on the `Cargo.lock` in the first place).
8891de8
to
27eb477
Compare
Thanks for this! Here's the rundown for anyone who's interested: [[package.metadata.esp-idf-sys.extra_components]]
component_dirs = ["components"]
bindings_header = "src/bindings.h" Contents of #include "esp_littlefs.h" Here's the partition table used when flashing:
After building the project and generating the bindings, I simply mounted the partition and registered the littlefs filesystem. let mut fs_conf = esp_idf_sys::esp_vfs_littlefs_conf_t {
base_path: cstr!("/littlefs").as_ptr(),
partition_label: cstr!("littlefs").as_ptr(),
..Default::default()
};
fs_conf.set_format_if_mount_failed(true as u8);
fs_conf.set_dont_mount(false as u8);
unsafe {esp!(esp_idf_sys::esp_vfs_littlefs_register(&fs_conf))?};
let (mut fs_total_bytes, mut fs_used_bytes) = (0, 0);
unsafe {esp!(esp_idf_sys::esp_littlefs_info(fs_conf.partition_label, &mut fs_total_bytes, &mut fs_used_bytes))?};
info!("LittleFs Info: total bytes = {}, used bytes = {}.", fs_total_bytes, fs_used_bytes); Finally, I could use the standard library file operations to read from and write to the filesystem. {
let mut file = fs::OpenOptions::new().write(true).create(true).open("/littlefs/log")?;
file.write_all(b"Hello from the Rustland!\n")?;
}
{
let mut file = fs::OpenOptions::new().read(true).write(true).open("/littlefs/log")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("{}", contents);
} |
The first bulk of this PR is refactoring the build configuration. This is done so that the configuration that before could only be specified with environment variables can now also be set in the
package.metadata.esp-idf-sys
table of the root crate's manifest.Since we'll be using
cargo metadata
for specifying extra components anyway, it only makes sense that all configuration can be put into theCargo.toml
and not only configuration regarding extra esp-idf components.The refactored build configuration uses
serde
, its derive macros, and a new dependencyenvy
to deserialize environment variables and metadata values from a manifest. This has the advantage that all configuration options are now specified in a single struct and not littered throughout the build script. Additionally extending the configuration is much easier.The second part is extending this configuration system to allow specifying extra, external esp-idf components (though solely in manifest metadata).
This is possible by adding an object to the
package.metadata.esp-idf-sys.extra_components
array of the manifest. For example:Fixes #32, fixes #72