Building Lines Game for MacOS and iOS

To build my app for iOS I tried to run CMake from the command line without QT Creator:

cmake -S /Users/admin/dev/repos/examples/src/LinesGame/LinesGameQt -B . -DCMAKE_GENERATOR:STRING=Xcode \
  -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=./.qtc/package-manager/auto-setup.cmake -DQT_QMAKE_EXECUTABLE:FILEPATH=/Users/admin/dev/libs/QT6/release/iOS/bin/qmake6 \
  -DCMAKE_PREFIX_PATH:PATH=/Users/admin/dev/libs/QT6/release/iOS \
  -DCMAKE_C_COMPILER:FILEPATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang \
  -DCMAKE_CXX_COMPILER:FILEPATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ \
  -DCMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/admin/dev/libs/QT6/release/iOS/lib/cmake/Qt6/qt.toolchain.cmake \
  -DCMAKE_OSX_ARCHITECTURES:STRING=arm64 -DCMAKE_OSX_SYSROOT:STRING=iphoneos -DCMAKE_CXX_FLAGS_INIT:STRING= \
  -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM:STRING=XXXXXXX

but it requires .qtc to be copied into build directory before running CMake, but it is not clear where is it:

admin@son Qt Creator % find . -iname ".qtc"
admin@son Qt Creator % cd Applications
admin@son Applications % find . -iname ".qtc"
admin@son Applications % find . -iname "package-manager"
admin@son Applications % cd ~/dev/libs/QT6
admin@son QT6 % find . -iname ".qtc"
admin@son QT6 % find . -iname "package-manager"

Another idea was to add the following prior to project in my CMake:

cmake_minimum_required(VERSION 3.21.3)

