---
title: OSC2021 Nagoya 「ゼロからのOS自作入門」の執筆を支える技術
tags:  #oss #git #re:view  
author: [内田公太](https://docswell.com/user/uchan_nos)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/GEW3ZYLKE2.jpg?width=480
description: 「ゼロからのOS自作入門」を執筆する際に活用したOSSツールを紹介します。また、執筆中によく使ったGit Rebaseのテクニックも説明します。
published: May 31, 21
canonical: https://docswell.com/s/uchan_nos/ZRXEWR-osc2021-nagoya-tips-to-write-programming-book
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/GEW3ZYLKE2.jpg)

「ゼロからのOS自作入門」
の執筆を支える技術
2021年5月29日
OSC2021 Online/Nagoya
@uchan_nos


# Page. 2

![Page Image](https://bcdn.docswell.com/page/47ZV1XMNE3.jpg)

自己紹介
内田公太 @uchan_nos
サイボウズ・ラボ株式会社でOSと言語処理系の研究開発
自作OSもくもく会コアメンバー
校正協力
執筆
執筆


# Page. 3

![Page Image](https://bcdn.docswell.com/page/YJ65L4N97V.jpg)

「ゼロからのOS自作入門」の紹介
「OS」を自分で作る過程を解説する書籍
他のOSに頼らず「Hello, world」を出力するアプリから始め、
30章で本格的なOSを作成
 64ビット動作、メモリ管理、マルチタスク、ファイルシステム……
本書で作成する「MikanOS」上で様々なアプリが動く様子


# Page. 4

![Page Image](https://bcdn.docswell.com/page/GJ5Y1Q5DJ4.jpg)

執筆に使ったツール
Re:VIEW
 太字指定などの各種マークアップ、索引指定、PDF化
review-text-imager
 アスキーアートで書いた図をPNGに変換する
Git
 MikanOSの開発にも使用
git-extract-tags
 引用するソースコードをGitリポジトリから取得する
もちろん、全部OSSです！


# Page. 5

![Page Image](https://bcdn.docswell.com/page/LE351V5QJ5.jpg)

Re:VIEW
書籍用マークアップ言語


# Page. 6

![Page Image](https://bcdn.docswell.com/page/8EDDX8DWEG.jpg)

書籍用マークアップ
書籍原稿には様々な指定が必要
 太字、等幅フォント
 図、表、リスト、コマンドラインの
スタイル
 図、表、リストの参照
 章構成
執筆途中で紙面を確認したい
 手軽にPDFを生成したい
書籍にはRe:VIEWがおすすめ！
 書籍執筆用だけあり、必要な機能が
揃っている
リストの例
ハローワールドプログラムの本体は@&lt;tt&gt;
{Main.c}ファイルです。@&lt;list&gt;{day02
a_Main.c}にその全体を示します。ぱっと
見て@&lt;chapref&gt;{day01}で作った@&lt;tt&gt;
{hello.c}よりすっきりしていることが分
かると思います。
Re:VIEWソースコードの例


# Page. 7

![Page Image](https://bcdn.docswell.com/page/V7PXP8XXE8.jpg)

Re:VIEW
https://github.com/kmuto/review
書籍用のマークアップ言語+ビルドシステム
 Re:VIEW記法の原稿から、PDF、EPUB、HTML等に変換できる
 日本人が開発の主体なので、日本語サポートがばっちり
2015年頃から開発され、最新が5.1.1
 「ゼロからのOS自作入門」の原稿を書いていたころはバージョン3系
 1年でメジャーバージョンが1上がるほど、開発が活発
 技術書典で回を経る毎に使う人が増加していった（肌感）


# Page. 8

![Page Image](https://bcdn.docswell.com/page/2JVL2NL37Q.jpg)

Re:VIEW記法
「ゼロからのOS自作入門」で使った記法を一部紹介
等幅フォント
@&lt;tt&gt;{Main.c}
画像参照 @&lt;img&gt;{event-propagation}
画像埋め込み
//image[event-propagation][イベントの伝搬][scale=0.8]{
//}
索引登録 @&lt;idx&gt;{タイマ}
脚注参照 @&lt;fn&gt;{heavy-task}
脚注
//footnote[heavy-task][脚注本文]
ユーザ定義タグも作れる
 等幅フォント化+索引登録
@&lt;codeidx&gt;{SendMouseMessage()}


# Page. 9

![Page Image](https://bcdn.docswell.com/page/5EGXRKXYJL.jpg)

ラフ図案を手軽に描く


# Page. 10

![Page Image](https://bcdn.docswell.com/page/4JQ8VN867P.jpg)

ラフ図案
本文を執筆中に図を入れたくなることがある
その場で本格的な作図をしたくない
 本格的な作図により、本文用の脳内メモリが奪われる
ASCIIアートで本文中に描いて、それを図の代用としたい
//image[layering][レイヤによる画面描画][scale=0.9]{
マウスのレイヤ --&gt; -------------------＼
---＼
デスクトップの --&gt; - ＼
＼ ↑ ＼ &lt;---＼--- マウスのウィンドウ
レイヤ
＼ ＼
---＼
＼
-------------------＼
＼
-------------------//}


# Page. 11

![Page Image](https://bcdn.docswell.com/page/K742MG2MJ1.jpg)

コメントを抽出してPNG化する
Re:VIEWの「//image{…}」は、コメントが埋め込める
→コメントを抽出してPNG化して埋め込めばいいかも？
専用ツールpngnize-image-bodyを作りました
 https://github.com/uchan-nos/review-text-imager
先ほどのコメントをPNG化した結果
ImageMagick
+
IPAゴシック
でPNG生成


# Page. 12

![Page Image](https://bcdn.docswell.com/page/LJ1M8DMYEG.jpg)

本文でMikanOSのソースコー
ドを引用する


# Page. 13

![Page Image](https://bcdn.docswell.com/page/GJW3ZY31J2.jpg)

「ゼロからのOS自作入門」の特性
MikanOS自体の開発の歴史と、本文の執筆の歴史がある
本文でMikanOSのソースコードを引用する
MikanOSの過去のバージョンを直したくなることがある
 本文の説明をストレートにするため
day01
day02
MikanOSの
Gitリポジトリ
コードの引用
本文の
Gitリポジトリ
day03


# Page. 14

![Page Image](https://bcdn.docswell.com/page/4EZV1XVXJ3.jpg)

2つの歴史
MikanOSは大規模なソフトウェア
→専用のリポジトリが欲しい
 https://github.com/uchan-nos/mikanos
本文も大規模になるので、バージョン管理したい
 https://github.com/uchan-nos/legacy-free-os-book
MikanOSの実装を進めつつ本文を執筆
2つのGitリポジトリが、並行に進展


# Page. 15

![Page Image](https://bcdn.docswell.com/page/Y765L45PEV.jpg)

MikanOSのソースコードを引用する
MikanOSのソースコードを解説するために、本文に引用したい
手動でコピペするとミスが出る
Re:VIEWのファイル埋め込み機能が使えそう！
 #@mapfile(ファイル名)～#@end
と書くと、そのファイルの内容を展開してくれる
プリプロセッサが
ソースコード
を展開する
//list[list_tag][リストタイトル]{
#@mapfile(foo.c)
#@end
//}


# Page. 16

![Page Image](https://bcdn.docswell.com/page/G75Y1QYP74.jpg)

masterブランチから引用する？
//list[main][MikanOSのメイン関数]{
#@mapfile(../mikanos/kernel/main.cpp)
#@end
//}
問題：最新版のソースコードを引用するので大丈夫？
答え：ダメ。章ごとに機能を追加していくから。
特定のバージョンを引用したい
day03
day04
master
MikanOSの
Gitリポジトリ
タグ
引用するバージョンを固定したい
ブランチ


# Page. 17

![Page Image](https://bcdn.docswell.com/page/9J2G1PGZJR.jpg)

main.cppの内容の変遷
osbook_day03aのmain.cpp
extern &quot;C&quot; void KernelMain() {
while (1) __asm__(&quot;hlt&quot;);
}
main.cppを引用する
タグXのmain.cppを引用する
osbook_day03cのmain.cpp
#include &lt;cstdint&gt;
extern &quot;C&quot; void KernelMain(uint64_t frame_buffer_base,
uint64_t frame_buffer_size) {
uint8_t* frame_buffer = reinterpret_cast&lt;uint8_t*&gt;(frame_buffer_base);
for (uint64_t i = 0; i &lt; frame_buffer_size; ++i) {
frame_buffer[i] = i % 256;
}
while (1) __asm__(&quot;hlt&quot;);
}


# Page. 18

![Page Image](https://bcdn.docswell.com/page/DEYVZ5VNEM.jpg)

タグを指定して引用したい
タグ毎にファイルを配置したディレクトリを用意すればできる
実際に、こんなディレクトリ構成にしてみた
text/
images/
dayN.re
…
distrib/
dayN/
MikanLoaderPkg/Main.c
kernel/main.cpp
…
…


# Page. 19

![Page Image](https://bcdn.docswell.com/page/VJNM3NMV78.jpg)

タグを指定して引用する
タグ毎にファイルを配置したディレクトリを用意すればできる
実際に、こんなディレクトリ構成にしてみた
text/
images/
dayN.re
…
distrib/
dayN/
osbook_dayN
MikanLoaderPkg/Main.c
タグに対応
kernel/main.cpp
…
…
希望のタグから
ソースコードを引用する


# Page. 20

![Page Image](https://bcdn.docswell.com/page/YE9N9RNVE3.jpg)

タグを指定して引用する
Re:VIEWを使った本文の例
//list[day02a_Main.c][EDK IIを使ったハローワールドアプリ（Main.c）][c]{
#@mapfile(../distrib/day02a/MikanLoaderPkg/Main.c)
#include &lt;Uefi.h&gt;
#include &lt;Library/UefiLib.h&gt;
EFI_STATUS EFIAPI UefiMain(
EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *system_table) {
Print(L&quot;Hello, Mikan World!\n&quot;);
while (1);
return EFI_SUCCESS;
}
#@end
//}
ハローワールドプログラムの本体は@&lt;tt&gt;{Main.c}ファイルです。
@&lt;list&gt;{day02a_Main.c}にその全体を示します。


# Page. 21

![Page Image](https://bcdn.docswell.com/page/GE8K9WK47D.jpg)

タグ内容を抽出するツール
osbook_dayNというタグに対応するソースコードを取得し
distrib/dayNディレクトリに展開したい
専用ツールgit-extract-tagsを作りました
 https://github.com/uchan-nos/git-extract-tags
使い方
$ git extract-tags -s distrib \
osbook_ ../mikanos
 プレフィクスが「osbook_」であるタグから
ファイルを抽出してdistribに書き出す
legacy-free-os-book/
text/
images/
dayN.re
…
distrib/
dayN/
…
mikanos/
MikanLoaderPkg/
kernel/
…
想定するディレクトリ構成


# Page. 22

![Page Image](https://bcdn.docswell.com/page/LELZWNZVJR.jpg)

MikanOSの過去のバージョン
を直したくなることがある


# Page. 23

![Page Image](https://bcdn.docswell.com/page/4JMV9XVNJW.jpg)

ソフトウェアにはバグがある
執筆中にOSのバグを見つけることがよくある
 解説文を書いていると、コードの動作を深く考えるから、余計に。
osbook_day06cでバグを入れてしまったことに
第20章を執筆中に気付くと、大変辛い。
 6c、20という数字はただの例。後で見つかれば見つかるほど辛い
選択肢1：第20章に「osbook_day06cの実装にバグがあったので、
直します」みたいな解説文を書き、osbook_day20xを修正する
選択肢2：osbook_day06cに修正を加え、何事も無かったかのよう
に執筆を進める


# Page. 24

![Page Image](https://bcdn.docswell.com/page/PJR2GN24E9.jpg)

MikanOSの歴史を綺麗に保つ
day06b
day06c
master
MikanOSの
Gitリポジトリ
本文の
Gitリポジトリ
…
master
…
やはり「選択肢2」を取りたい
 選択肢1の方がリアルな開発姿勢だが、解説がごちゃごちゃする
 ただでさえ大変なOS自作なので、解説くらいは綺麗にしたい
Gitで過去のバージョンを修正するには？
→リベース！


# Page. 25

![Page Image](https://bcdn.docswell.com/page/PEXDXNDZ7X.jpg)

リベース
1. バグ修正を
コミットする
day06c
day06b
A
…
D
C
B
master
X
a バグ修正コミット
day06c
day06b
2. リベースする
A
a
…
D
C
B
C’
D’
X
…
master
X’
リベース：Cのベースをaに付け替える


# Page. 26

![Page Image](https://bcdn.docswell.com/page/3EKXWNXV7D.jpg)

リベースの問題点
MikanOSの利用者が困惑する
 公開されたブランチをリベースするのは混乱の元
 MikanOSでは、しばらくはリベースがたくさん発生するよ、とREADME
に書いた
タグが付け変わらない
 day06cがCを指したまま
 C’を指して欲しい
day06c
a
…
D
C
B
C’
タグを手動で付け替えるのは大変
 BからXまでの、全タグを付け替える必要あり
 リベース作業はバグ発見のたびに何度も発生
D’
master
X
…
X’


# Page. 27

![Page Image](https://bcdn.docswell.com/page/L7351VRQE5.jpg)

タグを付け替えるツール
元のブランチからリベース先のブランチへ各タグを移動したい
専用ツールgit-retagを作りました
 https://github.com/uchan-nos/git-extract-tags
使い方
$ git retag osbook_ old new
 プレフィクスが「osbook_」であるタグを、oldからnewへ付け替える
tag2
tag1
C
B
A
a
B’
new
E
D
C’
old
D’
E’


# Page. 28

![Page Image](https://bcdn.docswell.com/page/87DDX8YW7G.jpg)

タグ付け替えの例
 「handle close button」と「exit
task on window close」の間に修
正を挿入する例
 挿入した修正「hoge-fix」
 「osbook_dayX」というタグす
べてを、「new-day30f」ブラン
チに移動したい


# Page. 29

![Page Image](https://bcdn.docswell.com/page/VJPXP86X78.jpg)

git-retag使用例
 git retag
--dry-run
osbook_
osbook_day30f
new-day30f
 指定した2つのブラン
チの共通の祖先を見つ
け、
 プレフィクスが
「osbook_」であるタ
グを移動する


# Page. 30

![Page Image](https://bcdn.docswell.com/page/2EVL2N33JQ.jpg)

Git rebase入門


# Page. 31

![Page Image](https://bcdn.docswell.com/page/57GXRK3YEL.jpg)

コミットグラフを理解しよう
リベース操作は複雑で分かりにくい？
コミットグラフの変化が想像できるようになれば、怖くない！
コミット：ワークツリー全体のスナップショット
 Diffではない
ブランチ：コミットを指すラベル
 コミットの列、ではない
ブランチ
コミット
A
master
B
C
D


# Page. 32

![Page Image](https://bcdn.docswell.com/page/4EQ8VN56JP.jpg)

コミットはDiffではない
A
B
C
コミットは、親に対する差分、ではない
コミットは、ワークツリー全体のスナップショットである
1つのコミットは、管理対象の全ファイルの完全な内容を持つ
 もちろん、無変更のファイルの内容は持たない、などの最適化はある
Diffではないので、自由に組み替え可能


# Page. 33

![Page Image](https://bcdn.docswell.com/page/KJ42MG9ME1.jpg)

リベース
$ git checkout -b fix-bug B
《ワークツリーを修正》
$ git commit -a
A
B
D
C
master
fix-bug
a
$ git rebase fix-bug master
A
B
fix-bug
a
C’
D’
master


# Page. 34

![Page Image](https://bcdn.docswell.com/page/LE1M8DKY7G.jpg)

リベース（interactiveモード）
非常に多用途な git rebase -i
 コミットの順番を入れ替える、
 不要なコミットを捨てる、
 コミットメッセージを修正する、など
ここを入れ替えたいなあ……
$ git checkout master
$ git rebase -i A
行を入れ替えて保存
A
B
C
D
master


# Page. 35

![Page Image](https://bcdn.docswell.com/page/GEW3ZYD1E2.jpg)

git rebase -iのその他の機能
「pick」を希望のコマンドに書き換える
# Commands:
# p, pick &lt;commit&gt; = use commit
# r, reword &lt;commit&gt; = use commit, but edit the commit message
# e, edit &lt;commit&gt; = use commit, but stop for amending
# s, squash &lt;commit&gt; = use commit, but meld into previous commit
# f, fixup &lt;commit&gt; = like &quot;squash&quot;, but discard this commit&#039;s log message
# x, exec &lt;command&gt; = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with &#039;git rebase --continue&#039;)
# d, drop &lt;commit&gt; = remove commit
# l, label &lt;label&gt; = label current HEAD with a name
# t, reset &lt;label&gt; = reset HEAD to a label
# m, merge [-C &lt;commit&gt; | -c &lt;commit&gt;] &lt;label&gt; [# &lt;oneline&gt;]
#
# These lines can be re-ordered; they are executed from top to bottom.


# Page. 36

![Page Image](https://bcdn.docswell.com/page/47ZV1XGXE3.jpg)

コミットグラフを理解する便利なコマンド
$ git log --graph --all
ここでマージされた
ここで枝分かれして


# Page. 37

![Page Image](https://bcdn.docswell.com/page/YJ65L4YP7V.jpg)

間違ったリベースを無かったことにする
Git reflog
 「ブランチやタグ等が、過去何を指していたか」が
 コミットやリベース等、Gitの操作をするたびに記録される
リベースなどでミスしてもデータが失われるわけではないので、
安心して実験しましょう
ブランチを任意のコミットに付け直すには
$ git checkout &lt;branch&gt;
$ git reset --hard &lt;commit&gt;


# Page. 38

![Page Image](https://bcdn.docswell.com/page/GJ5Y1QGPJ4.jpg)

まとめ
「ゼロからのOS自作入門」の執筆に様々なOSSを使った
 Re:VIEW、review-text-imager、Git、git-extract-tags
ラフ図案をASCIIアートで→pngnize-image-body
「ゼロからのOS自作入門」は2本のGitリポジトリで構成される
タグを指定したソースコード引用を行いたい→git-extract-tags
引用プログラムのバグを直したい→git-retag
リベースを使いこなそう


