自分の仕事へ値段をつける3つの方法

今日ある人とお話をしている中で、「どうやって自分の仕事に対して値段を設定しているのか?」ということを聞かれました。

# 一応補足しておくと、私はフリーランスのソフトウェアエンジニアをやっているので、自分のお仕事の値段は自分で決めています。

私がフリーランスになった当初も、同じように悩んだことがあったので、
詳細はぼかしつつもどういったロジックで値段を決めているかだけ、書いてみようと思います。
これからフリーランスになる人や、転職を考えている人への参考程度に読んで頂ければと思います。

ちなみに、3つほど計算方法を書きますが、相手や状況によってどの数字を出すかは変わります。
もちろん仕事の内容や契約によっても変わります。
ここに載せたものは、あくまで概算としてのものだという点にご注意ください。

1. 生活に必要な金額から計算する(最低ラインを決める)

ざっくり言うと、生活のための消費や貯蓄などに事業支出や税金などを加えて、そこに利益を載せた上でさらにマージンを乗っけた金額になります。
だいたいどんな計算をするかというと、下図のようになります。

f:id:crimsonwoods:20130212221349p:plain

見たまんまですね。
これが生活するのに最低限必要なラインになります。
通年または単月など見方はあるものの、平均的にはここで定めた数字が生活を維持するための最低限の金額になります。

2. 業界の相場から計算する(平均ラインを決める)

この数字は、相手が必要としている知識や技術がよく判らない場合や、
初めてお話をする時に「単価っていくらですか?」と聞かれた場合などに、
だいたいの目安としてお話することが多い数字になります。

景気の影響をだいぶ受けるのですが、職種や業種ごとのなんとなくの相場みたいなものがあります。
たとえば、『N年目以降の業務系プログラマで実装のみなら月単価XX万円』みたいなものです。
これは簡単に計算して出せるものではないので、営業をやっている知り合いからそれとなく聞き出すとか、
特定派遣をやっている会社の求人情報を見ておおよその数字を出すなどの方法で、ざっくりとした値段を決めます。

そうして求めた平均額をベースに、自分の能力を含めて金額を計算します。
この金額を出す場合には、「平均的なエンジニアに比べて自分は~だからN倍の生産性がありますよ」ということを説明します。

希望収入平均単価 × 生産効率 + α

『+α』の部分は、マージンだったり、年齢給的なものだったりです。

3. 技術や知識に値段をつける(最高ラインを決める)

これは明確な計算方法があるわけではないのですが、
私が所有している知識や技術の優位性、仕事の緊急度合いなどによっては、それなりの額を考えます(例えば相場の1.5倍とか)。
とはいえ、今までのところ個人事業主として交渉する場で、この金額を出してお話をしたことはありません。
いつか「予算はいっぱいある!」とか言われるようなことがあれば、それとなく提示してみようかなーと思っています。


とまぁこんな感じで考えたりしています。
クライアントとの付き合いが長い場合は、相手の予算感などから金額を出したりするようなケースもありますが、
それはまた別の話ということで。
以上、自分の仕事にどうやって値段をつけているか?というお話でした。

「就社すんな」についての補足

先日の高専カンファレンス in 沼津2で行われたディスカッションに、ゲストとして参加してきました。

ディスカッションでは、いくつかのテーマについて他のゲストの方も交えてお話をさせて頂いたのですが、
テーマの中のひとつに高専生の就職に関するものがありました。
その時の内容について、限られた時間での話で、文脈が不明瞭な部分もあったと思います。
このエントリでは、もう少しきちんとした文章という形で、改めてお伝えしたいと思います。

自信を持った就職をするためには

回答

就社しないでください。

前置き

「就社」そのものは悪ではありませんし、
「就社」そのものを否定するつもりはありません。

ディスカッションの中でも話ましたが、
社会の中で生きていく中で大事なことの一つに「Priority(優先度)」の付け方があります。
世の中には「就社」の優先度を高く設定する人もいますし、そうではない人もいます。

今回お話させて頂いたのは、「就社」がいまいちピンと来ていなさそうな学生が対象だろう、
そう私の方で判断して喋らせて頂きました。

就社とは

会社に就く(かいしゃにつく)という意味の言葉として使いました。
職業に就く(しょくぎょうにつく)という就職に対して、
特定の企業・会社・法人・組織など(以降単に会社と表記します)に就くという意味合いを強調しています。

もう少し具体的に言うと、就社というのは、会社の名前(ブランド)やイメージ、給与水準、福利厚生など、
職業や業務内容とは別の基準で会社を選び、その会社に就業することです。

「就社」になる理由

多くの学生は会社というものを知りません。
世の中にどんな職業があるのかを知りません。
どうやったらお金を稼げるのかを知りません。

