Plans for Android Studio

In terms of this link Convert Android Eclipse ADT game project into Android Studio project, I found it useful for importing the initial project into Android Studio and setting up the ndk.dir setting correctly.

In terms of actually building the project, I actually ended up having to edit the build files and ended up using a script called jnibuild.sh to build from the command line. It’s much simpler and easier to maintain, to simply edit the Android makefiles than to try to configure gradle to pass makefile related flags to the ndk layer.

In terms of edits to the build files, these are the changes that I made:


diff --git a/proj.studio/testgame/src/main/jni/Android.mk b/proj.studio/testgame/src/main/jni/Android.mk
index 75e64b0..da85a68 100644
--- a/proj.studio/testgame/src/main/jni/Android.mk
+++ b/proj.studio/testgame/src/main/jni/Android.mk
@@ -2,19 +2,38 @@ LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 
-$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)
-$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)
-$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)
+$(call import-add-path,/Users/gino/cocos2d-x-3.4)
+$(call import-add-path,/Users/gino/cocos2d-x-3.4/external)
+$(call import-add-path,/Users/gino/cocos2d-x-3.4/cocos)
 
 LOCAL_MODULE := cocos2dcpp_shared
 
 LOCAL_MODULE_FILENAME := libcocos2dcpp
-LOCAL_SRC_FILES := hellocpp/main.cpp \
-                   ../../Classes/AppDelegate.cpp \
-                   ../../Classes/HelloWorldScene.cpp
+FILE_LIST := $(wildcard $(LOCAL_PATH)/../../../../../Classes/*.cpp) \
+       $(wildcard $(LOCAL_PATH)/../../../../../Classes/*.c) \
+       $(wildcard $(LOCAL_PATH)/../../../../../Classes/swig/*.cpp) \
+
+
+
+LOCAL_SRC_FILES := hellocpp/main.cpp
+
+LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%)
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../../../Classes \
+                   $(LOCAL_PATH)/../../../../../Classes/swig
+
+
+# following flag will cause assert() to abort program execution:
+LOCAL_CFLAGS += -UNDEBUG
+
+# need to disable SSE instruction generation if we're compiling for x86:
+ifeq ($(TARGET_ARCH_ABI),x86)
+LOCAL_CFLAGS += -U__SSE__
+LOCAL_CPPFLAGS += -U__SSE__
+endif
+
 
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
 
diff --git a/proj.studio/testgame/src/main/jni/Application.mk b/proj.studio/testgame/src/main/jni/Application.mk
index 02b8eab..2783509 100644
--- a/proj.studio/testgame/src/main/jni/Application.mk
+++ b/proj.studio/testgame/src/main/jni/Application.mk
@@ -1,4 +1,5 @@
 APP_STL := gnustl_static
+APP_PLATFORM := android-10
 
 APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -std=c++11 \
        -fsigned-char \
@@ -8,6 +9,10 @@ APP_LDFLAGS := -latomic
 
 #APP_ABI := armeabi armeabi-v7a x86
 APP_ABI := x86
+#APP_ABI := armeabi
+
+NDK_TOOLCHAIN_VERSION := 4.9
+
 

(BTW, you can safely skip/ignore the references to the Classes/swig related directory. I use some swig generated code, which I kept under Classes/swig, which needed to be compiled in.)

Also, I needed to add:

  sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call

to the file build.gradle, so that Android Studio would not try to build the jni source code at all.

Looks like Android Studio really doesn’t support ndk builds, aside from being instructed to ignore them, which makes it possible to just invoke ndk-build from the command line and not worry about Android Studio trying to recompile it on its own.

2 Likes

Continuing the discussion from Plans for Android Studio:

[quote=“ginobean, post:21, topic:18713”]
In terms of this link [Convert Android Eclipse ADT game project into Android Studio project][1], I found it useful for importing the initial project into Android Studio and setting up the ndk.dir setting correctly.[/quote]

Thanks @ginobean for your accurate answer.

It happened that I follow the exact tutorial, with the final versions of all the lib and programs and, after modifying some versioning problems among other things, I could continue with the whole process. However, just at the end, I am getting an error that doesn’t let me compile. I spoke with Naeem (the owner of the tut) and I haven’t resolved it.

I am copying here the problem I expose in his blog:

[quote]
…At the moment of compiling, I got an error at synchronizing the build.gradle file. When I try to build it, I get an error:
Error:(17, 0) Could not find property ‘sourceSets’ on root project ‘proj.androidstudio’.

It takes me to that file and points me the error in (appears with a different background color):

dependencies {
classpath ‘com.android.tools.build:gradle:1.1.0’
}

I discovered that the problem is also in the build.gradle file in this place (which also has a different background color):

dependencies {
compile project(’:libcocos2dx’)
}

Which when I try to sync, it throws the same error. If I mouse over it, it reads:
‘dependencies’ cannot be applied to ‘(groovy.lang.Closure)’

I went to Many places on the net and spent time looking for answers before coming here. I modify many properties of the files you also modified, but mainly I found out that I had some missing properties inside the build.gradle file. I grabbed many modified build.gradle files I found and at the end I modified it like this:

compileSdkVersion 24
buildToolsVersion “24.1.2”

minSdkVersion 10
targetSdkVersion 24
versionCode 1
versionName “1.0”

runProguard false
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’

targetSdkVersion gives me an error if I put it in 14, reads “Not targeting the last version of Android” That’s why I changed it to 24, the same as the other ones.

Even after all this changes, I still can’t compile the program. [/quote]

I feel that it has to be a minor problem, maybe related to the libcocos2dx dependency, I guess.

I tried to follow your guide but honestly I got lost. I have learned so much during this week about all this, but I accept I am new and still learning.

Do you have an idea why I am still getting that error? Maybe you encounter this same problem. If so, can you give me a more digerible guide on how you successfuly accomplish it?

I am thinking to download the latest version of the Eclipse + ADT bundle but I refuse to use it, I believe that I should start with the right foot from the beginning.

Thanks a ton @ginobean for your support. Please, keep having a wonderful day!

Sounds like you probably have the sourceSets in the wrong area.

Here’s what my build.gradle file looks like:
testgame/build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22   // generally, this should be the same as targetSdkVersion
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.mydomain.testgame"
        minSdkVersion 10
        targetSdkVersion 22  // always target the latest api version

        ndk {
            moduleName "cocos2dcpp_shared"
        }
    }


    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'my-proguard-rules.txt'
        }
    }

    sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call

}



configurations {
    antcp {
      description = 'ant classpath'
      transitive = true
      exclude module: 'ant'
    }
}


dependencies {
    compile project(':libcocos2dx')
    antcp "ant-contrib:ant-contrib:1.0b3"
}




 task jnibuild << {
    ant.taskdef resource: "net/sf/antcontrib/antcontrib.properties",
                classpath: configurations.antcp.asPath
    ant.ant antfile: "custom_rules.xml", target: "jnibuild", dir: "."
  }


 task jnibuild_clean << {
    ant.taskdef resource: "net/sf/antcontrib/antcontrib.properties",
                classpath: configurations.antcp.asPath
    ant.ant antfile: "custom_rules.xml", target: "jnibuild_clean", dir: "."
  }




task syncAssetsFromResources ( type : Sync) {
    from '../../Resources'
    into 'src/main/assets'
}



// WARNING: this will copy the contents of ../../Resources into src/main/assets !
// any existing assets under src/main/assets will be *overwritten*, so only enable this dependency
// if you understand exactly what this syncAssetsFromResources is intended to do !
//
// preBuild.dependsOn syncAssetsFromResources

custom_rules.xml

<?xml version="1.0" encoding="UTF-8"?>

<project name="my_custom_rules"  >




<target name="jnibuild" >

  <exec executable="/usr/local/bin/jnibuild.sh">
  </exec>

</target>


<target name="jnibuild_clean" >

  <exec executable="/usr/local/bin/jnibuild.sh">
    <arg value="clean" />
  </exec>

</target>



</project>

jnibuild.sh (my version)
(note that this jnibuild.sh script assumes that you’re using git to version control your project. It actually
looks for the .git directory to locate the top level of your project…)

#!/usr/bin/bash
#
# The purpose of this script is to aide building native libs in 
# Android Studio using recent versions of Gradle 0.8.+. As of this 
# version of the Gradle plugin building jni doesn't work just yet.
# So as a workaround you need to disable Gradle from building 
# jni sources by adding the following to your project's build.gradle:
#
# android {
#   sourceSets.main {
#	    jni.srcDirs = []
#   }
# }
#
# For now you need to build native code manually with ndk-build.
# I highly recommend creating a jni/Application.mk file because 
# you can specify everything you need built:
#
# APP_ABI := all
# APP_PLATFORM := android-19
# APP_PROJECT_PATH := /path/to/project/src/main
#
# This script invokes ndk-build, setting the obj output folder
# to the build/jni-obj folder, to align more with Android Studio,
# and the lib output folder to jniLibs.
# 
# Finally, Gradle will pick up these libs in the jniLibs folder
# automatically now.  No need to tell Gradle where to look for 
# 'prebuilts'.
#
# The project path is hardcoded.  I put this script in my path
# in order to invoke a jni build from anywhere.  You can 
# modify it as needed, or put yours in your project somewhere
# and get Gradle to run it for you.
#
# You can also do 'jnibuild.sh clean' if needed.
# To see verbose command line info, use the V=1 flag:
#    jnibuild.sh V=1
#

convertSeconds() {
    ((h=${1}/3600))
    ((m=(${1}%3600)/60))
    ((s=${1}%60))
    printf "%02d:%02d:%02d" $h $m $s
}


START_TIME=$(date +%s)

original_dir="$PWD"
wd="$PWD"

MY_MODULE_ROOT=

while [[ "$wd" != "/" ]]
do
    if [[ -d .git ]]
    then
        MY_MODULE_ROOT="$PWD"
        break # we're at the top level..
    fi

    builtin cd ..
    wd="$PWD"
done

if [[ "$MY_MODULE_ROOT" == "" ]]
then
    echo "Was unable to locate your module's root directory."
    exit -1
fi


jnidir=$(find . -name 'jni' | egrep -v intermediates | grep main | head -1)

if [[ "${jnidir}" == "" ]]
then
    echo "Was unable to locate your project's jni directory."
    exit -1
fi

builtin cd "${jnidir}/.."

# set this to the directory where your jni folder resides...
PROJECTDIR="${PWD}"

if [[ ! -d "${PROJECTDIR}" ]]
then
    echo "unexpectedly, ${PROJECTDIR} is not a directory !"
    echo "(cannot safely continue..)"
    exit -1
fi


echo "PROJECTDIR -> ${PROJECTDIR} "

pushd "${PROJECTDIR}"

(	# subshell context for exported variables
export NDK_OUT="$PROJECTDIR/../../build/jni-obj";
export NDK_LIBS_OUT="$PROJECTDIR/jniLibs";
ndk-build -C "${PROJECTDIR}" $*
)

popd


END_TIME=$(date +%s)
DIFF_TIME=$(( $END_TIME - $START_TIME ))
fmtStr=$(convertSeconds $DIFF_TIME)

# say 'jay n eye build has finished'

echo "jnibuild.sh duration: $fmtStr "

@ginobean nice tip! i was able to get my game running but i still have some problems, any idea how i debug native cpp, in android studio?

I usually just insert log statements to help debug native cpp on Android. I am not aware of any current Android Studio features that would support debugging native cpp.

Hi @ginobean can you just send a hello world program for cocos2dx-js ? that would be great :slight_smile: thanks in advance

I’m not familar with cocos2dx-js.

NDK support in Android studio is now available for test (update android studio from canary)