Slack代替のMattermostをNetBSD/amd64で使う(セットアップ編)

NetBSD Advent Calendar 2017の10日目の記事です。

はじめに

前回は、Slack代替のチャットプラットフォームである Mattermostの配布用アーカイブファイルを作成するところまでを説明した。

今回は、その配布用アーカイブファイルを使って、インストールし、 日本語のメッセージを全文検索できるようにするまでを説明する。

データベースサーバーの選択とインストール

Mattermostは、MySQLとPostgreSQLをバックエンドのデータベースサーバーとして 選択することができる。 しかし、日本語の全文検索が簡単にできるようになるのは、MySQL 5.7を使用 した場合のみである。 MySQL 5.7で新たに搭載された ngram full-text parserを使用するのである。

pkgsrcでは、MySQL 5.7.20を簡単に導入することができる。 以下のように実行すれば良い。


# cd /usr/pkgsrc/databases/mysql57-server
# make install
# cp /usr/pkg/share/examples/rc.d/mysqld /etc/rc.d
# echo "mysqld=YES" >> /etc/rc.conf

MySQL 5.7の下準備

MySQL 5.7では、データベースサーバーの初回起動時に、一時パスワードを 提示されるようになっている。


# vi /usr/pkg/etc/my.cnf
[mysqld]
ngram_token_size=2

# /etc/rc.d/mysqld start
Initializing MySQL database system tables.
2017-12-09T05:44:23.256256Z 0 [Warning] Changed limits: max_open_files: 3404 (requested 5000)
2017-12-09T05:44:23.258372Z 0 [Warning] Changed limits: table_open_cache: 1621 (requested 2000)
2017-12-09T05:44:23.260654Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2017-12-09T05:44:23.277197Z 0 [ERROR] Failed to create event (errno= 9).
2017-12-09T05:44:23.277217Z 0 [ERROR] Failed to start timer notify thread.
2017-12-09T05:44:23.277226Z 0 [ERROR] Failed to initialize timer component (errno 9).
2017-12-09T05:44:25.731713Z 0 [Warning] InnoDB: New log files created, LSN=45790
2017-12-09T05:44:25.995569Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2017-12-09T05:44:26.111703Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 043062cf-dca4-11e7-b252-940764e13c88.
2017-12-09T05:44:26.117750Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
2017-12-09T05:44:27.029478Z 0 [Warning] CA certificate ca.pem is self signed.
2017-12-09T05:44:27.189609Z 1 [Note] A temporary password is generated for root@localhost: zPLeg5>afD/k
Starting mysqld.
ここでは、zPLeg5>afD/kがMySQLのrootユーザーの一時パスワードである。

一時パスワードは、変更しないと、以降の操作をすることはできない。 以下のように変更する。


$ mysql --user='root' --password='zPLeg5>afD/k'
mysql> alter user 'root'@'localhost' identified by 'root-password';

その上で、Mattermost用のユーザーmmuserを追加する。


$ mysql --user='root' --password='root-password'
mysql> create user 'mmuser'@'localhost' identified by 'mm-user-password';

Mattermost用のデータベースmattermostを追加し、 mmuserユーザーに操作権限を付与する。 Mattermostサーバーの初回起動時にテーブルの作成等を自動的に実行するので、 それに必要な操作権限がないといけない。 ここでは、mmuserに mattermostデータベースに関する全権限を付与した。


mysql> create database mattermost;
mysql> grant all on mattermost.* to 'mmuser'@'localhost';

Mattermostサーバーを配置する

MattermostはGo言語で生成されたバイナリーファイルであり、 配置する場所を選ばない。 ここでは、/opt/mattermostディレクトリーに配置することにする。


# mkdir /opt
# cd /opt
# tar zxvf /home/ryoon/go/src/github.com/mattermost/mattermost-server/dist/mattermost-team-netbsd-amd64.tar.gz
これにより、Mattermostサーバーは/opt/mattermost/bin/platform ファイルとして配置される。

Mattermostサーバーを起動する

単純に/opt/mattermost/bin/platformを起動すれば良いだけである。 永続的に使用するのであれば、いずれ/etc.rc.localで起動 するようにしておけば良い。 初回起動時には、/opt/mattermost/config/config.jsonファイルが 設定ファイルの雛形として生成される。 一度起動し、データベースが見つからないと 出たらCtrl-cで停止させ、/opt/mattermost/config/config.json 設定ファイルを編集しよう。 ここでは、ウェブ画面の標準の言語を日本語にする変更も実施しておく。 各ユーザーで指定できるが、最初の初期設定画面を日本語化しておくためである。


# /opt/mattermost/bin/platform
(省略)
(Ctrl-c押下)
# vi /opt/mattermost/config/config.json
(省略)
    "SqlSettings": {
        "DriverName": "mysql",
        "DataSource": "mmuser:mm-user-password@tcp(localhost:3306)/mattermost?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s",
        "DataSourceReplicas": [],
        "DataSourceSearchReplicas": [],
        "MaxIdleConns": 20,
        "MaxOpenConns": 300,
        "Trace": false,
        "AtRestEncryptKey": "zhk8pfcexaxsubwguc8eqqu8c75j4a9p",
        "QueryTimeout": 30
    },
(省略)
        "DefaultClientLocale": "ja",
(省略)
# /opt/mattermost/bin/platform
(Ctrl-c押下)
これで、必要なテーブルやインデックスが作成される。

日本語の全文検索を有効にする

MySQL 5.7のbgram full-text parserを使ったインデックスを チャットの投稿メッセージに対して作成し直す必要がある。 以下のように操作する。


$ mysql --user='mmuser' --password='mm-user-password' mattermost
mysql> alter table Posts drop index idx_posts_message_txt;                      
mysql> alter table Posts add fulltext index idx_posts_message_txt (`Message`) with parser ngram;

Mattermostサーバーを起動する

以下のように実行すれば良い。


# /opt/mattermost/bin/platform &

Mattermostのウェブ画面を開く

標準では、http://localhost:8065/で表示できるようになっている。 サブディレクトリーに配置する設定は存在しない。 pkgsrc/www/firefoxで動作を確認できる。 日本語のメッセージを投稿して、2文字以上であれば全文検索できることを確認する。

まとめ

NetBSD/amd64で、Mattermostサーバーを立ち上げ、MySQL 5.7を使って ngram full-text parserを利用した全文検索ができるようにした。

Slack代替のMattermostをNetBSD/amd64で使う(ビルド編)

NetBSD Advent Calendar 2017の9日目の記事です。

はじめに

Mattermostと言う チャットプラットフォームがある。これのCommunity Editionは LDAP認証機能がないなどちょっと使いにくい部分はあるのだが、 Linuxでは良い感じに動くのを確認していた。 日本語ユーザーインターフェイスもベータ扱いではあるが、 ほぼ翻訳できていると思う。

