Linux 上で iOS 用の C++ SDL アプリケーションを構築する

この投稿では、Linux 上で iOS 用の C++ SDL アプリケーションを構築し、有料の Apple Developer サブスクリプションなしで ipa アーカイブに署名し、ジェイルブレイクなしで macOS を使用してクリーンなデバイス (iPad) にアプリケーションをインストールする手順について説明します。< /p>

まず、Linux 用のビルド ツールチェーンをインストールしましょう。
https://github.com/tpoechtrager/cctools-port

ツールチェーンをリポジトリからダウンロードし、Godot Engine Web サイトの指示に従ってインストールを完了する必要があります。
https://docs.godotengine.org/ru/latest/development/compiling/cross-compiling_for_ios_on_linux.html

現時点では、Xcode dmg をダウンロードし、そこから SDK をコピーして cctools-port をビルドする必要があります。この段階は macOS で簡単に完了でき、インストールされた Xcode から必要な SDK ファイルをコピーするだけです。アセンブリが成功すると、ターミナルにはクロスコンパイラー ツールチェーンへのパスが含まれます。

次に、iOS 用の SDL アプリケーションの構築を開始できます。 cmake を開いて、C++ コードをビルドするために必要な変更を追加しましょう。

SET(CMAKE_SYSTEM_NAME Darwin)
SET(CMAKE_C_COMPILER arm-apple-darwin11-clang)
SET(CMAKE_CXX_COMPILER arm-apple-darwin11-clang++)
SET(CMAKE_LINKER arm-apple-darwin11-ld)

これで、cmake と make を使用してコンパイルできるようになりますが、$PATH をクロスコンパイラー ツールチェーンに追加することを忘れないでください。


PATH=$PATH:~/Sources/cctools-port/usage_examples/ios_toolchain/target/bin

フレームワークや SDL と正しくリンクするために、それらを cmake に記述します。たとえば、ゲーム Space Jaguar の依存関係です。


