selmertsxの素振り日記

ひたすら日々の素振り内容を書き続けるだけの日記

一からtslintの設定をする方法

モチベーション

tslintについては、これまで誰かが作ってくれた設定ファイルを使ってきました。 しかし、そろそろちゃんと理解したいと思い、諸々調べてみました。 この資料に tslint を一から設定する方法を記載し、自分の理解を整理しようとおもいます。

※ 理解が間違っている点ありましたら、コメント貰えたら嬉しいです!

そもそもLint って何?

lint (software) - Wikipedia

そもそもLintについて理解がふわっとしていたので、wikipediaを読みました。linterとはソースコードを解析してプログラムの保守性・安全性を保ち、機能的なバグを防ぐためのもの。特にJavaScriptPythonなどのコンパイルフェーズを持たないものにとっては、実行する前にバグを見つけられることができるので有用とのことでした。

tslint 導入手順

  • install
  • configuration presetsの導入
  • 適用するrulesの選択

tslint install

TSLint command-line interface

上記ドキュメントを見て、tslintを導入していきます。 下記のコマンドをポチッと実行しましょう。

yarn add -D tslint

Exit Codesは、ルールを詳細に設定する際に必要となるため、ここにあるということだけは覚えておくと良いと思います。

Exit Codes
0: success
1: cliの引数エラー
2: Linting failed

configuration presets の導入

次は、下記のlinkからLintの設定方法について確認していきます。 Configuring TSLint

色々書いてありますが、最初は extendsConfiguration presets だけ見ておけば良いでしょう。extendsには下記のような説明が記載されています。

The name of a built-in configuration preset (see built-in presets below), or a path or array of paths to other configuration files which are extended by this configuration.

extendsは、build-inのプリセット設定ファイルを入れたり、設定ファイルのパスを記載するプロパティです。ここに記載するべき設定ファイルは、Configuration presets にて説明されています。Configuration presetsには、下記3つの設定ファイルが存在します。

presets description
tslint:recommended stable な設定ファイル
tslint:latest tslint:recommendedと新しく追加されたルールを含む
tslint:all 全てのチェックを行う設定ファイル

さて、ミニマムでtslintを使ってみます。 最もスタンダードそうな tslint:recommendedextends に記載します。 このとき設定ファイルの名前は tslint.json とする必要があります。

// tslint.json
{
  "extends": ["tslint:recommended"]
}

この設定でlintを実行していきましょう。下記のような結果が返ってきます。

$ yarn tslint 'src/**/*.ts'

ERROR: /xxx/iiopt/src/cli.ts[22, 1]: Exceeds maximum line length of 120
ERROR: /xxx/iiopt/src/cli.ts[29, 9]: The key 'alias' is not sorted alphabetically
ERROR: /xxx/iiopt/src/cli.ts[30, 23]: Missing trailing comma

vscode上で確認してみると、lintでErrorとなっている場所が、赤くなっていることが確認できます。

f:id:selmertsx:20180206192918p:plain

ルールの修正

Rule: object-literal-sort-keys

# bad
      overwrite: {
        type: "boolean",
        alias: "o",
        default: false,
      },
# good
      overwrite: {
        alias: "o",
        default: false,
        type: "boolean",
      },

ということですね。理由としては、下記のように記載されています。

Useful in preventing merge conflicts

overwrite objectにおいて、typeは渡されるデータの型、default は値が渡されなかった際のデフォルト値です。なのでこのルールに従うと、typeの前に defaultを渡す必要が出てきます。僕としては、まず型の情報を確認し、その後にデフォルト値を渡した方がしっくりくるので、それを阻むこのルールは取り除くことにしました。そのtslint.jsonの設定は下記のようになります

{
  "extends": ["tslint:recommended"],
  "rules": {
    "object-literal-sort-keys" : false
  }
}

vscode上でも怒られなくなりました。

f:id:selmertsx:20180206201656p:plain

まとめ

tslintの設定は一気にやろうとすると混乱するので、特に理由がない限り最初は configuration presetsを使って、ERRORになった部分を一つずつ確認し、ルールを作っていくとよいのかなぁと思いました。

補足: 修正しなかったルールとその理由

