Implement new commands build and check + introduce bundles (.contract files)#97
Implement new commands build and check + introduce bundles (.contract files)#97
build and check + introduce bundles (.contract files)#97Conversation
ascjones
left a comment
There was a problem hiding this comment.
What do you think about giving the resulting file a different name/extension than just metadata.json, so that we know we are dealing with a packed file? Might be useful for the canvas-ui to know to expect a packed file. @Robbepop?
There was a problem hiding this comment.
I think generating that pack is the default case. We should make that as easy as possible. Imho the cli should look like this:
There is only the build command which does what pack does today. It has two options skip-code and skip-metadata. If either of those is specified we also skip the generation of the pack. Specifying both is an error (obviously).
I like this idea, since in most cases you would want to do both - and incremental compilation means that even compiling both will not cost too much after the first time. |
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
So I also like it, but I'm not sure about the What I suggest instead is to have the I've added a commit which does that. Lmk what you think. |
athei
left a comment
There was a problem hiding this comment.
You are right. --skip-code makes no sense. My only complaint is that we should not use the word "packing". I think "bundle" better expresses what we are doing. "Pack" could also mean some kind of compression which is not what we are doing here. I mean we could apply compression on top but the main thing we are doing is still "bundle".
src/main.rs
Outdated
| #[structopt(long = "skip-packing", conflicts_with = "skip-metadata")] | ||
| skip_packing: bool, | ||
| /// Only the Wasm is created, generation of metadata and a packed .contract file is skipped | ||
| #[structopt(long = "skip-metadata", conflicts_with = "skip-packing")] | ||
| skip_metadata: bool, |
There was a problem hiding this comment.
Can we please name things positively instead of negatively? I.e. bundle or bundle_contract or build_bundle instead of skip_bundle? Same for skip_metadata.
There was a problem hiding this comment.
While I agree with the general sentiment of prioritizing positive naming, I'm not sure how we can do that here, since default behavior is wasm+metadata+bundle and we want to provide a possibility to leave certain things out.
So we need better flag names for
--skip-metadata Only the Wasm is created, generation of metadata and a packed .contract file is skipped
--skip-packing Only the Wasm and the metadata are generated, no packed .contract file is created
Hmm, maybe --only-wasm and --only-metadata would be better?
Or do you suggest changing default behavior?
There was a problem hiding this comment.
Why do we need these flags in the first place? I think this should be automated just like you don't need to specify to cargo which rust files to build.
There was a problem hiding this comment.
If your contract implementation has changed you always want to build the Wasm AND if your interfaces have changed you always want to build metadata. This already eliminates the wasm flag because bundling pretty much always involved building the wasm. So the only question is: Do we want to always build metadata? Do we want to infer it? And if so, how? Or do we want to make it skip-opt-in as proposed so far?
There was a problem hiding this comment.
I don't follow, can you elaborate?
We changed default behavior of cargo contract build to generate wasm+metadata+pack. And now we want to provide flags to skip certain steps. Which part of that can be automated?
There was a problem hiding this comment.
I estimate that those commands will be used most frequently:
cargo contract build(very often)cargo contract bundle(rarely)cargo contract metadata(nearly never)
So we could also remove cargo contract metadata and add a --skip-metadata flag to cargo contract bundle and keep cargo contract build. Building only metadata seldomly makes real sense.
You kind of can compare cargo contract bundle with cargo publish. Also ideally cargo contract bunlde should do checks similar to cargo publish like: Do contract authors exists and are they well formatted?
There was a problem hiding this comment.
What is the motivation to change behaviour of cargo contract build instead of adding yet another command cargo contract bundle?
See earlier discussion in this PR: #97 (review)
There was a problem hiding this comment.
So we could also remove cargo contract metadata and add a --skip-metadata flag to cargo contract bundle and keep cargo contract build. Building only metadata seldomly makes real sense.
So what this PR already does is that it removes the cargo contract generate-metadata cmd, makes cargo contract build build everything by default, and adds skip flags for omitting metadata/bundling.
There was a problem hiding this comment.
Then using the most frequently used command forces users to type in cargo contract build --skip-metadata which is messy imo. Generating metadat by default is bad here because it adds tons of overhead and users will question ink! with taking 2 minutes to do a fresh build for a hello world contract. We should focus to make the most frequent command the simplest to use:
- Most frequent:
cargo contract build - Less frequent:
cargo contract bundleorcargo contract bundle --skip-metadata - Least frequent:
cargo contract generate-metadata
There was a problem hiding this comment.
Building a bundle without updating the .wasm is pretty much never what you want so there should be no option available to do this.
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Building the pack should not be the default case since it incurs tons of overhead due to building |
|
Isn't that what incremental compilation is for? With metadata not using link time optimization it will not add much time. I predict that people just want a new *.contract file to upload almost always. We should optimize for this case. Who will fumble with two different files and think about what to rebuild in order to save a a second to skip metadata build? |
Have you tried building both |
|
They cannot use the cache from one another but their own cache from a previous run, don't they? |
Yes they can but still build times are going to be significantly worse when making bundling and all of its extra steps the default. On my system these are the benchmarks for:
Incremental builds are measured after From my evaluation of these results merging |
|
@Robbepop Why do you think generating a wasm without metadata ist the most common operation a user wants to do? My impression was that we nearly always mention the line |
Good question! |
|
All comments addressed. Output now: |
ascjones
left a comment
There was a problem hiding this comment.
Nice, like the new output. Just added a couple of extra comments
|
I updated the branch and built a fresh flipper contract. The output seems to be wrong again: The "Generating metadata" is at the wrong position. It should be directly behind step alexander:~% cargo contract build
[1/5] Building cargo project
...
Compiling flipper v0.1.0 (/var/folders/8g/_rkmq65n0qnf70c41xvp174h0000gn/T/cargo-contract_qOrMhF)
Finished release [optimized] target(s) in 23.10s
[2/5] Post processing wasm file
[3/5] Optimizing wasm file
...
Compiling flipper v0.1.0 (/var/folders/8g/_rkmq65n0qnf70c41xvp174h0000gn/T/cargo-contract_Qv7HEC)
Compiling metadata-gen v0.1.0 (/var/folders/8g/_rkmq65n0qnf70c41xvp174h0000gn/T/cargo-contract_Qv7HEC/.ink/metadata_gen)
Finished release [optimized] target(s) in 36.29s
Running `target/release/metadata-gen`
[4/5] Generating bundle
[5/5] Generating metadata
Original wasm size: 19.1K, Optimized: 2.5K
Your contract artifacts are ready. You can find them in:
/Users/alexander/Developer/parity/contracts/flipper/target
- flipper.contract (code + metadata)
- flipper.wasm (the contract's code)
- metadata.json (the contract's metadata) |
Robbepop
left a comment
There was a problem hiding this comment.
WIP: review - will continue later
| build Compiles the smart contract | ||
| generate-metadata Generate contract metadata artifacts | ||
| build Compiles the contract, generates metadata, bundles both together in a '.contract' file | ||
| check Check that the code builds as Wasm; does not output any build artifact to the top level `target/` directory |
There was a problem hiding this comment.
Maybe we should mention that this step also deploys (or will deploy) some custom checks that we implement on top besides just making sure that things compile for Wasm.
There was a problem hiding this comment.
I agree, but would only add it once we actually have some checks on top.
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| hash: Option<CodeHash>, |
There was a problem hiding this comment.
When is this ever None? I guess it is always useful even if we provide the sources.
There was a problem hiding this comment.
What I read from the discussion is that we still always want the hash field to be available. And also I don't think that we need --metadata-only. Please convince me of the opposite by coming up with a useful use case.
There was a problem hiding this comment.
What I read from the discussion is that we still always want the hash field to be available.
I understood the discussion in the way that we want to omit the hash:
It is not required, currently. It's just there as a nice to have. In the future the client tools could use that (if present) to verify the metadata matches the deployed code.
So I would say that if metadata-only is specified then that field should be omitted, even if the wasm is already there because it is not guaranteed to match.
|
It is still saying "Optimizing wasm file" when it actually goes on and starts building "metadata-gen": |
Closes #96 by implementing
cargo contract build, which results in atarget/metadata.json, atarget/<name>.wasm, and atarget/<name>.contract(the .pack file mentioned in the issue).cargo contract check, which just tries to build the contract without generating metadata or optimizing the Wasm.cargo contract generate-metadataforcargo contract build(which implicitly does this or via--metadata-onlyskips unnecessary operations not strictly needes for generating metadata).