そんな学生の手元にやってくる企業の求人票には、求人対象の業務内容の詳細は書かれていないのです。
そこに書いてあるのは、その会社の事業領域に関する若干の情報と、
多くはWebで調べればすぐ判るような企業概要情報、そして求人のための最低限明示される条件です。

会社に入ってどんな仕事をしなければならないのか、
その仕事にはどんな知識が必要なのか、
そもそも会社に入ってからどの部門に配属になるのかすらも判らない。
判らないだらけの中で、それでもどこか選んで就職活動をしなければならない。
それが学生にとっての現実です。

そうした背景から、企業の差別化を行う基準が業務内容から乖離した部分に定められてしまうのではないかと思っています。

見えない未来

ある程度規模の大きい企業に入社すると、
まずどの部門に配属になるかで、希望する業務に就けるかどうかの分岐点が来ます。
時期については企業に依るのですが、早ければ入社から半年とたたずに将来を決める一つの分岐点がやってくるわけです。
そして、その分岐点では、今後歩む道を決めるのは自分ではなく、
ろくに顔も合わせたことのなく、自分のことを知りもしない会社の中の「誰か」なわけです。

規模の小さい企業でも、実際に自分に任される業務内容というのは、
その会社に入ってみるまで明かされないことがあります。

会社に入ってさえ、自分の将来に対する不安が消えず、本当にこの会社に入って良かったのか?
自分が情熱を傾けれるような仕事が与えられるのだろうか?
与えられた仕事が自分に合わなかったらどうしようか?
そうした不安感を、就活の段階で拭い去ることは難しいかもしれません。

未来を見るためのツール

不安を拭い去るために必要なことは、思い切りや自己の装飾ではありません。
未来を見るために必要なツールは、「本当に必要なものは何か?」を見定める力と、「前に進む意志」です。
ディスカッションの場では「Priority(優先順位)」と「Motivation(動機)」という言葉を使用しています。

自分に与えられた、または自分が得られる可能性の中から、どの可能性を選ぶのか?
そしてその可能性を選ぶ基準となる動機を何に求めるのか?
これが決められれば、霞のかかっていた未来を、ほんの少しだけ見通すことができるようになります。
そして何より、自分で決めるという意志を持つことで、不用意に惑わされずに済むようになります。

会社や職業を決める前に、社会に出てから自分がどうやって生きていくのか、
何の価値を自分の中で最大化させたいのか、
学生という時期の評価基準で構わないので、まずそうした部分と向き合うのが良いのではないかと思います。

可能性を絞り込む

「就社」をする場合、優先順位を決めるための評価軸が複数でてくることがあると思います。
たとえば企業のイメージや給与、就業地、勤務体系、それから業態など、複数の項目を見て総合的に判断するということがよくあると思います。
こうした場合、迷いが入り込む余地が多くなってしまい、本来考えるべき「Priority」や「Motivation」が曖昧になってしまいます。
そうした場合、より迷う余地の少ない評価軸、つまり「職業」や「職種」を評価軸に導入し、その優先度を最大化することで、曖昧さを回避することができます。
もちろん「職業」や「職種」以外の評価軸を導入しても構いません。
ここでは話の本筋ではないので、特に触れませんが。

職業を知る

世の中にどんな職業があって、大人たちがどうやってお金を稼いでるのかを知りましょう。
学校の外に出て、そこで出会った大人の人に聞いてみてください。
「どんなお仕事をしてお金稼いでるんですか?」
「普段会社でどんなことをしているんですか?」
そうやって世の中にどんな仕事があるのか、いろんな人に尋ねてみてください。
高専カンファレンスに参加している先輩方に、機会があれば是非聴いてみてください。

最後に

以前にどこかで書いたような文書を書いて、最後にします。

社会に出てからの人生のうち、仕事に費やす時間というのはとても多いのです。
例えば20歳で就職して65歳まで会社勤めをしたとすると、45年間は何かしら仕事をすることになるわけです。
毎月の平均的な勤務時間が160時間だとすると、毎年1920時間を仕事に費やすわけです。
一年は8760時間ですから、一年の2割以上は仕事に費やすわけです。
残業や休日出勤、長期出張による勤務時間の増加や、通勤のための時間も加えれば、
実際にはもっと多くの時間が、それこそ3割程度を仕事に費やしている人もいるかもしれません。
さらに、一日の活動時間を考えると、睡眠を除いた活動可能な時間は、睡眠時間が8時間の人で16時間です。
つまり45年間という膨大な時間のうち、約半分が仕事のために費やされるのです。

それだけの時間を迷ったまま、納得のいかないまま、楽しめないまま過ごすのは勿体無いと思います。
世の中には「仕事はつらいもんだ」という人もいますが、人生の半分を「辛い時間」で終わらせるのが本当に良いことだとは私には思えません。
是非、自分の納得の行く職業を、仕事を探してください。

