Ubuntuシステムの下でClangコンパイラによってObjective-Cを記述する


Objective-CはAppleのfirst-classプログラミング言語として、長い間多くの開発者に人気を集めています.このうち、Objective-CはC言語に対する完全な互換性、柔軟性、OOP特性により、非常に優れ、バランスの高いプログラミング言語となっています.私が使ったすべてのプログラミング言語の中で、Objective-Cは駆動およびアプリケーション層プログラムの開発に最も適したプログラミング言語であり、C++よりも軽くて多いが、機能的にはC++よりも強い.完璧なC言語の基礎の上で教科書の類のOOPの特性を増加しました!その中で、メッセージメカニズムはその魂である.
 
他のプラットフォームで近代的なObjective-Cをよりよく使用できるように、ここではLLVM Clangコンパイルツールチェーンの使用をお勧めします.なお、以下に説明するインストール手順はUbuntu 16である.04では、以前のバージョンのUbuntuシステムも、以下の手順でインストールとコンパイルを完了することができます.
Ubuntuシステムをインストールすると、GCCとその関連するランタイムライブラリがデフォルトでシステムにインストールされます.現在、最新のObjective-CコンパイラおよびFoundationライブラリを使用していることを保証するために、次の手順に従ってGNUStepライブラリをインストールします.
1、sudo apt-get install gnustep
2、sudo apt-get install gnustep-devel
これでObjective-CのGNUStepランタイムライブラリをインストールしました.
次に、最新releaseのLLVM Clangをダウンロードしてインストールします.
1、sudo apt-get install llvm
2、sudo apt-get install clang
これらのインストールが完了したら、ClangでAppleが与えるBlocks構文に関するランタイムライブラリとAppleオープンソースのGrand Central Dispatchライブラリをインストールできます.
1、sudo apt-get install libblocksruntime-dev
2、sudo apt-get install libdispatch-dev
これで、コンパイラおよび必要なランタイムライブラリのインストールが終了します.Ubuntuシステムを使用する大きなメリットは、通常のツールをインストールするのに非常に便利で、sudo apt-get installが1つで済むことです.そのため、非深さLinuxユーザーの開発に適しています.
 
Objective-Cに依存するコンパイルオプションやランタイムライブラリが多いため.そこでここではmakefileを作るか、以下に説明するようにshellファイルを書いて、必要なコンパイルコマンドオプションを入れることをお勧めします.これにより、後でソースファイルをコンパイルするときに便利になります.
まず、次のコマンドを実行して、Objective-Cコンパイルに必要なコンパイルオプションを観察します.
gnustep-config --objc-flags
出力した内容をshellファイルにコピーして保存します.次のコマンドを実行して、Objective-C接続に必要なロードオプションを表示します.
gnustep-config --objc-libs
次に、ロードオプションをコピーしてshellファイルに貼り付けます.
 
次はmainを作成できます.mソースファイルをテストする:
 
#include 
#include 
#include 
#include 

#import 


