This commit is a bit bigger than it could have: Meson changes could have gone in separately from CI and Debian. This commit looks more complicated than it should reasonably be. Alas, Cargo is a piece of work, and it doesn't let honest people just choose different versions of dependencies, leading to a cascade of misery. Several things were tried to curb the disaster: - Cargo [feature] supports choosing dependencies, but doesn't support specifying dependency versions - Cargo has a cfg() syntax in sections for choosing dependencies by build options, but it explicitly doesn't support selecting on features… - Cargo allows choosing different dependencies based on features, so perhaps dependencies with different versions could live in stub crates pulled in as needed? Nope! If a dependency doesn't exist in the repo (and that's the point here), Cargo throws up its hands. This means Cargo.toml needs to be generated based on the build type. More misery: - we lose the simplicity of just doing `cargo.sh` for simple housekeeping like deps updates. HACKING.md was updated to reflect that. Perhaps that's inevitable - build options need to be like this. - Some flaky adjustments needed in `cargo.sh` because of an additional argument that can be mistaken for an argument to the exec in `cargo run`. - Specifying a custom `Cargo.toml` means Cargo can no longer find any tests, examples, benchmarks, or binaries, because it searches relative to the directory of `Cargo.toml`, which is now the build dir. Extra care needed to not forget about them now. As soon as Cargo allows anything better for managing deps versions, the above should be undone in its favor. Good side is that a couple bugs went away: - build flags not always making it to Cargo - arm64 builds were optional while they shouldn't - test layouts in unit tests are loaded from an explicit directory now The Bullseye versions of dependencies are canonical now, Buster considered legacy.
		
			
				
	
	
	
		
			6.5 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	Hacking
This document describes the standards for modifying and maintaining the squeekboard project.
Principles
The project was built upon some guiding principles, which should be respected primarily by the maintainers, but also by contributors to avoid needlessly rejected changes.
The overarching principle of squeekboard is to empower users.
Software is primarily meant to solve problems of its users. Often in the quest to make software better, a hard distinction is made between the developer, who becomes the creator, and the user, who takes the role of the consumer, without direct influence on the software they use. This project aims to give users the power to make the software work for them by blurring the lines between users and developers.
Nonwithstanding its current state, squeekboard must be structured in a way that provides users a gradual way to gain more experience and power to adjust it. It must be easy, in order of importance:
- to use the software,
 - to modify its resources,
 - to change its behaviour,
 - to contribute upstream.
 
To give an idea of what it means in practice, those are some examples of what has been important for squeekboard so far:
- being quick and useable,
 - allowing local overrides of resources and config,
 - storing resources and config as editable, standard files,
 - having complete, up to date documentation of interfaces,
 - having an easy process of sending contributions,
 - adapting to to user's settings and constrains without overriding them,
 - avoiding compiling whenever possible,
 - making it easy to build,
 - having code that is simple and obvious,
 - having an easy process of testing and accepting contributions.
 
You may notice that they are ordered roughly from "user-focused" to "maintainer-focused". While good properties are desired, sometimes they conflict, and maintainers should give additional weight to those benefitting the user compared to those benefitting regular contributors.
Sending patches
By submitting a change to this project, you agree to license it under the GPL license version 3, or any later version. You also certify that your contribution fulfills the Developer's Certificate of Origin 1.1.
Development environment
Squeekboard is regularly built and tested on the develpment environment.
Recent Fedora releases are likely to be tested as well.
Dependencies
On a Debian based system run
sudo apt-get -y install build-essential
sudo apt-get -y build-dep .
For an explicit list of dependencies check the Build-Depends entry in the debian/control file.
Testing
Most common testing is done in CI. Occasionally, and for each release, do perform manual tests to make sure that
- the application draws correctly
 - it shows when relevant
 - it changes layouts
 - it changes views
 
Testing with an application:
python3 tools/entry.py
Testing visibility:
$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false
Testing layouts:
Layouts can be selected using the GNOME Settings application.
# define all available layouts. First one is currently selected.
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb', 'de')]"
Coding
Project structure
Rust modules should be split into 2 categories: libraries, and user interface. They differ in the way they do error handling.
Libraries should:
- not panic due to external surprises, only due to internal inconsistencies
 - pass errors and surprises they can't handle to the callers instead
 - not silence errors and surprises
 
User interface modules should:
- try to provide safe values whenever they encounter an error
 - do the logging
 - give libraries the ability to report errors and surprises (e.g. via giving them loggers)
 
Style
Code submitted should roughly match the style of surrounding code. Things that will not be accepted are ones that often lead to errors:
- skipping brackets 
{}after everyif(),else, and similar 
Bad example:
if (foo)
  bar();
Good example:
if (foo) {
  bar();
}
- mixing tabs and spaces in the same block of code (or config)
 
Strongly encouraged:
- don't make lines too long. If it's longer than ~80 characters, it's probably unreadable already, and the code needs to be clarified;
 - put operators in the beginning of a continuation line
 
Bad example:
foobar = verylongexpression +
    anotherverylongexpression + 
    yetanotherexpression;
Good example:
foobar = verylongexpression
    + anotherverylongexpression
    + yetanotherexpression;
- use 
///for documentation comments in front of definitions and/*! ... */for documentation comments in the beginning of modules (see Rust doc-comments) 
If in doubt, check PEP8, the kernel coding style, or the Rust style guide.
Maintenance
Squeekboard uses Rust & Cargo for some of its dependencies.
Use the cargo.sh script for maintaining the Cargo part of the build. The script takes the usual Cargo commands, after the first 2 positionsl arguments: source directory, and output artifact. So, cargo test becomes:
cd build_dir
sh /source_path/cargo.sh test
Cargo dependencies
All Cargo dependencies must be selected in the version available in PureOS, and added to the file debian/control. Please check with https://software.pureos.net/search_pkg?term=librust .
Dependencies must be specified in Cargo.toml with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates.
Cargo.lock is used for remembering the revisions of all Rust dependencies. It must correspond to the default dependency configuration: without flags to use older or newer versions of dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:
cd build_dir
ninja build src/Cargo.toml
sh /source_path/cargo.sh update
ninja test