2021/02/20作成, 2020/02/05更新

cmakeを使ってxcodeを使わずにiosアプリを作成する

統合開発環境である xcode を使わずに、cmake を使ってプロジェクトを作成し、xcodebuild を使ってビルドを行います。これにより CMakeLists.txt さえ書けばビルドできるようになるのでプロジェクトの管理が楽になります。

当然ですが、ビルドするには正規ライセンスのmacosが必要になるのでmacが必要になります。しかしコマンドラインで完結できるようになるのでmacをsshで操作すればよくなり、macを極力触らないで良くなります。

また、このページではコマンドが長く読みづらいため改行を入れています。実際に使うときは1行にするかバックスラッシュを使ってください。

cmakeでプロジェクトを生成する

iOS向けのプロジェクトはあくまでもXcodeプロジェクトという扱いであり、mac向けのプロジェクトと基本は同じ使い方になります。また、cmake ios で検索をすると ios.toolchain を使ったサンプルを見かけますが実際にはツールチェインは使う必要はなくcmake単体でプロジェクトの生成ができます。

cmake .. -G Xcode
	-DCMAKE_MACOSX_BUNDLE=YES
	-DCMAKE_SYSTEM_NAME=iOS
	-DCMAKE_OSX_SYSROOT=iphoneos
	-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=チームID
	-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
名前意味
CMAKE_OSX_SYSROOTiphoneosiOS向けのSDKを使う
CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM開発アカウントのチームID
CMAKE_OSX_DEPLOYMENT_TARGET11.0などデプロイターゲットバージョン

CMakeList.txt

cmake_minimum_required(VERSION 3.10.2)
project(myappli)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

if (APPLE)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY	CACHE INTERNAL "" FORCE)
# $(OTHER_CFLAGS) は Xcodeのデフォルトのコンパイルオプションを
# 引き継ぐための文字列です。
# -x objective-c++ は .cpp を Objective-C++として扱う
set(CMAKE_CXX_FLAGS
	"$(OTHER_CFLAGS) ${CMAKE_CXX_FLAGS} -x objective-c++")

# オープンソースのサブプロジェクトを使うときに問題になりやすいので
# BitcodeはOFFにします。
set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE
	"NO" CACHE INTERNAL "")

# resourcesフォルダのファイルとフォルダを列挙し
# 結果をRESOURCE_FILESに格納する
file(GLOB RESOURCE_FILES	"../resources/*")

add_executable(
	myappli MACOSX_BUNDLE
	src/main.cpp         # -x objective-c++ で .mm として扱われる
	${RESOURCE_FILES}    # リソースも実行ファイルに追加する
)


set_target_properties(
	myappli		PROPERTIES
	MACOSX_BUNDLE  TRUE
	OUTPUT_NAME  myappli

	MACOSX_BUNDLE_GUI_IDENTIFIER        "バンドルID"
	MACOSX_BUNDLE_LONG_VERSION_STRING   "1"
	MACOSX_BUNDLE_SHORT_VERSION_STRING  "1"
	MACOSX_BUNDLE_BUNDLE_VERSION		1
	XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME	"AppIcon"
	# RESOURCE_FILESにRESOURCEプロパティをつけると
	# アプリ内でリソースとして扱われる。
	RESOURCE   "${RESOURCE_FILES}"
)

endif() # APPLE

テンプレート

以下のパラメータはiOS向けのビルド時に必須となるパラメータです。これらのパラメータが無いと正しい環境設定がされないのでキャッシュに入れてグローバル変数にしておくと良い。

set(CMAKE_MACOSX_BUNDLE YES CACHE INTERNAL "" FORCE)
set(CMAKE_SYSTEM_NAME iOS CACHE INTERNAL "" FORCE)
set(CMAKE_OSX_SYSROOT "iphoneos" CACHE INTERNAL "" FORCE)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY	CACHE INTERNAL "" FORCE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0などのターゲット" CACHE STRING   "" FORCE)
set(CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "チームID" CACHE STRING   "" FORCE)

トラブルシューティング

No 16 bit type found on this platform!

oggをビルドしていたら "No 16 bit type found on this platform!" というエラーが出た。CMAKE_TRY_COMPILE_TARGET_TYPEにSTATIC_LIBRARYを指定しておくと良い。そうしないとcmakeの不具合なのかConfigure時にinclude pathなど正しいコンパイラオプションが渡されないためstdint.hなどが見つけれずConfigureが失敗する。

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY CACHE INTERNAL "" FORCE)

プロジェクトをビルドする

ipaファイルを作る場合は後述のアーカイブを行うため通常はビルドを単体で行うことはありませんが、コンパイルが通るかだけのテストなどで使うこともできます。

xcodebuild
	-allowProvisioningUpdates
	-project myappli.xcodeproj
	-sdk iphoneos
	-scheme myappli

アーカイブする

ipaファイルを作るには「アーカイブ」→「エクスポート」の順に行う必要があります。また、アーカイブは必ずクリーンな環境でビルドされるためcleanを行う必要はありません。

そのため、ビルドとほぼほぼ同じコマンドライン引数が必要になります。これにより「tmp.xcarchive」フォルダにアーカイブデータが作成されます。

xcodebuild
	-allowProvisioningUpdates
	-project myappli.xcodeproj
	-sdk iphoneos
	-scheme myappli
	-archivePath tmp.xcarchive
	archive

エクスポートする

先のアーカイブデータを使いipaファイルをエクスポートします。その際に後述の adhoc.plist が必要になります。

xcodebuild
	-exportArchive
	-archivePath tmp.xcarchive
	-exportPath myappli.adhoc
	-exportOptionsPlist	../adhoc.plist

adhoc.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC
 "-//Apple//DTD PLIST 1.0//EN"
 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>compileBitcode</key>
	<true/>
	<key>method</key>
	<string>ad-hoc</string>
	<key>signingStyle</key>
	<string>automatic</string>
</dict>
</plist>

cmakeのソースコードは cmake/Sources/cmGlobalXCodeProject.cpp が担当ソースになっています。

Apple Mac mini
iOS用のビルドマシン(ビルドサーバー)専用にするなら置き場所に困らないMac miniがおすすめ。2012年モデルから買い替えるならSSD搭載でビルド速度も上がった今がグッドタイミング。
Amazon.comのページを別ウィンドウで開きます