static int (^BlockTest(void))(int)
{
    __block int a = 10;

    int (^block)(int) = ^int(int i) {
            a += i;
            return a;
        };

    block(100);

    printf("The value is: %d
", a); return Block_copy(block); } @interface DummyObject: NSObject @end @implementation DummyObject - (void)dealloc { NSLog(@"DummyObject deallocated!"); [super dealloc]; } @end @interface MyObject: NSObject { @private /** * GNUStep Clang ,Block Objective-C 。 * myBlock , property, * getter setter 。 */ void (^myBlock)(void); /** * Clang ,property , * 。 * , Clang , , * 。 */ NSString *string; DummyObject *dummyObject; } @property (nonatomic, retain) NSString *string; /** property setter */ @property (nonatomic, retain) DummyObject *dummyObject; @end @implementation MyObject @synthesize string, dummyObject; /** myBlock setter */ - (void)setMyBlock:(void(^)(void))block { if(myBlock != NULL) { Block_release(myBlock); myBlock = NULL; } if(block != NULL) myBlock = Block_copy(block); } /** myBlock getter */ - (void(^)(void))myBlock { return myBlock; } - (instancetype)init { self = [super init]; NSLog(@"MyObject initialized!"); return self; } - (void)dealloc { // setter self.myBlock = NULL; self.string = nil; self.dummyObject = nil; NSLog(@"MyObject deallocated!"); [super dealloc]; } @end static void MyTest(void) { // Block int (^block)(int) = BlockTest(); dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^void(void){ puts("Hello, world!"); int a = block(50); printf("a = %d
", a); }); Block_release(block); // NSArray *array = @[@10, @20, @"Hello, world"]; // Clang , :NSNumber *m = array[0]; NSNumber *m = [array objectAtIndexedSubscript:0]; NSNumber *n = [array objectAtIndex:1]; NSLog(@"The sum is: %d, and the string is: %@", m.intValue + n.intValue, [array objectAtIndex:2]); // Objective-C DummyObject *dummyObj = [DummyObject new]; MyObject *obj = [MyObject new]; obj.myBlock = ^void(void){ NSLog(@"The array size is: %tu", [array count]); }; obj.string = @"This is my object!"; obj.dummyObject = dummyObj; [dummyObj release]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(queue, ^void(void) { obj.myBlock(); NSLog(@"obj string: %@", obj.string); }); [obj release]; } int main(void) { @autoreleasepool { MyTest(); NSLog(@"Program complete!"); } }

 
 
 
 
 
 
終わったら、自分で整理したbuildを見せます.sh shellファイルのコンパイル:
 
clang main.m -std=gnu11 -fblocks -lBlocksRuntime -ldispatch -lgnustep-base -MMD -MP -DGNUSTEP -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGNUSTEP_BASE_LIBRARY=1 -fno-strict-aliasing -pthread -fPIC -Wall -DGSWARN -DGSDIAGNOSE -Wno-import -O2 -fgnu-runtime -fconstant-string-class=NSConstantString -I. -I/home/zenny-chen/GNUstep/Library/Headers -I/usr/local/include/GNUstep -I/usr/include/GNUstep -I/usr/lib/gcc/x86_64-linux-gnu/5/include/    -rdynamic -fgnu-runtime -L/home/zenny-chen/GNUstep/Library/Libraries -L/usr/local/lib -L/usr/lib -lobjc -lm -o test

上記build.shファイルでは、-std=gnu 11コマンドを使用して、現在のObjective-CおよびC言語標準をGNU 11標準構文に適合するように設定したことを示します.すなわち、C 11標準にClang GNU拡張を加えます.GNU構文拡張を使用しないと、Blocks構文は使用できません.-fblocksはClangコンパイラがBlocks構文を解析し、対応する実行時代を生成できるようにしますか.上記のコマンドオプションでは、Objective-Cの例外ランタイムライブラリを使用する必要がないため、例外ランタイムライブラリに関するすべてのコマンドを削除しました.また、プログラムをデバッグする必要もないので、-gコマンドも削除しました.
 
 
私たちはbuildを実行しています.shの時、Clangコンパイラはとても烏龍の間違いを報告します--GSVersionMacros.hで見つかりません./usrディレクトリの下でobjcディレクトリの場所を検索し(私のシステム環境では、ディレクトリの場所は/usr/lib/gcc/x 86_64-linux-gnu/5/include/)、デスクトップまたは他のユーザーディレクトリの下でblocks_を作成します.runtime.hヘッダファイルは、以下の内容を入力してsudoでそのobjディレクトリにコピーします.このヘッダファイルの内容は非常に簡単です.
 
#pragma once

#ifdef __cplusplus
extern "C" {
#endif


void *_Block_copy(const void *) __attribute__((weak));
void _Block_release(const void *) __attribute__((weak));

#ifdef __cplusplus
}
#endif

そして私たちが再構築するときにもっと無言のエラーが発生します.GSBlocksヘッダファイルの対_Blocks_copyおよび_Blocks_releaseの声明とBlock.hでの衝突.GSBlocksヘッダファイルを見つけて、開くと、元の中に宣言されていた_Blocks_copyと_Blocks_releaseのパラメータタイプはvoid*,Block.hで宣言されているのはconst void*......仕方なく、このソースファイルを修正して、パラメータタイプをconst void*に変更すると大成功です.
 
コンストラクションのコンパイルに成功すると、ARCに関連する2つの警告が見つかります.これらは無視されます.
もちろん、Blocksの文法に関するものを使いたくないし、GCCも使いたいなら、これらを振り回さなくてもいいです.次に、Blocks構文を使用しないプロジェクト構成を示します.
gcc main.m -std=gnu11 -Os -MMD -MP -DGNUSTEP -DGNUSTEP_BASE_LIBRARY=1 -DGNU_RUNTIME=1 -DGNUSTEP_BASE_LIBRARY=1 -fno-strict-aliasing -pthread -fPIC -Wall -DGSWARN -DGSDIAGNOSE -Wno-import -fgnu-runtime -fconstant-string-class=NSConstantString  -I. -I/root/GNUstep/Library/Headers -I/usr/local/include/GNUstep -I/usr/include/GNUstep -I/usr/lib/gcc/x86_64-linux-gnu/5/include/    -rdynamic -L/root/GNUstep/Library/Libraries -L/usr/local/lib -L/usr/lib -lobjc -lm -lgnustep-base -o test

 
最後に、Clang 3.8コンパイラでは、Objective-Cは@autoreleasepool、複合字面量、instancetypeなどの高度な文法特性をサポートします.しかし、property自動統合はサポートされておらず、クラスのcategoryおよびimplementationでメンバーオブジェクトを宣言することもできません.また、GNUStepライブラリでは、次の4つの方法が導入されていますが、辞書、配列の下付きインデックス構文もサポートされていません.
- (void)setObject:(id)object forKeyedSubscript:(id < NSCopying >)aKey; - (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)anObject atIndexedSubscript:(NSUInteger)index; - (id)objectAtIndexedSubscript:(NSUInteger)index;
上の2つはNSMutableDictionary、下の2つはNSMutableArrayに使用されます.しかし、文法的にはインデックス方式がサポートされていないため、コード例では、非常に簡潔なarray[0]ではなく[array objectAtIndex:0]という形式が用いられている.
しかし、総じて言えば、LLVM Clang 3.8はとても良くて、使う価値があります!