if (APPLE)
    # The variable CMAKE_OSX_DEPLOYMENT_TARGET must initialized as a cache variable prior to the first project() command
    # Your code won't work the variable IOS cannot be used before the project call. It will always be false.
    # You must use the CMAKE_SYSTEM_NAME instead
    message("CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
    # Probably QT Creator specifies -DCMAKE_SYSTEM_NAME=iOS in the command line, but I am not sure.
    if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
        #Does not take an effect, the workaround is setting XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET.
        set(CMAKE_OSX_DEPLOYMENT_TARGET "14.0" CACHE STRING "Minimum iOS deployment version")
    else()
        # Build for Apple Silicon.
        if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
            set(CMAKE_OSX_ARCHITECTURES arm64 x86_64)
        endif()
        set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum MacOS deployment version")
    endif()
    message("CMAKE_OSX_DEPLOYMENT_TARGET has been set to ${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()

project(LinesGameQt LANGUAGES CXX)

but it does not work well enough because CMAKE_SYSTEM_NAME is empty with a clean build and is defined as iOS when I restart QT Creator.

The next possible alternative is defining CMAKE_OSX_DEPLOYMENT_TARGET and CMAKE_OSX_ARCHITECTURES directly in QT Creator settings that are the following by default for iOS:

For iOS production builds I specify CMAKE_OSX_DEPLOYMENT_TARGET=14.0 and CMAKE_OSX_ARCHITECTURES=arm64 and CMake generates the following in XCode project file:

D8BA168A2DF84337BA721D22 /* Release */ = {
	isa = XCBuildConfiguration;
	buildSettings = {
		ARCHS = arm64;
		DEVELOPMENT_TEAM = XXXXXXX;
		IPHONEOS_DEPLOYMENT_TARGET = 14.0;
		SDKROOT = iphoneos;
		SWIFT_COMPILATION_MODE = wholemodule;
		SYMROOT = /Users/admin/dev/repos/examples/src/LinesGame/LinesGameQt/build/Qt_6_7_0_iOS_Release/build;
	};
	name = Release;
};

For MacOS production builds I specify CMAKE_OSX_DEPLOYMENT_TARGET=11.0 and CMAKE_OSX_ARCHITECTURES=arm64;x86_64 to build for Apple Silicon and CMake generates the following in XCode project file:

AC829B0DBACA487F8FFF4819 /* Release */ = {
	isa = XCBuildConfiguration;
	buildSettings = {
		ARCHS = "arm64 x86_64";
		MACOSX_DEPLOYMENT_TARGET = 11.0;
		SDKROOT = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk;
		SWIFT_COMPILATION_MODE = wholemodule;
		SYMROOT = /Users/admin/dev/repos/examples/src/LinesGame/LinesGameQt/build/Desktop_x86_darwin_generic_mach_o_64bit/build;
	};
	name = Release;

For MacOS debug builds and for iOS Simulator I specify CMAKE_OSX_ARCHITECTURES=x86_64.

Using Additional CMake options:

Local build for MacOS:

-DLINESGAME_SIGN_APP:BOOL=OFF

In QT Creator:

Building for MacOS:

-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=11.0 -DCMAKE_OSX_ARCHITECTURES:STRING=arm64;x86_64

Building for iOS:

-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=14.0 -DCMAKE_OSX_ARCHITECTURES:STRING=arm64

Building to iOS with Advertising

To prevent the following error:

ld: library 'Pods-AdExample' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Add ${PODS_CONFIGURATION_BUILD_DIR} to Release->LIBRARY_SEARCH_PATHS section of LinesGameQt.xcodeproj/project.pbxproj project in XCode:

Building with XCode from command line

ln -s $(pwd)/Podfile $(pwd)/build/Qt_6_7_0_iOS_Release_Simulator/Podfile
cd  build/Qt_6_7_0_iOS_Release_Simulator
pod install --repo-update
xcodebuild -list -project AdExample.xcodeproj
xcodebuild -workspace AdExample.xcworkspace -scheme AdExample -configuration Release build

cd  build/Qt_6_7_0_iOS_Debug_Simulator
xcodebuild -workspace LinesGameQt.xcworkspace -scheme LinesGameQt -configuration Debug build

or

xcodebuild -workspace AdExample.xcworkspace -scheme AdExample -configuration Release build > xlog.txt 2>&1 &
tail -f xlog.txt
grep -A 5 -B 4 "error:" xlog.txt

xcodebuild -workspace LinesGameQt.xcworkspace -scheme LinesGameQt -configuration Debug build > xlog.txt 2>&1 &

Building without workspace:

xcodebuild -scheme LinesGameQt -configuration Release build

9 Responses to Building Lines Game for MacOS and iOS

  1. dmitriano says:

    Compiling a sample code with clang:
    clang++ -std=c++20 -pthread a.cpp -o a

  2. dmitriano says:

    Guideline 1.3 – Safety – Kids Category

    You have selected the Kids category for your app, but it includes links out of the app or engages in commerce without first obtaining parental permission.

    Next Steps

    To resolve this issue, please update your app to add a parental gate before the user can leave the app or engage in commerce. You must also ensure that the parental gate cannot be disabled.

    **************

    how to implement a parental gate for iOS apps in the kid’s section
    https://stackoverflow.com/questions/19129734/how-to-implement-a-parental-gate-for-ios-apps-in-the-kids-section

    Parental Gate SDK for iOS Apps
    http://www.claireware.com/blog_files/ios-parental-gate-sdk.php

    The Kids Category
    https://developer.apple.com/app-store/kids-apps/

  3. dmitriano says:

    Parental Gate For iOS
    Applications made for kids very often contain screens that are designed for adults, e.g. in app purchases, feedback forms, etc. Apple requires those screens to be protected by Parental Gate.
    https://github.com/hossinasaadi/ParentalGate

  4. dmitriano says:

    App store link for “rate/review this app”
    https://stackoverflow.com/questions/3124080/app-store-link-for-rate-review-this-app

    let urlStr = "https://itunes.apple.com/app/id\(appID)?action=write-review" // (Option 2) Open App Review Page
    let url = URL(string: urlStr), UIApplication.shared.canOpenURL(url) else { return }

  5. dmitriano says:

    Manually request a review
    https://developer.apple.com/documentation/storekit/requesting_app_store_reviews#4312600

    let url = "https://apps.apple.com/app/id?action=write-review"

    guard let writeReviewURL = URL(string: url) else {
    fatalError("Expected a valid URL")
    }

    openURL(writeReviewURL)

  6. dmitriano says:

    Not possible to remove App from Kids category, even after 17+ rating
    https://forums.developer.apple.com/forums/thread/682386
    Go to App Information, Edit Age Rating Next uncheck App Made for Kids. thats it

  7. dmitriano says:

    In addition to unlocking the keychain, you might also specify the codesign identity (or set it in your target). Development certs take the form ‘iPhone Developer: Company Inc’, distribution certs like this ‘iPhone Distribution: Company Inc’.
    https://stackoverflow.com/a/7664871/2394762
    xcodebuild -project George.xcodeproj -alltargets -parallelizeTargets -configuration Debug build CODE_SIGN_IDENTITY='iPhone Developer: Company Inc'
    xcodebuild -sdk iphonesimulator

    Most probably your keychain is locked. Try unlocking it before executing the script, you can do it from command line (right before building):
    security unlock -p YourPasswordToKeychain ~/Library/Keychains/login.keychain

    Archive iOS app command line
    https://www.andrewhoog.com/post/how-to-build-an-ios-app-archive-via-command-line/
    xcodebuild archive -scheme "I am Groot" -sdk iphoneos -destination generic/platform=iOS -archivePath ./build/iamgroot.xcarchive

  8. dmitriano says:

    Copying files with destination folder depending on build config
    https://discourse.cmake.org/t/copying-files-with-destination-folder-depending-on-build-config/10686
    COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different

Leave a Reply

Your email address will not be published. Required fields are marked *