API 定義のグルーピング

C 言語ライブラリにおいて、ライブラリインターフェースは一般的にヘッダファイルを通じて定義される。このため、UCIDも基本的にはヘッダファイルの単位で記述し、UCIDのライブラリとしてグルーピングされることになる。
ただし、いわゆる ports や pkgsrc のようなパッケージシステムがソフトウェアを適当な単位に分割するのと同じように、UCIDのAPI記述も適当に分割することが想定されている。例えば、Win32 APIWindows.hをインクルードすることで使用できるが、Windows.hで提供されるAPIを実装しているDLLは様々に別れている; CreateWindowはuser32.dllに実装され、CreateFileはkernel32.dllに存在するがどちらもWindows.hのインクルードで使用できる。
このような場合でも、個々のライブラリを個別にimportするのは面倒なときのために統合したライブラリも提供する。これをサポートするために、UCIDはAPI記述のmergeを行うことができる。

  • (ucid os win32) - user32とkernel32などWin32API群を単純にmergeしたもの
    • (ucid os win32 user32) - user32.dllに存在する関数
    • (ucid os win32 kernel32)

Win32の場合、ごく一部の構造体はDLLを越えて共有されるため、DLLに全順序関係を作り、親にあたるDLL側の記述に持たせている。例えば、OVERLAPPED構造体はkernel32とwinsockで共有されるが、OVERLAPPEDの定義はkernel32側に含め、winsockはkernel32をimportしている。
MergeできるAPIセットを分割して提供することは分割自体がAPIを構成するという重要な問題がある(ie. あるAPI定義をライブラリ間で移動すると互換が崩れる)。よって、基本的にはmergeを行うのではなく巨大なAPIライブラリをひとつ提供する。Win32は分割が明示的であり、かつ、一部のDLLロードをサボれる可能性があるための特殊な例外と言える。

バックエンドを持つAPI

cairoは基本となる共通APIに加えて、バックエンド固有のAPIを分離したヘッダとして提供している。この場合、cairo全体のライブラリを提供することはせず、共通部分のライブラリとバックエンドのライブラリに分割される。

  • (ucid graphics cairo) - cairo_tに対する基本的な操作
  • (ucid graphics cairo win32) - Win32 surfaceに対する操作(CAIRO_HAS_WIN32_SURFACE)
  • (ucid graphics cairo png) - PNG出力機能(CAIRO_HAS_PNG_FUNCTIONS)

いわゆるconfig.hはCAIRO_HAS_マクロを定義するため、おおむね当該マクロ群のレベルでAPI記述も分割される。
バージョンでは分割されない。新機能の類は同じライブラリに追加されていき、実行時のバージョンチェックで撥ねられることになる。

C言語POSIXBSD

UCID記述における最大のカオスがC標準ライブラリと言える。CはUNIXを書くために生まれ、サブセットが標準化され、それぞれの実装が別々の進化を遂げているため、常識的なルールで記述を整理することは困難となっている。
UCIDでは、それぞれのOS標準Cライブラリを一旦完全に独立したライブラリとみなし、それらをいくつかのmetaモジュールにmergeを使用して集める。

  • (ucid os linux kernel signal) - Linuxのsys/signal.h
  • (ucid os freebsd kernel signal) - FreeBSDのsys/signal.h
  • (ucid lang vc12 signal) - Visual Studio 2013のsignal.h (注: 本当に存在する)
  • (ucid std iso c99 signal) - C99で規定されている signal.h がエクスポートしている定数等。C99互換なアプリケーションを記述するために使用できる。
  • (ucid core c signal) - metaモジュール。アプリケーションが動作するシステムが提供するsignal.hがエクスポートしていると期待される定数等。

アプリケーションは通常(ucid core c signal)をimportして書かれることになる。
この方式の最大の問題点は、標準規格と一般の実装に矛盾があるケースに良く対応できないことだろう。例えば、POSIXにおけるioctl(注: 本当に存在する)はrequest引数がintであり( http://pubs.opengroup.org/onlinepubs/009695399/functions/ioctl.html )、BSDにおけるioctlはrequest引数がlongとなる( http://www.freebsd.org/cgi/man.cgi?query=ioctl&sektion=2 )。この2つの定義には互換性が無い。この問題に対するうまい対処はいまのところ思いついていない。(ただし、この問題はもっと一般的にも起こる; CPUアーキテクチャによって型のサイズが変わるような場合に、typedefではなく#defineで済ませているようなケース等。)