Max エクスターナル用 Xcode プロジェクトの詳細

Xcodeプロジェクトにはコンパイルやビルドの設定に関する大規模なコレクションが含まれています。想像できると思いますが、100のMaxエクスターナルには、各々それ自身のプロジェクトが存在します。Cycling'74の仲間はこれらの設定をいじることに多くの時間を費やしています。そして、このSDKで述べているような現在の考え方は、新しいトリックが知られることによって進化し続けるかもしれません。

あなたが開発し、メンテナンスを行なうエクスターナルが存在する場合、使用している設定が適切で堅実なものであることを確認したいと思うことでしょう。

このセクションではMaxエクスターナルを開発するための重要な設定について説明しますが、すべての設定を正しく適切に行なうことを確実にするために、Xcodeで作られた基本的なテンプレートを利用してスクラッチからプロジェクトをビルドするより、サンプルのエクスターナルオブジェクト用プロジェクトをコピーして使用する方法をお勧めします。

その1つの理由として、あるXcodeプロジェクトを他のものに変更することは基本的に不可能であるという点があります。そのため、例えばXcodeプロジェクトのタイプとして「Application」を選択した場合、このプロジェクトをライブラリ用に変更することはできません。

将来的には、プロジェクトのコピーを必要としないような、Maxエクスターナルのためのテンプレートができるかも知れません。しかし、私たちの経験から言って、テンプレートの変更はほとんどプロジェクトのコピーと同じくらいの手間を要します。

プロジェクト、ターゲット、環境設定(コンフィギュレーション)

Xcodeの設定には、3つのレベルの階層があります。第1にプロジェクトがありますが、これはXcodeドキュメントに関連するものです。プロジェクトはターゲットのためのコンテナ(入れ物)と考えることができます。ターゲットにはほとんどのアクションが存在しています。

ターゲットはどのようなファイルがコンパイルされ、リンクされるかを指定します。さらに、ターゲットはどのような種類のものをビルドするかをも決定します。例えば、Maxのためのビルドを行なうプロジェクトの場合、いくつかのターゲットを含んでいます。これには、通常の編集を行なうバージョン、ランタイムのためのバージョン、そしてプラグインとして使用される MaxPlugLibのためのバージョンがあります。最初の2つはアプリケーションですが、最後のものはライブラリです。

各々のターゲットにはビルド設定があります。ビルド設定はターゲットをビルドする方法に関する、コンパイラとリンカのための設定の集まりです。例えば、1つのビルド設定がコンパイラの最適化をオンにしているのに対し、他方ではオフにしているというような具合です。

SDKに含まれるサンプルのMaxエクスターナルオブジェクト用プロジェクトには、オブジェクト名による1つのターゲットと、Development および Deploymentと呼ばれる2つのビルド環境設定があります。ここで、2つのビルド設定の違いについてまとめておきましょう。

設定 Development Deployment
アーキテクチャ 使用しているプロセッサにネイティブ ユニバーサルバイナリ
デバッグシンボル 含まれる 取り除かれる
最適化 Off Full("Os")
生成先 buildフォルダの中のDevelopmentフォルダ buildフォルダの中のDeploymentフォルダ
ゼロリンク On(下記を参照、要注意!) Off

考え方はこうです。まず、オブジェクトの開発過程の間は、"Development"というビルド環境設定を使用します。そして、ひとたび「これでよし」となった場合、"Deployment" というビルド環境設定を使用します。 Development ビルド開発環境は次のようにデザインされています。

  • コンパイル速度の向上(ユニバーサルバイナリがのソースファイルを各々2回コンパイルするのに比べ、およそ半分程度のコンパイル時間で済みます。)
  • デバッグが容易(最適化はデバッガでソースコードを追跡することを困難にします)
  • クラッシュの診断を容易にします。(デバッグシンボルを残してあるため、クラッシュログがクラッシュしたソース行を指摘することができます)

ビルド設定の編集

ビルド設定の編集を行なうためには、そのオブジェクトのプロジェクトウィンドウ(一方にファイルのリストを持つもの)を前面にし、「プロジェクト」メニューから「アクティブターゲット”maximum”(実際には該当のオブジェクトの名前)を編集」を選択します。「ターゲット”maximum”の情報」というタイトルのウィンドウが開きますが、これをビルド設定ウィンドウとして参照します。

ウィンドウの上部にはいくつかのタブがあります。

「一般」タブ

「一般」セクションの一番上の部分で、ターゲットの名前を変更することができます。これは、実際のオブジェクトの名前を変更したわけではなく、Xcodeがターゲット名として表示するものを変更するだけです。この名前はオブジェクト名と同じであることを推奨しますが、どのような名前でも(例えばターゲット”K-Mart”、”Wal-Mart”といったものでさえ)可能です。

