cmake で framework を生成する

この前の記事で、cmake のプロジェクトで cocoa の framework を作成するオプションを見つけたので試してみる。

framework の生成

必ずしも info.plist は必須ではないようだ。
サンプルのうち、以下のように info.plist と CODE_SIGN の部分を潰しても framework は生成される。

CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(TestFramework C)
add_libraryFr(TestFamework SHARED
 TestFramework.h
 TestFramework.c)

set_target_properties(TestFramework PROPERTIES
  FRAMEWORK TRUE
  FRAMEWORK_VERSION C
  MACOSX_FRAMEWORK_IDENTIFIER com.akiba.TestFramework
  #MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
  # "current version" in semantic format in Mach-O binary file
  #VERSION 16.4.0
  # "compatibility version" in semantic format in Mach-O binary file
  #SOVERSION 1.0.0
  PUBLIC_HEADER TestFramework.h
  #XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Developer ID Application: Taro Akiba(123xxx789)"
)

この状態で

cmake -S . -B build

としても Makefile は生成される。もちろん make で TestFramework.framework も生成される。生成するだけならば

FRAMEWORK TRUE

とするだけでいいようだ。

生成された framework を使ってみる

とりあえずお試しなので TestFramework.h と TestFramework.c は以下のような簡単なものにした。

TestFramework.h
#ifndef TESTFRAMEWORK_H
#define TESTFRAMEWORK_H

int twice(int);

#endif
TestFramework.c
#include <stdio.h>
#include "TestFramework.h"

int twice(int n) {
    return 2*n;
}

これで、cmake を走らせると確かに TestFramework.framework はできている。

次に Xcode で別のプロジェクトを作成して TestFramework.framework を取り込む。

main.m から以下のように使う。

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

int main(int argc, const char * argv[]) {
    
    NSLog(@"%2d",twice(3));
    
    return 0;
}

走らせてみると・・

予想通り 6 と表示してくれました。

成功、成功。

rpath の設定

なお、設定にもよるのだが、こうして作成されたコマンドラインプログラムを(Xcode 上ではなくて)ターミナルから実行すると

Library not loaded: @rpath

というエラーが出る時がある。
このエラーは、コンパイル時の @rpath の設定が実際に生成されたプログラムが参照すべきライブラリ(今回は TestFramework)の path と一致していない時に発生する。

その場合は、Xcode の Runpath Search Paths あたりの設定を見直してください。

ここ、指定しておかないと framework の所定の置き場所しか見に行かないようです。

正しく設定できていれば、ターミナル上からも

と Xcode 環境で走らせた時と同様の結果になります。