高専カンファレンス in 沼津2に参加してきたよ

表題の件でいろいろ思うところがあったので、ちゃんと記録に残しておこうと思います。

まずは開催おめでとうございます。
そして無事に会が終了できたのは、運営スタッフを始めとした参加者の皆さんのご協力の賜物であり、
大変有り難く、また幸運に恵まれた結果であると思っております。
スタッフ各位、発表者各位、そして参加者の皆々様ありがとうございました。
そしてお疲れ様でした。

今回の開催は、当初開催までの期間の短さなどから心配していた部分もあったのですが、
蓋を開けてみれば心配がただの杞憂であったことが判りました。
本会においては細かい部分に目をつむれば(運営的な面のお話として)、概ね良かったのではないかと思っています。
各発表についての論評は、本記事の本題ではないので、ここでは差し控えさせて頂きます。

といったところで本題です。
このエントリの趣旨は、以下の2つです。

  1. ホストとゲストという立場を知ろう
  2. 制御されない自由はただの暴走でしかない


詳細を語る前に一応断っておくと、内輪感がどうだとか、
コミュニケーションがどうだとか、そういう話はこのエントリの本筋ではありません。
そういうのを期待していた人は各個人のブログにでも好きなだけ書いてください。


「ホスト」と「ゲスト」という立場

といったところで、まず1つ目の「ホストとゲストという立場」についてです。

高専カンファレンスの運営は、各開催の実行委員に委ねられており、
個別の開催に関する実務的な権限に関しても、原則として各運営の裁量に任されています。
そしてカンファレンスを形作るのは運営だけではなく、発表者や参加者が一体となって成り立っています。
ここで言いたいことは、参加者はお客さんではないとか、スタッフも参加者も垣根は無いとか、そういうことではありません。
むしろ逆で、スタッフと他の参加者は明確に違うんですよということを理解してもらいたいと思っています。
会場を押さえたり、場の運営をしたりする以上、スタッフには参加者に支持を出す権限がありますし、
第一義的にスタッフは支障が出ないように場をコントロールすることがそもそもの仕事なわけです。
参加者が起こした問題は、それを抑えられなかったスタッフの責任ですし、運営側の最高責任者の不手際なわけです(参加者がどうであれ社会的な道理で言えば運営者の責任であることは明白です)。

今回の開催ですごく気になったのは、ホストがゲストに対して、満足な対応ができていたのか?という点です。
一人で寂しそうにしている人がいたら話しかけてみるとか、そういう簡単なことで良いんです。
そういうことやれてましたか?初めて参加した人が、居心地の良い空間づくりができていたでしょうか?
ホストとして、礼節をふまえた上で恥ずかしくない対応ができていましたか?
あなたがたのしていたことは、ただの独り善がりでは無かったですか?

「制御されない自由」はただの「暴走」でしかない

私はできるかぎり自由を尊重したいです。
それがたとえ多少の危険や問題を抱えていたとしても、自由であることの利益が大きいのであれば、
その価値を可能な限り優先したいと思います(具体的に何がどうだって話は書けないこともあるので書きません)。
ただ、その自由がいきすぎてしまえば、時に無作為に人を傷つけたり、何らかの災禍を引き寄せたりしてしまいます。
楽しさや自由の裏側で、それを支えるべき道理があるのだということをきちんと理解してください。
若いうちはノリや勢いが大事なこともあるでしょう。そういうときは年嵩の人間がきちんと手綱を握りましょう。
それができる体制や信頼関係を作るように努力してください。
もしそうしたことが出来ないようであれば、たとえどんなに優れた人であっても、人や組織を率いるべきではありません。
厳しいことを言うようですが、今回の開催の一場面を切り取って見ると、子供の集まりでしか無いように見えました。
子供の集まりがやりたいなら別の形で、誰の迷惑にもならないようにやってください。

まとめ

線のひき方を間違えないでください。
線を超えるのは、線をひいた後でいくらでもできます。
まずちゃんと線をひくことを覚えましょう。

Android NDKについて、年末だしいろいろ棚卸しするよ

需要があるか判らないけど、自分のためにも書いておきます。

NDKとは?

Androidでの開発において、プロセッサネイティブなコードを使用して処理の高速化などを行う場合、
Androidが公式に提供しているNDK(Native Development Kit)を使用します。
2012年12月31日現在での最新バージョンはr8dというものになります。

ダウンロードはこちらから行えます