「ビルド」タブ

「ビルド」タブでほとんどの作業を行います。各々のビルド設定の説明に入る前に、一番上の「構成」と「コレクション」という表示のあるメニューに注意し、これを理解しておくことが重要です。

「構成」メニューは編集しようとするビルド設定を選択します。ある特定のビルド設定を変更したい場合には(そのようなケースはあまり多くないでしょうが)、このメニューからDevelopment または Deploymentを選択します。ターゲットのすべてのビルド設定で何らかの変更を行いたい場合には、「構成」メニューから「すべての構成」を選択します。

「コレクション」メニューは、このウィンドウにリストとして挙げられている非常に多くの設定の案内役になっています。一般的に、最も重要な設定は各コレクションのトップに近いあたりにあります。プロジェクトがコピーしたままであれば、Collectionメニューの(「一般」セクションの中にある)「パッケージング」を選択することで、通常変更すべき設定をすばやく表示させることができます。そうすることによって、一番上の右側には新しいエクスターナルオブジェクトの名前となるべきプロダクト名が表示されます。

重要なプロジェクト設定についての詳細

ここでは、どのようなMaxエクスターナルオブジェクトの開発を行う場合にも重要な設定のすべてを見ていきましょう。ここで順番に説明するすべての設定を行うために、コレクションメニューから「すべての設定」を選択して下さい。

アーキテクチャ

Development ビルド設定では、この項目は $(NATIVE_ARCH) になっています。これは、Xcode が PowerPCマシンで実行されている場合には PowerPCマシン用のコード、Intelマシンで実行されている場合はIntelマシン用のコードのみをコンパイルすることを表しています。

Deployment ビルド設定では、この項目は ppci386 になっています。この設定ではオブジェクトのユニバーサルバイナリ・バージョンが生成されます。

SDKパス

これは、どちらの設定の場合も /Developer/SDKs/MacOSX10.4u.sdk でなければなりません。Interマシンだけで開発を行う場合は、この項目を空白にしておいてもかまいませんが、PowerPCでIntelマシン向けに開発したいのであれば、/Developer/SDKs/MacOS10.4u.SDK が必要になります。SDKパスはハードドライブのルートレベルで検出されるすべてのヘッダ、フレームワーク、ライブラリの完全なコピーに対するパスです。PowerPCマシンでは、10.4 Universal SDK にはユニバーサルバイナリコードによる様々なライブラリが含まれています。一般的なシステムのルートレベルにある同様なライブラリはPowerPC専用のものです。

ターゲット設定を編集してSDKパスを入力する場合、SDKフォルダの正確なパス名を把握していなければならない点には注意が必要です。しかし、プロジェクト設定ウィンドウを使う場合、その正確なパス名を知らなくても、便利なポップアップメニューを使って全てのターゲットやビルド設定のためにSDKパスの変更を行うことができます。

ビルドプロダクトのパス

デフォルトでは、これは “build”に設定されています。それによって、Xcodeプロジェクトファイルを含むディレクトリにサブディレクトリが作られ、そこへ make されたコンパイル済みオブジェクトが作られます。最終的にエクスターナルオブジェクトをこの場所へ置いておくつもりはないにしても、多分この部分はそのままにしておきたいのではないでしょうか。自動的に生成されたオブジェクトをbuildフォルダから移動させる方法については、後述する「作成したオブジェクトを Xcode にインストールさせる (Making Xcode Install Your Object)」 というセクションを参照して下さい。

構成ごとのビルドプロダクトのパス

デフォルトでは、これは $(BUILD_DIR)/&(CONFIGRATION)に設定されています。BUILD_DIRの値は、上記のビルドプロダクトパスで指定したものです。CONFIGRATION の値は Development か Deployment を示します。このことは、必然的にbuild/Development にはDevelopment ビルド設定を用いてコンパイルされたエクスターナルが格納され、build/Deployment には、Deploymentビルド設定を用いてコンパイルされたエクスターナルが格納されることを意味します。この方法は2種類のビルドを別々に管理するための良い方法であることがわかります。その理由は、他の方法を用いたとしても、この2つの違いは明らかにならないからです。

ヘッダ検索パス

これは、ソースコードでインクルードされたファイル(例えば ext.h)をXcodeが探す場所を決定します。

これらは、すでにプロジェクトファイルからの相対位置として設定されていますが、必要ならこれを絶対パスとして指定することができます。SDKでは、maximumオブジェクトのためのヘッダ検索パスとして../../c74support/max-includesが設定されています。また、plus~オブジェクトのためには ../../c74support/msp-includesが追加されています。

