Skip to content

Latest commit

 

History

History
193 lines (125 loc) · 7.01 KB

development.md

File metadata and controls

193 lines (125 loc) · 7.01 KB

Slint development guide

The build instructions are in the building.md file. The testing instructions are in the testing.md file.

Repository structures

helper_crates

A set of crates that are somehow not strictly related to Slint, and that could be moved to their own repository and have their own version release at some point.

internal

internal contains code that isn't meant to be used directly by a user of Slint.

compiler

The main library for the compiler for .slint.

Nothing in there should depend on the runtime crates.

There is a test subdirectory that contains the syntax tests. These tests allow you to test the proper error conditions.

Runtime libraries

The library crates that are used at runtime.

  • core is the main library. It's meant to be used for all front-ends. Ideally it should be kept as small as possible. corelib-macros contains some procedural macro used by core library.
  • backends contains the different backend for the different platform, separated from core library. Currently there is just the gl backend
  • interpreter is the library used by the more dynamic languages backend to compile and interpret .slint files. It links both against core library and the compiler lib

tools

  • compiler is the tool to generate the target language (e.g. c++) from the .slint files for frontend that have a compilation step and generated code.
  • viewer is a tool that allow to open and view a .slint file.

api

Here one can find the frontends for different languages.

tests

The integration test that are testing a bunch of .slint with different front-ends

See testing.md

examples

Some manual tests

Documentation

There are some documentations comments in the code. HTML documentation can be generated with something like

cargo doc --document-private-items --no-deps --open

Rust to C++ bindings

We use a rather complex mechanism to expose internal data structures implemented in Rust to C++, in a way that allows us to provide a nice C++ API.

As a starting point, we recommend reading the blog entry we published about this:

https://slint.dev/blog/expose-rust-library-to-other-languages.html

What this article omits are how we invoke cbindgen and what kind of tweaks we apply on various levels:

The C++ library consists of four components:

  1. The slint-cpp cdylib created by cargo/rustc from api/cpp.
  2. The public header files in api/cpp/include.
  3. Internal header files generated by cbindgen, via cargo xtask cbindgen.
  4. The CMake project to tie it all together by invoking corrosion to call cargo and invoking cbindgen.

cbindgen

The cbindgen xtask generates multiple header files for four different modules:

  1. The types in the core library. This is the bulk of the generated code.
  2. The entry points into the C++ library for creating backends, invoking the event loop, etc. - from api/cpp/lib.rs.
  3. The types specific to the Qt backend used by the Qt style, such as NativeButton, etc.
  4. The types used by the C++ interpreter API, written to slint_interpreter_internal.h.

Typically the input to cbindgen is within ffi sub-modules in the corresponding input crates to cbindgen. These ffi modules are gated with #[cfg(feature = "ffi")].

Commit History & Code Reviews

Linear history is preferred over merge commits. Long lived features can live in feature branches and those can be integrated with merge commits, of course.

As a consequence, we typically integrate pull requests as "rebase and merge" or "squash and merge".

During code review, consider adding small commits on top to make it easier for the reviewer and contributor to track feedback and how the feedback was incorporated - rebase can tend to make it harder. It's perfectly fine to then squash these commits when the review phase is complete and approval is given.

Example:

A PR consists of three commits:

  1. Add new widget
  2. Add documentation for new widget
  3. Change example to use new widget

In the review phase, the reviewer suggests to make changes to the widget implementation and the documentation. Consider pushing these as follow-up fixes:

  1. Add new widget
  2. Add documentation for new widget
  3. Change example to use new widget
  4. Fix an issue in widget found during review
  5. Fix a typo in the documentation

Finally, the PR is approved. As contributor, in your local branch, feel free to merge 4. into 1. and 5. into 2.:

(commits are real, sha1s are just examples)

As a first step, let's rebase our changes to make sure that there are no conflicts:

git rebase origin/master

This might run through without stoppping. If there are merge conflicts to be resolved, git rebase will stop and let you fix it. For instructions how to resolve the conflicts and continue, see Resolving merge conflicts after a Git rebase.

When your branch is rebased, proceed to squash the fixup commits. Start an interactive rebase that starts at the base commit:

$ git rebase -i origin/master

This launches the configured editor with the above list of commits, in the order as they will committed:

pick 82916bc2 Add new widget
pick e55bde4c Add documentation for new widget
pick 9bc8d203 Change example to use new widget
pick a6feda52 Fix an issue in widget found during review
pick 032032dc Fix a typo in the documentation

Let's merge 4. into 1. and 5. into 2. by changing the above:

pick 82916bc2 Add new widget
fixup a6feda52 Fix an issue in widget found during review
pick e55bde4c Add documentation for new widget
fixup 032032dc Fix a typo in the documentation
pick 9bc8d203 Change example to use new widget

Save and exit the editor.

Now git will start at the base commit, cherry-pick the first commit, and squash the "Fix an issue in widget found during code review" change into the same commit. Use squash instead of fixup if you want to also further edit the commit message.

Save and exit the editor.

Now git continues to do the same with the second squash. Do as in the previous step and adjust the commit message to suit the original intent ("Add documentation for new widget").

Save and exit the editor. Rinse and repeat until the rebase is complete.

Use a tool like GitHub Desktop or gitk to take another look at the git history of commits.

Are all the fix-up commits merged with the original changes? Do the commit messages look okay?

If you need further changes, run $ git rebase -i origin/master again.

When the history is clean, double check that you're going to push to the right branch:

$ git push --dry-run -f

If that looks okay and targets the right branch for your PR, push with force:

$ git push -f