Sunday, December 29, 2019

Cocos2D-x Bootstrapping

This is a brain-dump of my learnings with Cocos2D-x.

I'm using an old 1st Edition copy of Roger Engelbert's Cocos2D-x by Example: Beginners Guide which has several learner projects and resources to download.

The book is obviously a bit out of date with respect to Cocos2D and C++ as well, but the algorithms are sound. Studying the book and updating the ideas to C++17 and Cocos2D-x 4.0 is a interesting learning challenge.



I'm using C++ and Xcode on Mac targeting iOS and Android.

My source code is here in my Github.

Downloads

Ensure Cocos2D-x is downloaded, but not installed yet.

Get CMake, the dev environment, Android Studio and Xcode all setup and installed.

The commands below use the Terminal - you type what's after the $ - and they assume you have a working Python 2.7 which should be the case for a stock Mac OSX 10.15.x machine.  I use a setup where my build (binary dependencies & downloads) go in to ${HOME}/build and my source code projects are in ${HOME}/depot - use whatever you know & substitute in for what I have.

Then...

Setup Cocos2D-x

Assuming the Cocos2D zip file was unzipped into ~/build:

~/build/cocos2dx $ ./setup.py

The above command will detect your Xcode and Android toolchain along with the NDK.  Android and the NDK should have been installed in ~/Library/

After its finished source in the new environment variables the command adds to your profile:

~/build/cocos2dx $ . ~/.bash_profile

Create a new project

From a directory where you normally store projects, eg source code, run the cocos command to generate your new game:

~/depot $ cocos new -p au.com.smithsoft.skydefence -l cpp skydefence
> Copy template into /Users/sez/depot/cocos2dx/skydefence
> Copying Cocos2d-x files...
> Rename project name from 'HelloCpp' to 'skydefence'
> Replace the project name from 'HelloCpp' to 'skydefence'
> Replace the project package name from 'org.cocos2dx.hellocpp' to 'au.com.smithsoft.skydefence'
> Replace the Mac bundle id from 'org.cocos2dx.hellocpp' to 'au.com.smithsoft.skydefence'
> Replace the iOS bundle id from 'org.cocos2dx.hellocpp' to 'au.com.smithsoft.skydefence'

Note that if you've had multiple versions of Cocos2D installed it will be the directory where the cocos command line tool is located that determines which cocos version you use (unless you stipulate otherwise).  If you've run setup.py as above it will have modified your shell for you.

~/depot/cocos2dx $ which cocos
/Users/sez/build/cocos2d-x/tools/cocos2d-console/bin/cocos

Create iOS, Android & Mac

From the project that was created, run the cocos tool which will invoke the Cmake command line to run a generator for Xcode that creates the project files and then builds the project.  Same for Android.

~/depot/cocos2dx $ cd skydefence
~/depot/cocos2dx/skydefence $ cocos compile . -p ios

Building mode: debug

running: 'cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator'



-- PROJECT_NAME:skydefence

-- PROJECT_SOURCE_DIR:/Users/sez/depot/cocos2dx/skydefence

-- COCOS2DX_ROOT_PATH:/Users/sez/depot/cocos2dx/skydefence/cocos2d

-- CMAKE_MODULE_PATH:/Users/sez/depot/cocos2dx/skydefence/cocos2d/cmake/Modules/

-- PROJECT_BINARY_DIR:/Users/sez/depot/cocos2dx/skydefence/ios-build
-- ENGINE_BINARY_PATH:/Users/sez/depot/cocos2dx/skydefence/ios-build/engine
-- PYTHON_PATH:/usr/bin/python2
-- COCOS_COMMAND_PATH:/Users/sez/build/cocos2d-x/tools/cocos2d-console/bin/cocos
-- HOST_SYSTEM:Darwin
-- CMAKE_GENERATOR: Xcode
-- COCOS2DX_LUAJIT_ROOT:/Users/sez/build/cocos2d-x/tools/cocos2d-console/bin/../plugins/plugin_luacompile/bin
-- cocos_mark_code_files: cocos2d
-- cocos_mark_code_files: skydefence
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/sez/depot/cocos2dx/skydefence/ios-build
running: 'cmake --build . --config Debug'

User defaults from command line:
    HideShellScriptEnvironment = YES
...
echo Build\ all\ projects
Build all projects

** BUILD SUCCEEDED **

Build succeed.


  • Repeat for Android & Mac
~/depot/cocos2dx/skydefence $ cocos compile . -p mac
...not shown...

~/depot/cocos2dx/skydefence $ cocos compile . -p android

