* [BLOG] rust blog post
@ 2019-11-25 10:30 Efraim Flashner
2019-11-26 9:58 ` Pierre Neidhardt
0 siblings, 1 reply; 7+ messages in thread
From: Efraim Flashner @ 2019-11-25 10:30 UTC (permalink / raw)
To: guix-devel
[-- Attachment #1.1: Type: text/plain, Size: 309 bytes --]
There's one or two FIXMEs and the like in the blog post but I figured
I'd send it off anyway.
--
Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted
[-- Attachment #1.2: rust-in-guix --]
[-- Type: text/plain, Size: 8323 bytes --]
It's easy to think of Rust as a new programming language but it has already been around for five years. Rust has made it past it's 1.0 release and the compiler is written in Rust. We even have mrustc to act as a secondary method to bootstrap new Rust releases without falling back to downloading precompiled tarballs. So how is the state of Rust in Guix today?
Truthfully, Rust in Guix could be better. The developer story for Rust is pretty straightforward: write your program, declare your dependencies in a Cargo.toml file, and ```cargo foo``` will figure out your dependency chain. ```cargo build``` will download any missing dependencies, even using a cache directory to reduce downloads, and compile the bits of the dependencies that are needed.
But what about for distro maintainers?
Obviously we can't download dependencies at build time, they need to be packaged ahead of time. So we package those dependencies. But wait, those dependencies have dependencies that are needed, and those ones too. It's dependencies all the way down, hidden in 5 years of iterative development that we're late to the party to, trying to capture snapshots in time where specific versions of libraries built using previous generations. All this all the way back to the beginning, whenever that is.
Obviously humans are prone to errors, so to work around this while packaging Rust crates Guix has effectively two importers for crates, one that will import a specific version and list it's dependencies, and one that can take a crate and recursively import all the packages that it depends on. Currently some work is needed to allow the recursive importer to interpret version numbers, but for now it works quite well.
Taking a break from Rust for a moment, let's look at some of the other languages that are packaged. Packages written in C/C++, processed with autotools or cmake or meson, are the easiest. Dependencies are declared, source code is provided, and there's a clear distinction between source code and compiled binary; source code is for hacking on, binaries are for executing. The closest to a middle ground are libraries which allow programs to use features from other programs. In order to use a package, all of its dependencies must be packaged and the libraries linked.
Taking a look at the other end we have Javascript. Javascript is source code, it's ready to be read and hacked on. Javascript is already ready to be run, therefor it must be a binary. Its... both? Javascript libraries leave distro maintainers in a difficult position. Building Javascript ends up in the same problem as we saw with Rust, recursive dependencies all the way down, iterative versions depending on previous ones, and a misty past from whence everything sprang forth, which must be recreated in order to bring us back to the present day. But there's more difficulty, often even after a 'build' phase has been run and tests have been run on Javascript we're left with unchanged code. Except now it's no longer source, it's a binary... or something. So just what did we build and test?
We can worry about Javascript another time, Rust has a clear boundary between source code and binaries.
So how about python? Python is a scripting language and can be run without being compiled, but it also can be compiled (pre-interpreted?) to bytecode and installed either locally or globally. That leaves us with source code which can double as a binary, and a bytecode which is clearly a binary. Given these two states, we declare the uncompiled version as source code, ignore that it can be run as a script except when testing the code, and we never return to second-guess ourselves.
How about Go? Go is another language that defies packaging efforts, primarily because build instructions often make use of the HEAD of other git branches, not tagged and released versions. That the names of the libraries are long and cumbersome is mostly a secondary issue. On the developer side a binary is a ```go build``` away. Go will download missing source and compile libraries as needed. On a packager side the libraries are carefully gathered one by one, precompiled, and placed carefully in a directory hierarchy for use in future builds. What could be a long build of a program is replaced by an intermediate series of packages where libraries are pre-compiled, and at each stage only the new code has to be compiled.
For all except the distro maintainer, the similarities are strong between Rust and Go. In both cases dependencies are downloaded as part of the build process, there's a cache for the downloaded sources and the compiled libraries, and build artifacts can be reused between different programs with overlapping dependencies. For the distro maintainer many of these similarities are thrown out. Dependencies are packaged ahead of time and previously packaged libraries is literally a cache. Libraries can be reused for other packages, yes, but for Rust they're not.
Why not? If they're already compiled why not reuse them?
Previously we've discussed source code and compiled binaries (or libraries), but in Rust there are two types of libraries. There are dynamic libraries, packaged as ```libfoo.so```, and there are Rust libraries, packaged as ```libfoo.rlib``` or ```libfoo-MAGICHASH.rlib```. When a Rust package declares a dependency on a Rust library, it doesn't declare a dependency on the whole library but rather just on the parts that it needs. This means that we can get away with packaging only a portion of the dependent library, or the library with only some of its features or its own dependencies. When compiling a final binary, a Rust binary doesn't link to an rlib, it takes just the part that it needs and incorporates it into the binary. As far as package maintainers are concerned, this isn't ideal but it is something we can live with, we already have this case with static libraries from other languages. If we were to compile the binary manually the command would be ```rustc --binary foo --extern bar=/path/to/libbar.rlib``` and we'd continue on. However, when bar depends on baz, the similar command, ```rust --library bar --extern baz=/path/to/libbaz.rlib``` _doesn't_ link libbaz to libbar. This leaves us in a pickle; we know which libraries we need but we're unable to compile them individually and build them up iteratively until we reach the binary endgoal.
One of our packaged Rust programs, rust-cbindgen, is used by Icecat. Rust-cbindgen declares 8 (TODO: check this number) dependencies. When run outside of the build environment ```cargo build``` downloads a total of 58 (TODO: check this number) packages, compiles them and produces a binary. Our recursive importer created more than 300 new packages before it was told to stop. Returning to our build process for rust libraries, since we couldn't link one rlib to another rlib, we opted to compile one rlib and then place its source in the build directory of the next one where it was recompiled. Baz would be built, then baz's source would be put in bar's vendor directory where baz and bar would be built. After this baz's and bar's sources would be put in foo's vendor directory, where all three would be compiled. This sounds like Go, except that we're throwing away all the results of our builds each time we start a new package.
Since we were just copying the sources from package to package, the simplest solution was to consider the Rust dependants as shared sources and not as shared libraries. Yes, the same source would be used between multiple programs, but each one package already only took the small portion of the shared source that it needed so there was no benefit to compiling the entire package ahead of time, especially with the mounting recursive dependencies, who's compiled libraries were being thrown away anyway.
Rust-cbindgen ships with a Cargo.toml listing 8 dependants. It also ships with a Cargo.lock, detailing the 8 dependencies and the bits of other libraries that are needed. By packing the sources of the 58 enumerated libraries and placing them in the vendor directory where the necessary parts could be compiled we ended at the same place we were headed anyway; only the sources were propagated from package build to package build, only the source was the relevant part, only the source is shared.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BLOG] rust blog post
2019-11-25 10:30 [BLOG] rust blog post Efraim Flashner
@ 2019-11-26 9:58 ` Pierre Neidhardt
2019-11-26 10:27 ` Efraim Flashner
0 siblings, 1 reply; 7+ messages in thread
From: Pierre Neidhardt @ 2019-11-26 9:58 UTC (permalink / raw)
To: Efraim Flashner, guix-devel
[-- Attachment #1: Type: text/plain, Size: 159 bytes --]
I think the attachment broke the formatting of the file (there is no
paragraph break). Could you resend it?
--
Pierre Neidhardt
https://ambrevar.xyz/
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BLOG] rust blog post
2019-11-26 9:58 ` Pierre Neidhardt
@ 2019-11-26 10:27 ` Efraim Flashner
2019-11-26 12:26 ` Bengt Richter
0 siblings, 1 reply; 7+ messages in thread
From: Efraim Flashner @ 2019-11-26 10:27 UTC (permalink / raw)
To: Pierre Neidhardt; +Cc: guix-devel
[-- Attachment #1.1: Type: text/plain, Size: 470 bytes --]
Hopefully this is better. I added a new line between each paragraph
On Tue, Nov 26, 2019 at 10:58:41AM +0100, Pierre Neidhardt wrote:
> I think the attachment broke the formatting of the file (there is no
> paragraph break). Could you resend it?
>
--
Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted
[-- Attachment #1.2: rust-in-guix --]
[-- Type: text/plain, Size: 8353 bytes --]
It's easy to think of Rust as a new programming language but it has already been around for five years. Rust has made it past it's 1.0 release and the compiler is written in Rust. We even have mrustc to act as a secondary method to bootstrap new Rust releases without falling back to downloading precompiled tarballs. So how is the state of Rust in Guix today?
Truthfully, Rust in Guix could be better. The developer story for Rust is pretty straightforward: write your program, declare your dependencies in a Cargo.toml file, and ```cargo foo``` will figure out your dependency chain. ```cargo build``` will download any missing dependencies, even using a cache directory to reduce downloads, and compile the bits of the dependencies that are needed.
But what about for distro maintainers?
Obviously we can't download dependencies at build time, they need to be packaged ahead of time. So we package those dependencies. But wait, those dependencies have dependencies that are needed, and those ones too. It's dependencies all the way down, hidden in 5 years of iterative development that we're late to the party to, trying to capture snapshots in time where specific versions of libraries built using previous generations. All this all the way back to the beginning, whenever that is.
Obviously humans are prone to errors, so to work around this while packaging Rust crates Guix has effectively two importers for crates, one that will import a specific version and list it's dependencies, and one that can take a crate and recursively import all the packages that it depends on. Currently some work is needed to allow the recursive importer to interpret version numbers, but for now it works quite well.
Taking a break from Rust for a moment, let's look at some of the other languages that are packaged. Packages written in C/C++, processed with autotools or cmake or meson, are the easiest. Dependencies are declared, source code is provided, and there's a clear distinction between source code and compiled binary; source code is for hacking on, binaries are for executing. The closest to a middle ground are libraries which allow programs to use features from other programs. In order to use a package, all of its dependencies must be packaged and the libraries linked.
Taking a look at the other end we have Javascript. Javascript is source code, it's ready to be read and hacked on. Javascript is already ready to be run, therefor it must be a binary. Its... both? Javascript libraries leave distro maintainers in a difficult position. Building Javascript ends up in the same problem as we saw with Rust, recursive dependencies all the way down, iterative versions depending on previous ones, and a misty past from whence everything sprang forth, which must be recreated in order to bring us back to the present day. But there's more difficulty, often even after a 'build' phase has been run and tests have been run on Javascript we're left with unchanged code. Except now it's no longer source, it's a binary... or something. So just what did we build and test?
We can worry about Javascript another time, Rust has a clear boundary between source code and binaries.
So how about python? Python is a scripting language and can be run without being compiled, but it also can be compiled (pre-interpreted?) to bytecode and installed either locally or globally. That leaves us with source code which can double as a binary, and a bytecode which is clearly a binary. Given these two states, we declare the uncompiled version as source code, ignore that it can be run as a script except when testing the code, and we never return to second-guess ourselves.
How about Go? Go is another language that defies packaging efforts, primarily because build instructions often make use of the HEAD of other git branches, not tagged and released versions. That the names of the libraries are long and cumbersome is mostly a secondary issue. On the developer side a binary is a ```go build``` away. Go will download missing source and compile libraries as needed. On a packager side the libraries are carefully gathered one by one, precompiled, and placed carefully in a directory hierarchy for use in future builds. What could be a long build of a program is replaced by an intermediate series of packages where libraries are pre-compiled, and at each stage only the new code has to be compiled.
For all except the distro maintainer, the similarities are strong between Rust and Go. In both cases dependencies are downloaded as part of the build process, there's a cache for the downloaded sources and the compiled libraries, and build artifacts can be reused between different programs with overlapping dependencies. For the distro maintainer many of these similarities are thrown out. Dependencies are packaged ahead of time and previously packaged libraries is literally a cache. Libraries can be reused for other packages, yes, but for Rust they're not.
Why not? If they're already compiled why not reuse them?
Previously we've discussed source code and compiled binaries (or libraries), but in Rust there are two types of libraries. There are dynamic libraries, packaged as ```libfoo.so```, and there are Rust libraries, packaged as ```libfoo.rlib``` or ```libfoo-MAGICHASH.rlib```. When a Rust package declares a dependency on a Rust library, it doesn't declare a dependency on the whole library but rather just on the parts that it needs. This means that we can get away with packaging only a portion of the dependent library, or the library with only some of its features or its own dependencies. When compiling a final binary, a Rust binary doesn't link to an rlib, it takes just the part that it needs and incorporates it into the binary. As far as package maintainers are concerned, this isn't ideal but it is something we can live with, we already have this case with static libraries from other languages. If we were to compile the binary manually the command would be ```rustc --binary foo --extern bar=/path/to/libbar.rlib``` and we'd continue on. However, when bar depends on baz, the similar command, ```rust --library bar --extern baz=/path/to/libbaz.rlib``` _doesn't_ link libbaz to libbar. This leaves us in a pickle; we know which libraries we need but we're unable to compile them individually and build them up iteratively until we reach the binary endgoal.
One of our packaged Rust programs, rust-cbindgen, is used by Icecat. Rust-cbindgen declares 8 (TODO: check this number) dependencies. When run outside of the build environment ```cargo build``` downloads a total of 58 (TODO: check this number) packages, compiles them and produces a binary. Our recursive importer created more than 300 new packages before it was told to stop. Returning to our build process for rust libraries, since we couldn't link one rlib to another rlib, we opted to compile one rlib and then place its source in the build directory of the next one where it was recompiled. Baz would be built, then baz's source would be put in bar's vendor directory where baz and bar would be built. After this baz's and bar's sources would be put in foo's vendor directory, where all three would be compiled. This sounds like Go, except that we're throwing away all the results of our builds each time we start a new package.
Since we were just copying the sources from package to package, the simplest solution was to consider the Rust dependants as shared sources and not as shared libraries. Yes, the same source would be used between multiple programs, but each one package already only took the small portion of the shared source that it needed so there was no benefit to compiling the entire package ahead of time, especially with the mounting recursive dependencies, who's compiled libraries were being thrown away anyway.
Rust-cbindgen ships with a Cargo.toml listing 8 dependants. It also ships with a Cargo.lock, detailing the 8 dependencies and the bits of other libraries that are needed. By packing the sources of the 58 enumerated libraries and placing them in the vendor directory where the necessary parts could be compiled we ended at the same place we were headed anyway; only the sources were propagated from package build to package build, only the source was the relevant part, only the source is shared.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BLOG] rust blog post
2019-11-26 10:27 ` Efraim Flashner
@ 2019-11-26 12:26 ` Bengt Richter
2019-11-26 13:01 ` Pierre Neidhardt
0 siblings, 1 reply; 7+ messages in thread
From: Bengt Richter @ 2019-11-26 12:26 UTC (permalink / raw)
To: Efraim Flashner; +Cc: guix-devel
Hi Guix,
In case someone likes a narrower style:
On +2019-11-26 12:27:37 +0200, Efraim Flashner wrote:
> Hopefully this is better. I added a new line between each paragraph
>
> On Tue, Nov 26, 2019 at 10:58:41AM +0100, Pierre Neidhardt wrote:
> > I think the attachment broke the formatting of the file (there is no
> > paragraph break). Could you resend it?
> >
>
> --
> Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
> GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
> Confidentiality cannot be guaranteed on emails sent or received unencrypted
It's easy to think of Rust as a new programming language but
it has already been around for five years. Rust has made it
past it's 1.0 release and the compiler is written in Rust.
We even have mrustc to act as a secondary method to
bootstrap new Rust releases without falling back to
downloading precompiled tarballs. So how is the state of
Rust in Guix today?
Truthfully, Rust in Guix could be better. The developer
story for Rust is pretty straightforward: write your
program, declare your dependencies in a Cargo.toml file, and
```cargo foo``` will figure out your dependency chain.
```cargo build``` will download any missing dependencies,
even using a cache directory to reduce downloads, and
compile the bits of the dependencies that are needed.
But what about for distro maintainers?
Obviously we can't download dependencies at build time, they
need to be packaged ahead of time. So we package those
dependencies. But wait, those dependencies have dependencies
that are needed, and those ones too. It's dependencies all
the way down, hidden in 5 years of iterative development
that we're late to the party to, trying to capture snapshots
in time where specific versions of libraries built using
previous generations. All this all the way back to the
beginning, whenever that is.
Obviously humans are prone to errors, so to work around this
while packaging Rust crates Guix has effectively two
importers for crates, one that will import a specific
version and list it's dependencies, and one that can take a
crate and recursively import all the packages that it
depends on. Currently some work is needed to allow the
recursive importer to interpret version numbers, but for now
it works quite well.
Taking a break from Rust for a moment, let's look at some of
the other languages that are packaged. Packages written in
C/C++, processed with autotools or cmake or meson, are the
easiest. Dependencies are declared, source code is provided,
and there's a clear distinction between source code and
compiled binary; source code is for hacking on, binaries are
for executing. The closest to a middle ground are libraries
which allow programs to use features from other programs. In
order to use a package, all of its dependencies must be
packaged and the libraries linked.
Taking a look at the other end we have Javascript.
Javascript is source code, it's ready to be read and hacked
on. Javascript is already ready to be run, therefor it must
be a binary. Its... both? Javascript libraries leave distro
maintainers in a difficult position. Building Javascript
ends up in the same problem as we saw with Rust, recursive
dependencies all the way down, iterative versions depending
on previous ones, and a misty past from whence everything
sprang forth, which must be recreated in order to bring us
back to the present day. But there's more difficulty, often
even after a 'build' phase has been run and tests have been
run on Javascript we're left with unchanged code. Except now
it's no longer source, it's a binary... or something. So
just what did we build and test?
We can worry about Javascript another time, Rust has a clear
boundary between source code and binaries.
So how about python? Python is a scripting language and can
be run without being compiled, but it also can be compiled
(pre-interpreted?) to bytecode and installed either locally
or globally. That leaves us with source code which can
double as a binary, and a bytecode which is clearly a
binary. Given these two states, we declare the uncompiled
version as source code, ignore that it can be run as a
script except when testing the code, and we never return to
second-guess ourselves.
How about Go? Go is another language that defies packaging
efforts, primarily because build instructions often make use
of the HEAD of other git branches, not tagged and released
versions. That the names of the libraries are long and
cumbersome is mostly a secondary issue. On the developer
side a binary is a ```go build``` away. Go will download
missing source and compile libraries as needed. On a
packager side the libraries are carefully gathered one by
one, precompiled, and placed carefully in a directory
hierarchy for use in future builds. What could be a long
build of a program is replaced by an intermediate series of
packages where libraries are pre-compiled, and at each stage
only the new code has to be compiled.
For all except the distro maintainer, the similarities are
strong between Rust and Go. In both cases dependencies are
downloaded as part of the build process, there's a cache for
the downloaded sources and the compiled libraries, and build
artifacts can be reused between different programs with
overlapping dependencies. For the distro maintainer many of
these similarities are thrown out. Dependencies are packaged
ahead of time and previously packaged libraries is literally
a cache. Libraries can be reused for other packages, yes,
but for Rust they're not.
Why not? If they're already compiled why not reuse them?
Previously we've discussed source code and compiled binaries
(or libraries), but in Rust there are two types of
libraries. There are dynamic libraries, packaged as
```libfoo.so```, and there are Rust libraries, packaged as
```libfoo.rlib``` or ```libfoo-MAGICHASH.rlib```. When a
Rust package declares a dependency on a Rust library, it
doesn't declare a dependency on the whole library but rather
just on the parts that it needs. This means that we can get
away with packaging only a portion of the dependent library,
or the library with only some of its features or its own
dependencies. When compiling a final binary, a Rust binary
doesn't link to an rlib, it takes just the part that it
needs and incorporates it into the binary. As far as package
maintainers are concerned, this isn't ideal but it is
something we can live with, we already have this case with
static libraries from other languages. If we were to compile
the binary manually the command would be ```rustc --binary
foo --extern bar=/path/to/libbar.rlib``` and we'd continue
on. However, when bar depends on baz, the similar command,
```rust --library bar --extern baz=/path/to/libbaz.rlib```
_doesn't_ link libbaz to libbar. This leaves us in a pickle;
we know which libraries we need but we're unable to compile
them individually and build them up iteratively until we
reach the binary endgoal.
One of our packaged Rust programs, rust-cbindgen, is used by
Icecat. Rust-cbindgen declares 8 (TODO: check this number)
dependencies. When run outside of the build environment
```cargo build``` downloads a total of 58 (TODO: check this
number) packages, compiles them and produces a binary. Our
recursive importer created more than 300 new packages before
it was told to stop. Returning to our build process for rust
libraries, since we couldn't link one rlib to another rlib,
we opted to compile one rlib and then place its source in
the build directory of the next one where it was recompiled.
Baz would be built, then baz's source would be put in bar's
vendor directory where baz and bar would be built. After
this baz's and bar's sources would be put in foo's vendor
directory, where all three would be compiled. This sounds
like Go, except that we're throwing away all the results of
our builds each time we start a new package.
Since we were just copying the sources from package to
package, the simplest solution was to consider the Rust
dependants as shared sources and not as shared libraries.
Yes, the same source would be used between multiple
programs, but each one package already only took the small
portion of the shared source that it needed so there was no
benefit to compiling the entire package ahead of time,
especially with the mounting recursive dependencies, who's
compiled libraries were being thrown away anyway.
Rust-cbindgen ships with a Cargo.toml listing 8 dependants.
It also ships with a Cargo.lock, detailing the 8
dependencies and the bits of other libraries that are
needed. By packing the sources of the 58 enumerated
libraries and placing them in the vendor directory where the
necessary parts could be compiled we ended at the same place
we were headed anyway; only the sources were propagated from
package build to package build, only the source was the
relevant part, only the source is shared.
--
Regards,
Bengt Richter
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BLOG] rust blog post
2019-11-26 12:26 ` Bengt Richter
@ 2019-11-26 13:01 ` Pierre Neidhardt
2019-11-27 0:19 ` Bengt Richter
0 siblings, 1 reply; 7+ messages in thread
From: Pierre Neidhardt @ 2019-11-26 13:01 UTC (permalink / raw)
To: Bengt Richter, Efraim Flashner; +Cc: guix-devel
[-- Attachment #1: Type: text/plain, Size: 523 bytes --]
Bengt Richter <bokr@bokr.com> writes:
> be a binary. Its... both? Javascript libraries leave distro
Typo: "It's".
Interesting read, thanks for sharing.
Do you intend to publish it on Guix' blog? If so, I think the tone
might come across as a little bit too "rantish", maybe make it a little
more neutral / balanced.
I'd also elaborate the intro / conclusion to make the context a bit
clearer and maybe explain what you think should be done.
Cheers!
--
Pierre Neidhardt
https://ambrevar.xyz/
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BLOG] rust blog post
2019-11-26 13:01 ` Pierre Neidhardt
@ 2019-11-27 0:19 ` Bengt Richter
2019-11-27 9:38 ` Efraim Flashner
0 siblings, 1 reply; 7+ messages in thread
From: Bengt Richter @ 2019-11-27 0:19 UTC (permalink / raw)
To: Pierre Neidhardt; +Cc: guix-devel
Hi Pierre, and apologies to Efraim...
On +2019-11-26 14:01:10 +0100, Pierre Neidhardt wrote:
> Bengt Richter <bokr@bokr.com> writes:
>
> > be a binary. Its... both? Javascript libraries leave distro
>
> Typo: "It's".
>
I noticed that too, but it's Efraim's typo,
as is the entire text: I merely reformatted Efraim's post
into a sort of rfc-style, i.e., Left-and-Right-justified.
So, credit to Efraim for the:
> Interesting read, thanks for sharing.
> Do you intend to publish it on Guix' blog? If so, I think the tone
> might come across as a little bit too "rantish", maybe make it a little
> more neutral / balanced.
>
> I'd also elaborate the intro / conclusion to make the context a bit
> clearer and maybe explain what you think should be done.
>
> Cheers!
>
> --
> Pierre Neidhardt
> https://ambrevar.xyz/
Efraim, thanks for your work -- I didn't mean to hijack it, honest :)
Sorry for not making it clear that I was just reformatting your post ;-/
Ah, perhaps Pierre merely clicked reply-all and he really was thanking you, Efraim,
and it just appeared to be directed toward me because of the "> Bengt Richter <bokr@bokr.com> writes:"
heading?
--
Regards,
Bengt Richter
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BLOG] rust blog post
2019-11-27 0:19 ` Bengt Richter
@ 2019-11-27 9:38 ` Efraim Flashner
0 siblings, 0 replies; 7+ messages in thread
From: Efraim Flashner @ 2019-11-27 9:38 UTC (permalink / raw)
To: Bengt Richter; +Cc: guix-devel
[-- Attachment #1: Type: text/plain, Size: 1933 bytes --]
On Tue, Nov 26, 2019 at 04:19:01PM -0800, Bengt Richter wrote:
> Hi Pierre, and apologies to Efraim...
>
> On +2019-11-26 14:01:10 +0100, Pierre Neidhardt wrote:
> > Bengt Richter <bokr@bokr.com> writes:
> >
> > > be a binary. Its... both? Javascript libraries leave distro
> >
> > Typo: "It's".
> >
It's one of the ones I have a hard time with. When I remember I'm great
with it.
>
> I noticed that too, but it's Efraim's typo,
> as is the entire text: I merely reformatted Efraim's post
> into a sort of rfc-style, i.e., Left-and-Right-justified.
Thanks
>
> So, credit to Efraim for the:
>
> > Interesting read, thanks for sharing.
> > Do you intend to publish it on Guix' blog? If so, I think the tone
> > might come across as a little bit too "rantish", maybe make it a little
> > more neutral / balanced.
Definitely wasn't aiming for rantish, I'll see what I can do about
making it better. It was more of a stream-of-consciousness typing and I
figured I could go back and rework it later.
> >
> > I'd also elaborate the intro / conclusion to make the context a bit
> > clearer and maybe explain what you think should be done.
Sounds like a good idea.
> >
> > Cheers!
> >
> > --
> > Pierre Neidhardt
> > https://ambrevar.xyz/
>
> Efraim, thanks for your work -- I didn't mean to hijack it, honest :)
> Sorry for not making it clear that I was just reformatting your post ;-/
>
> Ah, perhaps Pierre merely clicked reply-all and he really was thanking you, Efraim,
> and it just appeared to be directed toward me because of the "> Bengt Richter <bokr@bokr.com> writes:"
> heading?
Likely. I normally hit reply-all for mailing list posts
--
Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2019-11-27 9:39 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-11-25 10:30 [BLOG] rust blog post Efraim Flashner
2019-11-26 9:58 ` Pierre Neidhardt
2019-11-26 10:27 ` Efraim Flashner
2019-11-26 12:26 ` Bengt Richter
2019-11-26 13:01 ` Pierre Neidhardt
2019-11-27 0:19 ` Bengt Richter
2019-11-27 9:38 ` Efraim Flashner
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/guix.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.