NDKで出来る事

  • CやC++でコードを書くことができます。
  • コンパイラとしてgcc-4.4.3, gcc-4.6, gcc-4.7, clang-3.1を利用できます。
  • プロセッサのアーキテクチャに依存した命令を書くことができます(NEONとか)。
  • JNIを通して、DalvikVMからコードを相互に呼び出すことができます。
  • armeabi, armeabi-v7a, x86, mips用それぞれのコードを生成することができます。
  • NativeActivityを使用してGUIアプリケーションを記述できます。
  • Linuxカーネルのシステムコールを利用したコードを記述できます(forkしたりできます)。
  • Androidの標準のものやサードパーティの既存のライブラリをStatic LibraryまたはShared Libraryとして利用できます。
  • DalvikVMのヒープサイズ制限の外側でメモリを使用できます。

NDKについて知っておくと、そのうち使える日が来るかもしれない知識

NDKのコマンドライン編

  • NDKによるビルドは、NDKパッケージ中に存在する「ndk-build」を使って行います。「ndk-build」にはGNU makeに渡すのと同じコマンドライン引数を指定できるので、並列ビルド用の「-j2」などを指定することができます。
  • buildが上手く行かない場合には「$ ndk-build -n」などとして、実際に使用されるコマンドライン文字列を出力させながら問題点を見つけることができます。
  • NDKのパッケージ中にはビルド済みの「gdbserver」が同梱されています。gdbserverを利用することで、ネイティブな部分に対してデバッガを利用した解析を行うことができます。gdbserverの操作方法についての解説は省きます。
  • まさか手作業で書いてる人はいないと思いますが、JNI用のヘッダファイルを自動生成するのには「javah」コマンドを利用できます。javahはJDKに入っているコマンドラインツールです。

ファイル構成編

  • NDKを利用する場合でも、Androidのプラットフォームのバージョンに依存する部分が存在します。NDKでの開発の際は、「default.properties」または「project.properties」に"target=android-XX"(XXにはAndroidAPIバージョンの数字が入ります)と記載することで、バージョンを設定します。
  • アプリケーション全体に渡る設定は「Application.mk」に記述します。「APP_ABI」や「APP_OPTIM」などが該当します。詳細については、NDKパッケージ中の「docs/APPLICATION-MK.html」に記載されています。
  • モジュールをビルドするためのMakeファイルの代わりになるのが「Android.mk」です。Androidのビルドシステムが用意しているマクロを利用してビルドを行う形になります。通常のMakefileと同様に「include」したり、シェルの機能を呼び出すこともできます。Static Library, Shared Library, Executable Binaryの3種類それぞれごとに、モジュールという形でビルド方法を記述していきます。詳細については、NDKパッケージ中の「docs/ANDROID-MK.html」に記載されています。

C編

  • C言語消えてくれるともっと幸せになれるのですが・・・。ちなみに「-std=c99」をつければC99が使えます。

C++

  • C++のランタイムライブラリには「system」という名前の標準のもの(例外やRTTIなどの機能が制限されています)と、「GAbi++」というもの、その他にSTL系のライブラリが存在します。
  • STLライブラリにはSTLport系の「stlport_static」、「stlport_shared」、GNU STLの「gnustl_static」, 「gnustl_shared」があります。詳細はNDKのインストールディレクトリ中の「docs/CPLUSPLUS-SUPPORT.html」に記載されています。それぞれ例外のサポートなどが異なるので注意が必要です。
  • 上記のライブラリの指定は、「Application.mk」の「APP_STL」の値として記述します。
  • 例外を使用する場合は、APP_STLに例外をサポートしているライブラリを選択した上で、「Application.mk」の「APP_CPPFLAGS」に"-fexceptions"を付け加えます(Android.mkの中で個別に指定しても構いません)。
  • RTTIを使用する場合は、APP_STLにRTTIをサポートしているライブラリを選択した上で、「Application.mk」の「APP_CPPFLAGS」に"-frtti"を付け加えます(Android.mkの中で個別に指定しても構いません)。
  • C++11を使用する場合は、「Application.mk」の「APP_CPPFLAGS」に"-std=c++0x"を付け加えます(Android.mkの中で個別に指定しても構いません)。GNU拡張版のC++11を使用する場合は"-std=gnu++0x"を指定してください。

JNI編

  • 一度に作成できるローカルリファレンスの最大数はせいぜい256個程度までのようです。
  • pthread_createしたスレッド内部でFindClassなどを使用すると、なぜかNoClassDefFoundになるので、pthread_createする前にFindClassなどをする必要があります。

その他

  • Androidが使用しているlibcは「bionic」というもので、Linuxのlibcとは別物になります。従って、LinuxではサポートされているのにAndroidではサポートされていない関数が存在します。
  • gcc4.7を使用する場合は、「Application.mk」の「NDK_TOOLCHAIN_VERSION」に"4.7"を指定します。
  • 大抵の環境では、メモリを食い過ぎるとネイティブプロセスであってもSIGKILLで殺されます。
  • プロセス間通信やプロセスの複製、デバイスドライバに対するioctlの発行など、いろんなことができます。
  • Android標準で提供されてるShared Libraryを、NDK環境でリンクして使いたい場合は、「Android.mk」の「LOCAL_LDFLAGS」などに上手いこと書くか、ダミーのモジュールを定義して、「LOCAL_SHARED_LIBRARIES」などに指定した上で、実機などから吸い出したライブラリを「obj/local/xxx」(xxxにはarmeabiなどが入ります)などに配置します。

