magのOSS備忘録

使ったOSSソフトウェアについて書いていきます。

flycheckでC/C++のプロジェクトごとの設定を行う

動機

通常, C/C++(に限ったことではないが)プロジェクトではそれぞれで定義するヘッダファイルをインクルードするため, 全体的に共通の設定を行うと余計な設定まで含んでしまうことになる. プロジェクトAでインクルードするファイルは, プロジェクトBではインクルードしないが共通の設定を使っていると, プロジェクトBでは不要な設定を適用することになる. そのため, プロジェクトごと(ディレクトリごと)に設定を行いたい.

ディレクトリごとにローカルな変数設定

Emacsには「.dir-locals.el」というファイルによって, そのディレクトリとその配下のディレクトリにのみ適用する設定を記載することが出来る.

例えば下記のようなディレクトリ構造で, projectディレクトリの直下に.dir-locals.elが配置してあると, includeやsrcディレクトリにあるファイルを開いたときにも.dir-locals.elファイルの内容が適用される.

project
├── .dir-locals.el
├── include
│   └── common.h
└── src
    ├── main.cpp
    ├── sub.cpp
    └── sub.h

flycheckの場合

flycheckでも.dir-locals.elの設定が適用される. 例えば, 下記のように設定することで, そのプロジェクト(ディレクトリ)配下のソースコードを開いたときに有効な設定を書くことが出来る.

((nil . ((flycheck-clang-language-standard . "c++11") ; このプロジェクトはC++11に対応している
         (flycheck-clang-include-path . ("."          ; インクルードパスを設定する
                                         "src"
                                         "include"
                                         ))
         )
      ))

参考

EmacsでフォントにCamingoCodeを使用する

EmacsでCamingoCodeを使用するように設定する. 日本語部分にはRicty Diminishedをあてる.

実行環境

CamingoCode, Ricty Diminishedフォントのインストール

 下記よりそれぞれのフォントをダウンロードし, インストールする.

~/.emacs.d/init.elの設定

 ~/.emacs.d/init.elに下記のように設定を追加する.

 設定方法はOut of Dimension: Emacs のフォント設定を克服するを参考にした.  このサイトでも指摘されている通り, 異なる日本語フォントと英字フォントを組み合わせているため同じフォントサイズでは上手く幅が合わない.  そのため, 日本語フォントと英字フォントのサイズを少しズラして調整する.

;;; CamingoCode + Ricty Diminished
;;;   下記のようなサイズの組み合わせだと全角文字と半角文字のバランスがよい.
;;;   他の組み合わせだとズレるので注意.
;;;     + CamingoCode:size=13, Ricty Diminished:size=14
;;;     + CamingoCode:size=15, Ricty Diminished:size=16
;;;     + CamingoCode:size=17, Ricty Diminished:size=18
(create-fontset-from-ascii-font "CamingoCode:size=13:weight=normal:slant=normal"
                                nil
                                "CamingoCode_RictyDiminished")