Mattermostは、サーバーはGo言語で書かれており、 ビルドにはnode.jsも必要となる。 どちらもGo 1.8以降、node.js 8以降が必要で、 例えばDebian GNU/Linux 9で動かそうとすると、 標準のパッケージマネジメントシステムに収録されている Goとnode.jsはこれよりずっと古いので、ディストリビューションのリポジトリー 以外から新しいバージョンをインストールしなくてはいけない。 その点、pkgsrcであれば、Goは新しいし、node,jsも新しいものを選べる。

また、Mattermostの開発環境には、dockerが必要なように思われるかもしれないが、 別になくてもちゃんと動かすことができる。

以下では、NetBSD/amd64 current上でMattermostのサーバーと ウェブアプリケーションをビルドするまでを紹介する。 実際に動かすまでは、次回に紹介したい。

ビルドに必要なツールを用意する

サーバーはGo言語で書かれているため、 pkgsrc/lang/goを インストールする。 以下のように操作すれば良い。


# cd /usr/pkgsrc/lang/go
# make install
この記事を書いている時点では、go-1.9.2というパッケージがインストールされる。

ウェブアプリケーションは、node.jsでビルドするため、以下のように最新のnode.jsを インストールしておく。


# cd /usr/pkgsrc/lang/nodejs
# make install
この記事を書いている時点では、nodejs-9.2.0nb1というパッケージがインストールされる。

ウェブアプリケーションのビルドの途中で、node.jsのmozjpegモジュールを インストールすることになる。 このモジュールは、Linuxであれば、コマンドのバイナリーファイルを 提供してくれるのだが、NetBSD用など当然ないので、バイナリーファイルを ビルドしないといけない。 そのためには、以下のパッケージが必要になる。 ちなみに、Debian GNU/Linux 9の場合にもlibpng12.soが提供 されていないため、mozjpegを使おうとする箇所で失敗する。

  • pkgsrc/devel/pkgconf
  • pkgsrc/devel/libtool-base
  • pkgsrc/graphics/png
もしかしたら、他にも必要かもしれない。 ここまで用意しておけば、mozjpegをローカルでビルドしようと試みるように なるので、エラーメッセージを見れば分かるはずである。

ウェブアプリケーションをビルドするには、 yarnというパッケージマネジメント システムが必要である。 yarnのインストール手順によると、以下のようにnpmコマンドを 使ってのインストールは推奨されていないようであるが、一番簡単な方法であり、 このためにしか使わないので、これを採用してしまう。


$ mkdir ~/yarn
$ cd ~/yarn
$ npm install yarn
$ set PATH=~/yarn/node_module/yarn/bin:$PATH

また、GNU makeも必要なので、インストールしておく。どこかで、gmakeをmakeとして呼び出しているようなので、シンボリックリンクも作っておく。


# cd /usr/pkgsrc/deve/gmake
# make install
$ ln -s /usr/pkg/bin/gmake ~/yarn/node_modeule/yarn/bin/make

ソースコードを配置する

Compiling Mattermostのウェブページにあるように配置していく。


$ mkdir -p ~/go/src/github.com/mattermost
$ cd ~/go/src/github.com/mattermost
$ git clone https://github.com/mattermost/mattermost-server.git
$ git clone https://github.com/mattermost/mattermost-webapp.git

配置したソースコードの場所を、環境変数に設定する。


$ set GOPATH=$HOME/go
$ export GOPATH
$ set PATH=$PATH:$GOPATH/bin

ビルドに必要なパッチを当てる

残念ながら、MattermostのMakefileは、あまり移植性を考慮していないようである。 また、開発用にはdockerを使うので、配布用のアーカイブファイルを作成する 部分について、最近は忘れられているようである。

どう直すのが適当であるかは明確ではないが、配布用のアーカイブファイルを 作成するには以下のようなパッチが必要である。 config/config.jsonファイルは、なければ自動的に生成されるので 用意しておく必要はないはずである。


diff --git a/build/release.mk b/build/release.mk
index 5eaee8022..285dcadac 100644
--- a/build/release.mk
+++ b/build/release.mk
@@ -36,16 +36,6 @@ package:
  cp -RL templates $(DIST_PATH)
  cp -RL i18n $(DIST_PATH)
 