ARM Linux環境でptrace使ってバックトレース

タイトルそのまんまの記事です。

やりたいことは、ARMの上で動いているLinuxデバッグしたい。
デバッグといっても、デバッガ突っ込めるわけじゃない(gdbserverとか使えない)環境で、
とりあえずSIGSEGVくらいは何とかして潰したいよねという感じ。

で、じゃぁどうにかしましょうということで、ptraceを使って異常終了をキャッチして、
その場でえいやーっとバックトレースまで吐き出すコードを書いてみました。
バックトレースを解析するところは、libunwindを使っています。
libunwindありがたやありがたや。

もちろんARM環境限定です。
ということでコードは↓にあります。


https://gist.github.com/4122796


ご自由にご利用ください。

# 動かないとかコンパイルできないとかは、いつもどおり自己責任で宜しくお願いします。

Android用にMonoをbuildする

AndroidスタンドアロンのMonoを使いたかったのでMonoをbuildしました。
その手順を忘れないように書いておきます。

対象となるMonoのバージョンは2.10.5です。
2.10.5の理由は手元のUbuntuのapt-getでinstallされたのが2.10.5だったからです。

以下の手順でbuildを行います。

  1. Androidのソースツリーを取得
  2. externalの下に「androidmono」という名前でディレクトリを作成
  3. external/androidmonoの中でgit cloneなりtarを展開するなりしてMonoのソースを展開
  4. 展開したMonoのディレクトリを「mono」という名前に変更
  5. Android.mkとApplication.mkを作成
  6. パッチを適用する
  7. ビルドに必要なヘッダファイル群を展開する

という感じです。

Android.mkの中身はこんな感じですね。

LOCAL_PATH := $(call my-dir)
MONO_PATH := $(LOCAL_PATH)/mono

MONO_ASSEMBLY_DIR := \"/data/local/mono/lib/\"
MONO_CONFIG_DIR   := \"/data/local/mono/bin/\"
MONO_BINARY_DIR   := \"/data/local/mono/bin/\"

MONO_CFLAGS := -DMONO_ASSEMBLIES=$(MONO_ASSEMBLY_DIR) \
               -DMONO_CFG_DIR=$(MONO_CONFIG_DIR) \
               -DMONO_BINDIR=$(MONO_BINARY_DIR) \
               -DHAVE_CONFIG_H -DARM_FPU_VFP -D_REENTRANT \
               -DPAGE_SIZE=4096 -DS_IWRITE=S_IWUSR \
               -DPLATFORM_ANDROID -D__linux__ -DREDIRECT_MALLOC=GC_malloc \
               -DHAVE_BOEHM_GC -DHAVE_GC_H -DUSE_INCLUDED_LIBGC -DHAVE_GC_GCJ_MALLOC -DHAVE_GC_ENABLE \
               -D_GNU_SOURCE -DUSE_MMAP -DUSE_MUNMAP -D_FILE_OFFSET_BITS=64 -DNO_UNALIGNED_ACCESS \
               -D__environ=environ

MONO_LIBGC_CFLAGS := -DPACKAGE_NAME=\"libgc-mono\" -DPACKAGE_VERSION=\"6.6\" -DPACKAGE_STRING=\"libgc-mono\ 6.6\" \
                     -DGC_LINUX_THREADS=1 -D_REENTRANT=1 \
                     -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 \
                     -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 \
                     -DLT_OBJDIR=\".libs/\" -DSILENT=1 -DNO_SIGNALS=1 -DNO_EXECUTE_PERMISSION=1 \
                     -DGC_GCJ_SUPPORT=1 -DJAVA_FINALIZATION=1 -DATOMIC_UNCOLLECTABLE=1 -D_IN_LIBGC=1 \

MONO_INCLUDES := $(MONO_PATH)/ \
                 $(MONO_PATH)/mono/ \
                 $(MONO_PATH)/eglib/src/ \
                 $(MONO_PATH)/mono/mini/ \
                 $(MONO_PATH)/libgc/include \
                 $(LOCAL_PATH)/configs \
                 $(LOCAL_PATH)/configs/eglib \
                 $(LOCAL_PATH)/configs/mono/mini \
                 $(LOCAL_PATH)/configs/mono/arch/arm \
                 bionic/linker

MONO_LDLIBS := -ldl

