Objective-C のビルド環境を Docker で構築

CentOS をベースとした Objective-C のビルド環境を Docker で構築してみました。

使用したソースは http://github.com/fits/try_samples/tree/master/blog/20151130/

Docker イメージ作成

今回は clang と GNUstep を使う事にします。

バージョンは古くなってしまいますが、どちらも yum でインストールするようにしました。

make をインストールしておかないと GNUstepgnustep-config コマンドが機能しない (結果が空になる) のでご注意ください。

また、gcc-objc をインストールしておかないと、Objective-C のソースをビルドする際に必要なヘッダーファイルを参照できず、fatal error: 'inttypes.h' file not found のようなエラーが発生しました。

Dockerfile
FROM centos

RUN yum -y update

RUN yum -y install epel-release
RUN yum -y install clang make gcc-objc gnustep-base-devel

RUN yum clean all

docker build で Docker イメージを作成します。

Docker イメージの作成
$ docker build --no-cache -t sample/objc:0.1 .

・・・
Successfully built ・・・

動作確認

以下のようなサンプルソースをビルドしてみます。

/vagrant/work/Sample.h
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>

@interface Sample : NSObject {
    NSString* _name;
}

@property (nonatomic, copy) NSString* name;

- (void)log;

@end
/vagrant/work/Sample.m
#import <Foundation/Foundation.h>
#import "Sample.h"

@implementation Sample : NSObject

@synthesize name = _name;

- (void)log {
    NSLog(@"%@", _name);
}

- (void)dealloc {
    [_name release];
    [super dealloc];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Sample* s = [[Sample new] autorelease];

        s.name = @"test";

        [s log];
    }

    return 0;
}

まずは sample/objc:0.1 イメージを使って Docker コンテナを起動します。

Docker コンテナの起動
$ docker run --rm -it -v /vagrant/work:/work sample/objc:0.1 bash

コンテナ内で clang を使ってビルドします。

コンパイラオプションに関しては以下で妥当なのかは不明ですが、一応ビルドには成功しました。 (場合によっては -objcmt-migrate-all 等の指定も必要かもしれません)

ビルド
# cd work

# clang `gnustep-config --objc-flags` `gnustep-config --objc-libs` -lgnustep-base -I /usr/lib/gcc/x86_64-redhat-linux/4.8.3/include Sample.m -o Sample

clang: warning: argument unused during compilation: '-shared-libgcc'

一応、それぞれのオプションを指定しなかった場合に発生したエラーをまとめておきます。

オプション指定 指定しなかった場合のエラー例
`gnustep-config --objc-flags` 無し(指定しなくてもビルドは成功)
`gnustep-config --objc-libs` undefined reference to symbol 'objc_getProperty'
-lgnustep-base undefined reference to `NSLog'
-I /usr/lib/gcc/・・・/include fatal error: 'objc/objc.h' file not found

ビルド結果の Sample を実行してみると一応動作しました。

実行例
# ./Sample

2015-11-30 20:15:00.121 Sample[32] test

なお、clang -v の実行結果は以下のようになりました。

clang -v
# clang -v

clang version 3.4.2 (tags/RELEASE_34/dot2-final)
Target: x86_64-redhat-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.3
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.8.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.8.3
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.3