trailing comma

$ yarn tslint 'src/**/*.ts'
ERROR: /xxx/iiopt/src/cli.ts[30, 23]: Missing trailing comma <= このエラー

trailing commaに関しては、下記のドキュメントに記載されています。 Rule: trailing-comma

# NG
      overwrite: {
        type: "boolean",
        alias: "o",
        default: false
      },
      overwrite: {
        type: "boolean",
        alias: "o",
        default: false,
      },

この理由について調査してみると、airbnbの資料にそれっぽい説明がありました。

GitHub - airbnb/javascript: JavaScript Style Guide

Why? This leads to cleaner git diffs. Also, transpilers like Babel will remove the additional trailing comma in the transpiled code which means you don’t have to worry about the trailing comma problem in legacy browsers.

git diffsがなくなるから良い。legacy browsersでエラーになることがあったけど、Babelを使えば問題無いよね。とのこと。納得したので、このルールは適用しようと思います。

ふつうのLinuxプログラミング読書 (3章)

ファイルとは

  • 何らかのデータを保持し
    • 何らかのデータとは、テキスト、画像、
  • パーミッションや更新時間などの付帯情報を保持しており
  • 名前で指定して閲覧・実行ができるものである

ファイルの種類

  • Regular File
    • 画像。動画。テキストなど。
  • Directory
    • このファイルの中に、入っているファイル一覧
  • Symbolic Link
    • このファイルが指し示す一つのファイル
  • Device File
    • バイスをファイルとして表現したもの
    • マウス、キーボード、モデム、HDD、SSDなどが含まれる

シンボリックリンクとハードリンク

本には書かれていないので、自分で確認したことを記載。

$ echo 'hogehoge' > ln.txt
$ ln -s ln.txt ln_soft.txt
$ ln ln.txt ln_hard.txt
$ ls -li
total 32
56944157 -rw-r--r--  2 shuhei_morioka  admin   9  2  5 20:49 ln.txt
56944157 -rw-r--r--  2 shuhei_morioka  admin   9  2  5 20:49 ln_hard.txt
56944166 lrwxr-xr-x  1 shuhei_morioka  admin   6  2  5 20:49 ln_soft.txt -> ln.txt

このような形でハードリンクとソフトリンクを使って、ファイルを生成しました。

$ cat ln_soft.txt
hogehoge
$ cat ln_soft.txt
cat: ln_soft.txt: No such file or directory
$ cat ln_hard.txt
hogehoge

ソフトリンクは参照しているファイルを削除してしまうと、何のファイルにもアクセスできなくなってしまいます。しかし、ハードリンクでは直接アクセスするためのi-nodeをリンク元のファイルと共有しているため、リンク元のファイルが削除されてもアクセスすることが出来ます。

ソフトリンクでは、リンク先のパスのみを保持しているため、新しいファイルを元のパスに配置すると読み込んでくれるようになります。

$ readlink ln_soft.txt
ln.txt
$ echo 'fugafuga' > ln.txt
$ cat ln_soft.txt
fugafuga

このようにソフトリンクの方が、プログラムから扱いやすそうに見えます。

Linux: ハードリンクと inode - Qiita シンボリックリンクとハードリンクの違い - Qiita

ファイルシステム

物理的なディスクをパーティションとして区切り、その上にファイルシステムをマウントさせることで、ファイルを扱う土台となるディレクトリツリーが出来上がります。以下、macosamazon linuxファイルシステムが違うよということの確認していきます。

# macosで実行した結果
➜  ~ mount
/dev/disk1 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
# amazon linuxで実行した結果
ec2-user@bastion ~
$ mount -t ext4
/dev/xvda1 on / type ext4 (rw,noatime,data=ordered)

プロセスとは

動作中のプログラムのこと。helloというプログラムを動かすと、helloプロセスが生成される。 プログラムとプロセスは1対多の関係であり、プロセスのユニーク性の識別するには Process ID を用いる。プロセスへ命令するものは シグナル と呼ばれ、よく使われるものとして Ctrl + c の割り込みシグナルなどがある。

ストリームとは