# build 'libeglib'
include $(CLEAR_VARS)

LOCAL_MODULE := eglib
LOCAL_MODULE_TAGS := eng
LOCAL_PATH := $(MONO_PATH)/eglib/src
LOCAL_SRC_FILES := garray.c gerror.c ghashtable.c gmem.c goutput.c \
    gstr.c gslist.c gstring.c gptrarray.c glist.c gqueue.c gpath.c \
    gshell.c gspawn.c gfile.c gfile-posix.c gpattern.c gmarkup.c \
    gutf8.c gunicode.c gdate-unix.c gdir-unix.c gfile-unix.c \
    gmisc-unix.c gmodule-unix.c gtimer-unix.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libmonoutils'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := monoutils
LOCAL_MODULE_TAGS := eng
LOCAL_PATH := $(MONO_PATH)/mono/utils
LOCAL_SRC_FILES := mono-semaphore.c mono-md5.c \
    mono-sha1.c mono-logger.c mono-codeman.c dlmalloc.h dlmalloc.c \
    mono-counters.c mono-compiler.h mono-dl.c mono-dl.h \
    mono-internal-hash.c mono-internal-hash.h \
    mono-io-portability.c mono-io-portability.h monobitset.c \
    mono-math.c mono-mmap.c mono-mmap.h mono-proclib.c \
    mono-proclib.h mono-time.c mono-time.h strtod.h strtod.c \
    strenc.h strenc.c mono-uri.c mono-poll.c mono-path.c \
    mono-stdlib.c mono-property-hash.h mono-property-hash.c \
    mono-value-hash.h mono-value-hash.c freebsd-elf_common.h \
    freebsd-elf32.h freebsd-elf64.h freebsd-dwarf.h dtrace.h \
    mono-filemap.c mono-networkinterfaces.c mono-error.c \
    mono-publib.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -ldl

include $(BUILD_STATIC_LIBRARY)

# build 'libmonoruntime'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := monoruntime
LOCAL_PATH := $(MONO_PATH)/mono/metadata
LOCAL_SRC_FILES := runtime.c \
    mono-basic-block.c mono-wsq.c mono-hash.c reflection.c object.c object-internals.h \
    icall.c icall-def.h char-conversions.h decimal.c decimal.h \
    boehm-gc.c sgen-gc.c sgen-gc.h gc.c gc-internal.h method-builder.h method-builder.c \
    mono-mlist.c mono-mlist.h tabledefs.h threads-types.h threadpool-internals.h \
    file-io.c file-io.h socket-io.c socket-io.h exception.c exception.h \
    debug-mono-symfile.h debug-mono-symfile.c mono-debug.h mono-debug.c \
    mono-debug-debugger.h mono-debug-debugger.c profiler-private.h attach.h attach.c \
    rand.h rand.c security.c security.h security-core-clr.c security-core-clr.h \
    string-icalls.c string-icalls.h sysmath.h sysmath.c process.c process.h \
    environment.c environment.h locales.c locales.h normalization-tables.h \
    filewatcher.c filewatcher.h culture-info.h culture-info-tables.h \
    security-manager.c security-manager.h console-io.h console-unix.c \
    coree.c coree.h domain.c domain-internals.h opcodes.c cil-coff.h \
    metadata.c metadata-internals.h number-formatter.h verify.c verify-internals.h \
    mono-endian.c mono-endian.h mono-config.c loader.c \
    class.c class-internals.h wrapper-types.h mempool.c \
    mono-perfcounters.c mono-perfcounters.h mono-perfcounters-def.h \
    debug-helpers.c mempool-internals.h metadata-verify.c \
    mono-cq.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libmonoruntimearm'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := monoruntimearm
LOCAL_MODULE_TAGS := eng
LOCAL_PATH := $(MONO_PATH)/mono/metadata
LOCAL_SRC_FILES := \
    monitor.c marshal.c threadpool.c threads.c appdomain.c \
    profiler.c cominterop.c assembly.c image.c null-gc.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libwapi'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := wapi
LOCAL_MODULE_TAGS := eng
LOCAL_PATH := $(MONO_PATH)/mono/io-layer
LOCAL_SRC_FILES := access.h atomic.c atomic.h \
    collection.h context.c context.h critical-sections.c \
    critical-sections.h critical-section-private.h error.c error.h \
    events.c events.h event-private.h handles.h \
    handles-private.h io.h io-portability.c io-portability.h \
    io-private.h io-layer.h macros.h messages.c messages.h misc.c \
    misc-private.h mutexes.c mutexes.h mutex-private.h \
    mono-mutex.c mono-mutex.h mono-spinlock.h processes.c \
    processes.h process-private.h security.c security.h \
    semaphores.c semaphores.h semaphore-private.h shared.c \
    shared.h sockets.c sockets.h socket-private.h \
    socket-wrappers.h status.h system.c system.h \
    threads.h thread-private.h timefuncs.c timefuncs.h \
    timefuncs-private.h types.h uglify.h versioninfo.c \
    versioninfo.h wait.c wait.h wapi_glob.h wapi_glob.c locking.c posix.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libwapiarm'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := wapiarm