target_link_libraries(
${FSEGT_PROJECT_NAME}
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libclang_rt.ios.a
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libSDL2.a
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libSDL2_mixer.a
${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/libSDL2_image.a
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreServices.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/ImageIO.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/Metal.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/AVFoundation.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/GameController.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreMotion.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreGraphics.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/AudioToolbox.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/CoreAudio.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/QuartzCore.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/OpenGLES.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/UIKit.framework"
"${FLAME_STEEL_PROJECT_ROOT_DIRECTORY}/scripts/buildScripts/ios/resources/libs/Foundation.framework"
)

私の場合、SDL、SDL_Image、SDL_mixer ライブラリは、静的リンクのために事前に macOS 上の Xcode でコンパイルされています。 Xcode からコピーされたフレームワーク。 libclang_rt.ios.a ライブラリも追加されました。これには、iOS 固有のランタイム呼び出し (isOSVersionAtLeast など) が含まれます。 Android と同様に、OpenGL ES を操作して、モバイル バージョンでサポートされていない機能を無効にするためのマクロが含まれています。

ビルドの問題をすべて解決したら、arm 用にアセンブルされたバイナリを取得する必要があります。次に、ジェイルブレイクなしでデバイス上でアセンブルされたバイナリを実行することを検討してみましょう。

macOS では、開発者プログラムの料金を支払わずに、Xcode をインストールし、Apple ポータルに登録します。 Xcode でアカウントを追加します ->設定 ->アカウント、空のアプリケーションを作成し、実際のデバイス上に構築します。組み立て中に、デバイスは無料の開発者アカウントに追加されます。アセンブリと起動後、アーカイブを構築する必要があります。これを行うには、[汎用 iOS デバイスと製品] を選択します。アーカイブ。アーカイブが構築されたら、そこからembedded.mobileprovisionファイルとPkgInfoファイルを抽出します。デバイスへのビルド ログから、正しい署名キーを含むコードデザイン行、拡張子 app.xcent を持つ資格ファイルへのパスを見つけてコピーします。

アーカイブから .app フォルダーをコピーし、アーカイブ内のバイナリを Linux のクロスコンパイラーでコンパイルされたバイナリ (SpaceJaguar.app/SpaceJaguar など) に置き換えてから、必要なリソースを .app に追加し、アーカイブからの .app 内の PkgInfo およびembedded.mobileprovision ファイルの整合性を確認するには、必要に応じて再度コピーします。 codesign コマンド – を使用して .app に再署名します。 codedesign には、署名用の入力キー、資格ファイルへのパス (.plist 拡張子で名前変更可能) が必要です。

再署名した後、Payload フォルダーを作成し、.app 拡張子の付いたフォルダーをそこに移動し、ルートに Payload を含む zip アーカイブを作成し、.ipa 拡張子を付けてアーカイブの名前を変更します。その後、Xcode でデバイスのリストを開き、新しい ipa をデバイスのアプリケーションのリストにドラッグ アンド ドロップします。この方法では、Apple Configurator 2 によるインストールは機能しません。再署名が正しく行われると、新しいバイナリを含むアプリケーションが 7 日間の証明書とともに iOS デバイス (iPad など) にインストールされます。テスト期間にはこれで十分です。

ソース

https://github.com/tpoechtrager/cctools-port
https://docs.godotengine.org/ru/latest/development/compiling/cross-compiling_for_ios_on_linux.html
https://jonnyzzz.com/blog/2018/06/13/link-error-3/
https://stackoverflow.com/questions/6896029/re-sign-ipa-iphone
https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html

C++ SDL アプリケーションの Android への移植

この投稿では、3D エディタのプロトタイプを移植した私の経験について説明します キューブ アート プロジェクト
まず、赤い 3D キューブ カーソルを持つエディタがエミュレータで実行されている結果を見てみましょう。

組み立てを成功させるには、次のことを行う必要がありました:

<オル>

  • 最新の Android SDK と NDK をインストールします(NDK バージョンは新しいほど良いです)
  • SDL2 ソース コードをダウンロードし、そこからテンプレートを取得して Android アプリケーションを構築します。
  • SDL イメージ、SDL ミキサーをアセンブリに追加します。
  • ゲーム エンジンとツールキットのライブラリ、それらの依存関係 (GLM、モダン C++ 用の JSON) を追加します
  • アセンブリ ファイルを Gradle に適合させる。
  • Android との互換性のために C++ コードを調整し、影響を受けるプラットフォーム依存コンポーネント(OpenGL ES、グラフィックス コンテキストの初期化)を変更する
  • エミュレータ上でプロジェクトをビルドしてテストします。
  • プロジェクト テンプレート

    ソース SDL、SDL イメージ、SDL ミキサーの読み込み:
    https://www.libsdl.org/download-2.0.php
    docs フォルダーには、Android プロジェクト テンプレートを使用するための詳細な手順が含まれています。 android-project ディレクトリを別のフォルダーにコピーするか、シンボリックリンクを作成するか、SDL フォルダーを android-project/app/jni にコピーします。
    avd フラグを正しい識別子に置き換えて、Sdk:

    ディレクトリから Android エミュレータを起動します。

    cd ~/Android/Sdk/emulator
    ./emulator -avd Pixel_2_API_24
    
    

    スクリプトでパスを指定し、プロジェクトをアセンブルします。

    rm -rf app/build || true
    export ANDROID_HOME=/home/demensdeum/Android/Sdk/
    export ANDROID_NDK_HOME=/home/demensdeum/Android/android-ndk-r21-beta2/
    ./gradlew clean build
    ./gradlew installDebug
    
    

    ファイルからの C コードを含む SDL プロジェクト テンプレートをアセンブルする必要があります

    android-sdl-test-app/cube-art-project-android/app/jni/src/YourSourceHere.c
    
    

    依存関係

    SDL_image、SDL_mixer のソース コードをアーカイブからダウンロードします。
    https://www.libsdl.org/projects/SDL_image/
    https://www.libsdl.org/projects/SDL_mixer/

    プロジェクトの依存関係(共有ライブラリなど)を読み込みます。
    https://gitlab.com/demensdeum/FlameSteelCore/
    https://gitlab.com/demensdeum/FlameSteelCommonTraits
    https://gitlab.com/demensdeum/FlameSteelBattleHorn
    https://gitlab.com/demensdeum/FlameSteelEngineGameToolkit/
    https://gitlab.com/demensdeum/FlameSteelEngineGameToolkitFSGL
    https://gitlab.com/demensdeum/FSGL
    https://gitlab.com/demensdeum/cube-art-project

    これらすべてを app/jni にアップロードし、各「モジュール」を別のフォルダー (例: app/jni/FSGL) にアップロードします。次に、Application.mk および Android.mk ファイルの動作するジェネレーターを見つけるオプションがあります。私はそれらを見つけられませんでしたが、おそらく CMake に基づく簡単な解決策があるでしょう。リンクをクリックして、Android NDK のアセンブリ ファイル形式について学び始めてください。
    https://developer.android.com/ndk/guides/application_mk
    https://developer.android.com/ndk/guides/android_mk

    NDK のさまざまな APP_STL 実装についてもお読みください。
    https://developer.android.com/ndk/guides/cpp-support.html

    慣れた後、「モジュール」ごとに Android.mk ファイルを作成し、続いて共有ライブラリ Cube-Art-Project のサンプル アセンブリ ファイルを作成します。

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    APP_STL := c++_static
    APP_CPPFLAGS := -fexceptions
    LOCAL_MODULE := CubeArtProject
    LOCAL_C_INCLUDES := $(LOCAL_PATH)/src $(LOCAL_PATH)/../include $(LOCAL_PATH)/../include/FlameSteelCommonTraits/src/FlameSteelCommonTraits
    LOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)/src/
    
    define walk
    $(wildcard $(1)) $(foreach e, $(wildcard $(1)/*), $(call walk, $(e)))
    endef
    
    ALLFILES = $(call walk, $(LOCAL_PATH)/src)
    FILE_LIST := $(filter %.cpp, $(ALLFILES))
    $(info CubeArtProject source code files list)
    $(info $(FILE_LIST))
    LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
    
    LOCAL_SHARED_LIBRARIES += FlameSteelCore
    LOCAL_SHARED_LIBRARIES += FlameSteelBattleHorn
    LOCAL_SHARED_LIBRARIES += FlameSteelCommonTraits
    LOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkit
    LOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkitFSGL
    LOCAL_SHARED_LIBRARIES += FSGL
    LOCAL_SHARED_LIBRARIES += SDL2
    LOCAL_SHARED_LIBRARIES += SDL2_image
    
    LOCAL_LDFLAGS := -static-libstdc++
    include $(BUILD_SHARED_LIBRARY)
    
    

    経験豊富な CMake ユーザーなら最初の行からこの構成を理解できるでしょう。形式は非常に似ており、Android.mk には GLOB_RECURSIVE がないため、walk 関数を使用してソース ファイルを再帰的に検索する必要があります。

    C コードではなく C++ をビルドするために Application.mk、Android.mk を変更します。

    APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
    APP_PLATFORM=android-16
    APP_STL := c++_static
    APP_CPPFLAGS := -fexceptions
    
    

    YourSourceHere.c -> YourSourceHere.cpp の名前を変更し、エントリを grep し、アセンブリ内のパスを変更します。

    app/jni/src/Android.mk:LOCAL_SRC_FILES := YourSourceHere.cpp
    
    

    次に、プロジェクトをビルドしてみます。ヘッダーがないことに関するコンパイラーからのエラーが表示された場合は、Android.mk 内のパスが正しいことを確認してください。 「未定義の参照」などのリンカーからのエラーがある場合は、アセンブリ内のソース コード ファイルが正しく指定されていることを確認してください。リストは、Android.mk ファイルで $(info $(FILE_LIST)) を指定することで追跡できます。 LOCAL_SHARED_LIBRARIES キーのモジュールを使用し、FSGL などの LD を介して正しいリンクを使用する、二重リンク メカニズムを忘れないでください。

    LOCAL_LDLIBS := -lEGL -lGLESv2
    
    

    適応と発売

    いくつかの点を変更する必要がありました。たとえば、iOS および Android のビルドから GLEW を削除し、一部の OpenGL 呼び出しの名前を変更し、EOS ポストフィックス (glGenVertexArrays -> glGenVertexArraysOES) を追加し、欠落している最新のデバッグ関数用のマクロを追加しました。おまけに、マクロを示す GLES2 ヘッダーが暗黙的に組み込まれていることです。 GL_GLEXT_PROTOTYPES 1:

    #define GL_GLEXT_PROTOTYPES 1
    #include "SDL_opengles2.h"
    
    

    また、最初の起動時に黒い画面が表示され、「E/libEGL: validate_display:255 error 3008 (EGL_BAD_DISPLAY)」のようなエラーが表示され、SDL ウィンドウの初期化、OpenGL プロファイルが変更され、すべてが機能しました。

    SDL_DisplayMode mode;
    SDL_GetDisplayMode(0,0,&mode);
    int width = mode.w;
    int height = mode.h;
    
    window = SDL_CreateWindow(
                title,
                0,
                0,
                width,
                height,
                SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE
            );
    
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
    

    エミュレータでは、アプリケーションはデフォルトで SDL アイコンと「Game」という名前でインストールされます。

    CMake に基づいてアセンブリ ファイルを自動的に生成するか、すべてのプラットフォームのアセンブリを Gradle に移行する可能性を検討する必要があります。ただし、CMake は現在進行中の C++ 開発における事実上の選択肢であり続けています。

    ソースコード

    https://gitlab.com/demensdeum/android- sdl-テスト-アプリ
    https://gitlab.com/demensdeum/android-sdl-test-app/tree/master/cube-art-project-android

    ソース

    https://developer.android.com/ ndk/guides/cpp-support.html
    https://developer.android.com/ndk/guides/application_mk
    https://developer.android.com/ndk/guides/android_mk
    https://lazyfoo.net/tutorials/SDL/52_hello_mobile/android_windows/index.php
    https://medium.com/androiddevelopers/getting-started-with-c-and-android-native-activities-2213b402ffff

    SDL2 – OpenGL ES

    I love Panda3D game engine. But right now this engine is very hard to compile and debug on Microsoft Windows operation system. So as I said some time ago, I begin to develop my own graphics library. Right now it’s based on OpenGL ES and SDL2.
    In this article I am going to tell how to initialize OpenGL ES context and how SDL2 helps in this task. We are going to show nothing.

    King Nothing

    First of all you need to install OpenGL ES3 – GLES 3 libraries. This operation is platform dependant, for Ubuntu Linux you can just type sudo apt-get install libgles2-mesa-dev. To work with OpenGL you need to initialize OpenGL context. There is many ways to do that, by using one of libraries – SDL2, GLFW, GLFM etc. Actually there is no one right way to initialize OpenGL context, but I chose SDL2 because it’s cross-platform solution, code will look same for Windows/*nix/HTML5/iOS/Android/etc.

    To install sdl2 on Ubuntu use this command sudo apt-get install libsdl2-dev

    So here is OpenGL context initialization code with SDL2:

        SDL_Window *window = SDL_CreateWindow(
                "SDL2 - OGLES",
                SDL_WINDOWPOS_UNDEFINED,
                SDL_WINDOWPOS_UNDEFINED,
                640,
                480,
                SDL_WINDOW_OPENGL
                );
    	    
    
        SDL_GLContext glContext = SDL_GL_CreateContext(window);
    

    After that, you can use any OpenGL calls in that context.

    Here is example code for this article:
    https://github.com/demensdeum/OpenGLES3-Experiments/tree/master/3sdl-gles
    https://github.com/demensdeum/OpenGLES3-Experiments/blob/master/3sdl-gles/sdlgles.cpp

    You can build and test it with command cmake . && make && ./SDLGles