フォルダとそのすべてのサブフォルダを追加したい場合には、アスタリスクを2つ追加する書き方で指定できます。例えば、c74supportフォルダと、このフォルダに含まれる全てのサブフォルダを対象としたい場合、ヘッダ検索パスは ../../c74support/** のように指定します。

UNIXの相対パス指定の方法に馴染みのない方のために付け加えておくと、../../という書き方は、Xcodeプロジェクトが含まれるフォルダから、フォルダ階層のディレクトリレベルを2つ上がることを意味しています。サンプルプロジェクトmaximumの場合、1つ上のレベルは “example-externs”フォルダになり、さらに1つ上のレベルはMaxMSP UB SDKになります。そしてMaxMSP UB SDK フォルダには c74support フォルダが含まれています。

フレームワーク検索パス

MaxAPI.framework と MaxAudioAPI.framework は /Library/Frameworks のルートレベルに置かれているため、Universl SDK を使用するためには、全てのビルド設定で、フレームワーク検索パスを /Library/Frameworks に設定しておかなくてはなりません。Xcode の設定関係では、フレームワーク検索のバグがまだ残っています。

Mach-O タイプ

Maxエクスターナルオブジェクトの場合、ここはバンドル(Bundle)でなければなりません。

初期化ルーチン(Initialization Routine)

これに関しては、少々説明が必要です。CFMランタイムアーキテクチャでは、オブジェクトが最初にロードされた時に呼び出されるルーチンを、オブジェクト自身が定義する規定がありました。それに比べて、残念なことにMach-Oバージョンでのこの機能は、超貧弱です。クラッシュせずに他の実行コードを呼び出すことは不可能なので、初期化ルーチンが使えるのは、いくつかのグローバル変数の初期化くらいのものです。Maxエクスターナルオブジェクトは、既知の初期化エントリポイント(main)を持っているので、本質的に、Mach-O初期化ルーチンは余計です。そこで、このフィールドはブランクのままにしてありますし、そのようにすることを推奨します。

プレバインド(prebinding)

これは、コードをより速くロードさせるためのMacOSXの奇妙な機能ですが、OS10.4では無くなっています。これをチェックした場合、OSX10.4だけのためにコンパイルすると(下記を参照)、無害な警告(warning)が出ます。これをチェックするかどうかは、比較的重要ではないように思われます。

ゼロリンク

上記の機能に対し、ゼロリンクはOSの奇妙な機能ではなく、混乱とエラーを招くようなXcode の機能です。ゼロリンクは、様々なコードモジュールとの結合を行わないことで、あなたのオブジェクトが作られる際のリンク時間を短縮しようとするものです。結果として、ゼロリンクをイネーブル(使用可)にしてコンパイルされたオブジェクトは、おそらく実際より小さなサイズになるでしょう。残りのコードは、プロジェクトのbuildフォルダの中に、様々な .o ファイルとして存在しています!

当然ですが、ゼロリンクを使用して作ったオブジェクトを他のマシンへ移しても、コードの一部分が残されたままの状態なので、ロードされません。さらに悪いことに(私たちもそれがどうしてなのかは不明ですが)、関数未定義のエラーがゼロリンクによって隠されてしまうため、この「余分なコード」に入ろうとする段階でクラッシュするケースが存在します。

奇妙なことに、ゼロリンクはリンクを行う時間を、実際にはそれほど短縮してはくれないように思われます。しかし、私たちは、あなたがオブジェクトを Deployment ビルド設定だけを使ってリリースするだろうということを仮定して、Development ビルド設定ではこれをそのまま(オンのまま)にしてあります。もし、私たちがあなたを怖がらせたことによって Developmentビルド設定のゼロリンクをオフにしたいと感じたならば、ビルドメニューの「ゼロリンクを許可」のチェックを外すことによって、すべてのケースでオフにすることができます。

標準ライブラリにリンク

Maxエクスターナルオブジェクトでは、常にこれを行います。
(適用しない多くのリンカの設定は飛ばします。)

プロダクト名

これはあなたのエクスターナルオブジェクト名から、拡張子 .mxoを取り除いたものにします。
(「実行可能ファイルのプレフィックス」および「実行可能ファイルの拡張子」の使用は避けて下さい。)

ラッパーの拡張子

これは mxo(前にピリオド「.」はつけません)でなくてはなりません。

パッケージ情報を強制的に生成

これは、必ずチェックしなければなりません。これによって生成されるPkgInfoファイルによってSubEthaEditワードプロセッサアプリケーションとのコンフリクトを避けることができます。SubEthaEditがインストールされていて、しかもあなたのエクスターナルオブジェクトのContentsフォルダにPkgInfoが含まれていない場合、Maxはあなたの.mxoバンドルをオブジェクトとして見つけることができず、ロードすることもできません。

Info.plist ファイル

私たちは、Info.plistファイルのファイル名として「Info.plist」を使います。一般的に、エクスターナルオブジェクトは Xcodeプロジェクトと同じフォルダにオブジェクト自身のInfo.plistファイルを置かなければなりません。Info.plistの前のパス名を省略した場合、この場所になります。

Mac OS X デプロイメントターゲット

オブジェクトのコードが動作するために必要な最低限のシステムバージョンを設定します。「コンパイラのデフォルト」が申し分なく適切なものであるというのが私たちの意見です。あなたが使おうとする機能をシステムがサポートしている場合、あなたのコードはロードされます。そうでない場合にはロードされません。これは、ほとんどの場合において、望ましい動作でしょう。しかし、あなたが実際に使いたい特定のオペレーティングシステム機能がシステムの後のバージョンで機能するケースがあるかもしれません。このような場合には、特定のバージョンを要求したいことがあるでしょう。なぜそのオブジェクトが古いシステムでは動作しないかを、Maxウィンドウにメッセージとして表示させることは、ユーザに対して最も親切な方法であるという点について考慮して下さい。

デプロイメントの位置、インストール・ビルド・プロダクトの場所、インストールディレクトリ

この設定をチェックすると、あなたのオブジェクトを、「インストール・ビルド・プロダクトの場所」と「インストールディレクトリ」の設定の組み合わせを使って指定された特定の場所にインストールします。この方法については、「作成したオブジェクトを Xcode にインストールさせる (Making Xcode Install Your Object)」 で後述します。

リンクされたプロダクトを除去

この設定をチェックすると、オブジェクトからシンボルが除去されます。これにより、オブジェクトのサイズは僅かですが小さくなります。

コンパイルでのソース解釈

デフォルトでは、「ファイルタイプに基づいて」に設定されています。これは、ソースファイルが、.cで終わる場合、C++コンパイラを使用しないということを意味します。もし、何らかの理由でC++コンパイラを使用したい場合は、これを「C++」に設定して下さい。ただし、この場合にはmain() 関数のために次のようなプロトタイプ宣言を行う必要があります。

extern “C” int main(void);

また、main() を intを返す関数として宣言し、返値として0を返す(return 0;)必要があります。

プレフィックスヘッダ

SDKのサンプルでは、プレフィックスヘッダは max-includes フォルダの中の max_sdk_macho_frefix.pch (訳注:実際には max_sdx_macho_prefix.hになっています)というファイルを参照しています。プロジェクトからの相対パスとして、プレフィックスヘッダは../../c74support/max-includes/macho-prefix.pch(訳注:これも、実際には ../../c74support/max-includes/macho-prefix.h になっています)と指定しています。

Maxエクスターナルオブジェクトをコンパイルするためには、プレフィックスヘッダは次の行を含む必要があります。

#include <Carbon/Carbon.h>

これによって、あなたが必要とするAppleのヘッダのほとんどをインクルードします。Appleのヘッダファイルに対するどのような参照の場合でも、あなたのソースコードの次のような行は、

#include “Dialogs.h”

はコンパイラにおけるエラーを引き起こす点に注意して下さい。少なくとも

#if !TARGET_RT_MAC_MACHO

をその周囲に置くようにしなければなりません。

「フレームワークヘッダを使う(Using Framework Headers)」というセクション(フレームワークに関する追加事項 の中にあります)では、プレフィックスヘッダファイルの中へすべてのMaxおよびMSPのヘッダファイルを付け加える方法について述べたいと思います。

プレフィックスヘッダをプリコンパイルする

これはチェックする必要があります。これによってコンパイラのスピードがかなり向上します。特に、あなたのすべてのプロジェクトが同じプリコンパイルされたヘッダを共有する場合、それらは一度コンパイルするだけです。

最適化レベル

Developmentビルド設定では、これは「なし」に設定します。Deployment ビルド設定では、「最も高速で最小」に設定します。最適化はデバッグを難しくするうえ、ある場合には、確実に動作している非最適化コードにクラッシュを引き起こす場合もあります。多くの場合、問題はプログラマの誤りによるものですが、最適化バージョンがクラッシュし、非最適化バージョンがクラッシュしない場合でも、これが必ずしもコンパイラのバグではないということを知っておくことは有益です。