LOCAL_MODULE_TAG := eng
LOCAL_PATH := $(MONO_PATH)/mono/io-layer
LOCAL_SRC_FILES := collection.c io.c wthreads.c handles.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libgc'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := gc
LOCAL_MODULE_TAG := eng
LOCAL_PATH := $(MONO_PATH)/libgc
LOCAL_SRC_FILES := allchblk.c blacklst.c \
    checksums.c dyn_load.c \
    headers.c mark.c \
    new_hblk.c pcr_interface.c \
    ptr_chck.c real_malloc.c solaris_pthreads.c \
    solaris_threads.c specific.c stubborn.c backgraph.c \
    win32_threads.c pthread_stop_world.c \
    darwin_stop_world.c mach_dep.c
LOCAL_CFLAGS := $(MONO_CFLAGS) $(MONO_LIBGC_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libgcarm'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := gcarm
LOCAL_MODULE_TAG := eng
LOCAL_PATH := $(MONO_PATH)/libgc
LOCAL_SRC_FILES := alloc.c dbg_mlc.c finalize.c gc_dlopen.c gcj_mlc.c malloc.c \
    mallocx.c  mark_rts.c obj_map.c os_dep.c misc.c reclaim.c pthread_support.c typd_mlc.c
LOCAL_CFLAGS := $(MONO_CFLAGS) $(MONO_LIBGC_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libmini'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := mini
LOCAL_MODULE_TAG := eng
LOCAL_PATH := $(MONO_PATH)/mono/mini
LOCAL_SRC_FILES := mini.c method-to-ir.c \
    xdebug.c decompose.c \
    jit-icalls.c trace.c \
    mini-arch.h dominators.c cfold.c regalloc.c \
    helpers.c liveness.c ssa.c abcremoval.c ssapre.c \
    local-propagation.c driver.c debug-mini.c \
    linear-scan.c aot-runtime.c \
    graph.c mini-exceptions.c mini-codegen.c mini-trampolines.c \
    declsec.c wapihandles.c branch-opts.c \
    mini-generic-sharing.c regalloc2.c simd-intrinsics.c \
    unwind.h unwind.c mini-posix.c \
    mini-arm.c exceptions-arm.c tramp-arm.c image-writer.c \
    dwarfwriter.c mini-gc.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libminiarm'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := miniarm
LOCAL_MODULE_TAG := eng
LOCAL_PATH := $(MONO_PATH)/mono/mini
LOCAL_SRC_FILES := aot-compiler.c debugger-agent.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)

include $(BUILD_STATIC_LIBRARY)

# build 'libmono'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := libmono
LOCAL_MODULE_TAGS := eng
LOCAL_PATH := $(MONO_PATH)/mono/mini
LOCAL_SRC_FILES := mini.c method-to-ir.c \
    xdebug.c decompose.c \
    jit-icalls.c trace.c \
    mini-arch.h dominators.c cfold.c regalloc.c \
    helpers.c liveness.c ssa.c abcremoval.c ssapre.c \
    local-propagation.c driver.c debug-mini.c \
    linear-scan.c aot-runtime.c \
    graph.c mini-exceptions.c mini-codegen.c mini-trampolines.c \
    declsec.c wapihandles.c branch-opts.c \
    mini-generic-sharing.c regalloc2.c simd-intrinsics.c \
    unwind.h unwind.c mini-posix.c \
    mini-arm.c exceptions-arm.c tramp-arm.c image-writer.c \
    dwarfwriter.c mini-gc.c
LOCAL_PRELINK_MODULE := false
LOCAL_CFLAGS := $(MONO_CFLAGS) -fPIC
LOCAL_C_INCLUDES := $(MONO_INCLUDES)
LOCAL_WHOLE_STATIC_LIBRARIES := monoutils gcarm monoruntime
LOCAL_STATIC_LIBRARIES := wapiarm monoruntimearm eglib gc wapi mini miniarm
LOCAL_LDFLAGS := -Wall -L$(SYSROOT)/usr/lib -llog -ldl -lm -lc
#LOCAL_STRIP_MODULE := false

include $(BUILD_SHARED_LIBRARY)

# build 'mono'
include $(CLEAR_VARS)

LOCAL_ARM_MODE := arm
LOCAL_MODULE := mono
LOCAL_MODULE_TAGS := eng
LOCAL_PATH := $(MONO_PATH)/mono/mini
LOCAL_SRC_FILES := main.c
LOCAL_CFLAGS := $(MONO_CFLAGS)
LOCAL_C_INCLUDES := $(MONO_INCLUDES)
LOCAL_SHARED_LIBRARIES := libmono
LOCAL_LDFLAGS := -llog -ldl -lm -lc

include $(BUILD_EXECUTABLE)

長いですね・・・。あとでgithubかなんかに突っ込んで終わりにしたいですね。

Application.mkは適当に

APP_ABI := armeabi armeabi-v7a

とか書いておけば良いです。

あてるパッチはこんな感じです。

diff --git a/libgc/dyn_load.c b/libgc/dyn_load.c
index e4be3c7..d8ce7ec 100644
--- a/libgc/dyn_load.c
+++ b/libgc/dyn_load.c
@@ -99,7 +99,9 @@
 # if !defined(OPENBSD)
 #   include <elf.h>
 # endif
+# if defined(HAVE_LINK_H)
 #   include <link.h>
+# endif
 #endif

 /* Newer versions of GNU/Linux define this macro.  We
diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c
index a3c5746..867e437 100644
--- a/mono/mini/aot-runtime.c
+++ b/mono/mini/aot-runtime.c
@@ -38,8 +38,12 @@
 #endif

 #ifdef HAVE_DL_ITERATE_PHDR
+#ifdef PLATFORM_ANDROID
+#include <linker.h>
+#else
 #include <link.h>
 #endif
+#endif

 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/class.h>
@@ -59,6 +63,21 @@
 #include "mono/utils/mono-compiler.h"
 #include <mono/utils/mono-counters.h>

+#if defined(PLATFORM_ANDROID)
+#ifdef PSR_c
+#undef PSR_c
+#endif
+#ifdef PSR_x
+#undef PSR_x
+#endif
+#ifdef PSR_s
+#undef PSR_s
+#endif
+#ifdef PSR_f
+#undef PSR_f
+#endif
+#endif
+
 #include "mini.h"
 #include "version.h"

diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c
index c15b098..92aa901 100644
--- a/mono/mini/mini-posix.c
+++ b/mono/mini/mini-posix.c
@@ -631,7 +631,7 @@ mono_runtime_syscall_fork ()
    return (pid_t) syscall (SYS_fork);
 #else
    g_assert_not_reached ();
-   return;
+   return -1;
 #endif
 }

これもあとでどっかにファイルおくだけにしたいですね・・・。

さて残りはヘッダなんですが、ソースをそのまま貼り付けるとえらいことになるので、
あとでgithubにでも突っ込んでおきます。
突っ込んだらこの記事も更新するつもりです。

libusbをAndroid用にポーティングする

お仕事で必要があってlibusbをAndroidに持っていくということをやりました。
この記事はlibusbをAndroid用にbuildする方法の備忘録です。

まず、Androidをlibusbにportingするのは先人が既にやっているので、そこを参考にします。
参考URL: http://android.serverbox.ch/?p=151

  1. androidソースコードをもってきます。 -> ここ「Downloading the Source Tree | Android Open Source」を参考に。
  2. androidソースコードをbuildします。
  3. externalの下にlibusbというディレクトリを切ります。
  4. libusbのソースを展開します。現在の最新版は「libusb-1.0.9」です。
  5. "external/libusb"の直下に「Android.mk」を作成します。
  6. "external/libusb/libusb"にも「Android.mk」を作成します。
  7. "external/libusb/libusb/io.c"を修正します。
  8. 「mm」でlibusbをbuildします。

androidのbuildは、もってきたsource codeのトップで

$ source build/envsetup.sh
$ lunch
$ make

とかやってください。

libusbの直下に作成するAndroid.mkはこんな感じです。

LOCAL_PATH := $(call my-dir)
subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, libusb))
include $(subdirs)

元にしているページのAndroid.mkは"subdirs"の頭の"s"が取れてしまっているので注意しましょう。

"external/libusb/libusb"の下に作成するAndroid.mkはこんな感じです。

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS:=-DLIBUSB_DESCRIBE

LOCAL_SRC_FILES:= \
  core.c \
  descriptor.c \
  io.c \
  sync.c \
  os/linux_usbfs.c \
  os/threads_posix.c

LOCAL_C_INCLUDES += \
external/libusb/ \
external/libusb/libusb/ \
external/libusb/libusb/os

LOCAL_MODULE:= libusb
LOCAL_MODULE_TAGS:=eng
LOCAL_PRELINK_MODULE:=false

include $(BUILD_SHARED_LIBRARY)

"libusb-1.0.9"以外のバージョンでは何らかの修正が必要になるかもしれません。
その場合は適宜修正して下さい。
あと、この方法でビルドはできると思いますが、ビルド後のバイナリの動作を保証するものではありません。