バイトが流れる通り道。つまり byte streamのこと。本書独自の用語である。 プロセスからファイルにアクセスするとき、プロセスはシステムコールを使って、ファイルやプロセスにアクセスするためのストリームを作る。

ファイルにアクセスができるので、テキストや画像だけでなく、ファイルの一種であるデバイスファイル(キャラクタデバイスであるモデムや、ブロックデバイスである HDD/SSDなど)にもアクセスすることができる。

プロセスとプロセスの間でストリームを通じて行われるデータのやりとりをプロセス間通信と呼ぶ。プロセス間通信の中には、下記の2つのやりとりが存在する。

  • パイプ
    • ストリームの向き先に別のプロセスを用意すること
  • ネットワーク通信
    • ストリームを別のコンピューターまで伸ばすこと

まとめ

  • 画像・テキストが格納されていたり、プログラムが記載されていたりする ファイル
  • プログラムを実際に実行している プロセス
  • プロセスが実行した結果をディスプレイ、ファイルなどに出力するためのデータの流れを作り出す ストリーム

この3点がLinux世界を構築する上で重要な概念である。

JavaScriptで正規表現(入門レベル)

モチベーション

現在、iioptという画像圧縮ツールを作成しています。このツールの一つの機能として、git pre-commit にhookしてcommit対象の画像を抽出し、圧縮が必要であれば圧縮するという機能を開発中です。

本記事は、そこで学んだ正規表現の書き方について記載します。記事の作成にあたって、下記のサイトを参考にさせていただきました。

developer.mozilla.org

※ 今まであんまり正規表現に触ってこなかったゆるふわエンジニアの記事なので、ある程度触った方には学ぶことがないかと思います。そのような方は、回れ右して頂くか、間違ってる点とう発見したらコメント貰えると喜びます!

やりたいこと

git pre-commit 時に git diff --cached --name-status を実行したとき、下記の結果が得られたとします。

# git diff --cached --name-status
M       images/need_match.jpg
M       images/not_matchjpg
M       images/need_match.png
M       images/not_match.ts
D       not_match.jpg
R100    images/sample.jpg       not_match.jpg
A       need_match.jpg
M       need_match.png

このとき、頭文字がM,Aであり、かつ拡張子がpng, jpgのファイル名のみを取得したいです。なので、求める最終的なアウトプットは下記のようになります。

'images/need_match.jpg',
'images/need_match.png',
'need_match.jpg',
'need_match.png'

最終的に採用したコード

  const input = `
M       images/need_match.jpg
M       images/not_matchjpg
M       images/need_match.png
M       images/not_match.ts
D       not_match.jpg
R100    images/sample.jpg       not_match.jpg
A       need_match.jpg
M       need_match.png
`
  const re = /^[AM]\s.+\.(?:jpg|png)$/gm;
  const files = input.match(re).map((line) => {
    console.log(line);
    return line.replace(/^[AM]\s*/, "")
  });
  console.log(files);
'images/need_match.jpg',
'images/need_match.png',
'need_match.jpg',
'need_match.png'

パターンについて

頭文字の判断

まず、頭文字 A & Mのもののみ取得したいです。 その場合、正規表現/^[AM]/となります。 実際にコードを書いて確かめると、下記のような結果が得られます。

console.log(/^[AM]/.test('A       sample1.jpg'));
console.log(/^[AM]/.test('D       hoge.jpg'));
true
false

ここで把握するべきものは、^[]の2つです。

まず[] についてです。これは文字列の集合を意味し、囲まれた文字のいずれか 1 個にマッチします。[]の中では - を使えば範囲を指定することができます。[0-9]とすれば、0から9までの数値すべてにマッチします。

> /[A-Z]/.test('BC123')
true
> /[A-B]/.test('123')
false

次の^ は、入力の先頭にマッチします。例えば、'BA' という文字列があったときに、/A/はマッチしますが、/^A/ はマッチしません。

ということで /^[AM]/ という正規表現を用意すれば、頭文字 A or M の文字列にマッチさせることができます。

特殊文字\sでタブ or 空白にマッチさせる

頭文字 A or M にマッチさせることができたので、次は空白 or タブにマッチさせたい。ここで把握するべき要素は、\s である。