Building mode: debug

Using Android Studio project : /Users/sez/depot/cocos2dx/skydefence/proj.android

Building apk...

running: '"/Users/sez/depot/cocos2dx/skydefence/proj.android/gradlew" --parallel --info assembleDebug -PPROP_BUILD_TYPE=cmake'



Downloading https://services.gradle.org/distributions/gradle-5.1.1-all.zip

........................................................................................................................................................................................................................................................................................................................................................................................................


> Task :skydefence:packageDebug
Task :skydefence:packageDebug in libcocos2dx Starting
Caching disabled for task ':skydefence:packageDebug' because:
  Build cache is disabled
Task ':skydefence:packageDebug' is not up-to-date because:
  No history is available.
All input files are considered out-of-date for incremental task ':skydefence:packageDebug'.
Task :skydefence:packageDebug in libcocos2dx Finished
:skydefence:packageDebug (Thread[Execution worker for ':' Thread 11,5,main]) completed. Took 0.447 secs.
:skydefence:assembleDebug (Thread[Execution worker for ':' Thread 11,5,main]) started.

> Task :skydefence:assembleDebug
Task :skydefence:assembleDebug in libcocos2dx Starting
Skipping task ':skydefence:assembleDebug' as it has no actions.
Task :skydefence:assembleDebug in libcocos2dx Finished
:skydefence:assembleDebug (Thread[Execution worker for ':' Thread 11,5,main]) completed. Took 0.0 secs.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.4.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 3m 4s
54 actionable tasks: 42 executed, 12 up-to-date
AAPT2 aapt2-3.5.3-5435860-osx Daemon #0: shutdown
AAPT2 aapt2-3.5.3-5435860-osx Daemon #1: shutdown
AAPT2 aapt2-3.5.3-5435860-osx Daemon #2: shutdown
AAPT2 aapt2-3.5.3-5435860-osx Daemon #3: shutdown
AAPT2 aapt2-3.5.3-5435860-osx Daemon #4: shutdown
Move apk to /Users/sez/depot/cocos2dx/skydefence/bin/debug/android
Build succeed.

iOS Device

Building for an iOS actual phone requires a switch to specify the non-emulator (non-x86) SDK:

~/depot/cocos2dx/skydefence $ cocos compile . -p ios -sdk iphoneos

Note that this will overwrite the details in your generated Xcode project in ios-build, so you wind up with a messed up set of libraries and linker errors relating to x86 vs arm for the cocos libraries. I tried using the -o switch to specify a different output directory but this didn't seem to work.

I suggest build for the iPhone if you ever plan to build for a real device (and you should) and then once the iPhone project is running you can start building for an emulator simply by picking an emulator from the device chooser.

Open Project Files in IDE

You should now be able to open the project files in Xcode

~/depot/cocos2dx/skydefence $ open ios-build/skydefence.xcodeproj


Go thru and do the setup you'd do for a normal project, setting your team so that you can build for a real device.  You'll need to add your account info to the Xcode prefs if you haven't done so already. 

Also update the organisation (and if you want class prefix) fields - these control the text that appears in new file copyright headers so its good to do this early.

Fix-ups Required

Update the General tab with a reasonable Target Version for your project.  I usually use about 1 version back from current (today) so for example at present latest is 13.2 so I have 12.2. I found after the cocos tool and CMake ran it was set to 8.0 - this clashes with the Cocos2D-x API's which use calls that are only available in more recent versions of the iOS API's:

 


Problem with missing Info.plist value

I got this error when trying to run the emulator:

Could not install at this time.  Bundle at path <path name> has missing or invalid CFBundleExecutable in its Info.plist.









To fix enter as the name in the Executable File field in the Info tab indicated in the screenshot below:

$(EXECUTABLE_NAME)


Also when trying to run on the device I had a shower of link errors, related to architectures: the compiler was referencing libraries compiled for the iPhone emulator and it turned out to be that a value pathed into the sdk for the emulator was appearing in the Framework search paths.

If you get these errors (likely because of trying to build the emulator first and then for a device) just delete the value so that the Framework path field is blank as below.

Screenshot annotated to show removing bad Simulator framework path


Troubleshooting

There's a lot of problems that can occur, but its mostly due to not having all the dependencies up-to-date and properly installed.

iOS Troubles

There's a lot of slight glitches in how CMake as configured by the Cocos2D folks is setting up the iOS project.  I had an issue with running the project where at run time it reported a bad setting in the 
With an issue like:

