MJHD

エモさ駆動開発

golangとbazelで作るいい感じなビルド環境

Makefileに一部間違いがあったため、修正しました

 

bazelはビルドシステムの一つで、Googleが開発し社内でも使用している。makeなどの従来のビルドシステムと比べると、簡潔な設定で幅広い言語・ビルド対象に対応していて、ビルドが必要なものはほとんどbazelで解決できる。

Bazel - a fast, scalable, multi-language and extensible build system" - Bazel

 

例えば、Goのビルドと同時にdockerイメージもビルドしたい、protoもビルドしたいといった場合、通常であれば個別にビルドコマンドを打つ必要があるのだが、この作業をbazelに一本化でき、とても便利。

必要な物

以下のものを使用する:

1. bazel

2. rules_go

3. gazelle

4. rules_docker

rules_goはGo言語向けbazelルール。go_libraries、go_test、go_binaryなどを提供し、Go言語に関するビルド、テスト処理を記述できるようになる。

gazelleはrules_goを用いたビルド設定を自動生成するツール。importなどを見て、自動で依存を解決し、ビルド設定を吐き出してくれる。

rules_dockerは、bazelを用いてdockerイメージをビルドしたり、プッシュすることができるルール。今回はgoのバイナリを含めたイメージをビルドし、実行する。

オススメの構成

以下にサンプルのレポジトリを作成した。

GitHub - mjhd-devlion/bazel-gazelle-sample

ディレクトリ構造としては以下のようになっており、cmd以下のsampleが、今回動かす対象のプログラム。pkg/sampleパッケージを読み込み、Hello, Worldを出力する。depによるvendoringも行いたかったため、いつもよりキレイめにHello, Worldを表示している。

./
├── BUILD.bazel
├── Gopkg.lock
├── Gopkg.toml
├── Makefile
├── WORKSPACE
├── cmd
│   └── sample
│       ├── BUILD.bazel
│       └── main.go
├── pkg
│   └── sample
│       ├── BUILD.bazel
│       ├── sample.go
│       └── sample_test.go
└── vendor

また、以下のようなMakefileを用意している。make gazelleコマンドを実行することでプロジェクト全体のBUILD.bazelファイルを更新し、その後make runすることによってプログラムを実行することができる。

.PHONY: run
run:
	bazel run //cmd/sample:go_image

.PHONY: build
build:
	bazel build //cmd/sample:go_image

.PHONY: test
test:
	bazel test //...

.PHONY: gazelle
gazelle:
bazel run //:gazelle
bazel run //:gazelle -- update-repos -from_file ./Gopkg.lock

ここで一つ注意点があり、Makefileのgazelleの項に、update-reposという記述をしている。

gazelleとvendoringは相性が悪く、特にprotoをビルドする際など、バージョンの違いによる問題が発生したりする。

