workflowpoasting II
This commit is contained in:
parent
df71e76fd5
commit
a0398ce675
3 changed files with 222 additions and 9 deletions
|
|
@ -3,7 +3,7 @@ date = "2021-05-18"
|
||||||
draft = false
|
draft = false
|
||||||
path = "/blog/docs-tricks-and-gnus"
|
path = "/blog/docs-tricks-and-gnus"
|
||||||
tags = ["site"]
|
tags = ["site"]
|
||||||
title = "Docs tricks and GNUs"
|
title = "My Workflow: Docs tricks and GNUs"
|
||||||
+++
|
+++
|
||||||
|
|
||||||
##### TL;DR: check out my GNU docs builds at <https://docs.jade.fyi/gnu>
|
##### TL;DR: check out my GNU docs builds at <https://docs.jade.fyi/gnu>
|
||||||
|
|
|
||||||
181
content/posts/workflow-unfamiliar-codebases.md
Normal file
181
content/posts/workflow-unfamiliar-codebases.md
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
+++
|
||||||
|
date = "2021-07-27"
|
||||||
|
draft = false
|
||||||
|
path = "/blog/workflow-unfamiliar-c-cpp-codebases"
|
||||||
|
tags = ["workflow"]
|
||||||
|
title = "My Workflow: Unfamiliar C and C++ codebases"
|
||||||
|
+++
|
||||||
|
|
||||||
|
Improving and automating my workflow is something I have put considerable
|
||||||
|
investment into, and I would like to share what I can. This is part of a
|
||||||
|
series of posts about my development workflow. You can read the other
|
||||||
|
installments here:
|
||||||
|
|
||||||
|
- [Docs](./docs-tricks-and-gnus)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
I have a curse: I know how to program and I run Linux, so I naturally tend to
|
||||||
|
fix things when I see them, which results in significant yak shaving, but also
|
||||||
|
fixes things permanently. I also know that one of the most effective ways to
|
||||||
|
learn things about libraries or programs that are misbehaving is reading their
|
||||||
|
source code.
|
||||||
|
|
||||||
|
# Acquiring source code
|
||||||
|
|
||||||
|
Actually getting the source to things is surprisingly annoying: every project
|
||||||
|
has its own Web site where they might link their source, and I would have to
|
||||||
|
find those. I don't want to navigate websites as they're distracting and too
|
||||||
|
often don't have the links to the code anywhere easy to find.
|
||||||
|
|
||||||
|
## Just grab it off GitHub
|
||||||
|
|
||||||
|
Because of the monoculture in open source, very few projects don't at least
|
||||||
|
have a mirror of their source on GitHub. This makes it very convenient to
|
||||||
|
acquire source for things, as I only have to look in one place that's also
|
||||||
|
quite uniform and machine accessible.
|
||||||
|
|
||||||
|
The `gh` GitHub command line tool is probably one of the better ways to
|
||||||
|
interact with the Web site without distractions. Unfortunately, there is an old
|
||||||
|
[feature request](https://github.com/cli/cli/issues/1004) for adding search,
|
||||||
|
which has not been implemented yet. Thankfully, you can add aliases. I've done
|
||||||
|
so with a fancy alias for searching repos which emits nice coloured output for
|
||||||
|
finding where the name of the repo for the thing I want.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
aliases:
|
||||||
|
search: 'api -X GET search/repositories -f q=''$1'' --template ''{{range .items}}{{ .full_name | color "white" }}: {{ .description }}{{"\n"}}{{ end }}'''
|
||||||
|
```
|
||||||
|
|
||||||
|
I can then do something like `gh search 'github cli'`, for example, and it will
|
||||||
|
print out the name and description of `cli/cli` which is the one I want. It can
|
||||||
|
then be cloned with `gh repo clone cli/cli`.
|
||||||
|
|
||||||
|
## Can't find it on GitHub
|
||||||
|
|
||||||
|
At this point I would either Google it on DuckDuckGo, or look at where the
|
||||||
|
distro package got it from (this is important in the case of things that have
|
||||||
|
been forked or have multiple versions). I use Arch, so that would entail either
|
||||||
|
looking at the package info with `pacman -Si PACKAGE-NAME` or grabbing the
|
||||||
|
package source with `asp checkout PACKAGE-NAME`, then reading the `PKGBUILD`.
|
||||||
|
Equivalent things exist for other distros, for example, reading `nixpkgs`
|
||||||
|
source for NixOS.
|
||||||
|
|
||||||
|
# Dealing with C or C++
|
||||||
|
|
||||||
|
C or C++ projects often have a lot of latitude to do creative things with their
|
||||||
|
build processes, and I want an IDE to work on them. I use [`nvim`] and
|
||||||
|
[`clangd`] for my IDE, so working on codebases with arbitrary build systems is
|
||||||
|
a question of generating a compilation database (`compile_commands.json`).
|
||||||
|
|
||||||
|
[`nvim`]: https://neovim.io/
|
||||||
|
[`clangd`]: https://clangd.llvm.org/
|
||||||
|
|
||||||
|
## Using various build systems
|
||||||
|
|
||||||
|
These are the build systems I have dealt with the most while working on random
|
||||||
|
C or C++ projects. Sometimes they don't document how to use the build system,
|
||||||
|
or I don't want to read the README.
|
||||||
|
|
||||||
|
### GNU autotools
|
||||||
|
|
||||||
|
**Identifier**: `.in` files or `configure` script at the root of the repo.
|
||||||
|
|
||||||
|
**Notes**: If `configure` is missing, there may be `bootstrap` or
|
||||||
|
`bootstrap.sh` that will generate one, or you may have to run
|
||||||
|
`autoreconf --install` if that's not there.
|
||||||
|
|
||||||
|
**Usage**: `./configure`, then `make -jN` where N is the number of build jobs.
|
||||||
|
`./configure` may need some options, it has a `--help` option that will list
|
||||||
|
the possible ones.
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
**Identifier**: `CMakeLists.txt` at the root of the repo.
|
||||||
|
|
||||||
|
**Usage**: `cmake -G Ninja -B build`, then `ninja -C build`.
|
||||||
|
|
||||||
|
### Meson
|
||||||
|
|
||||||
|
**Identifier**: `meson.build` at the root of the repo.
|
||||||
|
|
||||||
|
**Usage**: `meson ./build`, then `ninja -C build`.
|
||||||
|
|
||||||
|
## Compilation databases
|
||||||
|
|
||||||
|
### Unusual and obsolete build systems such as GNU autotools/GNU make
|
||||||
|
|
||||||
|
Use [Bear]: configure, then `bear -- make [make options]`. This will do
|
||||||
|
`LD_PRELOAD` magic and intercept the calls to the compiler and save them. This
|
||||||
|
tool works on basically any build system, even silly shell scripts. Just
|
||||||
|
remember to run it on a clean build or else it will miss some files!
|
||||||
|
|
||||||
|
Sometimes [`compiledb`] works better: `compiledb make -- [make options]`.
|
||||||
|
|
||||||
|
[Bear]: https://github.com/rizsotto/Bear
|
||||||
|
[`compiledb`]: https://github.com/nickdiego/compiledb
|
||||||
|
|
||||||
|
### Linux kernel
|
||||||
|
|
||||||
|
Pretty high up on the list of unusual build systems. [Build the kernel with
|
||||||
|
clang]: `make CC=clang defconfig` then `make CC=clang -jN`, then run
|
||||||
|
`scripts/clang-tools/gen_compile_commands.py`.
|
||||||
|
|
||||||
|
[Build the kernel with clang]: https://www.kernel.org/doc/html/latest/kbuild/llvm.html
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
CMake is nice because it can generate Ninja. You can invoke it with `-G Ninja`,
|
||||||
|
build, then ask Ninja for compile commands with
|
||||||
|
`ninja -C build -t compdb > compile_commands.json`.
|
||||||
|
|
||||||
|
### Meson
|
||||||
|
|
||||||
|
Like CMake, after building the software, you can use Ninja to get a compilation
|
||||||
|
database with `ninja -C build -t compdb > compile_commands.json`.
|
||||||
|
|
||||||
|
## My IDE got confused because they're doing cursed stuff
|
||||||
|
|
||||||
|
This has happened a couple of times, especially when reading source code to
|
||||||
|
`glibc`, for instance, where there are definitions in headers and definitions
|
||||||
|
in unrelated `.c` files, among other things. Fortunately, `ctags` is not smart
|
||||||
|
enough to get confused by cursed stuff and works fine in parallel with a LSP
|
||||||
|
server. Run `ctags -R .` at the root of the repo and use `nvim` to navigate
|
||||||
|
with the tags:
|
||||||
|
|
||||||
|
- <kbd>CTRL-]</kbd> jump to the identifier under the cursor.
|
||||||
|
- <kbd>CTRL-W g CTRL-]</kbd> jump to the identifier under the cursor in a new
|
||||||
|
split.
|
||||||
|
- `:tj TAG_NAME` selects from the tags called `TAG_NAME` or jumps there
|
||||||
|
directly if there's only one. Useful if there are multiple definitions of
|
||||||
|
the same identifier.
|
||||||
|
- <kbd>CTRL-O</kbd> goes back in history to the last jumped position.
|
||||||
|
- <kbd>CTRL-I</kbd> goes forward in history to the last jumped position.
|
||||||
|
|
||||||
|
# Finding things
|
||||||
|
|
||||||
|
I use [`ripgrep`] as it has good defaults and is extremely fast. Usually the
|
||||||
|
way I find things is I look for a unique word related to the thing I want in
|
||||||
|
the documentation, for instance, a long command line option or an error
|
||||||
|
message, then I search it case insensitively (`-i`) and start browsing code
|
||||||
|
from there.
|
||||||
|
|
||||||
|
Sometimes it's not that easy, and I have to use some more tricks as I can't
|
||||||
|
find it by searching. I often pull out a debugger after `strace`ing the program
|
||||||
|
to try to find an interesting system call I can set a breakpoint on to track
|
||||||
|
down the code path. Or, for instance, I know that a program opens two dialogs
|
||||||
|
before the interesting behaviour, so I set a breakpoint on `XCreateWindow`. I
|
||||||
|
then take a backtrace and have somewhere to start looking in the codebase. Be
|
||||||
|
creative!
|
||||||
|
|
||||||
|
Usually my debugger of choice is either [`rr`] or `gdb`.
|
||||||
|
|
||||||
|
[`ripgrep`]: https://github.com/burntsushi/ripgrep
|
||||||
|
[`rr`]: https://github.com/rr-debugger/rr
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This is part of a series of posts about my development workflow. You can read
|
||||||
|
the other installments here:
|
||||||
|
|
||||||
|
- [Docs](./docs-tricks-and-gnus)
|
||||||
|
|
@ -2,6 +2,7 @@ $text: #ddd;
|
||||||
$bg: #540362;
|
$bg: #540362;
|
||||||
$link: #f778e3;
|
$link: #f778e3;
|
||||||
$lowerbg1: darken($bg, 5);
|
$lowerbg1: darken($bg, 5);
|
||||||
|
$lowerbg2: darken($bg, 10);
|
||||||
$higherbg1: lighten($bg, 10);
|
$higherbg1: lighten($bg, 10);
|
||||||
$lower1: darken($text, 18);
|
$lower1: darken($text, 18);
|
||||||
$lower2: darken($text, 30);
|
$lower2: darken($text, 30);
|
||||||
|
|
@ -147,6 +148,10 @@ main {
|
||||||
color: $lower1;
|
color: $lower1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 860px;
|
max-width: 860px;
|
||||||
|
|
@ -229,24 +234,51 @@ hr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-article h2 {
|
// h1 at the top of blog post pages
|
||||||
|
:not(header) > h1 {
|
||||||
margin: {
|
margin: {
|
||||||
top: 2rem;
|
top: 2.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h2, :not(header) > h1 {
|
h1 {
|
||||||
margin: {
|
margin: {
|
||||||
top: 3rem;
|
bottom: -0.3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: {
|
||||||
|
top: 1.5rem;
|
||||||
|
bottom: -0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: {
|
||||||
|
top: 1.5rem;
|
||||||
|
bottom: -0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(nav) > ul > li {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
display:inline-block;
|
||||||
|
border: 1px solid $lowerbg2;
|
||||||
|
background-color: $lowerbg1;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
padding: 2px;
|
||||||
|
box-shadow: 0px 2px 3px $lowerbg2;
|
||||||
|
}
|
||||||
|
|
||||||
/* headings */
|
/* headings */
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
line-height: 1.10;
|
line-height: 1.10;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2 {
|
|
||||||
margin-block-end: 0.1rem;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue