GNUstep Make

GNUstep logo

GNUstepは、GNU MakeのMakefileのコレクションによる、独自のビルドツールを提供しています。

このビルドツールをGNUstep Makeと呼ぶことにします。 いくつかの簡単なルールを覚えてしまえば、手動で直接Objective-Cコンパイラを実行したり、自前のMakefileを書いたりする手間が大幅に省けるようになります。 たとえ単純なHello Worldプログラムであっても、直接Objective-Cコンパイラを呼び出すよりも、GNUstep Makeを利用する方が楽ができます。

したがって、Objective-C+GNUstepのプログラミングを続けるのに次に越えなければならないハードルは、GNUstep Makeのルールを覚えることであると言えます。

Ubuntu 24.04 LTS

パッケージgnustep-makeがインストールされていることを確認します。 このパッケージはgnustep-develをインストールした場合、同時にインストールされています。

gnustep-makeには、GNUstep Makeの環境をアクティブにするスクリプトが含まれています。 そのシェルスクリプトを現在のシェルにソースすることで、GNUstep Makeが利用可能な状態になります。

$ source /usr/share/GNUstep/Makefiles/GNUstep.sh

GNUstep自体をソースからインストールした場合は、/usr/local/share/GNUstep/Makefiles/GNUstep.shなどに配置されています。

シェルを立ち上げるたびに毎回このコマンドを実行する必要があります。 それほど長いコマンドではありませんが、面倒であればシェルのaliasを設定しておくと良いです。 $HOME/.bashrcなどに次の1行を追加しておきます。

alias gnustep-make-activate='source /usr/share/GNUstep/Makefiles/GNUstep.sh'

どのように使うかは、実例を見てみたほうが早いと思うので、そうします。

例1: Hello World

以前やったHello WorldプログラムをGNUstep Makeを使ってビルドしてみます。 まず新たに適当な名前のディレクトリを作ります。 その中にhello.mという名前のObjective-Cのソースファイルを作成します。

hello.m:

#include <Foundation/Foundation.h>

int main(void)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSLog(@"Hello, world!");
    [pool release];
    return 0;
}

同じディレクトリにGNUmakefileという名前のファイルを作成します。

GNUmakefile:

include $(GNUSTEP_MAKEFILES)/common.make

TOOL_NAME = HelloWorld
HelloWorld_OBJC_FILES = hello.m

include $(GNUSTEP_MAKEFILES)/tool.make

少し注意を払って内容を見てみます。

  • common.makeというMakefileをインクルードしている
  • TOOL_NAMEという変数にHelloWorldとセットしている
  • TOOL_NAMEにセットした名前に続けて_OBJC_FILESと加えた名前の変数に、Objective-Cのソースファイルをセットしている
  • tool.makeというMakefileをインクルードしている

まずTOOLとは何かと疑問に思われることかと思います。 これはプロジェクトのタイプを意味しています。 TOOLはコマンドラインツール(GUIではない)を意味しています1)。 コマンドラインツールであるならば、TOOL_NAMEをセットした上で、tool.makeをインクルードすることをGNUstep Makeが要求しています。 プロジェクトの種類は全部で16種類あり、コマンドラインツールはそのうちの一つです。

プロジェクトの種類に関する情報はどこで見つければよいのかというと、マニュアルが存在するのでこれがヒントになるかもしれません。 ただし、すべての情報が書かれているわけではないので、最悪の場合、GNUstep Makeが提供するMakefileの中身を直接確認する必要に迫られることがあるかもしれません。 GNUstep Makeの構成は非常に複雑ですので、時間を浪費しないためにも今の段階ではあまり深入りしないことをおすすめします。

この時点でソースツリーは次のようになっているとします。

HelloWorld/
├── GNUmakefile
└── hello.m

HelloWorldディレクトリの中でmakeを実行します。

$ make
This is gnustep-make 2.9.1. Type 'make print-gnustep-make-help' for help.
Running in gnustep-make version 2 strict mode.
Making all for tool HelloWorld...
 Compiling file hello.m ...
 Linking tool HelloWorld ...

objというディレクトリの中に実行可能バイナリファイルが生成されています。

HelloWorld/
├── GNUmakefile
├── hello.m
└── obj
    ├── HelloWorld      ←生成された実行可能バイナリファイル
    └── HelloWorld.obj
        ├── hello.m.d
        └── hello.m.o

実行するにはobj/HelloWorldとタイプします。

$ obj/HelloWorld
2025-05-21 06:48:48.697 HelloWorld[18696:18696] Hello, world!

これで完了です。

例2: Hello Panel

今度はプロジェクトのタイプがGUIアプリケーションのプロジェクトを作成してみます。 先のGNUMakefileからの変更点は次の2点です。

  • TOOL_NAMEAPP_NAME
  • tool.makeapplication.make

Objective-Cのソースコードは変更しなくてもいいのですが、せっかくなのでGUIアプリケーションらしいものに変更してみます。

適当な名前の新しいディレクトリを作成して、その中に次の2つのファイルを作成します。

hello.m 2):

#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>

int main(void)
{
    NSAutoreleasePool *pool;
    pool = [NSAutoreleasePool new];
    [NSApplication sharedApplication];
    NSRunAlertPanel(@"Hello Panel", @"Hello from the GNUstep AppKit", nil, nil, nil);
    [pool release];
    return 0;
}

GNUmakefile:

include $(GNUSTEP_MAKEFILES)/common.make

APP_NAME = HelloPanel
HelloPanel_OBJC_FILES = hello.m

include $(GNUSTEP_MAKEFILES)/application.make

この時点でソースツリーは次のようになります。

HelloPanel/
├── GNUmakefile
└── hello.m

HelloPanelディレクトリの中でmakeを実行します。

$ make
This is gnustep-make 2.9.1. Type 'make print-gnustep-make-help' for help.
Running in gnustep-make version 2 strict mode.
Making all for app HelloPanel...
 Creating HelloPanel.app/....
 Compiling file hello.m ...
 Linking app HelloPanel ...
 Creating HelloPanel.app/Resources...
 Creating stamp file...
 Creating HelloPanel.app/Resources/Info-gnustep.plist...
 Creating HelloPanel.app/Resources/HelloPanel.desktop...

HelloPanel.appとobjの2つのディレクトリが作成されます。 ソースツリーの状態は次のようになっています。

HelloPanel/
├── GNUmakefile
├── HelloPanel.app
│   ├── HelloPanel
│   ├── Resources
│   │   ├── HelloPanel.desktop
│   │   └── Info-gnustep.plist
│   └── stamp.make
├── hello.m
└── obj
    └── HelloPanel.obj
        ├── hello.m.d
        └── hello.m.o

例1のTOOLのときはobjディレクトリに実行可能バイナリファイルが出力されましたが、今度はHelloPanel.appディレクトリの中にあります。 このアプリケーションを実行するには、コマンドラインに直接このファイル名をタイプするのではなく、openappというランチャープログラムを使います。

$ openapp ./HelloPanel.app

少し補足しておきます。

  • カレントディレクトリを示す「./」は省略できません。 ⇒ openapp HelloPanel.appでは起動しません
  • 末尾の「.app」は省略可能です。 ⇒ openapp ./HelloPanel でも起動します。
  • 末尾に「/」がついていてもOKです。 ⇒ openapp ./HelloPanel.app/ でも起動します。

実行するとポップアップが表示されます。

Hello Panel

1)
実際にはコマンドラインツールであってもGUIアプリケーションとしてビルドすることができるので、この分類の仕方はあまり正確ではありません。
2)
こちらのチュートリアルから拝借して若干の変更を加えました。
文書の編集
文書の先頭へ