まず、'M hoge.jpg' にマッチする正規表現を書きたい。 このとき必要となるのが、特殊文字 \s であす。 \sはmdnのドキュメントにおいて、「スペース、タブ、改ページ、改行を含む 1 個のホワイトスペース文字にマッチ」するものと書かれています。

> /^[AM]\s/.test('Mhoge')
false
> /^[AM]\s/.test('M hoge')
true

末尾マッチとグループ化

これまでの内容で出来上がった正規表現は、 /^[AM]\s/となります。この正規表現からマッチする文字列は、 A hogehogeM hogehoge のような文字列です。

ここから、A hoge_hage/hogehoge.jpgM hogehage.png のような文字列にマッチさせる正規表現になるよう、仕上げていく必要があります。今回は ., +, と$、そしてグループ化です。

まず . ですが、これは改行文字以外のすべての文字列にヒットします。次に+は、直前の文字の1回以上の繰り返しにマッチします。よって、.+ は1文字以上何かの文字列があれば、全てにマッチさせることになります。

> /^[AM]\s.+/.test('A &&&hogeあ')
true

このように自由度高く受け入れられるようにした理由としては、ユーザーがどのような名前の画像を用意するかわからなかったため、受け入れられる文字列を幅広く設定したかったからです。iioptはCLIツールなので、自分で自分に悪意を持って操作しない限り、問題が起きる可能性が少ないと考えたためです。

次にjpg, pngの拡張子を持つパスを取得できるようにします。ここで重要になってくるのが、$です。まず、jpgの拡張子を持つファイルだけ取得できるようにしましょう。$入力の末尾にマッチする特殊文字なので、/.jpg$/ のように書くと、hogehoge.jpg などのファイルパスにマッチできるようになります。これまで正規表現とくっつけると、下記のようになります。

> /^[AM]\s.+\.jpg$/.test('A &&&/hoge')
false
> /^[AM]\s.+\.jpg$/.test('A &&&/hoge.jpg')
true
> /^[AM]\s.+\.jpg$/.test('A &&&/hoge.jpga')
false

jpgだけでなくて、pngも取得したいです。ここでグループ化 という概念が出てきます。

正規表現 - JavaScript | MDN

グループ化は、(?: PATTERN) といった書き方で使います。簡単な例を以下に記載します。

 // "foo"で1つのパターンとして認識するため、"foofoo"がtrueになる
> /(?:foo){2,3}/.test("foofoo")
true
// "o" がパターンとして認識される。そのため、foofoo だとoが3つ続かないのでfalse
> /foo{2,3}/.test("foofoo")  
false
// "foooo" はfoの後に o が2~3続くのでtrue
> /foo{2,3}/.test("foooo") 
true

このグループ化を使うと、jpg, png の両方の拡張子に対応する正規表現は、/\.(?:jpg|png)$/ となります。 これまでの正規表現と繋げると、/^[AM]\s.+\.(?:jpg|png)$/ となって、ここのサイトを使って図にすると、下記の図のようになります。

f:id:selmertsx:20180130223827p:plain

※ この正規表現に、セキュリティ的に問題がある!などご存知の方がいましたら、ご指摘頂けると幸いです。

正規表現フラグ

/m フラグ

これまでの結果から、M need_match.png のような文字列が与えられたときに、マッチするために必要な正規表現/^[AM]\s.+\.(?:jpg|png)$/ であるということがわかりました。でも今回与えられる文字列は複数行あります。そういうときは、 /m フラグをつけましょう。複数検索ができるようになります。/mをつけて、確認した結果を以下に記載します。

  const input = `
M       images/not_matchjpg
M       images/need_match.jpg
M       images/need_match.png
M       images/not_match.ts
D       not_match.jpg
R100    images/sample.jpg       not_match.jpg
A       need_match.jpg
M       need_match.png
`
  const re = /^[AM]\s.+\.(?:jpg|png)$/m;
  const matches = input.match(re);
  console.log(matches);
