2012年8月4日土曜日
2012年8月1日水曜日
Linux のコードが FreeBSDに
FreeBSD のことはよく知らないのですが、FreeBSDのソースをダウンロードしてくると、Linuxと同じようなファイルが含まれています。
ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/9.0-RELEASE
からsrc.txzを取ってきて、解凍すると、
usr/src/sys/ofed/include/linux 以下に
Linux Kernel の include/linux とそっくりなファイル群があります。
ディレクトリ名からして、Linux の方が本家だと想像します。
Linux は GPLライセンス, FreeBSD は BSDライセンスなので、こんなことできるんですかね?
FreeBSDが勝手にLinuxをコピーしているのか、それともLinux Communityに許可もらったのか、事情はよくわかりません。
include/linux/ 以下には他のソフトにもそのまま転用できそうな部品になるコードが結構ある。
たとえば、
include/linux/kernel.h に含まれる container_of マクロ。
include/linux/list.h の連結リストの関数群などなど。
自前のソフト開発で、Linux からコードをコピーするとGPL汚染すると思いますが、FreeBSDに入っている同等コードをコピーすれば、BSDライセンスとして扱ってよいということでしょうか。
企業なんかだと、コピー開示義務があるかどうかの違いは結構大きいと思います。
ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/9.0-RELEASE
からsrc.txzを取ってきて、解凍すると、
usr/src/sys/ofed/include/linux 以下に
Linux Kernel の include/linux とそっくりなファイル群があります。
ディレクトリ名からして、Linux の方が本家だと想像します。
Linux は GPLライセンス, FreeBSD は BSDライセンスなので、こんなことできるんですかね?
FreeBSDが勝手にLinuxをコピーしているのか、それともLinux Communityに許可もらったのか、事情はよくわかりません。
include/linux/ 以下には他のソフトにもそのまま転用できそうな部品になるコードが結構ある。
たとえば、
include/linux/kernel.h に含まれる container_of マクロ。
include/linux/list.h の連結リストの関数群などなど。
自前のソフト開発で、Linux からコードをコピーするとGPL汚染すると思いますが、FreeBSDに入っている同等コードをコピーすれば、BSDライセンスとして扱ってよいということでしょうか。
企業なんかだと、コピー開示義務があるかどうかの違いは結構大きいと思います。
Linux ライクな autoconf.h を簡単に作る
Linux の Makefile においては、.config ファイルの内容から
include/config/auto.conf
と
include/generated/autoconf.h
が作られる。
前者はすべての Makefile から include され、
後者は -include include/generated/autoconf.h としてすべてのCのソースに渡される。
Makefile でも Cのソースでも、同じ設定内容を参照できるようにするというアイデアは素晴らしいと思う。
自前のソフトでも同様のことをしたいが、Linux の scripts/kconfig/conf を使うほどでもないという場合、以下のように make の簡単なコードでほぼ同等のことをできる。
Makefile の実装例:
include .config
auto.conf: .config
@ ($(foreach v, $(filter CONFIG_%, $(.VARIABLES)), \
$(if $($v), echo $v='$($v)';))) > $@
autoconf.h: .config
@ ($(foreach v, $(filter CONFIG_%, $(.VARIABLES)), \
$(if $($v), echo \#define $v $(if $(filter y,$($v)),1,'$($v)');))) > $@
include/config/auto.conf
と
include/generated/autoconf.h
が作られる。
前者はすべての Makefile から include され、
後者は -include include/generated/autoconf.h としてすべてのCのソースに渡される。
Makefile でも Cのソースでも、同じ設定内容を参照できるようにするというアイデアは素晴らしいと思う。
自前のソフトでも同様のことをしたいが、Linux の scripts/kconfig/conf を使うほどでもないという場合、以下のように make の簡単なコードでほぼ同等のことをできる。
Makefile の実装例:
include .config
auto.conf: .config
@ ($(foreach v, $(filter CONFIG_%, $(.VARIABLES)), \
$(if $($v), echo $v='$($v)';))) > $@
autoconf.h: .config
@ ($(foreach v, $(filter CONFIG_%, $(.VARIABLES)), \
$(if $($v), echo \#define $v $(if $(filter y,$($v)),1,'$($v)');))) > $@
例えば、
CONFIG_FOO=y
CONFIG_BAR="abcdef"
CONFIG_BUZ=0x100
# CONFIG_QUX is not set.
という内容の .config を食わせてみる。
実行結果は以下の通り。
$ make auto.conf
$ make autoconf.h
$ cat auto.conf
CONFIG_FOO=y
CONFIG_BUZ=0x100
CONFIG_BAR="abcdef"
$ cat autoconf.h
#define CONFIG_FOO 1
#define CONFIG_BUZ 0x100
#define CONFIG_BAR "abcdef"
sed などで、 .config を parse してもよいのだが、make の .VARIABLES に定義済み変数が全部入っているので、そこから CONFIG_ で始まるものを抽出すれば簡単である。
.config 中で =y のものは、 autoconf.h では 1 に define される。
本家 Linux では =m のものは autoconf.h の方では (変数名)_MODULE が定義されるが、今回のサンプルには実装していない。
make の ifdef はわかりにくい
シェルにおいて
$ FOO=
とすると、シェル変数 FOO は空ではあるが、定義はされている。
変数 FOO を未定義にするには
$ unset FOO
としなければならない。
つまり、シェルスクリプトで、「変数が空」であることと、「変数が未定義」であることは明確に違う。
一方、make においてはこのあたりが紛らわしいというか、非常にわかりにくいと思うので、整理しておきたい。
make には ifdef という構文があるが、これの挙動を見てみる。
(実験1)
以下の内容の Makefile を用意する。
FOO=
all:
ifdef
@echo FOO is defined.
else
@echo FOO is NOT defined.
endif
実行すると以下のようになる。
$ make
FOO is NOT defined.
FOO=
のように、空文字を代入した場合、 ifdef は FOO を未定義だと判定した。
なるほど〜、makeにおいては
空の変数は未定義の扱いになる。
そして、make には unset がないから、変数を未定義に戻すには、空文字を代入すればいいんだ、と理解したくなるかもしれない。
だが、これは違う。
(実行2)
次の内容の Makefile を用意する。
FOO=
FOO ?= 1
BAR ?= 1
all:
@echo FOO = $(FOO)
$ FOO=
とすると、シェル変数 FOO は空ではあるが、定義はされている。
変数 FOO を未定義にするには
$ unset FOO
としなければならない。
つまり、シェルスクリプトで、「変数が空」であることと、「変数が未定義」であることは明確に違う。
一方、make においてはこのあたりが紛らわしいというか、非常にわかりにくいと思うので、整理しておきたい。
make には ifdef という構文があるが、これの挙動を見てみる。
(実験1)
以下の内容の Makefile を用意する。
FOO=
all:
ifdef
@echo FOO is defined.
else
@echo FOO is NOT defined.
endif
実行すると以下のようになる。
$ make
FOO is NOT defined.
FOO=
のように、空文字を代入した場合、 ifdef は FOO を未定義だと判定した。
なるほど〜、makeにおいては
空の変数は未定義の扱いになる。
そして、make には unset がないから、変数を未定義に戻すには、空文字を代入すればいいんだ、と理解したくなるかもしれない。
だが、これは違う。
(実行2)
次の内容の Makefile を用意する。
FOO=
FOO ?= 1
BAR ?= 1
all:
@echo FOO = $(FOO)
@echo BAR = $(BAR)
この実行結果は以下のようになる。
$ make
FOO =
BAR = 1
?= というのは、変数が未定義の時のみ、右辺の値を代入してくれる。
実験結果を見ると、
?= は BAR は未定義と判定したが、FOO は定義済みと判定したことになる。
(実験3)
以下の内容の Makefile を用意する。
FOO=
all:
@echo $(filter FOO, $(.VARIABLES))
実行結果は
$ make
FOO
となる。
.VARIABLES という makeの変数には、使用中の変数が全部入っている。
大量の変数が入っているのだが、その中に FOO も含まれていることがわかる。
つまり、 .VARIABLES には中身が空の変数も含めて、定義済みの変数がリストされている。
(実験1)〜(実験3)からわかることは、
makeにおいても、「変数が空」であることと「変数が未定義」であることは区別している。
(ただ、シェルと違って、いったん定義された変数を未定義に戻すことはできない。)
?= は変数が「未定義」であれば右辺値が代入される。
注意しておきたいことは、(実験1)からわかるように、 ifdef は「定義されているか」を判定するのではなく、「空でないかどうか」を判定するものだ。
これは、ひじょーーーーーに紛らわしい。
この ifdef の仕様は失敗じゃないの?と思う。
つまり
ifdef FOO
は
ifndef ($(FOO),)
と同じなのだ。
だから、 ifdef 自体、別になくても構わないし、私は使わない。
ifndef ($(FOO),)
を使うほうが、誤解がないから。
2012年7月28日土曜日
自分的 Fedora17 初期設定メモ
このところずっとUbuntu ユーザーだったんですが、諸事情 (2個前の「Zenbook Prime フリーズ問題」)がありまして、Fedora 17をインストールしてみました。
かなり久しぶりにFedoraに触ると、初期設定にとまどったので、備忘録としてメモっておく。
・日本語環境にする
「システム設定」→「地域と言語」
「言語」タブで日本語を選択。
「システム」タブで「設定のコピー...」をクリック。いったんログアウト。
・IME の ON/OFF を別キーに割り当てる
自分は日本語IMEのONに「変換」キー、OFFに「無変換」キーを割り当てたい人です。
Ubuntu の IBus は ON と OFF を別々に割り当てられるのに、Fedoraの IBusはトグルしか設定ができないみたい。
scim-mozc はバグなのか、動きませんでした。
ibus-mozc に以下の設定をすると、とりあえず自分のやりたいことはできた。
IBus が ON/OFF を別キーに設定できないなら、Mozcの機能で IME ON/OFFを別キーで切り替えるようにします。
「システム設定」→「地域と言語」を起動。
「レイアウト」タブで日本語以外は全部削除し、常に ibus-mozcだけが起動する状態にする。
デスクトップ右上のMozcのアイコンを右クリックして出てきたメニューから「Properties」を選ぶと、Mozcの設定ができる。
「一般」タブの「キー設定の選択」でことえりを選ぶ。
「編集...」をクリック。
「編集」ドロップダウンメニューの中からエクスポートを選ぶ。
keymap.txt に保存し、
DirectInput Henkan IMEOn
Precomposition MuHenkan IMEOff
の2行を追加。
「キー設定の選択」でカスタムを選び、「編集」ドロップダウンメニューのインポートを選んで、今作成した keymap.txtを取り込む。
これでうまくいきました。
・Chromiumブラウザ
自分はChromium (Chrome)ブラウザを使いたい人。
Ubuntu だとデフォルトで chromium がリポジトリに入っているが、Fedoraにはデフォルトでは入っていなかった。
http://fedoraproject.org/wiki/Chromium
に書いてあった。
http://repos.fedorapeople.org/repos/spot/chromium-stable/fedora-chromium-stable.repo
の内容を /etc/yum.repos.d
に放り込めばよいらしい。
かなり久しぶりにFedoraに触ると、初期設定にとまどったので、備忘録としてメモっておく。
・日本語環境にする
「システム設定」→「地域と言語」
「言語」タブで日本語を選択。
「システム」タブで「設定のコピー...」をクリック。いったんログアウト。
・IME の ON/OFF を別キーに割り当てる
自分は日本語IMEのONに「変換」キー、OFFに「無変換」キーを割り当てたい人です。
Ubuntu の IBus は ON と OFF を別々に割り当てられるのに、Fedoraの IBusはトグルしか設定ができないみたい。
scim-mozc はバグなのか、動きませんでした。
ibus-mozc に以下の設定をすると、とりあえず自分のやりたいことはできた。
IBus が ON/OFF を別キーに設定できないなら、Mozcの機能で IME ON/OFFを別キーで切り替えるようにします。
「システム設定」→「地域と言語」を起動。
「レイアウト」タブで日本語以外は全部削除し、常に ibus-mozcだけが起動する状態にする。
デスクトップ右上のMozcのアイコンを右クリックして出てきたメニューから「Properties」を選ぶと、Mozcの設定ができる。
「一般」タブの「キー設定の選択」でことえりを選ぶ。
「編集...」をクリック。
「編集」ドロップダウンメニューの中からエクスポートを選ぶ。
keymap.txt に保存し、
DirectInput Henkan IMEOn
Precomposition MuHenkan IMEOff
の2行を追加。
「キー設定の選択」でカスタムを選び、「編集」ドロップダウンメニューのインポートを選んで、今作成した keymap.txtを取り込む。
これでうまくいきました。
・Chromiumブラウザ
自分はChromium (Chrome)ブラウザを使いたい人。
Ubuntu だとデフォルトで chromium がリポジトリに入っているが、Fedoraにはデフォルトでは入っていなかった。
http://fedoraproject.org/wiki/Chromium
に書いてあった。
http://repos.fedorapeople.org/repos/spot/chromium-stable/fedora-chromium-stable.repo
の内容を /etc/yum.repos.d
に放り込めばよいらしい。
2012年7月26日木曜日
Make のポータビリティについて考える
Makefile のポータビリティについて考えてみる。
Makefile 中では、 $(MAKE) や $(AWK) など、変数で記述することがよく行われる。
これはポータビリティを考える上で当然である。
たとえば、Linux 上で普通 make といえば、GNU make のことを指す。
一方、Free BSDでは、make は GNU拡張されていない普通のmake のことであり、GNU makeのコマンド名は gmake だったりする。
そこで、make というコマンド名を直接 Makefile 中に埋め込むのではなく、 $(MAKE) という変数名で記述するわけだ。
今回、考えたいのは echo コマンドについて。Makefile 中でもよく使われている。
echo コマンドは環境によって、仕様にかなり違いがあり、シェルビルトインのechoもあるので、ポータビリティを考えだすと結構複雑だったりする。
例えば、bash を使っている人は
$ echo "hoge\npiyo"
hoge\npiyo
$ echo -e "hoge\npiyo"
hoge
piyo
$ type echo
echo はシェル組み込み関数です
となる。
一方、tcsh では
$ echo "hoge\npiyo"
hoge
piyo
$ echo -e "hoge\npiyo"
-e hoge
piyo
$ which echo
echo: シェルに入っているコマンドです.
となる。
最近の Ubuntu や Mint に標準で入っている dashの場合、
$ echo "hoge\npiyo"
hoge
piyo
$ echo -e "hoge\npiyo"
-e hoge
piyo
$ type echo
echo is a shell builtin
つまり、bash, tcsh, dash いずれもシェルビルトインのechoを持つが、bashビルトインのechoはデフォルトでは \n といったエスケープシーケンスを解釈してくれず、エスケープシーケンスを解釈させるためには -e オプションをつける必要がある。
一方、tcsh や dash のビルトインのecho はデフォルトでエスケープシーケンスを解釈してくれる代わりに、 -e オプションは解釈してくれない。
さらにシェルビルトインではない /bin/echo の仕様はプラットフォームごとに違うのだが、Linux であれば
$ /bin/echo "hoge\npiyo"
hoge\npiyo
$ /bin/echo -e "hoge\npiyo"
hoge
piyo
となり、bashビルトインのechoと同じような挙動をする。
このようにechoの仕様は結構違う。
そこで、Makefile の中で echo を使った場合、call される echo はどれなのか?
(ここでは GNU make についてのみ考える。)
これについては O'REILLY の「GNU Make」 の5章の冒頭に書かれている。
原著は以下で参照できる。
要約するとこういうことだ。
・make はコマンドを1行ごとに取り出し、サブシェルに渡して実行する。
・ただし、ワイルドカードやリダイレクションなどシェルの特殊文字が使われていない場合、高速化のためにサブシェルに渡さず、makeが直接コマンドを実行する。
・呼び出すサブシェルはデフォルトで /bin/sh であるが、make の変数 SHELL により変更できる。
・ただし、この変数は環境変数から引き継ぐものではない。make は環境変数を makeの変数として取り込むが、 SHELL だけは例外である。
本当にそうなっているか、以下の Makefile で実験してみる。
all1:
@echo --version
@type echo
all2:
@echo --version | cat
@type echo | cat
all3: SHELL=/bin/bash
all3:
@echo --version
@type echo
以下は Fedora 上で実行した結果である。
$ make all1
echo (GNU coreutils) 8.15
Copyright (C) 2012 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
作者 Brian Fox および Chet Ramey。
make: type: コマンドが見つかりませんでした
make: *** [all1] エラー 127
$ make all2
--version
echo はシェル組み込み関数です
$ make all3
--version
echo はシェル組み込み関数です
all1 は make が直接コマンドを実行しており、 /bin/echo が実行されている。
(そのため、 --version オプションを解釈している。)
all2 はパイプを使っている。ワイルドカードやリダイレクト、パイプなどを使っているとサブシェル /bin/sh の中で実行する。
Fedoraでは /bin/sh は bashへのシンボリックリンクになっているので、結局は bashビルトインのecho を実行している。(そして --version オプションを解釈しない)
all3 は make 変数 SHELL の値を /bin/bash に書き換えているので、bash ビルトインのecho を実行している。
前述のように、make 変数の SHELL は環境変数の SHELL とは無関係だ。
SHELL だけは環境変数から引き継が仕様になっている理由は、ユーザーの使っているシェルがmakefileの動作に影響しないためだ。
例えば、tcsh をデフォルトにしているユーザーは 環境変数 SHELL は /bin/tcsh になっているはずだが、だからといって、 makefile のルールを tcsh で実行するのはナンセンスだ。スクリプトを C shell系で記述することはほとんどないわけだから。
all1 と all2 の実行結果の違いを見てもわかるように、ワイルドカード、リダイレクト、パイプなどのシェルの特殊文字を使っているかどうかによって、サブシェルを呼ぶか、make が直接実行するかが変わる点は注目に値する。
make がサブシェルを呼ぶ場合、makefile 内で明示的に変数 SHELL を書きかえない限りは、 /bin/sh を呼ぶ。
Redhat 系ならば /bin/sh はbash へのシンボリックリンクだが、Ubuntu や Mint は dash へのシンボリックリンクになっているので、前述のように echo の動作が変わってくることになり、環境によっては期待通りに動いてくれないかもしれない。
環境によっては /bin/sh がシンボリックリンクではなく、本物の Bourne Shell なこともあるだろう。
対策として、 ECHO=/bin/echo のように変数を用意し、 $(ECHO) を使用することで、常に /bin/echo を実行するようにするということが考えられる。
サポートするビルド環境を、Linux などの単一のプラットフォームに限定するならば、これでもよい。
だが、 /bin/echo の仕様はプラットフォームごとに結構違うので、別のプラットフォームに移植するときに問題になり、ポータビリティには欠けると思う。
例えば、Linux の /bin/echo は -e オプションを解釈するが、FreeBSDの /bin/echo は解釈しない。
また、echo の改行を抑制するためには、Linux や FreeBSD では -n オプションを使用するが、Solaris や HP-UX は
echo "hoge\c"
のように \c で改行を抑制するようだ。
そういうわけで、多様なプラットフォームへの対応しないといけない場合、
Makefile に
SHELL=/bin/bash
と書いておき、常にbashビルトインのechoを使わせるようにするのがいいのではないかと思った。
(本当にこれで大丈夫なのかは確認していないのですが。。)
(本当にこれで大丈夫なのかは確認していないのですが。。)
ただし、その場合、make が直接コマンドを実行するという最適化は行われなくなる。
まあ、一番良いのは、あまりマニアックなオプションは使わないにこしたことはないです。
まあ、一番良いのは、あまりマニアックなオプションは使わないにこしたことはないです。
2012年7月15日日曜日
Zenbook Prime フリーズ問題
先日、Zenbook Prime (UX21A-K1256) を購入しました。
リカバリーディスクを作ったあと、さっそくWindows 7 を削除し、Ubuntu 12.04 LTS Desktop 64bitをインストールしました。
タッチパッドの右クリックが効かない(左クリックと同じになる)という問題はあるものの、自分はBluetoothマウスを使用するので、さほど問題にはなりません。
気に入って使い出したのだが、しょっちゅうフリーズする。
・電源入れて使い始めてすぐにフリーズしたことがあるので、熱問題ではないと思う。
・フリーズすると、急に熱くなって、ファン音がうるさくなる。
・フリーズすると、マウスポインタは止まり、Alt + SysRq + R + S + E + I + U + B も反応しません。
もしかしてハズレ引いてしまったのかな。
Windows7のまま使っていてフリーズ多発ならメーカーに文句も言えるが、OS入れ替えちゃってるし、クレームは言いづらいよな〜。
試行錯誤しています。
リカバリーディスクを作ったあと、さっそくWindows 7 を削除し、Ubuntu 12.04 LTS Desktop 64bitをインストールしました。
タッチパッドの右クリックが効かない(左クリックと同じになる)という問題はあるものの、自分はBluetoothマウスを使用するので、さほど問題にはなりません。
気に入って使い出したのだが、しょっちゅうフリーズする。
・電源入れて使い始めてすぐにフリーズしたことがあるので、熱問題ではないと思う。
・フリーズすると、急に熱くなって、ファン音がうるさくなる。
・フリーズすると、マウスポインタは止まり、Alt + SysRq + R + S + E + I + U + B も反応しません。
もしかしてハズレ引いてしまったのかな。
Windows7のまま使っていてフリーズ多発ならメーカーに文句も言えるが、OS入れ替えちゃってるし、クレームは言いづらいよな〜。
試行錯誤しています。
OS再インストールしてみた。
→ 効果なし。
Ubuntu 12.04 LTS Desktop 32bit をインストールしてみた。
→ やっぱりフリーズ。
Linux Mint 13 Maya をインストールしてみた。
→ やっぱりフリーズ。Mint もベースは Ubuntu だからそりゃそうか。
Fedora 17 64bit をインストールしてみた。
→ フリーズせずに、使えています。
<解決>
コメントでいただいたリンク先を読むと、Ubuntu の kernel 3.2.0-26でWi-Fi接続時にkernel panicが発生する問題があるそうな。
現時点ではkernel 3.2.0-27にアップデートされているようです。
しばらく使っていてもフリーズしませんので、大丈夫のようです。ありがとうございました。
→ 効果なし。
Ubuntu 12.04 LTS Desktop 32bit をインストールしてみた。
→ やっぱりフリーズ。
Linux Mint 13 Maya をインストールしてみた。
→ やっぱりフリーズ。Mint もベースは Ubuntu だからそりゃそうか。
Fedora 17 64bit をインストールしてみた。
→ フリーズせずに、使えています。
<解決>
コメントでいただいたリンク先を読むと、Ubuntu の kernel 3.2.0-26でWi-Fi接続時にkernel panicが発生する問題があるそうな。
現時点ではkernel 3.2.0-27にアップデートされているようです。
しばらく使っていてもフリーズしませんので、大丈夫のようです。ありがとうございました。
登録:
投稿 (Atom)