people.gnome.org_federico.atom.xml - sfeed_tests - sfeed tests and RSS and Atom files
HTML git clone git://git.codemadness.org/sfeed_tests
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
people.gnome.org_federico.atom.xml (1402111B)
---
1 <?xml version="1.0" encoding="utf-8"?>
2 <feed xmlns="http://www.w3.org/2005/Atom"><title>Federico's Blog</title><link href="https://people.gnome.org/~federico/blog/" rel="alternate"></link><link href="https://people.gnome.org/~federico/blog/feeds/atom.xml" rel="self"></link><id>https://people.gnome.org/~federico/blog/</id><updated>2021-09-01T13:57:47-05:00</updated><subtitle></subtitle><entry><title>GNOME themes, an incomplete status report, and how you can help</title><link href="https://people.gnome.org/~federico/blog/gnome-themes.html" rel="alternate"></link><published>2021-09-01T13:57:47-05:00</published><updated>2021-09-01T13:57:47-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2021-09-01:/~federico/blog/gnome-themes.html</id><summary type="html"><p>"Themes in GNOME" is a complicated topic in technical and social
3 terms. Technically there are a lot of incomplete moving parts;
4 socially there is a lot of missing documentation to be written, a lot
5 of miscommunication and mismatched expectations.</p>
6 <p>The following is a brief and incomplete, but hopefully encouraging,
7 summary …</p></summary><content type="html"><p>"Themes in GNOME" is a complicated topic in technical and social
8 terms. Technically there are a lot of incomplete moving parts;
9 socially there is a lot of missing documentation to be written, a lot
10 of miscommunication and mismatched expectations.</p>
11 <p>The following is a brief and incomplete, but hopefully encouraging,
12 summary of the status of themes in GNOME. I want to give you an
13 overall picture of the status of things, and more importantly, an idea
14 of how you can help. This is not a problem that can be solved by a
15 small team of platform developers.</p>
16 <p>I wish to thank Alexander Mikhaylenko for providing most of the
17 knowledge in this post.</p>
18 <h1>Frame of reference</h1>
19 <p>First, I urge you to read Cassidy James Blaede's comprehensive "<a href="https://blog.elementary.io/the-need-for-a-freedesktop-dark-style-preference/">The
20 Need for a FreeDesktop Dark Style
21 Preference</a>".
22 That gives an excellent, well-researched introduction to the "dark
23 style" problem, the status quo on other platforms, and exploratory
24 plans for GNOME and Elementary from 2019.</p>
25 <p>Go ahead, read it. It's very good.</p>
26 <p>There is also a <a href="https://www.youtube.com/watch?v=gi_3b81eBUE&amp;list=PLkmRdYgttscEuv9v2-H9P5FBj8-td_Nri&amp;index=31">GUADEC talk about Cassidy's
27 research</a>
28 if you prefer to watch a video.</p>
29 <p>Two key take-aways from this: First, about this being a
30 <strong>preference</strong>, not a system-enforced setting:</p>
31 <blockquote>
32 <p>I’m explicitly using the language “Dark Style Preference” for a
33 reason! As you’ll read further on, it’s important that this is
34 treated as a user “preference,” not an explicit “mode” or
35 strictly-enforced “setting.” It’s also not a “theme” in the sense
36 that it just swaps out some assets, but is a way for the OS to
37 support a user expressing a preference, and apps to respond to that
38 preference.</p>
39 </blockquote>
40 <p>Second, about the <strong>accessibility</strong> implications:</p>
41 <blockquote>
42 <p>Clearly there’s an accessibility and usability angle here. And as
43 with other accessibility efforts, it’s important to not relegate a
44 dark style preference to a buried “Universal Access” or
45 “Accessibility” feature, as that makes it less discoverable, less
46 tested, and less likely to be used by folks who could greatly
47 benefit, but don’t consider themselves “disabled.”</p>
48 </blockquote>
49 <h1>Libadwaita and the rest of the ecosystem</h1>
50 <p>Read the <a href="https://discourse.gnome.org/t/libadwaita-1-0-roadmap/7415">libadwaita
51 roadmap</a>;
52 it is very short, but links to very interesting issues on gitlab.</p>
53 <p>For example, this merge request is for an <a href="https://gitlab.gnome.org/GNOME/libadwaita/-/merge_requests/224">API to query the dark style
54 and high-contrast
55 preferences</a>.
56 It has links to pending work in other parts of the platform: libhandy,
57 gsettings schemas, portals so that containerized applications can
58 query those preferences.</p>
59 <p>As far as I understand it, applications that just use GTK3 or libhandy
60 can opt in to supporting the dark style preference — it is opt-in
61 because doing that unconditionally in GTK/libhandy right now would
62 break existing applications.. If your app uses libadwaita, it is
63 assumed that you have opted into supporting that preference, since
64 libadwaita's widgets already make that assumption, and it is not
65 API-stable yet — so it can make that assumption from the beginning.</p>
66 <p>There is discussion of the accessibility implications in <a href="https://gitlab.gnome.org/Teams/Design/settings-mockups/-/issues/27#note_1257700">the design
67 mockups</a>.</p>
68 <h1>CSS parity across implementations</h1>
69 <p>In GNOME we have three implementations of CSS:</p>
70 <ul>
71 <li>
72 <p>librsvg uses servo's engine for CSS selector matching, and micro-parsers for CSS values based on servo's cssparser.</p>
73 </li>
74 <li>
75 <p>GTK has its own CSS parser and processor.</p>
76 </li>
77 <li>
78 <p>Gnome-shell uses an embedded version of libcroco for parsing, but it
79 does most of the selector matching and cascading with gnome-shell's
80 own Shell Toolkit code.</p>
81 </li>
82 </ul>
83 <p>None of those implementations supports <code>@media</code> queries nor custom
84 properties with <code>var()</code>. That is, unlike in the web platform, GNOME
85 applications cannot have this in their CSS:</p>
86 <div class="highlight"><pre><span></span><code><span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-color-scheme</span><span class="o">:</span> <span class="nt">dark</span><span class="o">)</span> <span class="p">{</span>
87 <span class="c">/* styles for dark style */</span>
88 <span class="p">}</span>
89
90 <span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-color-scheme</span><span class="o">:</span> <span class="nt">light</span><span class="o">)</span> <span class="p">{</span>
91 <span class="c">/* styles for light style */</span>
92 <span class="p">}</span>
93 </code></pre></div>
94
95 <p>Or even declaring colors in a civilized fashion:</p>
96 <div class="highlight"><pre><span></span><code><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
97 <span class="nv">--main-bg-color</span><span class="p">:</span> <span class="kc">pink</span><span class="p">;</span>
98 <span class="p">}</span>
99
100 <span class="nt">some_widget</span> <span class="p">{</span>
101 <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="nv">--main-bg-color</span><span class="p">);</span>
102 <span class="p">}</span>
103 </code></pre></div>
104
105 <p>Or combining the two:</p>
106 <div class="highlight"><pre><span></span><code><span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-color-scheme</span><span class="o">:</span> <span class="nt">dark</span><span class="o">)</span> <span class="p">{</span>
107 <span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
108 <span class="nv">--main-bg-color</span><span class="p">:</span> <span class="c">/* some nice dark background color */</span><span class="p">;</span>
109 <span class="nv">--main-fg-color</span><span class="p">:</span> <span class="c">/* a contrasty light foreground */</span><span class="p">;</span>
110 <span class="p">}</span>
111 <span class="p">}</span>
112
113 <span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-color-scheme</span><span class="o">:</span> <span class="nt">light</span><span class="o">)</span> <span class="p">{</span>
114 <span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
115 <span class="nv">--main-bg-color</span><span class="p">:</span> <span class="c">/* some nice light background color */</span><span class="p">;</span>
116 <span class="nv">--main-fg-color</span><span class="p">:</span> <span class="c">/* a contrasty dark foreground */</span><span class="p">;</span>
117 <span class="p">}</span>
118 <span class="p">}</span>
119
120 <span class="nt">some_widget</span> <span class="p">{</span>
121 <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="nv">--main-bg-color</span><span class="p">);</span>
122 <span class="p">}</span>
123 </code></pre></div>
124
125 <p>Boom. I think this would remove some workarounds we have right now:</p>
126 <ul>
127 <li>
128 <p>Just like GTK, libadwaita generates four variants of the system's
129 stylesheet using scss (regular, dark, high-contrast,
130 high-contrast-dark). This would be obviated with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media"><code>@media</code>
131 queries</a>
132 for <code>prefers-color-scheme</code>, <code>prefers-contrast</code>, <code>inverted-colors</code> as
133 in the web platform.</p>
134 </li>
135 <li>
136 <p>GTK has a custom <code>@define-color</code> keyword, but neither gnome-shell
137 nor librsvg support that. This would be obviated with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/--*">CSS custom
138 properties</a> -
139 the <code>var()</code> mechanism. (I don't know if some "environmental" stuff
140 would be better done as
141 <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/env()"><code>env()</code></a>,
142 but none of the three implementations support that, either.)</p>
143 </li>
144 </ul>
145 <h1>Accent colors</h1>
146 <p>They are currently implemented with GTK's <code>@define-color</code>, which is
147 not ideal if the colors have to trickle down from GTK to SVG icons,
148 since librsvg doesn't do <code>@define-color</code> - it would rather have
149 <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/459"><code>var()</code>
150 instead</a>.</p>
151 <p>Of course, gnome-shell's libcroco doesn't do <code>@define-color</code> either.</p>
152 <p>Look for <code>@accent_color</code>, <code>@accent_bg_color</code>, <code>@warning_color</code>, etc. in the <a href="https://gitlab.gnome.org/GNOME/libadwaita/-/blob/main/src/stylesheet/_defaults.scss">default
153 stylesheet</a>,
154 or better yet, <strong>write documentation!</strong></p>
155 <p>The default style:</p>
156 <p><img alt="Default blue style" src="https://people.gnome.org/~federico/blog/images/adwaita-default.png"></p>
157 <p>Accent color set to orange (e.g. tweak it in GTK's CSS inspector):</p>
158 <p><img alt="Orange accents for widgets" src="https://people.gnome.org/~federico/blog/images/adwaita-accent-orange.png"></p>
159 <div class="highlight"><pre><span></span><code><span class="c">/* Standalone, e.g. the &quot;Page 1&quot; label */</span>
160 <span class="p">@</span><span class="k">define-color</span> <span class="nt">accent_color</span> <span class="p">@</span><span class="k">orange_5</span><span class="p">;</span>
161
162 <span class="c">/* background+text pair */</span>
163 <span class="p">@</span><span class="k">define-color</span> <span class="nt">accent_bg_color</span> <span class="p">@</span><span class="k">orange_4</span><span class="p">;</span>
164 <span class="p">@</span><span class="k">define-color</span> <span class="nt">accent_fg_color</span> <span class="nt">white</span><span class="p">;</span>
165 </code></pre></div>
166
167 <h1>Custom widgets</h1>
168 <p>Again, your app's custom stylesheet for its custom widgets can use the
169 colors defined through <code>@define-color</code> from the system's stylesheet.</p>
170 <h1>Recoloring styles</h1>
171 <p>You will be able to do this after it gets merged into the main branch,
172 e.g. recolor everything to sepia:</p>
173 <p><img alt="Adwaita recolored to sepia" src="https://people.gnome.org/~federico/blog/images/adwaita-recolored.png"></p>
174 <div class="highlight"><pre><span></span><code><span class="p">@</span><span class="k">define-color</span> <span class="nt">headerbar_bg_color</span> <span class="p">#</span><span class="nn">eedcbf</span><span class="p">;</span>
175 <span class="p">@</span><span class="k">define-color</span> <span class="nt">headerbar_fg_color</span> <span class="p">#</span><span class="nn">483a22</span><span class="p">;</span>
176
177 <span class="p">@</span><span class="k">define-color</span> <span class="nt">bg_color</span> <span class="p">#</span><span class="nn">f9f3e9</span><span class="p">;</span>
178 <span class="p">@</span><span class="k">define-color</span> <span class="nt">fg_color</span> <span class="p">#</span><span class="nn">483a22</span><span class="p">;</span>
179
180 <span class="p">@</span><span class="k">define-color</span> <span class="nt">dark_fill_color</span> <span class="nt">shade</span><span class="o">(</span><span class="p">#</span><span class="nn">f9f3e9</span><span class="o">,</span> <span class="p">.</span><span class="nc">95</span><span class="o">)</span><span class="p">;</span>
181
182 <span class="p">@</span><span class="k">define-color</span> <span class="nt">accent_bg_color</span> <span class="p">@</span><span class="k">orange_4</span><span class="p">;</span>
183 <span class="p">@</span><span class="k">define-color</span> <span class="nt">accent_color</span> <span class="p">@</span><span class="k">orange_5</span><span class="p">;</span>
184 </code></pre></div>
185
186 <p>Of course <code>shade()</code> is not web-platform CSS, either. We could keep
187 it, or redo it by implementing <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/calc()"><code>calc()</code>
188 function</a> for
189 color values.</p>
190 <h1>Recoloring icons</h1>
191 <p>Currently GTK takes some defined colors and <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/539#note_669487">creates a chunk of CSS to
192 inject into SVG for
193 icons</a>.
194 This has <a href="https://gitlab.gnome.org/GNOME/gtk/-/issues/2314">some
195 problems</a>.</p>
196 <p>There is also some discussion about <a href="https://gitlab.gnome.org/GNOME/gtk/-/issues/1762">standardizing recolorable
197 icons</a> across
198 desktop environments.</p>
199 <h1>How you can help</h1>
200 <p>Implement support for <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"><code>@media</code>
201 queries</a>
202 in our three CSS implementations (librsvg, gnome-shell, GTK). Decide
203 how CSS media features like <code>prefers-color-scheme</code>,
204 <code>prefers-contrast</code>, <code>inverted-colors</code> should interact with the GNOME's
205 themes and accessibility, and decide if we should use them for
206 familiarity with the web platform, or if we need media features with
207 different names.</p>
208 <p>Implement support for <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties">CSS custom properties -
209 <code>var()</code></a>
210 in our three CSS implementations. Decide if we should replace the
211 current <code>@define-color</code> with that (note that <code>@define-color</code> is only
212 in GTK, but not in librsvg or gnome-shell).</p>
213 <p>See the <a href="https://discourse.gnome.org/t/libadwaita-1-0-roadmap/7415">libadwaita
214 roadmap</a>
215 and help out!</p>
216 <p>Port applications to use the proposed APIs for querying the dark style
217 preference. There are a bunch of hacky ways of doing it right now;
218 they need to be migrated to the new system.</p>
219 <p>Personally I would love help with finishing to <a href="https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1355">port gnome-shell's
220 styles to
221 Rust</a> -
222 this is part of unifying librsvg's and gnome-shell's CSS machinery.</p></content><category term="misc"></category><category term="gnome"></category></entry><entry><title>Bzip2's experimental repository is changing maintainership</title><link href="https://people.gnome.org/~federico/blog/bzip2-changing-maintainership.html" rel="alternate"></link><published>2021-06-03T19:21:04-05:00</published><updated>2021-06-03T19:21:04-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2021-06-03:/~federico/blog/bzip2-changing-maintainership.html</id><summary type="html"><p>Bzip2's stable repository is maintained <a href="https://sourceware.org/git/?p=bzip2.git;a=summary">at Sourceware</a> by
223 Mark Wielaard. In 2019 I started maintaining an <a href="https://gitlab.com/bzip2/bzip2/">experimental
224 repository in GitLab</a>, with the intention of updating
225 the build system and starting a Rust port of bzip2. Unfortunately I
226 have left this project slip by.</p>
227 <p>The new maintainer of the <a href="https://gitlab.com/bzip2/bzip2/">experimental repository …</a></p></summary><content type="html"><p>Bzip2's stable repository is maintained <a href="https://sourceware.org/git/?p=bzip2.git;a=summary">at Sourceware</a> by
228 Mark Wielaard. In 2019 I started maintaining an <a href="https://gitlab.com/bzip2/bzip2/">experimental
229 repository in GitLab</a>, with the intention of updating
230 the build system and starting a Rust port of bzip2. Unfortunately I
231 have left this project slip by.</p>
232 <p>The new maintainer of the <a href="https://gitlab.com/bzip2/bzip2/">experimental repository</a> for
233 Bzip2 is Micah Snyder. Thanks, Micah, for picking it up!</p></content><category term="misc"></category><category term="bzip2"></category><category term="rust"></category></entry><entry><title>Librsvg, Rust, and non-mainstream architectures</title><link href="https://people.gnome.org/~federico/blog/librsvg-rust-and-non-mainstream-architectures.html" rel="alternate"></link><published>2021-02-24T19:14:55-06:00</published><updated>2021-02-24T19:14:55-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2021-02-24:/~federico/blog/librsvg-rust-and-non-mainstream-architectures.html</id><summary type="html"><p>Almost five years ago <a href="https://people.gnome.org/~federico/news-2016-10.html#25">librsvg introduced Rust into its source
234 code</a>. Around the same time, Linux distributions
235 started shipping the first versions of Firefox that also required
236 Rust. I unashamedly wanted to ride that wave: distros would <em>have</em> to
237 integrate a new language in their build infrastructure, or they would …</p></summary><content type="html"><p>Almost five years ago <a href="https://people.gnome.org/~federico/news-2016-10.html#25">librsvg introduced Rust into its source
238 code</a>. Around the same time, Linux distributions
239 started shipping the first versions of Firefox that also required
240 Rust. I unashamedly wanted to ride that wave: distros would <em>have</em> to
241 integrate a new language in their build infrastructure, or they would
242 be left without Firefox. I was hoping that having a working Rust
243 toolchain would make it easier for the rustified librsvg to get into
244 distros.</p>
245 <p>Two years after that, <a href="https://lwn.net/Articles/771355/">someone from Debian complained</a>
246 that this made it hard or impossible to build librsvg (and all the
247 software that depends on it, which is A Lot) on all the architectures
248 that Debian builds on — specifically, on things like HP PA-RISC or
249 Alpha, which <a href="https://www.debian.org/ports/">even Debian marks as "discontinued" now</a>.</p>
250 <p>Recently there was a similar kerfuffle, this time from <a href="https://lwn.net/Articles/845535/">someone from
251 Gentoo</a>, specifically about how Python's cryptography
252 package now requires Rust. So, it doesn't build for platforms that
253 Rust/LLVM don't support, like hppa, alpha, and Itanium. It also
254 doesn't build for platforms for which there are no Rust packages from
255 Gentoo yet (mips, s390x, riscv among them).</p>
256 <h2>Memories of discontinued architectures</h2>
257 <p>Let me reminisce about a couple of discontinued architectures. If I'm
258 reading <a href="https://en.wikipedia.org/wiki/DEC_Alpha">Wikipedia</a> correctly, the DEC Alpha ceased to be
259 developed in 2001, and HP, who purchased Compaq, who purchased DEC,
260 stopped selling Alpha systems in 2007. Notably, Compaq phased out the
261 Alpha in favor of the Itanium, which stopped being developed in 2017.</p>
262 <p>I <em>used</em> an Alpha machine in 1997-1998, back at the University.
263 <a href="https://twitter.com/migueldeicaza/">Miguel</a> kindly let me program and learn from him at the Institute
264 where he worked, and the computer lab there got an Alpha box to let
265 the scientists run mathematical models on a machine with really fast
266 floating-point. This was a time when people actually regularly ssh'ed
267 into machines to run X11 applications remotely — in their case, I
268 think it was Matlab and Mathematica. Good times.</p>
269 <p>The Alpha had fast floating point, much faster than Intel x86 CPUs,
270 and I was delighted to do graphics work on it. That was the first
271 64-bit machine I used, and it let me learn how to fix code that only
272 assumed 32 bits. It had a really picky floating-point unit. Whereas
273 x86 would happily throw you a NaN if you used uninitialized memory as
274 floats, the Alpha would properly fault and crash the program. I fixed
275 so many bugs thanks to that!</p>
276 <p>I also have fond memories of the 32-bit SPARC
277 boxes at the University and their flat-screen fixed-frequency CRT
278 displays, but you know, I haven't <em>seen</em> one of those machines since
279 1998. Because I was doing graphics work, I used the single SPARC
280 machine in the computer lab at the Institute that had 24-bit graphics,
281 with a humongous 21" CRT display. PCs at the time still had 8-bit video
282 cards and shitty little monitors.</p>
283 <p>At about the same time that the Institute got its Alpha, it also got
284 one of the first 64-bit UltraSPARCs from Sun — a very expensive
285 machine definitely not targeted to hobbyists. I think it had two CPUs!
286 Multicore did not exist!</p>
287 <p>I think I saw a single Itanium machine in my life, probably around
288 2002-2005. The Ximian/Novell office in Mexico City got one, for QA
289 purposes — an incredibly loud and unstable machine. I don't think we
290 ever did any actual development on that box; it was a "can you
291 reproduce this bug there" kind of thing. I think Ximian/Novell had a
292 contract with HP to test the distro there, I don't remember.</p>
293 <h2>Unsupported architectures at the LLVM level</h2>
294 <p>Platforms like the Alpha and Itanium that Rust/LLVM don't support —
295 those platforms are dead in the water. The compiler cannot target
296 them, as Rust generates machine code via LLVM, and LLVM doesn't
297 support them.</p>
298 <p>I don't know why distributions maintained by volunteers give
299 themselves the responsibility to keep their software running on
300 platforms that have not been manufactured for years, and that were
301 never even hobbyist machines.</p>
302 <p>I read the other day, and now I regret not keeping the link, something
303 like this: don't assume that your hobby computing entitles you to free
304 labor on the part of compiler writers, software maintainers, and
305 distro volunteers. (If someone helps me find the source, I'll happily
306 link to it and quote it properly.)</p>
307 <h2>Non-tier-1 platforms and "$distro does not build Rust there yet"</h2>
308 <p>I think people are discovering these once again:</p>
309 <ul>
310 <li>
311 <p>Writing and supporting a compiler for a certain architecture takes Real Work.</p>
312 </li>
313 <li>
314 <p>Supporting a distro for a certain architecture takes Real Work.</p>
315 </li>
316 <li>
317 <p>Fixing software to work on a certain architecture takes Real Work.</p>
318 </li>
319 </ul>
320 <p>Rust divides its support for different platforms into <a href="https://doc.rust-lang.org/nightly/rustc/platform-support.html">tiers</a>, going
321 from tier 1, the most supported, to tier 3, the least supported. Or,
322 I should say, <em>taken care of</em>, which is a combination of people who
323 actually have the hardware in question, and whether the general CI and
324 build tooling is prepared to deal with them as effectively as it does
325 for tier 1 platforms.</p>
326 <p>In other words: there are more people capable of paying attention to, and
327 testing things on, x86_64 PCs than there are for
328 <code>sparc-unknown-linux-gnu</code>.</p>
329 <h2>Some anecdotes from Suse</h2>
330 <p>At Suse we actually support IBM's s390x big iron; those mainframes run
331 Suse Linux Enterprise Server. You have to pay a lot of money to get a
332 machine like that and support for it. It's a room-sized beast that
333 requires professional babysitting.</p>
334 <p>When librsvg and Firefox started getting rustified, there was of
335 course concern about getting Rust to work properly on the s390x.
336 I worked sporadically with the people who made the distro work there,
337 and who had to deal with building Rust and Firefox on it (librsvg
338 was a non-issue after getting Rust and Firefox to work).</p>
339 <p>I think all the LLVM work for the s390x was done at IBM. There were
340 probably a couple of miscompilations that affected Firefox; they got fixed.</p>
341 <p>One would expect bugs in software for IBM mainframes to be fixed by
342 IBM or its contractors, not by volunteers maintaining a distro in
343 their spare time.</p>
344 <p>Giving computing time on mainframes to volunteers in distros could seem
345 like a good samaritan move, or a trap to extract free labor from
346 unsuspecting people.</p>
347 <h3>Endianness bugs</h3>
348 <p>Firefox's problems on the s390x were more around big-endian bugs than
349 anything. You see, all the common architectures these days (x86_64
350 and arm64) are little-endian. However, s390x is <a href="https://en.wikipedia.org/wiki/Endianness">big-endian</a>,
351 which means that all multi-byte numbers in memory are stored backwards
352 from what most software expects.</p>
353 <p>It is not a problem to write software that assumes little-endian or
354 big-endian all the time, but it takes a little care to write software
355 that works on either.</p>
356 <p>Most of the software that volunteers and paid people write assumes
357 little-endian CPUs, because that is likely what they are targeting.
358 It is a pain in the ass to encounter code that works incorrectly on
359 big-endian — a pain because <em>knowing where to look</em> for evidence of
360 bugs is tricky, and <em>fixing existing code</em> to work with either
361 endianness can be either very simple, or a major adventure in
362 refactoring and testing.</p>
363 <p>Two cases in point:</p>
364 <p><strong>Firefox.</strong> When Suse started dealing with Rust and Firefox in the
365 s390x, there were endianness bugs in the graphics code in Firefox that
366 deals with pixel formats. Whether pixels get stored in memory as
367 ARGB/ABGR/RGBA/etc. is a platform-specific thing, and is generally a
368 combination of the graphics hardware for that platform, plus the
369 actual CPU architecture. At that time, it looked like the C++ code in
370 Firefox that deals with pixels had been rewritten/refactored, and had
371 lost big-endian support along the way. I don't know the current
372 status (not a single big-endian CPU in my vincinity), but I haven't
373 seen related bugs come in the Suse bug tracker? Maybe it's fixed now?</p>
374 <p><strong>Librsvg</strong> had <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues?scope=all&amp;utf8=%E2%9C%93&amp;state=closed&amp;search=s390">two root causes of bugs for
375 big-endian</a>. One was in the old code for SVG
376 filter effects that was written in C; <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/195">it never supported big-endian</a>. The
377 initial port to Rust inherited the same bug (think of a line-by-line
378 port, althought it wasn't exactly like that), but it got fixed when my
379 Summer of Code intern Ivan Molodetskikh refactored the code to have a
380 <code>Pixel</code> abstraction that works for little-endian and big-endian, and
381 wraps Cairo's funky requirements.</p>
382 <p>The other endian-related bug in librsvg was when <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/328">computing
383 masks</a>. Again, a little refactoring with that <code>Pixel</code>
384 abstraction fixed it.</p>
385 <p>I knew that the original C code for SVG filter effects didn't work on
386 big-endian. But even back then, at Suse we never got
387 reports of it producing incorrect results on the s390x... maybe people don't use
388 their mainframes to run <code>rsvg-convert</code>? I was hoping that the port to
389 Rust of that code would automatically fix that bug, and it kind of
390 happened that way through Ivan's careful work.</p>
391 <p>And the code for masks? There were two bugs reported with that same
392 root cause: <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/328">one from
393 Debian</a> as a
394 failure in librsvg's test suite (yay, it caught that bug!), and one
395 from <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/322">someone running an Apple PowerBook
396 G4</a> with a MATE
397 desktop and seeing incorrectly-rendered SVG icons.</p>
398 <p>And you know what? I am <strong>delighted</strong> to see people trying to keep
399 those lovely machines alive. A laptop that doesn't get warm enough to
400 burn your thighs, what a concept. A perfectly serviceable 32-bit
401 laptop with a maximum of about 1 GB of RAM and a 40 GB hard drive (it
402 didn't have HDMI!)... But you know, it's the same kind of delight I
403 feel when people talk about doing film photography on a
404 <a href="https://en.wikipedia.org/wiki/Rollei_35">Rollei 35</a>. A lot of
405 nostalgia for hardware of days past, and a lot of mixed feelings about
406 not throwing out working things and creating more trash.</p>
407 <p>As a graphics programmer I feel the responsibility to write code that
408 works on little-endian and big-endian, but you know, it's not exactly
409 an everyday concern anymore. The last big-endian machine I used on an
410 everyday basis was the SPARCs in the university, more than 20 years
411 ago.</p>
412 <h3>Who gets paid to fix this?</h3>
413 <p>That's the question. Suse got paid to support Firefox on the s390x; I
414 suppose IBM has an interest in fixing LLVM there; both actually have
415 people and hardware and money to that effect.</p>
416 <p>Within Suse, I am by default responsible for keeping librsvg
417 working for the s390x as well — it gets built as part of the distro,
418 after all. I have never gotten an endianness bug report from the Suse
419 side of things.</p>
420 <p>Which leads me to suspect that, probably similar to Debian and Gentoo,
421 we <em>build</em> a lot of software because it's in the build chain, but we
422 don't <em>run</em> it to its fullest extent. Do people run GNOME desktops on
423 s390x virtual machines? Maybe? Did they not notice endianness bugs
424 <strong>because they were not in the code path that most GNOME icons
425 actually use</strong>? Who knows!</p>
426 <p>I'm thankful to Simon from the Debian bug for pointing out
427 the failure in librsvg's test case for masks, and to Mingcong for
428 actually showing a screenshot of a MATE desktop running on a PPC
429 PowerBook. Those were useful things for them to do.</p>
430 <p>Also — they were kind about it. It was a pleasure to interact with them.</p></content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category></entry><entry><title>Do not use librsvg 2.40.x</title><link href="https://people.gnome.org/~federico/blog/do-not-use-librsvg-2.40.x.html" rel="alternate"></link><published>2020-11-27T10:28:46-06:00</published><updated>2020-11-27T10:28:46-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-11-27:/~federico/blog/do-not-use-librsvg-2.40.x.html</id><summary type="html"><p>Please do not use librsvg 2.40.x; <strong>it cannot render recent Adwaita icon themes correctly</strong>.</p>
431 <p>The librsvg 2.40.x series is the last "C only" version of the library;
432 it was deprecated in 2017.</p>
433 <p>During the port to Rust, I rewrote the path parser to be
434 spec-compliant, and …</p></summary><content type="html"><p>Please do not use librsvg 2.40.x; <strong>it cannot render recent Adwaita icon themes correctly</strong>.</p>
435 <p>The librsvg 2.40.x series is the last "C only" version of the library;
436 it was deprecated in 2017.</p>
437 <p>During the port to Rust, I rewrote the path parser to be
438 spec-compliant, and fixed a few cases that the C version did not
439 handle. One of this cases is for compact Arc data.</p>
440 <p>The <a href="https://www.w3.org/TR/SVG11/paths.html#PathDataBNF">SVG path grammar</a> allows
441 one to remove whitespace between numbers if the next number starts
442 with a sign. For example, <code>23-45</code> gets parsed as two numbers <code>23
443 -45</code>.</p>
444 <p>In addition, the arguments of the Arc commands have two flags in the
445 middle of a bunch of numbers. The flags can be <code>0</code> or <code>1</code>, and there
446 may be no whitespace between the flags and the next number. For
447 example, <code>A1.98 1.98 0 0015 13.96</code> gets parsed as <code>A1.98 1.98 0 0 0 15
448 13.96</code> — note the two <code>0 0</code> flags before the <code>15</code>.</p>
449 <p>Librsvg 2.40.x does not parse this correctly.
450 Adwaita-icon-theme-3.36, and possibly earlier versions, uses minimized
451 SVG files with compressed whitespace, and will not render correctly
452 with the C-only version of librsvg.</p>
453 <p>This is <code>help-contents-symbolic.svg</code> rendered with librsvg 2.40.21:</p>
454 <p><img alt="icon rendered incorrectly" src="https://people.gnome.org/~federico/blog/images/help-contents-symbolic-2.40.21.png"></p>
455 <p>And this is <code>help-contents-symbolic.svg</code> rendered with librsvg 2.50.2:</p>
456 <p><img alt="icon rendered correctly" src="https://people.gnome.org/~federico/blog/images/help-contents-symbolic-2.50.2.png"></p>
457 <p>This is not the only icon with compact Arc commands; there are many
458 others that will also be mis-rendered in 2.40.x.</p>
459 <p>I don't know when Adwaita started using SVGs with compressed
460 whitespace; probably it didn't when librsvg 2.40.x was the latest
461 version, or everyone would have noticed mis-rendered icons.</p>
462 <p><strong>Background:</strong> Someone recently filed a
463 <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/654">bug</a> about
464 memory unsafety in librsvg 2.40.x's path parser, which mysteriously
465 enough only manifests itself in big-endian platforms. I wouldn't be
466 surprised if this had latent bugs on little-endian as well.</p>
467 <p>Please use at least librsvg 2.48.x; any earlier versions are not
468 supported. Generally I keep an eye on the last two stable release
469 sets (2.48.x and 2.50.x as of this writing), but only commit fixes to
470 the latest stable series (2.50.x currently).</p></content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category></entry><entry><title>Librsvg's test suite is now in Rust</title><link href="https://people.gnome.org/~federico/blog/librsvg-test-suite-is-now-in-rust.html" rel="alternate"></link><published>2020-10-26T10:38:12-06:00</published><updated>2020-10-26T10:38:12-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-10-26:/~federico/blog/librsvg-test-suite-is-now-in-rust.html</id><summary type="html"><p>Some important changes are afoot in librsvg.</p>
471 <h2>Changes to continuous integration</h2>
472 <p>Some days ago, <a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398">Dunja Lalic rewrote the continuous integration
473 scripts</a> to be much faster. A complete pipeline used to take
474 about 90 minutes to run, now it takes about 15 minutes on average.</p>
475 <p><img alt="Graph with pipeline timings, which shrink drastically" src="https://people.gnome.org/~federico/blog/images/librsvg-fast-ci.png" title="Guess when the CI changed"></p>
476 <p>The <a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398">description of changes</a> is interesting …</p></summary><content type="html"><p>Some important changes are afoot in librsvg.</p>
477 <h2>Changes to continuous integration</h2>
478 <p>Some days ago, <a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398">Dunja Lalic rewrote the continuous integration
479 scripts</a> to be much faster. A complete pipeline used to take
480 about 90 minutes to run, now it takes about 15 minutes on average.</p>
481 <p><img alt="Graph with pipeline timings, which shrink drastically" src="https://people.gnome.org/~federico/blog/images/librsvg-fast-ci.png" title="Guess when the CI changed"></p>
482 <p>The <a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398">description of changes</a> is interesting. The idea is to make tests fail as fast as possible, close to the beginning of the pipeline. To speed up the whole pipeline, Dunja did the following:</p>
483 <ul>
484 <li>
485 <p>Move the <code>cargo check</code> stage to the beginning. This test means,
486 "does this even have a chance of compiling?".</p>
487 </li>
488 <li>
489 <p>Have the code style and formatting tests, <code>cargo clippy</code> and <code>cargo
490 fmt</code>, run in parallel with the unit tests. These lints can fail,
491 but they are easy to fix after one is finished modifying the main
492 code.</p>
493 </li>
494 <li>
495 <p>Run the unit tests and the smoke tests in debug mode, so they compile
496 quickly.</p>
497 </li>
498 <li>
499 <p>Run the complete integration test suite in release mode. This takes
500 longer to compile, but there are some slow tests that benefit a lot
501 from faster execution.</p>
502 </li>
503 <li>
504 <p>Move the release tests until the end, and only run them once a week
505 — or whenever, by hand. These take a good amount of time to run,
506 because they do a full <code>make distcheck</code> and autotools is slow. Even
507 then, now these tests take 30-40 minutes, instead of the 90 from
508 before.</p>
509 </li>
510 <li>
511 <p>Between each stage of the pipeline, don't cache what doesn't help
512 reduce compilation time. It seems that keeping around a big cache,
513 with the whole build <code>target</code>, between each pipeline stage can be
514 worse than not having one at all.</p>
515 </li>
516 </ul>
517 <p><img alt="Complete pipeline with all the stages" src="https://people.gnome.org/~federico/blog/images/librsvg-complete-pipeline.png"></p>
518 <h2>Test suite in Rust</h2>
519 <p>Beteen Sven Neumann, Dunja Lalic, and myself we have finally <a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/408">ported
520 the test suite to Rust</a>: all of librsvg's tests are
521 now in Rust, except for the C API tests. We had to do a few things:</p>
522 <ul>
523 <li>
524 <p>Review the old tests and remove some obsolete ones.</p>
525 </li>
526 <li>
527 <p>Port each of the test modules to Rust. They are small, but each one
528 has special little things — test for crashes in the XML loading
529 code, test for crashes during rendering, test the library's security
530 limits.</p>
531 </li>
532 <li>
533 <p>Fix the small tests that come as part of the documentation.</p>
534 </li>
535 <li>
536 <p>Untangle the reference tests and port them to Rust.</p>
537 </li>
538 <li>
539 <p>Move little chunks of code around so the unit tests and integration
540 tests can share utilities to compare images, compute file paths for
541 test fixtures, etc.</p>
542 </li>
543 </ul>
544 <p>The most complicated thing to port was the reference tests. These are
545 the most important ones; each test loads an SVG document, renders it,
546 and compares the result to a reference PNG image. There are some
547 complications in the tests; they have to create a special
548 configuration for Fontconfig and Pango, so as to have reproducible
549 font rendering. The pango-rs bindings do not cover this part of
550 Pango, so we had to do some things by hand.</p>
551 <p>Anyway, <a href="https://gitlab.gnome.org/GNOME/librsvg/-/tree/master/tests/src">the tests are now in Rust</a>. One nice thing is that
552 now the tests run automatically in parallel, across all CPU cores, so
553 we save on total testing time.</p>
554 <h2>What's next: cargo-c and publish to crates.io</h2>
555 <p>We want to be able to <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/635">publish librsvg in crates.io</a> as a
556 normal crate; this implies being able to compile, test, and publish
557 entirely from Cargo. The compilation and testing part is done.</p>
558 <p>Now, we have to reorganize the code so it can be published to
559 crates.io. Librsvg comes in three parts, <code>rsvg_internals</code> with the
560 implementation of the library, <code>librsvg</code> with the traditional C API,
561 and <code>librsvg_crate</code> with the Rust API. However, to publish the Rust
562 API to crates.io, it would be more convenient to have a single crate
563 instead of one with the internals and one with the API.</p>
564 <p>The next step is thus to reorganize the code:</p>
565 <ul>
566 <li>
567 <p>Make it possible to implement the C API as a compile-time option on
568 top of the normal Rust code. We want to <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/552">use cargo-c</a> to
569 compile the traditional shared library <code>librsvg.so</code>, instead of
570 depending on C tools for compiling and linking.</p>
571 </li>
572 <li>
573 <p>Combine <code>rsvg_internals</code> and <code>librsvg_crate</code> in a single crate, to
574 publish them together. Crates.io has a 10 MB limit per crate; now
575 that the test suite lives in a separate <code>tests</code> crate, this
576 shouldn't be a problem.</p>
577 </li>
578 <li>
579 <p>I would like to <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/597">polish the public error types</a> before
580 publishing the Rust API; right now they expose some implementation
581 details that are of no interest to callers of the library.</p>
582 </li>
583 </ul>
584 <h2>What remains to be ported to Rust?</h2>
585 <p>Only two things, which amount to less than 900 lines of C code:</p>
586 <ul>
587 <li>
588 <p><a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/534">rsvg-convert</a> - the command-line program that everyone uses to
589 convert SVG to PNG and other formats. Fortunately, Sven Neumann
590 wrote some <a href="https://gitlab.gnome.org/GNOME/librsvg/-/blob/master/tests/src/cmdline/rsvg_convert.rs">fantastic tests</a> for rsvg-convert,
591 as it is like an API that we need to keep stable: if we change the
592 command-line options or the program's behavior, we would break
593 everyone's scripts.</p>
594 </li>
595 <li>
596 <p>The gdk-pixbuf module for loading SVG. Alberto Ruiz <a href="https://gitlab.gnome.org/GNOME/librsvg/-/tree/wip/aruiz/rust-pixbuf-loader">has started
597 porting it to Rust</a>. The generic part of this code
598 could later serve to wrap other Rust image codecs and plug them to
599 gdk-pixbuf.</p>
600 </li>
601 </ul></content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Librsvg is accepting interns for Outreachy's December 2020 round</title><link href="https://people.gnome.org/~federico/blog/librsvg-accepting-outreachy-interns-2020.html" rel="alternate"></link><published>2020-10-05T09:52:27-05:00</published><updated>2020-10-05T09:52:27-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-10-05:/~federico/blog/librsvg-accepting-outreachy-interns-2020.html</id><summary type="html"><p>There are two projects in librsvg available for <a href="https://www.outreachy.org">Outreachy</a> applicants
602 in the December 2020 / March 2021 round:</p>
603 <ul>
604 <li>
605 <p><strong>Revamp the text engine</strong> - Do you know about international text
606 layout? Can you read a right-to-left language, or do you write in a
607 language that requires complex shaping? Would you like to implement …</p></li></ul></summary><content type="html"><p>There are two projects in librsvg available for <a href="https://www.outreachy.org">Outreachy</a> applicants
608 in the December 2020 / March 2021 round:</p>
609 <ul>
610 <li>
611 <p><strong>Revamp the text engine</strong> - Do you know about international text
612 layout? Can you read a right-to-left language, or do you write in a
613 language that requires complex shaping? Would you like to implement
614 the <a href="https://www.w3.org/TR/SVG2/text.html">SVG 2 text specification</a> in a <a href="https://gitlab.gnome.org/GNOME/librsvg/-/blob/master/rsvg_internals/src/text.rs">pleasant Rust code
615 base</a>? This project requires someone who can write Rust
616 comfortably; it will require reading and refactoring some
617 existing code. You don't need to be an expert in exotic lifetimes
618 and trait bounds and such; the code doesn't use them.</p>
619 </li>
620 <li>
621 <p><strong>Implement SVG2/CSS3 features</strong> - Are you excited by all the <a href="https://www.w3.org/TR/SVG2/changes.html">SVG2
622 features</a> in Inkscape, and would like to add support for them
623 in librsvg? Would you like to do small changes to many parts of the
624 code to implement small features, one at a time? Do you like
625 test-driven development? This project requires someone who can
626 write Rust code at a medium level; you'll learn a lot by
627 cutting&amp;pasting from existing code and refactoring things to
628 implement SVG2 features.</p>
629 </li>
630 </ul>
631 <p><strong>Important:</strong> Outreachy's December 2020 / March 2021 round is available <a href="https://www.outreachy.org/docs/applicant/#eligibility">only
632 for students in the Southern hemisphere</a>. People in the
633 Northern hemisphere can wait until the 2021 mid-year round.</p>
634 <p>You can see <a href="https://www.outreachy.org/apply/project-selection/#gnome">GNOME's projects in Outreachy</a> for this round.
635 <strong>The deadline for initial contributions and project applications is
636 October 31, 2020 at 16:00 UTC.</strong></p></content><category term="misc"></category><category term="mentoring"></category><category term="librsvg"></category></entry><entry><title>"Rust does not have a stable ABI"</title><link href="https://people.gnome.org/~federico/blog/rust-stable-abi.html" rel="alternate"></link><published>2020-08-12T22:01:44-05:00</published><updated>2020-08-12T22:01:44-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-08-12:/~federico/blog/rust-stable-abi.html</id><summary type="html"><p>I've seen GNOME people (often, people who have been working for a long
637 time on C libraries) express concerns along the following lines:</p>
638 <ol>
639 <li>Compiled Rust code doesn't have a stable ABI (application binary interface).</li>
640 <li>So, we can't have shared libraries in the traditional fashion of
641 Linux distributions.</li>
642 <li>Also Rust bundles …</li></ol></summary><content type="html"><p>I've seen GNOME people (often, people who have been working for a long
643 time on C libraries) express concerns along the following lines:</p>
644 <ol>
645 <li>Compiled Rust code doesn't have a stable ABI (application binary interface).</li>
646 <li>So, we can't have shared libraries in the traditional fashion of
647 Linux distributions.</li>
648 <li>Also Rust bundles its entire standard library with every binary it compiles, which makes Rust-built libraries huge.</li>
649 </ol>
650 <p>These are extremely valid concerns to be addressed by people like
651 myself who propose that chunks of infrastructural libraries
652 should be done in Rust.</p>
653 <p>So, let's begin.</p>
654 <p>The first part of this article is a super-quick introduction to shared
655 libraries and how Linux distributions use them. If you already know
656 those things, feel free to skip to the "<a href="#rust_does_not_have_a_stable_abi">Rust does not have a stable
657 ABI</a>" section.</p>
658 <h2>How do distributions use shared libraries?</h2>
659 <p>If several programs run at the same time and use the same shared library
660 (say, <code>libgtk-3.so</code>), the operating system can load a single copy of
661 the library in memory and share the read-only parts of the code/data
662 through the magic of virtual memory.</p>
663 <p><em>In theory</em>, if a library gets a bugfix but does not change its
664 interface, one can just recompile the library, stick the new <code>.so</code> in
665 <code>/usr/lib</code> or whatever, and be done with it. Programs that depend on
666 the library do not need to be recompiled.</p>
667 <p>If libraries limit their public interface to a plain C ABI
668 (application binary interface), they are relatively easy to consume
669 from other programming languages. Those languages don't have to deal
670 with name mangling of C++ symbols, exception handlers, constructors,
671 and all that complexity. Pretty much every language has some form of
672 C FFI (foreign function interface), which roughly means "call C
673 functions without too much trouble".</p>
674 <p>For the purposes of a library, what's an
675 <a href="https://en.wikipedia.org/wiki/Application_binary_interface">ABI</a>?
676 Wikipedia says, "An ABI defines how data structures or computational
677 routines are accessed in machine code [...] A common aspect of an
678 ABI is the calling convention", which means that to call a function in
679 machine code you need to frob the call and stack pointers, pass some
680 function arguments in registers or push some others to the stack, etc.
681 Really low-level stuff. Each machine architecture or operating system
682 usually defines a C standard ABI.</p>
683 <p>For libraries, we commonly understand an ABI to mean the machine-code
684 implications of their programming interface. Which functions are
685 available as public symbols in the <code>.so</code> file? To which numeric
686 values do C enum values correspond, so that they can be passed to
687 those functions? What is the exact order and type of arguments that
688 the functions take? What are the struct sizes, and the order and
689 types and padding of the fields that those functions take? Does one
690 pass arguments in CPU registers or on the stack? Does the caller or
691 the callee clean up the stack after a function call?</p>
692 <h2>Bug fixes and security fixes</h2>
693 <p>Linux distributions generally try <em>really hard</em> to have a single
694 version of each shared library installed in the system: a single
695 <code>libjpeg.so</code>, a single <code>libpng.so</code>, a single <code>libc.so</code>, etc.</p>
696 <p>This is helpful when there needs to be an update to fix a bug,
697 security-related or not: users can just download the updated package
698 for the library, which when installed will just stick in a new <code>.so</code>
699 in the right place, and the calling software won't need to be updated.</p>
700 <p>This is possible only if the bug <em>really only changes the internal
701 code</em> without changing behavior or interface. If a bug fix requires
702 part of the public API or ABI to change, then you are screwed; all
703 calling software needs to be recompiled. "Irresponsible" library
704 authors either learn really fast when distros complain loudly about
705 this sort of change, or they don't learn and get forever marked by
706 distros as "that irresponsible library" which always requires special
707 handling in order not to break other software.</p>
708 <p>Sidenote: sometimes it's more complicated. Poppler (the PDF
709 rendering library) ships at least two stable APIs, one Glib-based in
710 C, and one Qt-based in C++. However, some software like texlive uses
711 Poppler's internals library directly, which of course does not have a
712 stable API, and thus texlive breaks frequently as Poppler evolves.
713 Someone should extend the public, stable API so that texlive doesn't
714 have to use the library's internals!</p>
715 <h2>Bundled libraries</h2>
716 <p>Sometimes it is not irresponsible authors of libraries, but rather
717 that people who use the libraries find out that over time the behavior
718 of the library changes subtly, maybe without breaking the API or ABI,
719 and they are better off bundling a specific version of the library
720 with their software. That version is what they test their software
721 against, and they try to learn its quirks.</p>
722 <p>Distros inevitably complain about this, and either patch the calling
723 software by hand to force it to use the system's shared library, or
724 succeed in getting patches accepted by the software so that they have
725 a <code>--use-system-libjpeg</code> option or similar.</p>
726 <p>This doesn't work very well if the bundled version of the library has
727 extra patches that are not in a distro's usual patches. Or
728 vice-versa; it may actually work better to use the distro's version of
729 the library, if it has extra fixes that the bundled library doesn't.
730 Who knows! It's a case-by-case situation.</p>
731 <h2 id="rust_does_not_have_a_stable_abi">Rust does not have a stable ABI</h2>
732 <p>By default indeed it doesn't, because the compiler team wants to have
733 the freedom to change the data layout and Rust-to-Rust calling
734 conventions, often for performance reasons, at any time. For example,
735 it is not guaranteed that struct fields will be laid out in memory in
736 the same order as they are written in the code:</p>
737 <div class="highlight"><pre><span></span><code><span class="k">struct</span> <span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
738 <span class="w"> </span><span class="n">bar</span>: <span class="kt">bool</span><span class="p">,</span><span class="w"></span>
739 <span class="w"> </span><span class="n">baz</span>: <span class="kt">f64</span><span class="p">,</span><span class="w"></span>
740 <span class="w"> </span><span class="n">beep</span>: <span class="kt">bool</span><span class="p">,</span><span class="w"></span>
741 <span class="w"> </span><span class="n">qux</span>: <span class="kt">i32</span><span class="p">,</span><span class="w"></span>
742 <span class="p">}</span><span class="w"></span>
743 </code></pre></div>
744
745 <p>The compiler is free to rearrange the struct fields in memory as it
746 sees fit. Maybe it decides to put the two <code>bool</code> fields next to each
747 other to save on inter-field padding due to alignment requirements;
748 maybe it does static analysis or profile-guided optimizations and
749 picks an optmal ordering.</p>
750 <p>But we can override this! Let's look at data layout first, and then
751 calling conventions.</p>
752 <h3>Data layout for C versus Rust</h3>
753 <p>The following is the same struct as above, but with an extra <code>#[repr(C)]</code> attribute:</p>
754 <div class="highlight"><pre><span></span><code><span class="cp">#[repr(C)]</span><span class="w"></span>
755 <span class="k">struct</span> <span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
756 <span class="w"> </span><span class="n">bar</span>: <span class="kt">bool</span><span class="p">,</span><span class="w"></span>
757 <span class="w"> </span><span class="n">baz</span>: <span class="kt">f64</span><span class="p">,</span><span class="w"></span>
758 <span class="w"> </span><span class="n">beep</span>: <span class="kt">bool</span><span class="p">,</span><span class="w"></span>
759 <span class="w"> </span><span class="n">qux</span>: <span class="kt">i32</span><span class="p">,</span><span class="w"></span>
760 <span class="p">}</span><span class="w"></span>
761 </code></pre></div>
762
763 <p>With that attribute, the struct will be laid out just as this C struct:</p>
764 <div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"></span>
765 <span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp"></span>
766
767 <span class="k">struct</span> <span class="nc">Foo</span> <span class="p">{</span>
768 <span class="kt">bool</span> <span class="n">bar</span><span class="p">;</span>
769 <span class="kt">double</span> <span class="n">baz</span><span class="p">;</span>
770 <span class="kt">bool</span> <span class="n">beep</span><span class="p">;</span>
771 <span class="kt">int32_t</span> <span class="n">qux</span><span class="p">;</span>
772 <span class="p">}</span>
773 </code></pre></div>
774
775 <p>(Aside: it is unfortunate that <a href="https://people.gnome.org/~federico/news-2017-04.html#gboolean-is-not-rust-bool"><code>gboolean</code> is not <code>bool</code></a>,
776 but that's because <code>gboolean</code> predates C99, and clearly standards from
777 20 years ago are <em>too new</em> to use. (Aside aside: since I wrote that
778 other post, Rust's repr(C) for bool is actually defined as C99's bool;
779 it's no longer undefined.))</p>
780 <p>Even Rust's data-carrying enums can be laid out in a manner friendly
781 to C and C++:</p>
782 <div class="highlight"><pre><span></span><code><span class="cp">#[repr(C, u8)]</span><span class="w"></span>
783 <span class="k">enum</span> <span class="nc">MyEnum</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
784 <span class="w"> </span><span class="n">A</span><span class="p">(</span><span class="kt">u32</span><span class="p">),</span><span class="w"></span>
785 <span class="w"> </span><span class="n">B</span><span class="p">(</span><span class="kt">f32</span><span class="p">,</span><span class="w"> </span><span class="kt">bool</span><span class="p">),</span><span class="w"></span>
786 <span class="p">}</span><span class="w"></span>
787 </code></pre></div>
788
789 <p>This means, use C layout, and a <code>u8</code> for the enum's discriminant. It
790 will be laid out like this:</p>
791 <div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"></span>
792 <span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp"></span>
793
794 <span class="k">enum</span> <span class="n">MyEnumTag</span> <span class="p">{</span>
795 <span class="n">A</span><span class="p">,</span>
796 <span class="n">B</span>
797 <span class="p">};</span>
798
799 <span class="k">typedef</span> <span class="kt">uint32_t</span> <span class="n">MyEnumPayloadA</span><span class="p">;</span>
800
801 <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
802 <span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
803 <span class="kt">bool</span> <span class="n">y</span><span class="p">;</span>
804 <span class="p">}</span> <span class="n">MyEnumPayloadB</span><span class="p">;</span>
805
806 <span class="k">typedef</span> <span class="k">union</span> <span class="p">{</span>
807 <span class="n">MyEnumPayloadA</span> <span class="n">a</span><span class="p">;</span>
808 <span class="n">MyEnumPayloadB</span> <span class="n">b</span><span class="p">;</span>
809 <span class="p">}</span> <span class="n">MyEnumPayload</span><span class="p">;</span>
810
811 <span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
812 <span class="kt">uint8_t</span> <span class="n">tag</span><span class="p">;</span>
813 <span class="n">MyEnumPayload</span> <span class="n">payload</span><span class="p">;</span>
814 <span class="p">}</span> <span class="n">MyEnum</span><span class="p">;</span>
815 </code></pre></div>
816
817 <p>The gory details of data layout are in the <a href="https://doc.rust-lang.org/nomicon/other-reprs.html">Alternative Representations section of the
818 Rustonomicon</a> and
819 the <a href="https://rust-lang.github.io/unsafe-code-guidelines/introduction.html">Unsafe Code
820 Guidelines</a>.</p>
821 <h3>Calling conventions</h3>
822 <p>An ABI's calling conventions detail things like how to call functions
823 in machine code, and how to lay out function arguments in registers or
824 the stack. <a href="https://en.wikipedia.org/wiki/X86_calling_conventions">The wikipedia page on X86 calling
825 conventions</a>
826 has a good cheat-sheet, useful when you are looking at assembly code
827 and registers in a low-level debugger.</p>
828 <p>I've already written about how it is possible to write Rust code to
829 export functions callable from C; one uses the <code>extern "C"</code> in the
830 function definition and a <code>#[no_mangle]</code> attribute to keep the symbol
831 name pristine. This is how librsvg is able to have the following:</p>
832 <div class="highlight"><pre><span></span><code><span class="cp">#[no_mangle]</span><span class="w"></span>
833 <span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">extern</span><span class="w"> </span><span class="s">&quot;C&quot;</span><span class="w"> </span><span class="k">fn</span> <span class="nf">rsvg_handle_new_from_file</span><span class="p">(</span><span class="w"></span>
834 <span class="w"> </span><span class="n">filename</span>: <span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="n">libc</span>::<span class="n">c_char</span><span class="p">,</span><span class="w"></span>
835 <span class="w"> </span><span class="n">error</span>: <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">glib_sys</span>::<span class="n">GError</span><span class="p">,</span><span class="w"></span>
836 <span class="p">)</span><span class="w"> </span>-&gt; <span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="n">RsvgHandle</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
837 <span class="w"> </span><span class="c1">// ...</span>
838 <span class="p">}</span><span class="w"></span>
839 </code></pre></div>
840
841 <p>Which compiles to what a C compiler would produce for this:</p>
842 <div class="highlight"><pre><span></span><code><span class="n">RsvgHandle</span> <span class="o">*</span><span class="nf">rsvg_handle_new_from_file</span> <span class="p">(</span><span class="k">const</span> <span class="n">gchar</span> <span class="o">*</span><span class="n">filename</span><span class="p">,</span> <span class="n">GError</span> <span class="o">**</span><span class="n">error</span><span class="p">);</span>
843 </code></pre></div>
844
845 <p>(Aside: librsvg <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/416">still uses an intermediate C library full of
846 stubs</a> that just
847 call the Rust-exported functions, but there is now <a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/552">tooling to produce a .so
848 directly from
849 Rust</a> which I
850 just haven't had time to investigate. Help is appreciated!)</p>
851 <h3>Summary of ABI so far</h3>
852 <p>It is <em>one's decision</em> to export a stable C ABI from a Rust library.
853 There is some awkwardness in how types are laid out in C, because the
854 Rust type system is richer, but things can be made to work well with a
855 little thought. Certainly no more thought than the burden of
856 designing and maintaining a stable API/ABI in plain C.</p>
857 <p>I'll fold the second concern into here — "we can't have shared
858 libraries in traditional distro fashion". Yes, we can, API/ABI-wise,
859 but read on.</p>
860 <h2>Rust bundles its entire standard library with Rust-built .so's</h2>
861 <p>I.e. it statically links all the Rust dependencies. This produces a
862 large .so:</p>
863 <ul>
864 <li>librsvg-2.so (version 2.40.21, C only) - 1408840 bytes</li>
865 <li>librsvg-2.so (version 2.49.3, Rust only) - 9899120 bytes</li>
866 </ul>
867 <p>Holy crap! What's all that?</p>
868 <p>(And I'm cheating: this is both with link-time optimization turned on,
869 and by running <code>strip(1)</code> on the .so. If you just <code>autogen.sh &amp;&amp; make</code>
870 it will be bigger.)</p>
871 <p>This has Rust's standard library statically linked (or at least the
872 bits of that librsvg actually uses), plus all the Rust dependencies
873 (cssparser, selectors, nalgebra, glib-rs, cairo-rs, locale_config,
874 rayon, xml5ever, and an assload of crates). I could explain why each
875 one is needed:</p>
876 <ul>
877 <li>cssparser - librsvg needs to parse CSS.</li>
878 <li>selectors - librsvg needs to run the CSS selector matching
879 algorithm.</li>
880 <li>nalgebra - the code for SVG filter effects uses vectors and
881 matrices.</li>
882 <li>glib-rs, cairo-rs - draw to Cairo and export GObject types.</li>
883 <li>locale_config - so that localized SVG files can work.</li>
884 <li>rayon - so filters can use all your CPU cores instead of processing
885 one pixel at a time.</li>
886 <li>Etcetera. SVG is big and requires a lot of helper code!</li>
887 </ul>
888 <p>Is this a problem?</p>
889 <p>Or more exactly, why does this happen, and why do people perceive it
890 as a problem?</p>
891 <h3>Stable APIs/ABIs and distros</h3>
892 <p>Many Linux distributions have worked <em>really hard</em> to ensure that
893 there is a single copy of "system libraries" in an installation.
894 There is Just One Copy of <code>/usr/lib/libc.so</code>, <code>/usr/lib/libjpeg.so</code>,
895 etc., and packages are compiled with special options to tell them to
896 really use the sytem libraries instead of their bundled versions, or
897 patched to do so if they don't provide build-time options for that.</p>
898 <p>In a way, this works well for distros:</p>
899 <ul>
900 <li>
901 <p>A bug in a library can be fixed in a single place, and all
902 applications that use it get the fix automatically.</p>
903 </li>
904 <li>
905 <p>A security bug can be patched in a single place, and in theory
906 applications don't need to be audited further.</p>
907 </li>
908 </ul>
909 <p>If you maintain a library that is shipped in Linux distros, and you
910 break the ABI, you'll get complaints from distros very quickly.</p>
911 <p>This is good because it creates responsible maintainers for libraries
912 that can be depended on. It's how Inkscape/GIMP can have a stable
913 toolkit to be written in.</p>
914 <p>This is bad because it encourages stagnation in the long term. It's
915 how we get a horrible, unsafe, error-prone API in libjpeg that can
916 never ever be improved because it would requires changes in tons of
917 software; it's why <code>gboolean</code> is still a 32-bit <code>int</code> after
918 twenty-something years, even though everything else close to C has
919 decided that booleans are 1 byte. It's how Inkscape/GIMP take many
920 years to move from GTK2 to GTK3 (okay, that's lack of paid developers
921 to do the grunt work, but it is enabled by having forever-stable APIs).</p>
922 <p>However, a long-term stable API/ABI has a <strong>lot of value</strong>. It is why
923 the Windows API is the crown jewels; it is why people can rely on glib
924 and glibc to not break their code for many years and take them for granted.</p>
925 <h3>But we only have a single stable ABI anyway</h3>
926 <p>And that is the C ABI. Even C++ libraries have trouble with this, and
927 people sometimes write the internals of a library in C++ for
928 convenience, but export a stable C API/ABI from it.</p>
929 <p>High level languages like Python have <em>real trouble</em> calling C++ code
930 precisely because of ABI issues.</p>
931 <h3>Actually, in GNOME we have gone further than that</h3>
932 <p>In GNOME we have constructed a sweet little universe where <a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html">GObject
933 Introspection</a> is
934 basically a C ABI with a ton of machine-generated annotations to make
935 it friendly to language bindings.</p>
936 <p>Still, we rely on a C ABI underneath. See <a href="https://twitter.com/federicomena/status/1286447929880801280">this exploratory twitter
937 thread on advancing the C ABI from Rust</a> for
938 lots of food for thought.</p>
939 <h3>Single copies of libraries with a C ABI</h3>
940 <p>Okay, let's go back to this. What price do we pay for single copies
941 of libraries that, by necessity, must export a C ABI?</p>
942 <ul>
943 <li>
944 <p>Code that can be conveniently called from C, maybe from C++, and
945 moderately to very inconvently from ANYTHING ELSE. With most new
946 application code being written definitely not in C, maybe we should
947 reconsider our priorities here.</p>
948 </li>
949 <li>
950 <p>No language facilities like generics or field visibility, which are
951 not even "modern language" features. Even C++ templates get
952 compiled and statically linked into the calling code, because
953 there's no way to pass information like the size of <code>T</code> in
954 <code>Array&lt;T&gt;</code> across a C ABI. You wanted to make some struct fields
955 public and some private? You are out of luck.</p>
956 </li>
957 <li>
958 <p>No knowledge of data ownership except by careful reading of the C
959 function's documentation. Does the function free its arguments?
960 How - with <code>free()</code> or <code>g_free()</code> or <code>my_thing_free()</code>? Or does the
961 caller just lend it a reference? Can the data be copied bit-by-bit
962 or must a special function be called to make a copy?
963 GObject-Introspection carries this information in its annotations,
964 while the C ABI has no idea and just ships raw pointers around.</p>
965 </li>
966 </ul>
967 <p>More food for thought note: <a href="https://twitter.com/hsivonen/status/1232204147740508162">this twitter
968 thread</a> says
969 this about the C++ ABI: "Also, the ABI matters for whether the actual
970 level of practicality of complying with LGPL matches the level of
971 practicality intended years ago when some project picked LGPL as its
972 license. Of course, the standard does not talk about LGPL, either.
973 LGPL has rather different implications for Rust and Go than it does
974 for C and Java. It was obviously written with C in mind."</p>
975 <h2>Monomorphization and template bloat</h2>
976 <p>While C++ had the problem of "lots of template code in header files",
977 Rust has the problem that <a href="https://pingcap.com/blog/generics-and-compile-time-in-rust#monomorphized-generics">monomorphization of generics creates a lot
978 of compiled
979 code</a>.
980 There are tricks to avoid this and they are all the decision of the
981 library/crate author. Both share the root cause that templated or
982 generic code must be recompiled for every specific use, and thus
983 cannot live in a shared library.</p>
984 <p>Also, see this wonderful <a href="https://thume.ca/2019/07/14/a-tour-of-metaprogramming-models-for-generics/">article on how different languages implement
985 generics</a>,
986 and think that a plain C ABI means we have NOTHING of the sort.</p>
987 <p>Also, see <a href="https://gankra.github.io/blah/swift-abi/">How Swift Achieved Dynamic Linking Where Rust
988 Couldn't</a> for more food for
989 thought. This is extremely roughly equivalent to GObject's boxed
990 types; callers keep values on the heap but know the type layout via
991 annotation magic, while the library's actual implementation
992 is free to have the values on the stack or wherever for its own use.</p>
993 <h2>Should all libraries export APIs with generics and exotic types?</h2>
994 <p>No!</p>
995 <p>You probably want something like a low-level array of values,
996 <code>Vec&lt;T&gt;</code>, to be inlined everywhere and with code that knows the
997 type of the vector's elements. Element accesses can be inlined to a
998 single machine instruction in the best case.</p>
999 <p>But not everything requires this absolute raw performance with
1000 everything inlined everywhere. It is fine to pass references or
1001 pointers to things and do dynamic dispatch from a vtable if you are
1002 not in a super-tight loop, as we love to do in the GObject world.</p>
1003 <h2>Library sizes</h2>
1004 <p>I don't have a good answer to librsvg's compiled size. If gnome-shell
1005 merges my branch to rustify the CSS code, it will also grow its binary
1006 size by quite a bit.</p>
1007 <p>It is my intention to have a Rust crate that both librsvg and
1008 gnome-shell share for their CSS styling needs, but right now I have no
1009 idea if this would be a shared library or just a normal Rust crate.
1010 Maybe it's possible to have a very general CSS library, and the
1011 application registers which properties it can parse and how? Is it
1012 possible to do this as a shared library without essentially
1013 reinventing libcroco? I don't know yet. We'll see.</p>
1014 <h2>A metaphor which I haven't fully explored</h2>
1015 <p>If every application or end-user package is kind of like a living
1016 organism, with its own cycles and behaviors and organs (dependent
1017 libraries) that make it possible...</p>
1018 <p>Why do distros expect all the living organisms on your machine to
1019 share The World's Single Lungs Service, and The World's Single Stomach
1020 Service, and The World's Single Liver Service?</p>
1021 <p>You know, instead of letting every organism have its own slightly
1022 different version of those organs, customized for it? We humans know
1023 how to do vaccination campaigns and everything; maybe we need better
1024 tools to apply bug fixes where they are needed?</p>
1025 <p>I know this metaphor is extremely imperfect and not how things work in
1026 software, but it makes me wonder.</p></content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Looking for candidates for the 2020 GNOME Foundation elections</title><link href="https://people.gnome.org/~federico/blog/looking-for-candidates-2020.html" rel="alternate"></link><published>2020-05-26T17:05:31-05:00</published><updated>2020-05-26T17:05:31-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-05-26:/~federico/blog/looking-for-candidates-2020.html</id><summary type="html"><p>I forgot to write this a few days ago; I hope it is not too late.</p>
1027 <p>The GNOME Foundation's <a href="https://mail.gnome.org/archives/foundation-announce/2020-May/msg00000.html">elections for the Board</a> are coming
1028 up, and we are looking for candidates. Of the 7 directors, we are
1029 replacing 4, and the 3 remaining positions remain for another year.
1030 You …</p></summary><content type="html"><p>I forgot to write this a few days ago; I hope it is not too late.</p>
1031 <p>The GNOME Foundation's <a href="https://mail.gnome.org/archives/foundation-announce/2020-May/msg00000.html">elections for the Board</a> are coming
1032 up, and we are looking for candidates. Of the 7 directors, we are
1033 replacing 4, and the 3 remaining positions remain for another year.
1034 You could be one of those four.</p>
1035 <p>I would like it very much if there were candidates and directors that
1036 fall outside the box of "white male programmer"; it is unfortunate
1037 that for the current Board we ended up with all dudes. GNOME has a
1038 <a href="https://wiki.gnome.org/Foundation/CodeOfConduct">Code of Conduct</a> to make it a good place to be.</p>
1039 <p>Allan Day wrote a <a href="https://blogs.gnome.org/aday/2020/05/26/gnome-foundation-board-of-directors-a-year-in-review/">review of the Board's activies for the last
1040 year</a>. We are moving from a model where the Board does a
1041 little bit of everything, to one with a more strategic role — now that
1042 the Foundation has full-time employees, they take care of most of the
1043 executive work.</p>
1044 <p><strong>The call-for-candidates is open until May 29, so hurry up!</strong></p>
1045 <ul>
1046 <li><a href="https://blogs.gnome.org/aday/2020/05/26/gnome-foundation-board-of-directors-a-year-in-review/">GNOME Foundation Board of Directors: a Year in Review</a></li>
1047 <li><a href="https://mail.gnome.org/archives/foundation-announce/2020-May/msg00000.html">Call for candidates and elections</a></li>
1048 </ul></content><category term="misc"></category><category term="gnome"></category></entry><entry><title>Bringing my Emacs from the past</title><link href="https://people.gnome.org/~federico/blog/bringing-my-emacs-from-the-past.html" rel="alternate"></link><published>2020-04-28T18:03:22-05:00</published><updated>2020-04-28T18:03:22-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-04-28:/~federico/blog/bringing-my-emacs-from-the-past.html</id><summary type="html"><p>I started using Emacs in 1995, and since then I have been carrying a <code>.emacs</code>
1049 that by now has a lot of accumulated crap. It is such an old configuration that
1050 it didn't even use the modern convention of <code>~/.emacs.d/init.el</code> (and it looks
1051 like a newer Emacs …</p></summary><content type="html"><p>I started using Emacs in 1995, and since then I have been carrying a <code>.emacs</code>
1052 that by now has a lot of accumulated crap. It is such an old configuration that
1053 it didn't even use the modern convention of <code>~/.emacs.d/init.el</code> (and it looks
1054 like a newer Emacs version will allow <code>.config/emacs</code> as per the XDG
1055 standard... at last).</p>
1056 <p>I have wanted to change my Emacs configuration for some time, and give it all
1057 the pretty and modern toys.</p>
1058 <p>The things that matter the most to me:</p>
1059 <ul>
1060 <li>Not have a random dumpster in <code>~/.emacs</code> if possible.</li>
1061 <li>Pretty colors.</li>
1062 <li>Magit.</li>
1063 <li>Rust-mode or whatever the new thing is for rust-analyzer and the Language Server.</li>
1064 </ul>
1065 <p>After looking at several examples of configurations that mention <code>use-package</code>
1066 as a unified way of loading packages and configuring them, I found <a href="https://github.com/alhassy/emacs.d">this
1067 configuration</a> which is extremely well
1068 documented. The author does literate programming with org-mode and elisp —
1069 something which I'm casually interested in, but not just now — but that way
1070 everything ends up very well explained and easy to read.</p>
1071 <p>I extracted bits of that configuration and ended up with the following.</p>
1072 <h2>Everything in <code>~/.emacs/init.el</code> and with <code>use-package</code></h2>
1073 <div class="highlight"><pre><span></span><code><span class="c1">;; Initialize package system</span>
1074
1075 <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;package</span><span class="p">)</span>
1076
1077 <span class="p">(</span><span class="k">setq</span> <span class="nv">package-archives</span>
1078 <span class="o">&#39;</span><span class="p">((</span><span class="s">&quot;org&quot;</span> <span class="o">.</span> <span class="s">&quot;https://orgmode.org/elpa/&quot;</span><span class="p">)</span>
1079 <span class="p">(</span><span class="s">&quot;gnu&quot;</span> <span class="o">.</span> <span class="s">&quot;https://elpa.gnu.org/packages/&quot;</span><span class="p">)</span>
1080 <span class="p">(</span><span class="s">&quot;melpa&quot;</span> <span class="o">.</span> <span class="s">&quot;https://melpa.org/packages/&quot;</span><span class="p">)))</span>
1081
1082 <span class="p">(</span><span class="nv">package-initialize</span><span class="p">)</span>
1083 <span class="c1">;(package-refresh-contents)</span>
1084
1085 <span class="c1">;; Use-package for civilized configuration</span>
1086
1087 <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">package-installed-p</span> <span class="ss">&#39;use-package</span><span class="p">)</span>
1088 <span class="p">(</span><span class="nv">package-install</span> <span class="ss">&#39;use-package</span><span class="p">))</span>
1089 <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;use-package</span><span class="p">)</span>
1090
1091 <span class="p">(</span><span class="k">setq</span> <span class="nv">use-package-always-ensure</span> <span class="no">t</span><span class="p">)</span>
1092 </code></pre></div>
1093
1094 <h2><code>~/.emacs.d/custom.el</code> for <code>M-x customize</code> stuff</h2>
1095 <div class="highlight"><pre><span></span><code><span class="c1">;; Set customization data in a specific file, without littering</span>
1096 <span class="c1">;; my init files.</span>
1097
1098 <span class="p">(</span><span class="k">setq</span> <span class="nv">custom-file</span> <span class="s">&quot;~/.emacs.d/custom.el&quot;</span><span class="p">)</span>
1099 <span class="p">(</span><span class="nf">load</span> <span class="nv">custom-file</span><span class="p">)</span>
1100 </code></pre></div>
1101
1102 <h2>Which-key to get hints when typing command prefixes</h2>
1103 <div class="highlight"><pre><span></span><code><span class="c1">;; Make it easier to discover key shortcuts</span>
1104
1105 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">which-key</span>
1106 <span class="nb">:diminish</span>
1107 <span class="nb">:config</span>
1108 <span class="p">(</span><span class="nv">which-key-mode</span><span class="p">)</span>
1109 <span class="p">(</span><span class="nv">which-key-setup-side-window-bottom</span><span class="p">)</span>
1110 <span class="p">(</span><span class="k">setq</span> <span class="nv">which-key-idle-delay</span> <span class="mf">0.1</span><span class="p">))</span>
1111 </code></pre></div>
1112
1113 <h2>Don't pollute the modeline with common modes</h2>
1114 <div class="highlight"><pre><span></span><code><span class="c1">;; Do not show some common modes in the modeline, to save space</span>
1115
1116 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">diminish</span>
1117 <span class="nb">:defer</span> <span class="mi">5</span>
1118 <span class="nb">:config</span>
1119 <span class="p">(</span><span class="nv">diminish</span> <span class="ss">&#39;org-indent-mode</span><span class="p">))</span>
1120 </code></pre></div>
1121
1122 <h2>Magit to use git in a civilized fashion</h2>
1123 <div class="highlight"><pre><span></span><code><span class="c1">;; Magit</span>
1124
1125 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">magit</span>
1126 <span class="nb">:config</span>
1127 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;C-x g&quot;</span><span class="p">)</span> <span class="ss">&#39;magit-status</span><span class="p">))</span>
1128 </code></pre></div>
1129
1130 <h2>Move between windows with Shift-arrows</h2>
1131 <div class="highlight"><pre><span></span><code><span class="c1">;; Let me switch windows with shift-arrows instead of &quot;C-x o&quot; all the time</span>
1132 <span class="p">(</span><span class="nv">windmove-default-keybindings</span><span class="p">)</span>
1133 </code></pre></div>
1134
1135 <h2>Pretty colors</h2>
1136 <p>I was using <code>solarized-dark</code> but I like this one even better:</p>
1137 <div class="highlight"><pre><span></span><code><span class="c1">;; Pretty colors</span>
1138
1139 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">flatland-theme</span>
1140 <span class="nb">:config</span>
1141 <span class="p">(</span><span class="nv">custom-theme-set-faces</span> <span class="ss">&#39;flatland</span>
1142 <span class="o">&#39;</span><span class="p">(</span><span class="nv">show-paren-match</span> <span class="p">((</span><span class="no">t</span> <span class="p">(</span><span class="nb">:background</span> <span class="s">&quot;dark gray&quot;</span> <span class="nb">:foreground</span> <span class="s">&quot;black&quot;</span> <span class="nb">:weight</span> <span class="nv">bold</span><span class="p">))))</span>
1143 <span class="o">&#39;</span><span class="p">(</span><span class="nv">show-paren-mismatch</span> <span class="p">((</span><span class="no">t</span> <span class="p">(</span><span class="nb">:background</span> <span class="s">&quot;firebrick&quot;</span> <span class="nb">:foreground</span> <span class="s">&quot;orange&quot;</span> <span class="nb">:weight</span> <span class="nv">bold</span><span class="p">))))))</span>
1144 </code></pre></div>
1145
1146 <h2>Nyan cat instead of scrollbars</h2>
1147 <div class="highlight"><pre><span></span><code><span class="c1">;; Nyan cat instead of scrollbar</span>
1148 <span class="c1">;; scroll-bar-mode is turned off in custom.el</span>
1149
1150 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">nyan-mode</span>
1151 <span class="nb">:config</span>
1152 <span class="p">(</span><span class="nv">nyan-mode</span> <span class="mi">1</span><span class="p">))</span>
1153 </code></pre></div>
1154
1155 <h2>Move buffers to adjacent windows</h2>
1156 <div class="highlight"><pre><span></span><code><span class="c1">;; Move buffers between windows</span>
1157
1158 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">buffer-move</span>
1159 <span class="nb">:config</span>
1160 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;&lt;C-S-up&gt;&quot;</span><span class="p">)</span> <span class="ss">&#39;buf-move-up</span><span class="p">)</span>
1161 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;&lt;C-S-down&gt;&quot;</span><span class="p">)</span> <span class="ss">&#39;buf-move-down</span><span class="p">)</span>
1162 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;&lt;C-S-left&gt;&quot;</span><span class="p">)</span> <span class="ss">&#39;buf-move-left</span><span class="p">)</span>
1163 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;&lt;C-S-right&gt;&quot;</span><span class="p">)</span> <span class="ss">&#39;buf-move-right</span><span class="p">))</span>
1164 </code></pre></div>
1165
1166 <h2>Change buffer names for files with the same name</h2>
1167 <div class="highlight"><pre><span></span><code><span class="c1">;; Note that ‘uniquify’ is builtin.</span>
1168 <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;uniquify</span><span class="p">)</span>
1169 <span class="p">(</span><span class="k">setq</span> <span class="nv">uniquify-separator</span> <span class="s">&quot;/&quot;</span> <span class="c1">;; The separator in buffer names.</span>
1170 <span class="nv">uniquify-buffer-name-style</span> <span class="ss">&#39;forward</span><span class="p">)</span> <span class="c1">;; names/in/this/style</span>
1171 </code></pre></div>
1172
1173 <h2>Helm to auto-complete in grand style</h2>
1174 <div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">helm</span>
1175 <span class="nb">:diminish</span>
1176 <span class="nb">:init</span> <span class="p">(</span><span class="nv">helm-mode</span> <span class="no">t</span><span class="p">)</span>
1177 <span class="nb">:bind</span> <span class="p">((</span><span class="s">&quot;M-x&quot;</span> <span class="o">.</span> <span class="nv">helm-M-x</span><span class="p">)</span>
1178 <span class="p">(</span><span class="s">&quot;C-x C-f&quot;</span> <span class="o">.</span> <span class="nv">helm-find-files</span><span class="p">)</span>
1179 <span class="p">(</span><span class="s">&quot;C-x b&quot;</span> <span class="o">.</span> <span class="nv">helm-mini</span><span class="p">)</span> <span class="c1">;; See buffers &amp; recent files; more useful.</span>
1180 <span class="p">(</span><span class="s">&quot;C-x r b&quot;</span> <span class="o">.</span> <span class="nv">helm-filtered-bookmarks</span><span class="p">)</span>
1181 <span class="p">(</span><span class="s">&quot;C-x C-r&quot;</span> <span class="o">.</span> <span class="nv">helm-recentf</span><span class="p">)</span> <span class="c1">;; Search for recently edited files</span>
1182 <span class="p">(</span><span class="s">&quot;C-c i&quot;</span> <span class="o">.</span> <span class="nv">helm-imenu</span><span class="p">)</span>
1183 <span class="p">(</span><span class="s">&quot;C-h a&quot;</span> <span class="o">.</span> <span class="nv">helm-apropos</span><span class="p">)</span>
1184 <span class="c1">;; Look at what was cut recently &amp; paste it in.</span>
1185 <span class="p">(</span><span class="s">&quot;M-y&quot;</span> <span class="o">.</span> <span class="nv">helm-show-kill-ring</span><span class="p">)</span>
1186
1187 <span class="nb">:map</span> <span class="nv">helm-map</span>
1188 <span class="c1">;; We can list ‘actions’ on the currently selected item by C-z.</span>
1189 <span class="p">(</span><span class="s">&quot;C-z&quot;</span> <span class="o">.</span> <span class="nv">helm-select-action</span><span class="p">)</span>
1190 <span class="c1">;; Let&#39;s keep tab-completetion anyhow.</span>
1191 <span class="p">(</span><span class="s">&quot;TAB&quot;</span> <span class="o">.</span> <span class="nv">helm-execute-persistent-action</span><span class="p">)</span>
1192 <span class="p">(</span><span class="s">&quot;&lt;tab&gt;&quot;</span> <span class="o">.</span> <span class="nv">helm-execute-persistent-action</span><span class="p">)))</span>
1193 </code></pre></div>
1194
1195 <h2>Ripgrep to search in grand style</h2>
1196 <div class="highlight"><pre><span></span><code><span class="c1">;; Ripgrep</span>
1197
1198 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">rg</span>
1199 <span class="nb">:config</span>
1200 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;M-s g&quot;</span><span class="p">)</span> <span class="ss">&#39;rg</span><span class="p">)</span>
1201 <span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;M-s d&quot;</span><span class="p">)</span> <span class="ss">&#39;rg-dwim</span><span class="p">))</span>
1202
1203 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">helm-rg</span><span class="p">)</span>
1204 </code></pre></div>
1205
1206 <h2>Rust mode and Language Server</h2>
1207 <p>Now that RLS is in the process of being deprecated, it's getting substituted
1208 with rust-analyzer. Also, rust-mode goes away in favor of rustic.</p>
1209 <div class="highlight"><pre><span></span><code><span class="c1">;; Rustic, LSP</span>
1210
1211 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">flycheck</span><span class="p">)</span>
1212
1213 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">rustic</span><span class="p">)</span>
1214
1215 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">lsp-ui</span><span class="p">)</span>
1216
1217 <span class="p">(</span><span class="nb">use-package</span> <span class="nv">helm-lsp</span>
1218 <span class="nb">:config</span>
1219 <span class="p">(</span><span class="nf">define-key</span> <span class="nv">lsp-mode-map</span> <span class="p">[</span><span class="nv">remap</span> <span class="nv">xref-find-apropos</span><span class="p">]</span> <span class="nf">#&#39;</span><span class="nv">helm-lsp-workspace-symbol</span><span class="p">))</span>
1220 </code></pre></div>
1221
1222 <h2>Performatively not get distracted</h2>
1223 <div class="highlight"><pre><span></span><code><span class="p">;;;</span><span class="w"> </span><span class="n">Show</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">notification</span><span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="n">compilation</span><span class="w"> </span><span class="n">finishes</span><span class="w"></span>
1224
1225 <span class="p">(</span><span class="n">setq</span><span class="w"> </span><span class="n">compilation</span><span class="o">-</span><span class="n">finish</span><span class="o">-</span><span class="n">functions</span><span class="w"></span>
1226 <span class="w"> </span><span class="p">(</span><span class="n">append</span><span class="w"> </span><span class="n">compilation</span><span class="o">-</span><span class="n">finish</span><span class="o">-</span><span class="n">functions</span><span class="w"></span>
1227 <span class="w"> </span><span class="o">&#39;</span><span class="p">(</span><span class="n">fmq</span><span class="o">-</span><span class="n">compilation</span><span class="o">-</span><span class="n">finish</span><span class="p">)))</span><span class="w"></span>
1228
1229 <span class="p">(</span><span class="n">defun</span><span class="w"> </span><span class="n">fmq</span><span class="o">-</span><span class="n">compilation</span><span class="o">-</span><span class="n">finish</span><span class="w"> </span><span class="p">(</span><span class="n">buffer</span><span class="w"> </span><span class="n">status</span><span class="p">)</span><span class="w"></span>
1230 <span class="w"> </span><span class="p">(</span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="n">not</span><span class="w"> </span><span class="p">(</span><span class="n">member</span><span class="w"> </span><span class="n">mode</span><span class="o">-</span><span class="n">name</span><span class="w"> </span><span class="o">&#39;</span><span class="p">(</span><span class="s">&quot;Grep&quot;</span><span class="w"> </span><span class="s">&quot;rg&quot;</span><span class="p">)))</span><span class="w"></span>
1231 <span class="w"> </span><span class="p">(</span><span class="n">call</span><span class="o">-</span><span class="n">process</span><span class="w"> </span><span class="s">&quot;notify-send&quot;</span><span class="w"> </span><span class="n">nil</span><span class="w"> </span><span class="n">nil</span><span class="w"> </span><span class="n">nil</span><span class="w"></span>
1232 <span class="w"> </span><span class="s">&quot;-t&quot;</span><span class="w"> </span><span class="s">&quot;0&quot;</span><span class="w"></span>
1233 <span class="w"> </span><span class="s">&quot;-i&quot;</span><span class="w"> </span><span class="s">&quot;emacs&quot;</span><span class="w"></span>
1234 <span class="w"> </span><span class="s">&quot;Compilation finished in Emacs&quot;</span><span class="w"></span>
1235 <span class="w"> </span><span class="n">status</span><span class="p">)))</span><span class="w"></span>
1236 </code></pre></div>
1237
1238 <h2>Stuff from custom.el</h2>
1239 <p>The interesting bits here are making LSP work; everything else is preferences.</p>
1240 <div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nv">custom-set-variables</span>
1241 <span class="c1">;; custom-set-variables was added by Custom.</span>
1242 <span class="c1">;; If you edit it by hand, you could mess it up, so be careful.</span>
1243 <span class="c1">;; Your init file should contain only one such instance.</span>
1244 <span class="c1">;; If there is more than one, they won&#39;t work right.</span>
1245 <span class="o">&#39;</span><span class="p">(</span><span class="nv">column-number-mode</span> <span class="no">t</span><span class="p">)</span>
1246 <span class="o">&#39;</span><span class="p">(</span><span class="nv">custom-safe-themes</span>
1247 <span class="p">(</span><span class="k">quote</span>
1248 <span class="p">(</span><span class="s">&quot;2540689fd0bc5d74c4682764ff6c94057ba8061a98be5dd21116bf7bf301acfb&quot;</span> <span class="s">&quot;bffa9739ce0752a37d9b1eee78fc00ba159748f50dc328af4be661484848e476&quot;</span> <span class="s">&quot;0fffa9669425ff140ff2ae8568c7719705ef33b7a927a0ba7c5e2ffcfac09b75&quot;</span> <span class="s">&quot;2809bcb77ad21312897b541134981282dc455ccd7c14d74cc333b6e549b824f3&quot;</span> <span class="nv">default</span><span class="p">)))</span>
1249 <span class="o">&#39;</span><span class="p">(</span><span class="nv">delete-selection-mode</span> <span class="no">nil</span><span class="p">)</span>
1250 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-analyzer-display-chaining-hints</span> <span class="no">t</span><span class="p">)</span>
1251 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-analyzer-display-parameter-hints</span> <span class="no">nil</span><span class="p">)</span>
1252 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-analyzer-macro-expansion-method</span> <span class="p">(</span><span class="k">quote</span> <span class="nv">rustic-analyzer-macro-expand</span><span class="p">))</span>
1253 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-analyzer-server-command</span> <span class="p">(</span><span class="k">quote</span> <span class="p">(</span><span class="s">&quot;/home/federico/.cargo/bin/rust-analyzer&quot;</span><span class="p">)))</span>
1254 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-analyzer-server-display-inlay-hints</span> <span class="no">nil</span><span class="p">)</span>
1255 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-full-docs</span> <span class="no">t</span><span class="p">)</span>
1256 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-rust-server</span> <span class="p">(</span><span class="k">quote</span> <span class="nv">rust-analyzer</span><span class="p">))</span>
1257 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-ui-doc-alignment</span> <span class="p">(</span><span class="k">quote</span> <span class="nv">window</span><span class="p">))</span>
1258 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-ui-doc-position</span> <span class="p">(</span><span class="k">quote</span> <span class="nv">top</span><span class="p">))</span>
1259 <span class="o">&#39;</span><span class="p">(</span><span class="nv">lsp-ui-sideline-enable</span> <span class="no">nil</span><span class="p">)</span>
1260 <span class="o">&#39;</span><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="no">nil</span><span class="p">)</span>
1261 <span class="o">&#39;</span><span class="p">(</span><span class="nv">package-selected-packages</span>
1262 <span class="p">(</span><span class="k">quote</span>
codemadness.org:70 /git/sfeed_tests/file/input/sfeed/realworld/people.gnome.org_federico.atom.xml.gph:1273: line too long