ここ(go_proto_library dependency overhaul · Issue #1548 · bazelbuild/rules_go · GitHub)に詳しく載っているのだが、protoをビルドする際にrules_goが提供する依存のバージョンがvendoringしているものと衝突した場合、ビルド時、または実行時のエラーが発生する。

これを解決するためには、WORKSPACEにgo_repositoryルールを用いて依存するライブラリのバージョン指定をする必要があるのだが、手作業でやるのは流石に辛い。

ということで、実はgazelleはupdate-reposという「Gopkg.lockとgo_repositoryを同期する」プログラムを用意してくれている。(つい先日知った)

サンプルでは、このプログラムを用いてdepの解決した依存に、bazelの依存を同期し、安全にビルドが行えるよう、update-reposをgazelle実行時に呼ぶような設定を行っている。

微妙な点

実はvendorディレクトリを削除しても動く。依存はbazelがビルド時にダウンロードし、その後も管理をしてくれるため、vendorディレクトリの中身はビルド時に使用されていない。二重管理になってしまうため、vendorディレクトリを削除したいのだが、vendorディレクトリが無いとエディタが真っ赤になる…。

何かもっと良い方法をご存じの方、是非コメントいただけると嬉しいです。

ノートパソコンをタッチ対応に…Neonode AirBarを購入してみた

www.air.bar

AirBarは、タッチ未対応のノートパソコンの画面を、タッチ対応にするデバイス。(現在はWindows10のみの対応。今後Mac対応の製品が発売されるらしい)

お値段も$69.00で買え、13.3inchから15inchまでのサイズをそろえている。

 

最近、秋葉原で5000円ほどのタッチパネルを購入し、タッチ機能のすばらしさに気づいたため、どうせなら本体のディスプレイもタッチ対応にしてしまおうということで購入した。

 

Amazon.com(co.jpじゃない)だと安い

日本の並行輸入品だと1万超えてきてしまうし、海外で購入しても1週間ほどで届くため、注文時に多少英語を読む必要はあるけどAmazon.comで購入した方がお得。

Amazon.comでは、$69.00+Shipping($11.31)で購入できた。(Shippingはいくつかのオプションから選べたため、最も安いものを選択すれば$5ぐらい安くなる)

 

開封の儀

f:id:wait0000:20170711105004j:plain

f:id:wait0000:20170711105324j:plain

内容物は、予備のマグネット4個、スクリーンクリーナー、ケース、AirBar本体、説明書。

マグネット自体は本体にあらかじめ付いているため、予備は本当に予備。

AirBar本体が思ったよりも細長く、洗練された印象。

 

取付

f:id:wait0000:20170711105838j:plain

AirBar本体の背面に、マグネットが付いているため、このマグネットのシールをはがす。

粘着面が現れるため、AirBar本体のガイドラインをよく見ながら位置を合わせる。

位置は、ガイドラインと画面のはじを合わせ、画面した3mmほどのところに、水平に設置すると良いらしい。

位置を決めたら、AirBarを画面に押し付け、そっとはがすと、マグネットが画面に張り付く。

f:id:wait0000:20170711110502j:plain

これで設定完了。

あとは、AirBarを画面に取り付け、USBを接続すれば画面がタッチ対応になる。

設定が完了したら、

Updating the firmware on your AirBar for Windows 10 device – AirBar by Neonode

からファームウェアをアップデートすると良い。

(例えば、初期の状態では変なブザー音が鳴っていたのだが、解消された。)

 

感想

タッチパネルとしての感想だが、精度は中の下ぐらい。同じ光学式のタッチパネルと比べても、少し感度が悪いため、文字の手書きなどの用途には使えない。

また、設置の具合かもしれないが、画面右上の反応が悪いため、ウィンドウを全画面にした際にバッテンが押せないなどのもどかしさがある。

また、持ち運ぶにもへし折れそうなほど細長いので怖く、あまり持ち歩く気にならない…。

有線接続なのももったいない…かといって無線にすると電源が確保できないか…。

…ただ、ディスプレイを交換することなくタッチ機能を追加できるのは、メリット。

また、マルチタッチにも対応しているので、ちょっとズームをしたい際など、AirBarがあると便利。

 

結論

ノートPCってそもそも程よい位置にトラックパッドがあり、画面まで手をもっていかなくても操作をできるようになっているため、あえて追加のデバイスを使って、ノートPCを畳めなくしてまで、画面をタッチ対応にする必要もないなと思った。

ノートPCをすぐに畳めない、持ち運びに不安があるという懸念点があるため、ノートPCをデスクトップ化して使っている人など、持ち運ばない用途であれば十分価値があると思う。

 

余談

Windowsってタッチパネル2つあると、カーソルがどっちかのタッチパネルにしか表示されないっぽい。

惜しい…。

macOS SierraでJIS配列キーボードを US配列として使う方法

 

mjhd.hatenablog.com

 

この記事でも書いたのだが、macOS SierraからはKarabinerが使えない。

そこで、前回はカスタムキーボードレイアウトを作成することで対処をしたのだが、この方法の難点は、「日本語入力中の配列が JISのまま」というところ。

不完全な方法だった。

 

今回は、完璧にキーボード配列を書き換えられるSierra対応ソフトを見つけたため、その設定ファイルを公開したいと思う。

Locaille

Lacaille - 親指シフト for macOS

このソフトは、もともと親指シフトMacで実現するために作成されたものなのだが、かなり細かくキーボードレイアウトをカスタマイズすることができるのが特徴。

今回は、親指シフトを無効にして、 KarabinerのUS配列を移植した。

 

Locailleをダウンロードし、「設定ファイルを読み込む...」ボタンを押し、以下のファイルを読み込むことによって、完全に US配列に置き換えることができる。

drive.google.com


 

このUS配列の特徴は、単純にキーボードレイアウトをUS配列にした時に入力できない「`」「~」などの文字を「¥」キーの位置に割り当てていること。

 

完璧なUS配列ライフがおくれそう。

 

WSLをXenialにアップデートしてみた

mjhd.hatenablog.com 過去記事で紹介したBashOnWindows(WSL)環境において、UbuntuのバージョンをTrustyからXenialへアップデートしたメモ。

アップデート方法

以下のコマンドを実行するだけ。

sudo do-release-upgrade

その後、いくつかのアプリケーションに問題が起こった。

dbusがらみのエラーが起こる

DBusを使用するアプリケーションが、「Exhausted Authentication Mechanisms」的なエラーを吐いて起動しない。
“/etc/dbus-1/session.conf"を以下のように編集することで対応可能。

<auth>EXTERNAL</auth>

<!--<auth>EXTERNAL</auth>-->

とする。

GnomeTerminalがすぐ終了する

なんでか知らんけど、GnomeTerminalが子プロセス作って自分は勝手に終了しちゃう。
以下のように–disable-factoryを追加することで対応可能。

gnome-terminal --disable-factory

そんなぐらい。

オブジェクト指向とは

新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡 - Qiitaなどを参考にまとめたメモ。

オブジェクト指向プログラミングとは,オブジェクト同士の相互作用として,システムの振る舞いを捉える考え方である.所謂手続き型の言語しかなかった時代,コンピュータの性能向上につれて,データ構造,処理の複雑化し,正しく動く可読性の高いプログラムの記述が困難になった.1960年代にはこうした状況に「ソフトウェア危機」[1]という名前が付けられ,新たなプログラミングの手法が模索された.こうして考案されたのが「構造化プログラミング」[2]などのデザインパターンである.構造化プログラミングでは,言語特有のステートメントを直接使うのではなく,抽象化したステートメントを持つ仮想機械を想定し,その仮想機械上でプログラミングを行う.こうすることで, プログラムの正当性や可読性を向上することができるようになる.またこれとともに,「モジュラプログラミング」[3]と呼ばれる,同じ機能を持つ処理同士をモジュールという単位でまとめ,分割する手法が広まっていき,また良い分割を行うために,「状態」と「副作用」[4]を如何に扱うかが問題になっていった.その一つの解決策として現れたのが,オブジェクト指向プログラミングと,関数型プログラミングである.関数型プログラミングでは,基本的に副作用を持たず引数と返り値のみでプログラムを構成することで,参照透過性を保っているが,オブジェクト指向プログラミングでは,状態と副作用を「オブジェクト」に閉じ込めることで,抽象化を行った.このオブジェクト指向言語として初めて現れたのが,Simula[5]である.Simulaには,オブジェクト,クラス,動的ディスパッチ,継承,ガベージコレクションなどの現在のオブジェクト指向言語が持つ機能が実装されていて,後にC言語にこの機能が取り入れられ,C++言語ができた.また, Smalltalk[6]もSimulaに影響を受けた言語として制作され,C言語Smalltalkの機能を取り入れた言語として,Objective-C[7]言語などが作られた. オブジェクト指向プログラミングでは,プログラムはオブジェクトの集合として定義され,特徴として「カプセル化」[8]や「ポリモーフィズム」[9],「継承」[10]などの概念が挙げられる.初めに,カプセル化とは,Simulaで考案されたもので,データと処理を1つのオブジェクトとしてまとめることで,オブジェクト外部への副作用を減らすことができ,プログラムの正当性を高めることができるものである.例えば,グローバル変数を使い状態を共有しているモジュールがあった場合,片方の仕様を変更したとき,もう一方も修正しなくてはならなくなる.このような時,カプセル化を行うことでこのモジュール間の結合をなくすことができる.次に,ポリモーフィズムとは,現在の言語ではオーバーロードや仮想関数,インターフェースと呼ばれる機能などで実現されていて,異なるクラスであっても同一のコードで扱えるよう,クラスが複数のクラスに属すことのできる性質のことを言う.例えば,以下のリスト7の様な処理があった時,printNumber, printDate関数は,以下のリスト8の様に一つの関数としてまとめることができるようになる.最後に,継承とは,あるクラスを基に,機能を追加したり変更したりした別のクラスを定義することのできる機能である.これにより,副作用を基のクラスに隠蔽したまま,新たな機能を追加することができるため,プログラムの正当性,可読性に役立つ.

リスト7. ポリモーフィズムの例1 (疑似コード)


1:  class Number {
2:      public string ToString() {
3:          retutn 文字列へ変換する処理;
4:      }
5:  }
6:  
7:  class Date {
8:      public string ToString() {
9:          return 文字列へ変換する処理;
10:     }
11: }
12: 
13: public void printNumber(Number value) {
14:     print(value.ToString());
15: }
16: public void printDate(Date value) {
17:     print(value.ToString());
18: }
19: // プログラムの開始地点
20: public void main() {
21:     var number = new Number();
22:     var date   = new Date();
23: 
24:     // それぞれ別の関数に渡さなければいけない
25:     printNumber(number);
26:     printDate(date);
27: }

リスト8. ポリモーフィズムの例2 (疑似コード)


1:  interface IConvertible {
2:      public string ToString();
3:  }
4:  
5:  class Number : IConvertible {
6:      public string ToString() {
7:          retutn 文字列へ変換する処理;
8:      }
9:  }
10: 
11: class Date   : IConvertible {
12:     public string ToString() {
13:         return 文字列へ変換する処理;
14:     }
15: }
16: 
17: public void print(IConvertible value) {
18:     print(value.ToString());
19: }
20: // プログラムの開始地点
21: public void main() {
22:     var number = new Number();
23:     var date   = new Date();
24: 
25:     // 同じ関数に異なる型を渡すことができる
26:     print(number);
27:     print(date);
28: }

参考:

[1] ソフトウェア危機Wikipedia, http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%8D%B1%E6%A9%9F [2] 構造化プログラミング Wikipedia, http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%8D%B1%E6%A9%9F [3] モジュール Wikipedia, http://ja.wikipedia.org/wiki/%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB [4] 副作用(プログラム) Wikipedia, http://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%29 [5] Simula Wikipedia, http://ja.wikipedia.org/wiki/Simula [6] Smalltalk Wikipedia, http://ja.wikipedia.org/wiki/Smalltalk [7] Objective-C Wikipedia, http://ja.wikipedia.org/wiki/Objective-C [8] カプセル化 Wikipedia, http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%97%E3%82%BB%E3%83%AB%E5%8C%96 [9] ポリモーフィズム Wikipedia, http://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0 [10] 継承 Wikipedia, http://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%29

FuelPHPのemailで日本語メールを送る際に気を付けること

マルチバイト環境でFuelPHPのemailを使う際、いくつか気を付けなければいけない問題がある。

今回想定している環境は、以下。

  • FuelPHP 1.8
  • UTF8でメールを送りたい
  • HTMLメールを送りたい

 

自動改行処理を止める(あるいは、改善する)

FuelPHPのemailパッケージには、自動改行処理を行う部分がある。

デフォルトでは76文字で改行を行ってくれるのだが、この際に使用している関数がPHP標準のwordwrap関数。この関数はマルチバイト文字に対応していないため、改行付近で文字化けするという痛い問題が発生する。

自動改行処理を止めるには、/fuel/core/config/email.phpを/fuel/app/config/email.phpとしてコピーをし、


 'wordwrap' = 76,

となっている部分を、


 'wordwrap' = false,

と書き換える。

もし、自動改行処理は有効にしたいけど、文字化けを解消したいという方は、emailクラスを編集して、マルチバイトに対応させる必要がある。

具体的には、/fuel/packages/email/classes/email/driver.phpのwordwrapを呼び出している箇所(おそらく二か所)を、[PHP]マルチバイト対応のwordwrapが無いから作った - Qiitaこういったものに置き換える必要がある。

 

 代替テキストの生成を止める

HTMLメールを送る際、emailパッケージは親切にプレーンテキスト版を自動生成し、一緒に送信してくれる。

受信したクライアントは、HTML版、プレーンテキスト版の二つから好きな方を表示することができる便利な機能である。

しかし、メールの見た目を統一したいなどの理由で、代替テキストが表示されてほしくない場面もある。

この場合、/fuel/app/config/email.phpを編集し、'generate_alt'の欄をfalseに設定すればよいのだが、

日本語を送る関係で'encoding'に"quoted-printable"や"base64"を指定している場合、正常に表示ができなくなる。

これは、何故かemailパッケージが"Content-Transfer-Encoding"のヘッダーを出力しないためであり、

/fuel/packages/email/classes/email/driver.phpの以下の箇所を編集することで対応が可能。


protected function build_message($no_bbc = false)
{<
    ...中略...
    $parts = array('Date', 'Return-Path', ...中略..., 'Content-Type');

となっている部分を、以下のように変更する。


    protected function build_message($no_bbc = false)
    {
    ...中略...
    $parts = array('Date', 'Return-Path', ...中略..., 'Content-Type', 'Content-Transfer-Encoding'); // 追加した

これで、正常に表示ができるようになる。

最高のXiaomi Notebook Air 13.3を購入した

もともとはMacBookAir13を4年間使っていたのだが、macOS sierraにアップデートしてから様々な問題にぶち当たり、Macが少しだけ嫌いになったのと、もともとメモリ4GBしかなかったため流石にしんどくなってきたので、新しいPCを買うことに。

中国メーカーXiaomiが出しているMacBookAirもろリスペクトのノートPC、「Xiomi Notebook Air」を購入した。

安い

gearbestで購入したのだが、記事執筆時の値段は$809.99=「9.17万円」

スペックは後述するが、この性能でこの値段はなかなかない。

www.gearbest.com

スペック

CPU: Intel Core i5 2.3GHz(最大2.8GHz) 物理2コア

GPUGeForce GT 940MX 1GB

SSD: サムスン製 256GB

RAM: 8GB(アップグレード不可、はんだ付け)

バッテリー: 5400mAh (USB Type-Cポートを使用して充電、30分ほどで充電完了、5時間ほど持つ)

外部ポート: HDMI、イヤホン/マイク共用ジャック、USB Type-C、USB3 x 2

WiFiIntel(R) Dual Band Wireless-AC 8260、802.11n

Bluetooth: 4.1

ディスプレイ: 1920x1080 IPS 13.3inch

スピーカー: AKG speaker with Dolby Audio Premium Surround Sound(かなり良い)

OS:

Windows10 Homeの中国語版がプリインストールされている。日本語版をクリーンインストールすることでアクティベーション可能。

開封の儀

f:id:wait0000:20161111113154j:plain

f:id:wait0000:20161111113344j:plain

f:id:wait0000:20161111113426j:plain

これまたMacBookAirっぽい箱の中に、フィルムにくるまった状態で入っていた。

付属品は簡単な説明書と充電用アダプタだけだった。

充電用アダプタは前述したとおり、USB Type-Cの形状をしており、幅広い機器に使えるもののようだ。

手に持った感じ、MacBookAirと重さは変わらなかった。大きさは若干Xiaomi NotebookAirの方が小さかった。

 

ちゃんと最後まで開封してみた。

f:id:wait0000:20161111121341j:plain

ファンはCPU用とGPU用の二つ。

SSDスロットは拡張用含めて二つ。

スピーカーも二つ確認できた。

 

以下、使ってみての感想。

スピーカーが良い

一番感動しているのがココ。AKG製のスピーカーが背面に2つ入っているのだが、Dolbyのサラウンド対応ということで音がヤバイ。語彙力がないのでヤバイしか言えないのだが、映画などを観るとその凄さがよくわかる。

目の前のパソコンから音が出ているとは思えない…。

このPCを購入してから、イヤホンをほとんど使わなくなってしまった。

 

キーボード

MacBookAirのキーボードがグッグッなら、Xiaomi Notebook Airはパタパタという感じ。

打鍵音は大きめ、またキーの打鍵感も大きいので少し指がつかれるかも。

それでも打鍵感がかなり良く、打っていて楽しい。

 

デザインはほぼほぼMacBookAir

背面にリンゴがいない以外、ほぼほぼMacBookAir。

アルミ感満載なところ、キーにLEDがついてるところ、トラックパッドに関してはまったく同じ見た目。

 

f:id:wait0000:20161111113657j:plain

 

f:id:wait0000:20161111113724j:plain

f:id:wait0000:20161111114144j:plain

 

軽いしバッテリーのもちもいいし性能もいいし安いし、大満足。