(set-fontset-font "fontset-CamingoCode_RictyDiminished"
                  'unicode
                  (font-spec
                   :family "Ricty Diminished"
                   :size 14)
                  nil
                  'append)

;;; 上記で作成したフォントセットをデフォルトに設定する.
(add-to-list 'default-frame-alist '(font . "fontset-CamingoCode_RictyDiminished"))

表示

CamingoCodeはとても素敵.

f:id:boiled_mag:20180522192412p:plain

参考

Windows(MSYS2)でirony-modeをセットアップする

動機

Irony-ModeをWindows環境で使用する方法としてMSYS2を使用するか, MSVCを使用するかを選べるとのことで, 今回はMSYS2を使用してみることにした. Cygwinは…

基本的にSetting up irony mode on Windows · Sarcasm/irony-mode Wiki · GitHubに従って実施したが, MSYS2環境に慣れていなかったために引っかかったところを補足する.

実行環境

  • Windows 10 Pro 64bit版 (バージョン 1703)
  • MSYS2(mingw64)
  • emacs 25.3.1 (x86_64)
  • irony 20180418.1311
  • company-irony 20170905.1346

MSYS2のセットアップ

使用しているMSYS2のバージョン等は下記の通り. MSYS2自体はMSYS2 homepageに従ってインストールを実施した.

user@host MINGW64 ~
$ uname -a
MINGW64_NT-10.0 host 2.10.0(0.325/5/3) 2018-02-09 15:25 x86_64 Msys

必要なパッケージのインストール

MSYS2ではpacmanを使用するが下記のコマンドで最新の状態に持っていく. 途中で何度かMSYS2のターミナル(mintty)の再起動が必要になるため, 都度再起動する.

$ pacman -Syuu

ここではGCC, clang, make, CMakeが必要になるため, インストールする. 今回は64bit環境を選んでいるため, 下記のパッケージを使用する.

$ pacman -Suu mingw-w64-x86_64-gcc
$ pacman -Suu mingw-w64-x86_64-clang
$ pacman -Suu mingw-w64-x86_64-cmake
$ pacman -Suu make

Irony-Modeのサーバーバイナリをビルドする

Setting up irony mode on Windows · Sarcasm/irony-mode Wiki · GitHubに従い, サーバーバイナリをビルドする.

最初に実施したときに, pacmanmingw-w64-x86_64-cmakeではなく, cmakeをインストールしたためか「cmake -G "MSYS Makefiles" ..」を実施した際にGeneratorが見つからないとのエラーに遭遇した. 「mingw-w64-x86_64-cmake」をインストールしておけば問題ない. インストールしたパッケージではなく, パッケージによってCMakeのバージョンが「3.10.2-1」と「3.11.1-2」と違っていたためかもしれない.

下記のファイルが出来上がればOK.

irony-mode/server/build/bin/irony-server.exe

Emacsのセットアップ

引き続き手順に従ってEmacsのセットアップを行う. 作成したirony-server.exeを下記に移動する.

~/.emacs.d/irony/bin/irony-server.exe  

irony-modeのインストールにはpackage.elを使用しした. M-x list-packagesから, ironyを選択してインストールすればよい.

設定はuse-packageを利用して下記のようにした. 加えて, 補完のインタフェースにcompanyを使用してるため, company-ironyを合わせてインストールした.

メジャーモードがC/C++のときに設定を有効にする. また, clangに渡すコンパイルオプションに, それぞれC11/C++14を有効にするように指定している.

(setenv "PATH"
        (concat
         "C:\\msys64\\mingw64\\bin" ";"
         (getenv "PATH")))

(setq exec-path (append exec-path '("c:/msys64/mingw64/bin")))

(use-package irony
  :defer t
  :commands irony-mode
  :init
  (add-hook 'c-mode-hook 'irony-mode)
  (add-hook 'c++-mode-hook 'irony-mode)
  :config
  ;; C言語用にコンパイルオプションを設定する.
  (add-hook 'c-mode-hook
            '(lambda ()
               (setq irony-additional-clang-options '("-std=c11" "-Wall" "-Wextra"))))
  ;; C++言語用にコンパイルオプションを設定する.
  (add-hook 'c++-mode-hook
            '(lambda ()
               (setq irony-additional-clang-options '("-std=c++14" "-Wall" "-Wextra"))))
  (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
  ;; Windows環境でパフォーマンスを落とす要因を回避.
  (when (boundp 'w32-pipe-read-delay)
    (setq w32-pipe-read-delay 0))
  ;; バッファサイズ設定(default:4KB -> 64KB)
  (when (boundp 'w32-pipe-buffer-size)
    (setq irony-server-w32-pipe-buffer-size (* 64 1024)))
  )

(use-package company-irony
  :defer t
  :config
  ;; companyの補完のバックエンドにironyを使用する.
  (add-to-list 'company-backends '(company-irony-c-headers company-irony))
  )

参考

Wiresharkの独自プラグインで既存のDissectorを呼び出す

独自にLuaで定義したプラグイン(Dissector)にてJSON形式データをパースしたかったので, 既存のDissectorを利用した.

下記のように呼び出せばよい.

--
-- プロトコルを作成する.
--
json_proto = Proto("json_proto", "Description: JSON Test Protocol")

-- 名前が長いのでjson_proto.fieldsに別名をつける.
f_json = json_proto.fields

--
-- プロトコルの各フィールドについて型情報, 表示フィルタ, ラベル名等をそれぞれ定義する.
--

-- フレーム境界を認識するためのJSON形式データ長.
f_json.len  = ProtoField.uint32("json_proto.len",  "JSON Data Length", base.DEC)

-- JSON形式データ.
f_json.data = ProtoField.string("json_proto.data", "JSON Data",        base.ASCII)

--
-- 定義したProtoにdissectorという名称の関数を定義する.
--
function json_proto.dissector(buffer, pinfo, tree)
    pinfo.cols.protocol = "JSON Test Protocol"

    local subtree = tree:add(json_proto, buffer(), "JSON Test Protocol")
    local length = buffer(0, 4):uint()

    -- サブツリーに各フィールドを追加する.
    subtree:add(f_json.len,  buffer(0, 4),      length)
    -- ※蛇足だが文字列としても表示しておく.
    subtree:add(f_json.data, buffer(4, length), buffer(4, length):string())

    --
    -- Wireshark組み込みのJSON用のDissectorを呼び出す.
    --
    local json_dissector = Dissector.get("json")
    json_dissector:call(buffer(4, length):tvb(), pinfo, subtree)
end

--
-- 定義したプロトコルとTCPポート 20000 を紐付ける.
--
tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(20000, json_proto)

Wiresharkにこのプラグインを読み込ませ, キャプチャしたパケットを見ると下記のように表示される.

f:id:boiled_mag:20180506151717p:plain
Wiresharkでの表示

参考

11.6. Functions for new protocols and dissectors

LuaAPI/Dissector - The Wireshark Wiki

Rustの開発環境を整える(Windows, Emacs)

前提

  • 2017/8現在の状況で, Windows上のEmacsにてRustの開発環境を整える.
  • 開発のスピードが速く, 以前は必要だった設定が不要になっていることが多い. そのため, 出来るだけメンテナンスされている各ツールのマニュアルに従った方がよい. が, そもそも何をしたのか忘れちゃうので書き残す.
  • 基本的には各ツールのマニュアルに従って設定している.

実行環境

* Windows 10 Pro 64bit版 (バージョン 1703)
* rustup 1.5.0
* rustc 1.19.0
* racer 2.0.10
* cargo 0.20.0

rustupのインストール

Rustのサイトのインストール手順に従ってrustup-init.exeをダウンロードし, rustupをインストールする. これでrustup, rustc, Cargoがインストールされる. 今回はデフォルトのstable-x86_64-pc-windows-msvcを使用する.

https://www.rust-lang.org/ja-JP/install.html

続けてVisual C++ビルドツールが必要になるため, インストールする.

環境変数の確認

Windowsの場合, 環境変数Pathに「%USERPROFILE%.cargo\bin」が追加される. もしされていないようだったら, 自分で追加する.

Racerのインストール

続けて, Racerのインストールを行う. コマンドプロンプト等を起動し, 以下のように実行する.

cargo install racer

CargoはデフォルトだとCPUの数に合わせてコンパイルを並列実行するため, 自分でjobs数を変更してもあまり効果は見られなかった.

Emacsの設定

パッケージのインストール

packages.elを使って下記のパッケージをインストールする. この辺りの手順は省略する.

  • racer
  • flycheck
  • flycheck-rust

この他にも補完にはcompany, エラー表示などにflycheck-popup-tipを使用している.

init.elの設定

設定の記述にはuse-packageを利用した.

;;; rust-mode
(use-package rust-mode
  :defer t
  :config
  (setq rust-format-on-save t))

;;; racer
(use-package racer
  :init
  (add-hook 'rust-mode-hook #'racer-mode)
  (add-hook 'racer-mode-hook #'eldoc-mode))

;;; flycheck-rust
(use-package flycheck-rust
  :init
  (add-hook 'rust-mode-hook
            '(lambda ()
               (flycheck-mode)
               (flycheck-rust-setup))))

設定済み画面

racerによる補完

f:id:boiled_mag:20170815145220p:plain

flycheck + flycheck-popup-tipによるエラー表示

f:id:boiled_mag:20170815145748p:plain

トラブルシューティング

パスの設定などで躓いたときに, 調査で使ったコマンドを残す.

Emacsからracerが正しく実行できているか

  • exec-pathに~/.cargo/binがパスに入っているかどうか.
M-x describe-variable RET exec-path RET
  • 下記のコマンドを実行したときに, 補完の候補が見つかること.
M-! racer complete std::io::B

Proxy内でCargoを使ったツールインストール時のエラー対策(Windows環境)

Cargoを使ってツール(rustfmt, racer)をインストールしようとしたときのメモ。 ユーザ認証が必要なProxy環境でCargoを利用したときに設定した内容を残す。

環境

cargo install racerなどがエラーになる

Proxyを通過出来るように設定してインストールを行おうとしたときに、下記のようなエラーメッセージが表示される。

SSL connect error (schannel: next InitializeSecurityContext failed: Unknown error(0x80092013) - 省略)」

SSL接続時に証明書の失効サーバーへアクセスできないようなので、SSL証明書の失効を確認しないようにする。

設定内容

Cargoをインストールすると%USERPROFILE%(例:c:\Users\user)配下に.cargoフォルダが作成されるので、ここにconfigというファイルを作る。そして以下のように設定を行う。

[http]
    proxy = "http://ユーザ名:パスワード@ホスト名:ポート番号"
    check-revoke = false # SSL証明書の失効を確認しない

Rust自体インストール(Cargo含む)時のProxy設定

Rustの開発環境のインストールはrustupを使って行うが、こちらは環境変数http_proxy、https_proxyを参照するため、予め設定しておく必要がある。下記のページに従ってsetコマンド等で設定するか、環境変数に登録しておく。

rustup.rs/README.md at master · rust-lang-nursery/rustup.rs · GitHub

参考

fishでhistoryの表示に日付を追加する

動機

bash等の他のシェルでは, historyコマンドの出力に日付や時間を追加することができる. これをfishで行おうとしたときに, 調べるのに少し時間がかかったので手順を残す.

前提

fish 2.4からhistoryコマンドに実装されたオプションを使う方法のため, fish 2.4以降のバージョンを使うこと.

手順

historyコマンドの–show-timeオプションを使用する.

なお, フォーマットを指定しないとコマンドを実行した日付・時刻とコマンドが2行で表示される.

日付・時刻とコマンドを一行で表示にするには下記のようにfunctionを定義する. デフォルトでは新しいものから順に表示されるため, sortコマンドで日付で昇順になるように並び替える.

# ~/.config/fish/functions/history.fish

function history
    builtin history --show-time='%Y/%m/%d %H:%M:%S ' | sort
end

参考

  1. Add an option in history builtin to show timestamps · Issue #677 · fish-shell/fish-shell · GitHub
  2. Why there isn't a number of the command and a timestamp for fish? - Unix & Linux Stack Exchange