~/depot/cocos2dx/skydefence $ cocos compile . -p ios
Building mode: debug
running: 'cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator'

-- The C compiler identification is AppleClang 11.0.0.11000033
-- The CXX compiler identification is AppleClang 11.0.0.11000033
System is unknown to cmake, create:
Platform/iOS to use this system, please send your config file to cmake@www.cmake.org so it can be added to cmake
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
System is unknown to cmake, create:
Platform/iOS to use this system, please send your config file to cmake@www.cmake.org so it can be added to cmake
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -- broken
CMake Error at /usr/local/Cellar/cmake/3.8.2/share/cmake/Modules/CMakeTestCCompiler.cmake:51 (message):
  The C compiler
  "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
  is not able to compile a simple test program.

  It fails with the following output:

   Change Dir: /Users/sez/depot/cocos2dx/skydefence/ios-build/CMakeFiles/CMakeTmp

  
  Run Build Command:"/usr/bin/xcodebuild" "-project"
  "CMAKE_TRY_COMPILE.xcodeproj" "build" "-target" "cmTC_c96ba"
  "-configuration" "Debug"

  note: Using new build system

  note: Planning build

  note: Constructing build description

  error: unable to resolve product type 'com.apple.product-type.tool' for
  platform 'iphonesimulator' (in target 'cmTC_c96ba' from project
  'CMAKE_TRY_COMPILE')

  error: unable to resolve product type 'com.apple.product-type.tool' for
  platform 'iphonesimulator' (in target 'cmTC_c96ba' from project
  'CMAKE_TRY_COMPILE')


  ** BUILD FAILED **


  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:30 (project)


-- Configuring incomplete, errors occurred!
See also "/Users/sez/depot/cocos2dx/skydefence/ios-build/CMakeFiles/CMakeOutput.log".
See also "/Users/sez/depot/cocos2dx/skydefence/ios-build/CMakeFiles/CMakeError.log".

The above is due to CMake not recognising the current version of clang.  Upgrade cmake to the latest version available either via Brew or download from Kitware as above.


Signing not Set Up

If you haven't set up signing in the IDE and run the cocos compile command using the -sdk iphoneos switch you'll get an error like this:



...<other stuff>....

=== BUILD TARGET foobar OF PROJECT foobar WITH CONFIGURATION Debug ===

Check dependencies
Code Signing Error: Signing for "foobar" requires a development team. Select a development team in the Signing & Capabilities editor.
Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 13.2'

** BUILD FAILED **


The following build commands failed:
Check dependencies
(1 failure)

Error running command, return code: 65.

Just setup Signing in the IDE as discussed above.

Android Troubleshooting

Android problems mostly relate to not having setup your Android build environment fully.  Ensure you can build a hello world app using Android Studio first, and make sure your Android emulators are also ready.

Make sure that any old Android environment variables are not still in your ~/.bash_profile and that the Cocos2D ./setup.py completed without errors, and found your NDK.

Here not setting up the Android Studio properly - which would have been caught by trying to build a hello world - meant that current SDK licenses hadn't been properly installed:


...

Parsing /Users/sez/android/emulator/package.xml

Parsing /Users/sez/android/lldb/2.3/package.xml

Parsing /Users/sez/android/ndk-bundle/package.xml

Parsing /Users/sez/android/patcher/v4/package.xml

Parsing /Users/sez/android/platform-tools/package.xml

Parsing /Users/sez/android/platforms/android-18/package.xml

Parsing /Users/sez/android/platforms/android-22/package.xml
Parsing /Users/sez/android/system-images/android-22/default/armeabi-v7a/package.xml
Parsing /Users/sez/android/system-images/android-22/default/x86/package.xml
Parsing /Users/sez/android/system-images/android-22/google_apis/armeabi-v7a/package.xml
Parsing /Users/sez/android/system-images/android-22/google_apis/x86/package.xml
Parsing /Users/sez/android/tools/package.xml
Checking the license for package Android SDK Build-Tools 27.0.3 in /Users/sez/android/licenses
Warning: License for package Android SDK Build-Tools 27.0.3 not accepted.
Checking the license for package Android SDK Platform 28 in /Users/sez/android/licenses
Warning: License for package Android SDK Platform 28 not accepted.

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':libcocos2dx'.
Failed to install the following Android SDK packages as some licences have not been accepted.
     platforms;android-28 Android SDK Platform 28
     build-tools;27.0.3 Android SDK Build-Tools 27.0.3
  To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
  Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
  
  Using Android SDK: /Users/sez/android

* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 28s
Error running command, return code: 1.