- @# Disable developer settings
- sed -i'' -e 's|"ConsoleLevel": "DEBUG"|"ConsoleLevel": "INFO"|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"SiteURL": "http://localhost:8065"|"SiteURL": ""|g' $(DIST_PATH)/config/config.json
-
- @# Reset email sending to original configuration
- sed -i'' -e 's|"SendEmailNotifications": true,|"SendEmailNotifications": false,|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"FeedbackEmail": "test@example.com",|"FeedbackEmail": "",|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"SMTPServer": "dockerhost",|"SMTPServer": "",|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"SMTPPort": "2500",|"SMTPPort": "",|g' $(DIST_PATH)/config/config.json
-
  @# Package webapp
  mkdir -p $(DIST_PATH)/client
  cp -RL $(BUILD_WEBAPP_DIR)/dist/* $(DIST_PATH)/client

また、Go言語で書かれたサーバーをNetBSD/amd64向けにビルドするための ターゲットが必要である。 以下のように追加する。


diff --git a/Makefile b/Makefile
index a0cf74f1c..ff4bb8149 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: build package run stop run-client run-server stop-client stop-server restart restart-server restart-client start-docker clean-dist clean nuke check-style check-client-style check-server-style check-unit-tests test dist setup-mac prepare-enteprise run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-windows internal-test-web-client vet run-server-for-web-client-tests
+.PHONY: build package run stop run-client run-server stop-client stop-server restart restart-server restart-client start-docker clean-dist clean nuke check-style check-client-style check-server-style check-unit-tests test dist setup-mac prepare-enteprise run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-windows build-netbsd internal-test-web-client vet run-server-for-web-client-tests
 
 ROOT := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
 
diff --git a/build/release.mk b/build/release.mk
index 5eaee8022..c551e3ad0 100644
--- a/build/release.mk
+++ b/build/release.mk
@@ -13,6 +13,10 @@ build-windows:
  @echo Build Windows amd64
  env GOOS=windows GOARCH=amd64 $(GO) install $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform
 
+build-netbsd:
+ @echo Build NetBSD amd64
+ env GOOS=netbsd GOARCH=amd64 $(GO) install $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform
+
 build: build-linux build-windows build-osx
 
 build-client:

配布用のアーカイブファイルを作成する部分は、LinuxとmacOS、Windows用の全てを 用意するようになっているので、NetBSD用だけを用意するように変更してしまう。


diff --git a/build/release.mk b/build/release.mk
index 5eaee8022..0105cf681 100644
--- a/build/release.mk
+++ b/build/release.mk
@@ -61,38 +61,9 @@ endif
 
  @# ----- PLATFORM SPECIFIC -----
 
- @# Make osx package
  @# Copy binary
-ifeq ($(BUILDER_GOOS_GOARCH),"darwin_amd64")
  cp $(GOPATH)/bin/platform $(DIST_PATH)/bin # from native bin dir, not cross-compiled
-else
- cp $(GOPATH)/bin/darwin_amd64/platform $(DIST_PATH)/bin # from cross-compiled bin dir
-endif
- @# Package
- tar -C dist -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-osx-amd64.tar.gz mattermost
- @# Cleanup
- rm -f $(DIST_PATH)/bin/platform
-
- @# Make windows package
- @# Copy binary
-ifeq ($(BUILDER_GOOS_GOARCH),"windows_amd64")
- cp $(GOPATH)/bin/platform.exe $(DIST_PATH)/bin # from native bin dir, not cross-compiled
-else
- cp $(GOPATH)/bin/windows_amd64/platform.exe $(DIST_PATH)/bin # from cross-compiled bin dir
-endif
- @# Package
- cd $(DIST_ROOT) && zip -9 -r -q -l mattermost-$(BUILD_TYPE_NAME)-windows-amd64.zip mattermost && cd ..
- @# Cleanup
- rm -f $(DIST_PATH)/bin/platform.exe
-
- @# Make linux package
- @# Copy binary
-ifeq ($(BUILDER_GOOS_GOARCH),"linux_amd64")
- cp $(GOPATH)/bin/platform $(DIST_PATH)/bin # from native bin dir, not cross-compiled
-else
- cp $(GOPATH)/bin/linux_amd64/platform $(DIST_PATH)/bin # from cross-compiled bin dir
-endif
  @# Package
- tar -C dist -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-linux-amd64.tar.gz mattermost
+ tar -C dist -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-netbsd-amd64.tar.gz mattermost
  @# Don't clean up native package so dev machines will have an unzipped package available
  @#rm -f $(DIST_PATH)/bin/platform

ビルドする

これで、ビルドする準備はできたので、後はウェブアプリケーションとサーバーを ビルドし、配布用アーカイブファイルを作成すれば良い。 node.js、Goともにネットワーク経由でファイルを取得する。

まずはウェブアプリケーションをビルドする。以下のように実行すれば良い。 mattermost-serverディレクトリーの中で実行しているが、実際には mattermost-webapp内でビルドがされる。


$ cd ~/go/src/github.com/mattermost/mattermost-server
$ gmake build-client

次に、サーバーをビルドする。以下のように実行する。


$ cd ~/go/src/github.com/mattermost/mattermost-server
$ gmake build-netbsd

最後に、配布用アーカイブファイルを作成する。


$ cd ~/go/src/github.com/mattermost/mattermost-server
$ gmake package

まとめ

ここまでで、Mattermostのウェブアプリケーションとサーバーを含んだ mattermost-team-netbsd-amd64.tar.gzファイルが、 ~/go/src/github.com/mattermost/mattermost-server/dist ディレクトリーに生成される。

次回は、このmattermost-team-netbsd-amd64.tar.gzファイルを 使って、日本語のメッセージ検索が可能な環境を構築する。

NetBSD/amd64 8.0_BETAをConoHa VPSにインストールする

NetBSD Advent Calendar 2017の8日目の記事です。

はじめに

2015年5月17日以前にConoHaにアカウントを作っていたので、 新しくなったConoHaのVPSを試していなかった。 NetBSDに関しては、NetBSD/amd64 7.1のテンプレートが用意されているようだ。 しかし、NetBSD 8.0_BETAが試せるので、NetBSD/amd64 8.0_BETAを インストールしたいと言うのが人情だと思う。

ConoHa VPSではOpenStackをインフラストラクチャーとして使用しているとのことで、 OpenStack APIを使用することができる。 こう書くと便利なようだが、OpenStack APIを使わないとISOイメージの持ち込みも できないので、逆に不便な気もする。

多数の仮想マシンを展開する場合には、何でもAPIで実行できるのは意味が あると思うのだが、今回はAPIが必要でないものにはAPIを使用しないようにする。

手順を想定する

仮想マシンでないハードウェアにインストールする場合と変わることはないと 思うが、以下のような順序でインストールすることにする。

  1. ISOイメージを用意する
  2. ISOイメージをマウントする
  3. ISOイメージから起動させる
  4. インストールする
  5. シャットダウンする
  6. ISOイメージをアンマウントする
  7. 起動させる

OpenStack APIを調べてみる

それぞれのステップに必要なAPIや操作を調べてみる。

ISOイメージを用意する

ISOイメージダウンロードが使用できる。 http等で拡張子.isoのISOイメージファイルのみダウンロードできるとのこと。

ISOイメージをマウントする

ISOイメージの挿入(mount) が使用できる。 仮想マシンが停止中のみマウント可能であるとのこと。

ISOイメージから起動させる

仮想マシンの起動は、コントロールパネルのウェブページから可能である。 APIでもできるだろうが、ウェブページからできるので、APIは使用しない。

インストールする

インストールは、APIの関係するものではないので、APIは使用しない。

シャットダウンする

仮想マシンのシャットダウンは、NetBSDでshutdown -p nowを 実行すれば良いはずなので、APIは使用しない。

ISOイメージをアンマウントする

ISOイメージの排出(unmount) が使用できる。 仮想マシンが停止中のみ可能であるとのこと。

起動させる

「ISOイメージから起動させる」と同じであるので、コントロールパネルの ウェブページで起動可能である。APIを使用する必要はない。

APIを操作する

実際には、JSONをHTTPSで送ることによって操作する。 ConoHaのページには、 curlを 使う例が出ているのだが、そのまま使ってもおもしろくない。 なので、Firefox 57で動く拡張機能である RESTEDを使うことにする。

早速ISOイメージをダウンロードしようとしたのだが、認証のためのトークンが 必要であった。 APIを使用するためのトークンを取得するにあるようにしないといけない。 具体的にはテナントIDをウェブページに表示させ、 それを使ってIdentity Serviceでトークンを取得する。 下図のようにして、トークンを取得する。


無事にaccess.token.idでトークンが取得できたので、 トークンの期限が切れないうちに先に進めよう。

ISOイメージを用意する

以下のようにISOイメージをダウンロードする。 cdn.NetBSD.orgからダウンロードすることにする。

やはり、ダウンロードした結果を確認しないと不安である。

確かにダウンロードされたようである。スクリーンショットをとっている時間内にダウンロードは完了してしまったようである。 ちなみにISOイメージを消す機能はない。だがある程度時間が経つと、自動的に削除されるようである。

ISOイメージをマウントする

サーバーを用意し、サーバーのUUIDを確認しておく。 サーバーは停止しておく。

ISOイメージをアンマウントする

サーバーは停止しておく。

おわりに

NetBSD/amd64 8.0_BETAは特に問題なく稼動している。

安価なPostScriptレーザープリンターLexmark MS312dnをNetBSDから使う(lpd(8)編)

NetBSD Advent Calendar 2017の6日目の記事です。

はじめに

最近は安価にレーザープリンターを購入できるが、さすがにPostScriptレーザープリンターは、なかなか安くは購入できない。 NTT-X Storeで安価にPostScript白黒レーザープリンターであるLexmark MS312dnが8,800円(税込)で購入できた。 ちなみに、これを書いている時点で在庫は残り3台である。

NetBSDからこのレーザープリンターを使ってみた。 lpd(8)を使った場合について書く。 いずれCUPSを使った場合について書きたい。

lpd(8)とlp(1)の使い方

NetBSDに限らず、lpd(8)と lp(1)を使う話になってしまうかもしれない。

lpd(8)で印刷する対象として登録する

lpd(8)の設定ファイルは、 printcap(5)であり、 編集すべきファイルは、/etc/printcapである。

Lexmark社のウェブサイトから、Lexmark-ADS-PPD-Files.tar.Zをダウンロードし、 展開した内容のうち、 Lexmark_MS310_Series.ppdを、 /opt/share/print/Lexmark_MS310_Series.ppdのように配置しておく。

その上で、/etc/printcapに、以下のように追加する。


lp|lmprinter:\
        :lp=:sh:sd=/var/spool/lpd/lp:\
        :rm=lmprinter:\
        :lf=/var/log/lpd-errs:mx#0:\
        :af=/opt/share/print/Lexmark_MS310_Series.ppd:
ここで、lmprinterはネットワーク接続されたLexmark MS312dnのホスト名である。 我が家では、 pkgsrc/net/isc-dhcpd4 とNetBSD/amd64 7のbaseに収録されているbindで dynamic DNSを設定しているのだが、Lexmark MS312dnにはうまくホスト名を割り当て できなかった。 そのため、固定でIPv4のアドレスを割り当ててある。

lpd(8)を起動する

lpd(8)をデーモンとして起動しておく必要がある。 /etc/rc.confにlpd(8)を起動するように設定しておく。


# vi /etc/rc.conf
(以下を追加する)
lpd=YES
その上で、初回は手動で起動させる。

# /etc/rc.d/lpd start
もし、/var/spool/lpd/lpディレクトリーがない場合には、 以下のようにして作成しておく。

# mkdir -p /var/spool/lpd/lp

印刷する

lpd(8)にPostScriptファイルをlp(1)コマンドを使って送信する。 GhostScript をインストールしてあれば、 虎の絵が/usr/pkg/share/ghostscript/9.06/examples/tiger.epsに 格納されている。 これを印刷するのであれば、以下のように実行する。


$ cat /usr/pkg/share/ghostscript/9.06/examples/tiger.eps | lp -d lp
ここで、lpと言うのが、/etc/printcapに設定してある Lexmark MX312dnの名前である。

NetBSDでは、Mozilla FirefoxやxpdfでPostScriptファイルを生成できるので、 これでWindows環境に頼ることなく、自由に印刷できる。

NetBSD/i386用のRust言語のブートストラップキットを作成する

NetBSD Advent Calendar 2017の5日目の記事です。

はじめに

新しいMozilla Firefoxのビルドには、Rustプログラミング言語のコンパイラーであるrustcと、パッケージ管理プログラムのcargoが必要となっている。 jakllschさんがNetBSD/amd64には移植してくれているので、RustのアップストリームがNetBSD/amd64 7向けのブートストラップキットはビルドしてくれている。 だが、NetBSD/i386 7向けがないと、Mozilla FirefoxをNetBSD/i386でビルドできない。

私はhttps://deuterium.ryoon.net/pub/rust/でnetBSD/i386 7用のブートストラップキット を公開しているが、信頼できるか分からない人の作ったコンパイラーなど使うべきではない。 ここにブートストラップキットの作り方を書いておくので、自分のためのブートストラップキットを作って使って欲しい。

# RustのアップストリームにどうやってNetBSD/i386用をビルドしてもらうように交渉すれば良いのか…。

NetBSD/amd64の環境を用意する

NetBSD/amd64 7.0以降の環境を用意する。Rustのアップストリームのビルドしているブートストラップキットが動けばNetBSD/amd64のバージョンは問わない。 ここでは、NetBSD/amd64 7.1の環境があったので、それを使用することにした。

ところで、原理的にはNetBSD/amd64である必要もない。 ある程度POSIX準拠なオペレーティングシステムで、Rustがサポートしブートストラップキットを提供しているアーキテクチャーであれば良い。 次に説明するNetBSD/i386のクロスツールチェインはそこでビルドできるはずである。

NetBSD/i386 7用のクロスツールチェインとユーザーランドをビルドする

NetBSDはクロスツールチェインを簡単に生成でき、クロスコンパイルをする準備が簡単にできるのが良い所である。 まず、以下のように実行してクロスコンパイラーなどのツールチェインを作成する。 これは、NetBSD/i386のユーザーランドをビルドするのに使用するだけでなく、Rustブートストラップキットをビルドするのにも使用する。 ここで、/usr/srcにnetbsd-7のツリーを用意してあるとする。


$ cd /usr/src
$ ./build.sh -m i386 -U -T /usr/world/7/i386/tools -O /usr/world/7/i386/obj -D /usr/world/7/i386/destdir tools
$ ./build.sh -m i386 -U -T /usr/world/7/i386/tools -O /usr/world/7/i386/obj -D /usr/world/7/i386/destdir build
これで、/usr/world/7/i386/tools以下にクロスツールチェインが用意され、 それを使って/usr/world/7/i386/destdir以下にユーザーランドがビルドされインストールされた。

クロスツールチェインを改造する

Rustブートストラップキットに使用するクロスコンパイラーのgccとg++には、いくつかのコマンドライン引数を与えて動かす必要があるのだが、 Rustのブートストラップメカニズムはそのようなコマンドライン引数を与えてgcc/g++を呼び出してはくれない。 なので、必要なコマンドライン引数をあらかじめ指定したシェルスクリプトを用意し、それをクロスコンパイラーの代わりに使用することにする。 以下のようにi486--netbsdelf-g++-sysrootとi486--netbsdelf-gcc-sysrootを用意しておく。


$ cat /usr/world/7/i386/tools/bin/i486--netbsdelf-g++-sysroot
#! /bin/sh
/usr/world/7/i386/tools/bin/i486--netbsdelf-g++ --sysroot=/usr/world/7/i386/destdir -march=i586 "$@"

$ cat /usr/world/7/i386/tools/bin/i486--netbsdelf-gcc-sysroot
#! /bin/sh
/usr/world/7/i386/tools/bin/i486--netbsdelf-gcc --sysroot=/usr/world/7/i386/destdir "$@"
ここで、-march=i586は、atomic ops関連の関数がundefined referenceにならないために必要だったはずである。

NetBSD/i386のユーザーランドに必要なパッケージをインストールする

/usr/world/7/i386/destdirにユーザーランドが用意されているが、Rustブートストラップキットをビルドするには、 pkgsrc/lang/rustが必要としているような ライブラリーが必要になる。 llvm関係はRustのソースコードに含まれているので、それ以外を/usr/world/7/i386/destdirにインストールしておく。 NetBSD/amd64では、NetBSD/i386のバイナリーを実行できるので、ここではchroot(8)コマンドを使って、ライブラリーを準備してしまった。 これは安直な方法なので、例えば今後NetBSD/earm向けのRustブートストラップキットを作ろうと言う場合には、この方法は採用できない。 必要なライブラリーをクロスビルドして配置するか、NetBSD/earmでビルドとインストールしたユーザーランドをコピーして来る必要があるだろう。


# chroot /usr/world/7/i386/destdir /bin/ksh
# pkg_add libgit2-0.26.0nb1.tgz
; 手作業でlibhttp_parser.aをビルドし、/usr/libに配置する。
; 合わせて、http_parser.hを/usr/includeに配置する。
# exit
ここで、http-parserは、 /usr/pkg以下にあってはビルドに失敗した。 面倒だったので/usr以下に配置したが、本来であればRustで書かれたRustのビルドメカニズムを修正すべきであろう。

NetBSD/amd64 7用のRustをビルドできるようにする

この先、NetBSD/amd64用のrustcやcargoをビルドし、それを使ってNetBSD/i386 7用のrustcやcargoをビルドしていくのである。 当然だが、NetBSD/amd64向けにpkgsrc/lang/rust が必要とするライブラリー等が用意されている必要がある。 以下のように実行すれば、/usr/pkg以下にインストールされる。 ついでに、Rustブートストラップキットが必要とするGNU coreutils とOpenSSL用のルート証明書、 ninjaもインストールしてしまおう。 ninjaは、lllvmの部分をパラレルビルドするのに必要となる。


# cd /usr/pkgsrc/lang/rust
# make depends
# cd /usr/pkgsrc/sysutils/coreutils
# make install
# cd /usr/pkgsrc/security/mozilla-rootcerts-openssl
# make install

Rustブートストラップキットを展開する

基本的には、一つ前のリリースのブートストラップキットを使って、最新のリリースのブートストラップキットを作るのだと思う。 ここでは、Rust 1.22.1をNetBSD/i386 7でビルドしようとしているので、1.21.0のブートストラップキットを作ることになる。 その1.21.0のブートストラップキットをビルドするために使用するRustアップストリームのブートストラップキットは、1.20.0となる。 以下のように展開しておく。


$ mkdir ~/tmp
$ cd ~/tmp
$ ftp http://static.rust-lang.org/dist/rust-1.21.0-x86_64-unknown-netbsd.tar.gz
$ ftp http://static.rust-lang.org/dist/rust-std-1.20.0-i686-unknown-netbsd.tar.gz
$ tar zxvf rust-1.21.0-x86_64-unknown-netbsd.tar.gz
$ tar zxvf rust-std-1.20.0-i686-unknown-netbsd.tar.gz
$ mv rust-std-1.20.0-x86_64-unknown-netbsd/rust-std-x86_64-unknown-netbsd/lib/rustlib/x86_64-unknown-netbsd \
rust-1.20.0-x86_64-unknown-netbsd/rustc/lib/rustlib/
$ rm -r rust-std-1.20.0-x86_64-unknown-netbsd

NetBSD/i386のためのパッチを適用する

NetBSD/i386のRustブートストラップキットをビルドするのに必要なパッチを適用する。 そのパッチは以下のようである。


--- src/bootstrap/native.rs
+++ src/bootstrap/native.rs
@@ -407,6 +407,7 @@ impl Step for Openssl {
             "i686-unknown-freebsd" => "BSD-x86-elf",
             "i686-unknown-linux-gnu" => "linux-elf",
             "i686-unknown-linux-musl" => "linux-elf",
+            "i686-unknown-netbsd" => "BSD-x86-elf",
             "mips-unknown-linux-gnu" => "linux-mips32",
             "mips64-unknown-linux-gnuabi64" => "linux64-mips64",
             "mips64el-unknown-linux-gnuabi64" => "linux64-mips64",

NetBSD/amd64 7のためのパッチを適用する

NetBSD/amd64 7で動くllvmのバイナリーを得るには、以下のパッチが必要であった。NetBSD/amd64 8以降では不要らしい。


--- src/llvm/cmake/modules/AddLLVM.cmake
+++ src/llvm/cmake/modules/AddLLVM.cmake
@@ -1422,7 +1422,7 @@ function(llvm_setup_rpath name)
     set(_install_name_dir INSTALL_NAME_DIR "@rpath")
     set(_install_rpath "@loader_path/../lib" ${extra_libdir})
   elseif(UNIX)
-    set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
+#    set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
     if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
       set_property(TARGET ${name} APPEND_STRING PROPERTY
                    LINK_FLAGS " -Wl,-z,origin ")

config.tomlにビルド条件を設定する

以下のようにi686-unknown-netbsdブートストラップキットを作ること、その他のコマンドのパス等々を設定する。


# Sample TOML configuration file for building Rust.
#
# To configure rustbuild, copy this file to the directory from which you will be
# running the build, and name it config.toml.
#
# All options are commented out by default in this file, and they're commented
# out with their default values. The build system by default looks for
# `config.toml` in the current directory of a build for build configuration, but
# a custom configuration file can also be specified with `--config` to the build
# system.

# =============================================================================
# Tweaking how LLVM is compiled
# =============================================================================
[llvm]

# Indicates whether rustc will support compilation with LLVM
# note: rustc does not compile without LLVM at the moment
#enabled = true

# Indicates whether the LLVM build is a Release or Debug build
#optimize = true

# Indicates whether an LLVM Release build should include debug info
#release-debuginfo = false

# Indicates whether the LLVM assertions are enabled or not
#assertions = false

# Indicates whether ccache is used when building LLVM
#ccache = false
# or alternatively ...
#ccache = "/path/to/ccache"

# If an external LLVM root is specified, we automatically check the version by
# default to make sure it's within the range that we're expecting, but setting
# this flag will indicate that this version check should not be done.
#version-check = true

# Link libstdc++ statically into the librustc_llvm instead of relying on a
# dynamic version to be available.
static-libstdcpp = true

# Tell the LLVM build system to use Ninja instead of the platform default for
# the generated build system. This can sometimes be faster than make, for
# example.
ninja = true

# LLVM targets to build support for.
# Note: this is NOT related to Rust compilation targets. However, as Rust is
# dependent on LLVM for code generation, turning targets off here WILL lead to
# the resulting rustc being unable to compile for the disabled architectures.
# Also worth pointing out is that, in case support for new targets are added to
# LLVM, enabling them here doesn't mean Rust is automatically gaining said
# support. You'll need to write a target specification at least, and most
# likely, teach rustc about the C ABI of the target. Get in touch with the
# Rust team and file an issue if you need assistance in porting!
#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon"

# LLVM experimental targets to build support for. These targets are specified in
# the same format as above, but since these targets are experimental, they are
# not built by default and the experimental Rust compilation targets that depend
# on them will not work unless the user opts in to building them. Possible
# experimental LLVM targets include WebAssembly for the
# wasm32-experimental-emscripten Rust target.
#experimental-targets = ""

# Cap the number of parallel linker invocations when compiling LLVM.
# This can be useful when building LLVM with debug info, which significantly
# increases the size of binaries and consequently the memory required by
# each linker process.
# If absent or 0, linker invocations are treated like any other job and
# controlled by rustbuild's -j parameter.
#link-jobs = 0

# When invoking `llvm-config` this configures whether the `--shared` argument is
# passed to prefer linking to shared libraries.
#link-shared = false

# =============================================================================
# General build configuration options
# =============================================================================
[build]

# Build triple for the original snapshot compiler. This must be a compiler that
# nightlies are already produced for. The current platform must be able to run
# binaries of this build triple and the nightly will be used to bootstrap the
# first compiler.
build = "x86_64-unknown-netbsd"    # defaults to your host platform

# In addition to the build triple, other triples to produce full compiler
# toolchains for. Each of these triples will be bootstrapped from the build
# triple and then will continue to bootstrap themselves. This platform must
# currently be able to run all of the triples provided here.
host = ["i686-unknown-netbsd"]   # defaults to just the build triple

# In addition to all host triples, other triples to produce the standard library
# for. Each host triple will be used to produce a copy of the standard library
# for each target triple.
target = ["i686-unknown-netbsd"] # defaults to just the build triple

# Instead of downloading the src/stage0.txt version of Cargo specified, use
# this Cargo binary instead to build all Rust code
cargo = "/home/ryoon/tmp/rust-1.20.0-x86_64-unknown-netbsd/cargo/bin/cargo"

# Instead of downloading the src/stage0.txt version of the compiler
# specified, use this rustc binary instead as the stage0 snapshot compiler.
rustc = "/home/ryoon/tmp/rust-1.20.0-x86_64-unknown-netbsd/rustc/bin/rustc"

# Flag to specify whether any documentation is built. If false, rustdoc and
# friends will still be compiled but they will not be used to generate any
# documentation.
docs = true

# Indicate whether the compiler should be documented in addition to the standard
# library and facade crates.
compiler-docs = true

# Indicate whether submodules are managed and updated automatically.
#submodules = true

# The path to (or name of) the GDB executable to use. This is only used for
# executing the debuginfo test suite.
#gdb = "gdb"

# The node.js executable to use. Note that this is only used for the emscripten
# target when running tests, otherwise this can be omitted.
#nodejs = "node"

# Python interpreter to use for various tasks throughout the build, notably
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
# Note that Python 2 is currently required.
python = "/usr/pkg/bin/python2.7"

# Force Cargo to check that Cargo.lock describes the precise dependency
# set that all the Cargo.toml files create, instead of updating it.
#locked-deps = false

# Indicate whether the vendored sources are used for Rust dependencies or not
vendor = true

# Typically the build system will build the rust compiler twice. The second
# compiler, however, will simply use its own libraries to link against. If you
# would rather to perform a full bootstrap, compiling the compiler three times,
# then you can set this option to true. You shouldn't ever need to set this
# option to true.
full-bootstrap = false

# Enable a build of the extended rust tool set which is not only the compiler
# but also tools such as Cargo. This will also produce "combined installers"
# which are used to install Rust and Cargo together. This is disabled by
# default.
extended = true

# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
#verbose = 0

# Build the sanitizer runtimes
#sanitizers = false

# Build the profiler runtime
#profiler = false

# Indicates whether the OpenSSL linked into Cargo will be statically linked or
# not. If static linkage is specified then the build system will download a
# known-good version of OpenSSL, compile it, and link it to Cargo.
openssl-static = true

# Run the build with low priority, by setting the process group's "nice" value
# to +10 on Unix platforms, and by using a "low priority" job object on Windows.
#low-priority = false

# Arguments passed to the `./configure` script, used during distcheck. You
# probably won't fill this in but rather it's filled in by the `./configure`
# script.
#configure-args = []

# Indicates that a local rebuild is occurring instead of a full bootstrap,
# essentially skipping stage0 as the local compiler is recompiling itself again.
#local-rebuild = false

# =============================================================================
# General install configuration options
# =============================================================================
[install]

# Instead of installing to /usr/local, install to this path instead.
#prefix = "/usr/local"

# Where to install system configuration files
# If this is a relative path, it will get installed in `prefix` above
#sysconfdir = "/etc"

# Where to install documentation in `prefix` above
#docdir = "share/doc/rust"

# Where to install binaries in `prefix` above
#bindir = "bin"

# Where to install libraries in `prefix` above
#libdir = "lib"

# Where to install man pages in `prefix` above
#mandir = "share/man"

# Where to install data in `prefix` above (currently unused)
#datadir = "share"

# Where to install additional info in `prefix` above (currently unused)
#infodir = "share/info"

# Where to install local state (currently unused)
# If this is a relative path, it will get installed in `prefix` above
#localstatedir = "/var/lib"

# =============================================================================
# Options for compiling Rust code itself
# =============================================================================
[rust]

# Indicates that the build should be optimized for debugging Rust. Note that
# this is typically not what you want as it takes an incredibly large amount of
# time to have a debug-mode rustc compile any code (notably libstd). If this
# value is set to `true` it will affect a number of configuration options below
# as well, if unconfigured.
#debug = false

# Whether or not to optimize the compiler and standard library
# Note: the slowness of the non optimized compiler compiling itself usually
#       outweighs the time gains in not doing optimizations, therefore a
#       full bootstrap takes much more time with optimize set to false.
#optimize = true

# Number of codegen units to use for each compiler invocation. A value of 0
# means "the number of cores on this machine", and 1+ is passed through to the
# compiler.
#codegen-units = 1

# Whether or not debug assertions are enabled for the compiler and standard
# library. Also enables compilation of debug! and trace! logging macros.
#debug-assertions = false

# Whether or not debuginfo is emitted
#debuginfo = false

# Whether or not line number debug information is emitted
#debuginfo-lines = false

# Whether or not to only build debuginfo for the standard library if enabled.
# If enabled, this will not compile the compiler with debuginfo, just the
# standard library.
#debuginfo-only-std = false

# Whether or not jemalloc is built and enabled
#use-jemalloc = true

# Whether or not jemalloc is built with its debug option set
#debug-jemalloc = false

# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
#backtrace = true

# The default linker that will be hard-coded into the generated compiler for
# targets that don't specify linker explicitly in their target specifications.
# Note that this is not the linker used to link said compiler.
#default-linker = "cc"

# The "channel" for the Rust build to produce. The stable/beta channels only
# allow using stable features, whereas the nightly and dev channels allow using
# nightly features
channel = "stable"

# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
# platforms to ensure that the compiler is usable by default from the build
# directory (as it links to a number of dynamic libraries). This may not be
# desired in distributions, for example.
#rpath = true

# Suppresses extraneous output from tests to ensure the output of the test
# harness is relatively clean.
#quiet-tests = false

# Flag indicating whether tests are compiled with optimizations (the -O flag) or
# with debuginfo (the -g flag)
#optimize-tests = true
#debuginfo-tests = true

# Flag indicating whether codegen tests will be run or not. If you get an error
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true

# Flag indicating whether git info will be retrieved from .git automatically.
# Having the git information can cause a lot of rebuilds during development.
# Note: If this attribute is not explicity set (e.g. if left commented out) it
# will default to true if channel = "dev", but will default to false otherwise.
#ignore-git = true

# When creating source tarballs whether or not to create a source tarball.
#dist-src = false

# Whether to also run the Miri tests suite when running tests.
# As a side-effect also generates MIR for all libraries.
#test-miri = false

# =============================================================================
# Options for specific targets
#
# Each of the following options is scoped to the specific target triple in
# question and is used for determining how to compile each target.
# =============================================================================
[target.i686-unknown-netbsd]

# C compiler to be used to compiler C code. Note that the
# default value is platform specific, and if not specified it may also depend on
# what platform is crossing to what platform.
#cc = "cc"

# C++ compiler to be used to compiler C++ code (e.g. LLVM and our LLVM shims).
# This is only used for host targets.
#cxx = "c++"

# Archiver to be used to assemble static libraries compiled from C/C++ code.
# Note: an absolute path should be used, otherwise LLVM build will break.
#ar = "ar"

# Linker to be used to link Rust code. Note that the
# default value is platform specific, and if not specified it may also depend on
# what platform is crossing to what platform.
#linker = "cc"

# Path to the `llvm-config` binary of the installation of a custom LLVM to link
# against. Note that if this is specifed we don't compile LLVM at all for this
# target.
#llvm-config = "../path/to/llvm/root/bin/llvm-config"

# Path to the custom jemalloc static library to link into the standard library
# by default. This is only used if jemalloc is still enabled above
#jemalloc = "/path/to/jemalloc/libjemalloc_pic.a"

# If this target is for Android, this option will be required to specify where
# the NDK for the target lives. This is used to find the C compiler to link and
# build native code.
#android-ndk = "/path/to/ndk"

# Force static or dynamic linkage of the standard library for this target. If
# this target is a host for rustc, this will also affect the linkage of the
# compiler itself. This is useful for building rustc on targets that normally
# only use static libraries. If unset, the target's default linkage is used.
#crt-static = false

# The root location of the MUSL installation directory. The library directory
# will also need to contain libunwind.a for an unwinding implementation. Note
# that this option only makes sense for MUSL targets that produce statically
# linked binaries
#musl-root = "..."

# Used in testing for configuring where the QEMU images are located, you
# probably don't want to use this.
#qemu-rootfs = "..."

# =============================================================================
# Distribution options
#
# These options are related to distribution, mostly for the Rust project itself.
# You probably won't need to concern yourself with any of these options
# =============================================================================
[dist]

# This is the folder of artifacts that the build system will sign. All files in
# this directory will be signed with the default gpg key using the system `gpg`
# binary. The `asc` and `sha256` files will all be output into the standard dist
# output folder (currently `build/dist`)
#
# This folder should be populated ahead of time before the build system is
# invoked.
#sign-folder = "path/to/folder/to/sign"

# This is a file which contains the password of the default gpg key. This will
# be passed to `gpg` down the road when signing all files in `sign-folder`
# above. This should be stored in plaintext.
#gpg-password-file = "path/to/gpg/password"

# The remote address that all artifacts will eventually be uploaded to. The
# build system generates manifests which will point to these urls, and for the
# manifests to be correct they'll have to have the right URLs encoded.
#
# Note that this address should not contain a trailing slash as file names will
# be appended to it.
#upload-addr = "https://example.com/folder"

# Whether to build a plain source tarball to upload
# We disable that on Windows not to override the one already uploaded on S3
# as the one built on Windows will contain backslashes in paths causing problems
# on linux
#src-tarball = true

Rustブートストラップキットをビルドする

ここまで来れば、後は実行してしばらく待つだけである。私のところのマシンでは正確には把握していないが数時間は必要だった。 以下のように実行すれば良い。


$ mkdir ~/tmp/rust
$ cd ~/tmp/rust
$ LD_LIBRARY_PATH=/home/ryoon/tmp/rust-1.20.0-x86_64-unknown-netbsd/rustc/lib OPENSSL_DIR=/usr CC_i686_unknown_netbsd=i486--netbsdelf-gcc-sysroot CXX_i686_unknown_netbsd=i486--netbsdelf-g++-sysroot PATH=/usr/world/7/i386/tools/bin:/usr/pkg/gnu/bin:$PATH python2.7 ../rustc-1.21.0-src/x.py dist
エラーなく完了したら、以下のようにブートストラップキットができているはずである。

$ cd ~/tmp/rust
$ ls build/dist
(snip)
build/dist/rust-1.19.0-i686-unknown-netbsd.tar.gz
(snip)
build/dist/rust-std-1.19.0-i686-unknown-netbsd.tar.gz
(snip)
これをDISTDIRに置いて、pkgsrc/lang/rustをNetBSD/i386でビルドするのに使えば良い。

bta2dpd(8)を使って、NetBSDでBluetoothヘッドフォンを使う

NetBSD Advent Calendar 2017の4日目の記事です。

English version is here.

はじめに

Bluetoothでオーディオを再生するには、以前はbtsco(4)しかなく、 ubt(4)でbtsco(4)を使おうとすると、USBアイソクロナス転送が必要で、 NetBSDのechi(4)やxhci(4)ではアイソクロナス転送はサポートされて いないので、btsco(4)ではBluetoothのオーディオデバイスでは オーディオの録音、再生ができなかった。

しばらく前に、bta2dpd(8)と言うのがnat@によってNetBSD-currentに追加された。 これがxhci(4)で使えるのかが、ずっと気になっていた。 やっと、Jabra MOVE Wireless で試してみた。 結果としては、ubt(4)につないだJabra MOVE Wirelessで再生できた。

Bluetoothの基本的な設定

ペアリングやプロファイルの選択は、btsco(4)の場合と同じであった。 以下のようにすれば良い。

まずは、Bluetooth接続に必要なデーモン等を起動しておく。 以下のように追加する。


# vi /etc/rc.conf
bluetooth=YES
# /etc/rc.d/bluetooth start
configuring Bluetooth controllers: ubt0.
starting Bluetooth Link Key/PIN Code manager
starting Bluetooth Service Discovery server
もし、継続的に使用しないのであれば、以下のようにしても良い。

# /etc/rc.d/bluetooth onestart
configuring Bluetooth controllers: ubt0.
starting Bluetooth Link Key/PIN Code manager
starting Bluetooth Service Discovery server

ワイヤレスヘッドフォンをペアリング待ちにした上で、以下のように実行し、 ワイヤレスヘッドフォンのアドレスを取得する。


$ btconfig ubt0 inquiry
Device Discovery from device: ubt0 ... 1 response
  1: bdaddr XX:YY:ZZ:XX:YY:ZZ
   : name "Jabra MOVE v2.5.0"
   : class [0x240404] Wearable Headset  
簡便のためこのアドレスを/etc/bluetooth/hostsファイルに 登録しておく。ここでは、headset1と言う名前を付けておく。

# vi /etc/bluetooth/hosts
XX:YY:ZZ:XX:YY:ZZ headset1

次に、BluetoothのPINを設定する。


$ btpin -d ubt0 -a headset1 -p 0000
Jabra MOVE Wirelessでは、PINは0000で良いようだ。

次は、アドレスheadset1のデバイスをヘッドセット(HSET)に設定する。


# btdevctl -d ubt0 -a headset1 -s HSET -A
※ この設定は不要だった (2020-06-06)。

ここまでは、btsco(4)の場合と一緒である。 次がbta2dpd(8)の使用方法である。 まずテストしてみる。


$ file test.wav
test.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
# bta2dpd -a headset1 test.wav
しかし、これではwavファイルしか再生できないので、例えばmplayer等で OSSで再生したものをヘッドセットで聞くには以下のようにする。

# bta2dpd -a headset1 /dev/pad
このように実行すると、以下のようにdmesgに表示された。

pad0: outputs: 44100Hz, 16-bit, stereo
audio2 at pad0: half duplex, playback, capture, mmap
pad0: Virtual format configured - Format SLINEAR, precision 16, channels 2, frequency 44100
spkr3 at audio2: PC Speaker (synthesized)
wsbell at spkr3 not configured
よって、/dev/sound2で再生すると、 /dev/pad(/dev/pad0と同じものを指している)に その内容がコピーされることになると分かる。 例えば、以下のようにmplayerで再生すれば、ヘッドセットで聞こえた。

$ mplayer -ao oss:/dev/sound2 test.mp3

おわりに

xhci(4)でBluetoothオーディオを使えるのは非常に便利だった。

How to use bta2dpd(8) with Bluetooth headphone under NetBSD-current

Introduction

When USB Bluetooth dongle (ubt(4)) is used, classic Bluetooth SCO Audio (btsco(4)) requires USB isochronous transfer and ehci(4) and xhci(4) of NetBSD-current does not support USB isochronous transfer mode, So I cannot use btsco(4) to play audio under NetBSD-current.

Some time ago, bta2dpd(8) was imported to NetBSD-current by nat@. I had not tested bta2dpd(8) and I should test bta2dp(8) with Jabra MOVE Wireless. As a result, I can play audio with ubt(4) and Javra MOVE Wireless.

Basic Bluetooth settings

How to pairing and selecting profile is as same as btsco(4). Please perform the following steps.

At first, run daemon/service for Bluetooth. Please perform the following steps.


# vi /etc/rc.conf
bluetooth=YES
# /etc/rc.d/bluetooth start
configuring Bluetooth controllers: ubt0.
starting Bluetooth Link Key/PIN Code manager
starting Bluetooth Service Discovery server
If your Bluetooth connection is temporary, you can perform the following steps instead.

# /etc/rc.d/bluetooth onestart
configuring Bluetooth controllers: ubt0.
starting Bluetooth Link Key/PIN Code manager
starting Bluetooth Service Discovery server

Next, turn your wireless headphone to pairing mode and perform the followings to get Bluetooth address.


$ btconfig ubt0 inquiry
Device Discovery from device: ubt0 ... 1 response
  1: bdaddr XX:YY:ZZ:XX:YY:ZZ
   : name "Jabra MOVE v2.5.0"
   : class [0x240404] Wearable Headset  
For easier to identification, record this address in /etc/bluetooth/hosts as headset1.

# vi /etc/bluetooth/hosts
XX:YY:ZZ:XX:YY:ZZ headset1

Next, set Bluetooth PIN.


$ btpin -d ubt0 -a headset1 -p 0000
Jabra MOVE Wireless assumes PIN as 0000.

Next, the device, set headset1 as headset (HSET).


# btdevctl -d ubt0 -a headset1 -s HSET -A
XXX: This setting is not required. (2020-06-06)

Above procedure is as same as btsco(4). I will use bta2dpd(8) as follows. Perform basic test.


$ file test.wav
test.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
# bta2dpd -a headset1 test.wav
You may want to play mp3 file or others. If you use mplayer with OSS, you can use pad(4).

# bta2dpd -a headset1 /dev/pad
After this invocation, you can see as follows in your dmesg.

pad0: outputs: 44100Hz, 16-bit, stereo
audio2 at pad0: half duplex, playback, capture, mmap
pad0: Virtual format configured - Format SLINEAR, precision 16, channels 2, frequency 44100
spkr3 at audio2: PC Speaker (synthesized)
wsbell at spkr3 not configured
This messages show you that if you play audio to /dev/sound2, your audio stream will appear in /dev/pad0. For example, the following command plays audio your Bluetooth headphone.

$ mplayer -ao oss:/dev/sound2 test.mp3

Conclusion

You can use Bluetooth audio with xhci(4) of NetBSD-current.

HP ProLiant ML110 G7に32GBのメモリーを搭載する

HP ProLiant ML110 G7 Server Maintenance and Service Guide の62ページ目には、以下のように記載されている。 General DIMM slot population guidelines Th...