[ 'M       images/need_match.jpg',
  index: 1,
  input: '\nM       images/need_match.jpg\nM ...

2行目の取得するべき文字列を取得してくれました。 が、3行目以降は検索しませんでした。 以上の結果から、/m だけでは、全ての行から一致するものを取得することができません。

/mg フラグ

そこで必要となってくるのが、/g フラグです。 これは、グローバルサーチ と呼ばれるもので、マッチした全ての文字列を取得することができます。 下記が実行結果になります。

// /g をつけないと最初に一致したもので終了
> `hage hoge fuga fugu hogo`.match(/fu\w*/);
[ 'fuga', index: 10, input: 'hage hoge fuga fugu hogo' ]
// /gを付けると、マッチする文字列全てを取得可能
> `hage hoge fuga fugu hogo`.match(/fu\w*/g);
[ 'fuga', 'fugu' ]

これらのフラグですが、組み合わせて使うことが可能です。ということで、/m と /gを組み合わせると下記のような結果になります。

  console.log('今回マッチさせたいもの');
  const input = `
Mimages/not_match.jpg
M       images/not_matchjpg
M       images/need_match.png
M       images/not_match.ts
D       not_match.jpg
R100    images/sample.jpg       not_match.jpg
A       need_match.jpg
M       need_match.png
A       &&HOGE/need_match.png
`
  const re = /^[AM]\s.+\.(?:jpg|png)$/gm;
  const files = input.match(re).map((line) => {
    return line.replace(/^[AM]\s*/, "")
  });
  console.log(files);
今回マッチさせたいもの
[ 'images/need_match.png',
  'need_match.jpg',
  'need_match.png',
  '&&HOGE/need_match.png' ]

ということで、欲しいデータだけ取得することができました。

ふつうのLinuxプログラミング読書会 (第2章)

2章: Linuxカーネルの世界

最初に

本資料は、学習者が本を元にサマリーを書いたものです。 分量はものすごく減っていますし、間違ったことを書いている可能性もあります。なので、気になった人は直接本を読んで頂けると幸いです!!

知識として学べること

Linux世界とカーネル

Linuxとは何かと聞かれたとき、OSと答える人が多い。けれども、OSとは厳密な定義がなく、Linux世界 = OS とは言い難い。本書では、Linux世界とは カーネル が作り出した世界であると捉えて話を進める。

カーネルのコードは、/boot下にあるので簡単に確認できる。

# amazon linuxのカーネル
$ ls  /boot/ | grep vm
vmlinuz-4.9.77-31.58.amzn1.x86_64

カーネルのお仕事は、コンピュータを構成する全てのハードウェアとソフトウェアを管理すること。なので、デバイスデバイスドライバの取扱いもカーネルのお仕事と言って良い。

カーネルにお仕事をさせるための手段としてシステムコールというものが存在する。macOS上でシステムコールについて確認する方法として、dtrussというコマンドが存在する。

# vscodeのdtruss結果
$ sudo dtruss -c -p 85439
kevent(0x7, 0x7FFF59C8AE60, 0x0)         = 1 0
read(0x1F, "\001\0", 0x10000)        = 882 0
write(0xB, "\0", 0x1)        = 1 0
write(0x1F, "\001\0", 0x30)      = 48 0
write(0xB, "\0", 0x1)        = 1 0
select(0x8, 0x700004AB7E20, 0x0, 0x0, 0x700004AB7EA8)        = 1 0

...
CALL                                        COUNT
psynch_cvwait                                   2
read                                           14
psynch_mutexdrop                               15
psynch_mutexwait                               15
write                                          19
kevent                                         21
select                                         21

上記システムコールが、vscode上でちょいちょいコードを書いてみたりした結果、実行されたものである。read, write, select等々はmanコマンドで確認することができる。

ライブラリ

Linuxで使う関数をまとめたものをライブラリと呼ぶ。任意のライブラリに用意されている関数をライブラリ関数と呼ぶ。

システムコールカーネルに仕事をさせるものであるが、 ライブラリ関数は必ずしもそうでない。例えば strlen() などは、システムコールを利用しない。

libc

ライブラリの中でも、標準Cライブラリが特に重要。 printf() などが格納されている。

PRINTF(3)                BSD Library Functions Manual                PRINTF(3)

NAME
     printf, fprintf, sprintf, snprintf, asprintf, dprintf, vprintf, vfprintf, vsprintf, vsnprintf,
     vasprintf, vdprintf -- formatted output conversion

LIBRARY
     Standard C Library (libc, -lc) #<= ここに書いてある

nodejsでdebuggerを動かす

モチベーション

typescript & vscode & jest環境でdebugするにあたって、debuggerを使っていたが、そもそもdebuggerって何よ。ってくらいの理解だったので、この機会に色々確認したかった。

debuggerの実行方法

https://nodejs.org/dist/latest-v6.x/docs/api/debugger.html そもそも debuggerとは、nodejs本体に搭載されている機能である。

console.log('hogehoge');
var a = "hogehoge";
debugger;
a = "1234";
console.log('hagehage');
$ node debug test.js
< Debugger listening on [::]:5858
connecting to 127.0.0.1:5858 ... ok
break in test.js:1
> 1 console.log('hogehoge');
  2 debugger;
  3
debug> repl
Press Ctrl + C to leave debug repl
> a
'hogehoge'

ということで、何の設定もしなくても動く。

debuggerのコマンド

watch

指定した変数の変化を追ってくれる

debug> watch('a');
debug> n
< hogehoge
break in test.js:2
Watchers:
  0: a = undefined

  1 console.log('hogehoge');
> 2 var a = "hogehoge";
  3 debugger;
  4 a = "1234";
debug> n
break in test.js:3
Watchers:
  0: a = "hogehoge"

  1 console.log('hogehoge');
  2 var a = "hogehoge";
> 3 debugger;
  4 a = "1234";
  5 console.log('hagehage');
debug> unwatch('a')
debug> n
break in test.js:4
  2 var a = "a";
  3 debugger;
> 4 a = "1234";
  5 console.log('hagehage');

list

Listはソースコードを、実行中の部分から前後5行の範囲内で表示してくれる。

debug> list(1)
> 1 console.log('hogehoge');
  2 var a = "hogehoge";
debug> list(5)
> 1 console.log('hogehoge');
  2 var a = "hogehoge";
  3 debugger;
  4 a = "1234";
  5 console.log('hagehage');

とりあえず、普通に使う分には把握した気がする。

ふつうのLinuxプログラミング読書 (1章)

第1章は下記のような構成になっています

  • この本で学ぶことができること
  • C言語開発の一通りの手順
  • 情報の探し方と基礎知識について

それぞれについて、簡単にまとめます

この本で学べる内容

Linuxを構成するものやその世界を見て、Linuxに関する常識を身につけることを目的として、下記3点の概念について学びます。

  • ファイルプロセス
  • プロセス
  • ストリーム

この3点を選んだ理由は、この3つがLinux世界を構成する重要な概念だからです。

C言語開発の一通りの手順

ここでは下記の内容について学びます

gccを使ったビルド

# -o optionでビルドされるプログラム名を指定する
gcc -o ${ビルドされるプログラム名} {Cのプログラム名}

github.com

コマンドライン引数

int main (int argc, char *argv[]){
   ...
}

上記のプログラムにコマンドライン引数を与えて実行すると、argc, argvの値は下記のようになります。

$ ./args x y
argc=3
argv[0] = ./args 
argv[1] = x
argv[2] = y

ここで./args * などのグロブを使って、複数の引数を一度に渡すことも可能です。 また、ダブルコーテーションを使うと、コマンドライン変数をまとめることができます。 ./args "*"./args "x y z"と入力した場合、"*" や "x y z" も1つのコマンドライン引数とみなされます。

情報の探し方と基礎知識

cプログラミングで情報を集める際、manコマンドが便利です。 例えば、man strlen とすると、下記のような出力が得られます。

STRLEN(3)                BSD Library Functions Manual                STRLEN(3)

NAME
     strlen, strnlen -- find length of string

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <string.h>

     size_t
     strlen(const char *s);

     size_t
     strnlen(const char *s, size_t maxlen);
...

printfのように、コマンドや関数など、複数のセクションに同じ名前のページが存在する場合、man printf と入力すると下記のような出力が得られます。

PRINTF(1)                 BSD General Commands Manual                PRINTF(1)

NAME
     printf -- formatted output

SYNOPSIS
     printf format [arguments ...]
...
SEE ALSO
     echo(1), printf(3)

PRINTF(1)の(1)はコマンドを示します。STRLEN(3) の (3)は関数を示します。 LinuxUnixの世界では、この使われ方はよく出るので覚えておいて損は無いです。その他にも man png と入力するとpngのフォーマットが出力されたりします。表にすると下記の通りです。

1: ユーザーコマンド ( man printf)
2: システムコール (次の章で説明)
3: ライブラリ関数 (`man 3 printf` or `man strlen`)
4: デバイスファイル (`man tcp`)
5: ファイルフォーマット (`man png`)

まとめ

以上、この本で学べる内容、C言語でのビルドから、コマンドの調べ方まで、Linuxの世界を学ぶために必要な道具を渡される感じの1章でした。

自作ライブラリのバージョンの上げ方

モチベーション

github.com

  • iioptのupdateをしたい
  • updateに際して必要な対応を理解し、まとめたい

※ 自作ライブラリの管理は初めてなので、おかしい点があればコメント頂けるとうれしいです!

libraryのupdateで必要なこと

Libraryのバージョンを上げるときには、機能開発とは別に下記2点の対応が必要となってきます。

  • CHANGELOG.mdの作成
  • libraryのversionを上げる

この記事では、それぞれについて、資料を読んだのでまとめます。

CHANGELOG.mdの作成

CHANGELOGの作り方については、下記の資料を参考にしました。

keepachangelog.com

Wiki で一番最初に参照されているので、それなりの知名度があるのでしょう。 Changelog - Wikipedia

この Keep a ChangeLog のホームーページ上で記載されている内容について、簡単にまとめようと思います。

Change Logを作る意味

Change Logとは、このプロジェクトの各リリース間における変更について、何が注目に値するのか、開発者や利用者に対して、正確に把握して貰うために作るものです。

開発者も利用者も、新しく追加された機能や、その背景が気になるはずです。なのでChage Logを作って、それらを追えるようにする必要があります。

Change Logに書く内容

keep-a-changelog/CHANGELOG.md at master · olivierlacan/keep-a-changelog · GitHub

具体的にどのように書くのか把握するため、Keep a Change Logのサイト自体の Change Logを確認しました。抜粋したものを下に書きます。

Changelog
All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

Unreleased
1.0.0 - 2017-06-20
Added
New visual identity by @tylerfortune8.
Version navigation.

Changed
Start using "changelog" over "change log" since it's the common usage.
Start versioning based on the current English version at 0.3.0 to help translation authors keep things up-to-date.

0.0.3 - 2014-08-09
Added
"Why should I care?" section mentioning The Changelog podcast.

Change Logは上から最新のものを記載します。 それぞれのバージョンについて、更新内容と更新した日付を書きます。 更新内容については、added, changed, removed, fixed, Security の5つの項目に分けて記載します。それぞれ、書く内容は下記のようになっています。

  • Added: そのバージョンアップで追加した新しい機能
  • Changed: 既存の機能の修正
  • Removed: 機能の削除
  • Fixed: バグの修正
  • Security: 脆弱性対策

小ネタとして、まだリリースしていないけれども開発した内容は Unreleasedに乗せておくとよいとのことです。その理由は下記の通りです。

  • 人々は次のリリースで使えるようになる機能を見ることができる
  • releaseするときに、unreleased sectionを次のリリースバージョンに置き換えれば良い。

libraryのバージョンの上げ方

セマンティック バージョニング 2.0.0 | Semantic Versioning

libraryのバージョンの決め方は、こちらのサイトを参考にしました。

  • APIの変更に互換性のない場合はメジャーバージョンを、
  • 後方互換性があり機能性を追加した場合はマイナーバージョンを、
  • 後方互換性を伴うバグ修正をした場合はパッチバージョンを上げます

ということです。今回のiioptのupdateは機能追加だけなので、v0.2.0 としました。

まとめ

以上、自作ライブラリのバージョンの上げ方をまとめました。SemVerについては深掘りが足りてないので、おいおいちゃんと読んでいこうと思います。