If you have a c++ code base including google breakpad which you can compile using default configuration of ndk[r10d - r11c] and you want to upgrade to c++11, you found the correct blog post which may can help you. Possible reasons for upgrading to c++11 are listed below :

  • Lambda functions

  • auto types

  • Strongly typed enums

You can find all features of c++ 11 in this document

ndk with c++ option

You can configure c++ version of your ndk in Application.mk file by putting c++ flag as below.

APP_CPPFLAGS += -std=c++11

If you are getting errors about finding standart c++ header files, you need to set local include headers by setting the following option.

LOCAL_C_INCLUDES += sources/cxx-stl/gnu-libstdc++/4.9/include

This path is relative to your ndk home directory.

Running ndk-build and possible issues

When you run “ndk-build” after setting the above parameters in your Application.mk file, probably the first issue you will face will be the something the seen below :

In file included from ../../../../Breakpad/android/google_breakpad/../../src/common/memory.h:47:0,
                 from ../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:47,
                 from ../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/minidump_writer.h:40,
                 from ../../../../Breakpad/android/google_breakpad/../../src/client/linux/handler/exception_handler.h:44,
                 from ../../Android/AndroidMain.cpp:20:
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1474:20: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                    ".globl "SYS_SYSCALL_ENTRYPOINT"\n"
                    ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1475:20: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                    ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"
                    ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1481:20: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                    "mov  "SYS_SYSCALL_ENTRYPOINT"@GOT(%0), %0\n"
                    ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1488:28: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                            ".globl "SYS_SYSCALL_ENTRYPOINT"\n"                \
                            ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1489:28: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                            ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"           \
                            ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1496:28: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                            "mov  "SYS_SYSCALL_ENTRYPOINT"@GOT(%%eax), %%eax\n"\
                            ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1768:20: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                    ".globl "SYS_SYSCALL_ENTRYPOINT"\n"
                    ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1769:20: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                    ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"
                    ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1771:20: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
                    "mov "SYS_SYSCALL_ENTRYPOINT"@GOTPCREL(%%rip), %0\n"
                    ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1779:15: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
               ".globl "SYS_SYSCALL_ENTRYPOINT"\n"                             \
               ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1780:15: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
               ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"                        \
               ^
../../../../Breakpad/android/google_breakpad/../../src/third_party/lss/linux_syscall_support.h:1782:15: warning: invalid suffix on literal; C++11 requires a spa
ce between literal and identifier [-Wliteral-suffix]
               "mov "SYS_SYSCALL_ENTRYPOINT"@GOTPCREL(%%rip), %%rcx\n"         \
               ^
In file included from ../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/minidump_writer.h:40:0,
                 from ../../../../Breakpad/android/google_breakpad/../../src/client/linux/handler/exception_handler.h:44,
                 from ../../Android/AndroidMain.cpp:20:
../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:63:15: error: ISO C++ forbids declaration of 'typeof' with no
 type [-fpermissive]
 typedef typeof(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
               ^
../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:63:15: error: typedef 'google_breakpad::typeof' is initialize
d (use decltype instead)
../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:127:25: error: 'elf_aux_val_t' was not declared in this scope

   const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
                         ^
../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:127:38: error: template argument 1 is invalid
   const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
                                      ^
../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:205:19: error: 'elf_aux_val_t' was not declared in this scope

   wasteful_vector<elf_aux_val_t> auxv_;
                   ^
../../../../Breakpad/android/google_breakpad/../../src/client/linux/minidump_writer/linux_dumper.h:205:32: error: template argument 1 is invalid
   wasteful_vector<elf_aux_val_t> auxv_;

In berief, this error log says that typeof definition is missing in some files (linux_dumper.h and eintr_wrapper.h for me). As solution, just locate the header files and put the following “define” line which is replacing standart typeof usage.

#define typeof __typeof__

Breakpad issues are over by applying this typeof defines, but issues are not over yet.

Be careful of the names you give to header files!

If one of your header files’ names is “Math.h”, “Queue.h”, “Algorithm.h” or something like that which already used by c++ standart libraries, you are in trouble. Look at the following error message :

In file included from C:/Development/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/cmath:44:0,
                 from C:/Development/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/random:38,
                 from C:/Development/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/bits/stl_algo.h:65,
                 from C:/Development/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/algorithm:62,
                 from ../../../../AndroidNativeLib/Core/EventSource.h:5,
                 from ../../../../AndroidNativeLib/Core/KeyPressDispatcher.h:6,
                 from ../../../../AndroidNativeLib/Core/KeyPressDispatcher.cpp:1:
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::abs(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:168:9: error: '::fabs' has not been declared
  return ::fabs(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::sqrt(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:176:9: error: '::sqrtf' has not been declared
  return ::sqrtf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::sin(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:183:9: error: '::sinf' has not been declared
  return ::sinf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::cos(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:190:9: error: '::cosf' has not been declared
  return ::cosf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::tan(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:197:9: error: '::tanf' has not been declared
  return ::tanf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::asin(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:204:9: error: '::asinf' has not been declared
  return ::asinf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::acos(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:211:9: error: '::acosf' has not been declared
  return ::acosf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::atan(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:218:9: error: '::atanf' has not been declared
  return ::atanf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::atan2(T, T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:225:9: error: '::atan2f' has not been declared
  return ::atan2f(y,x);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::pow(T, T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:246:9: error: '::powf' has not been declared
  return ::powf(base, power);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::log(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:255:9: error: '::logf' has not been declared
  return ::logf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::log(T, T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:266:10: error: '::logf' has not been declared
  return (::logf(val) / ::logf(base));
          ^
../../../../AndroidNativeLib/Core/math.h:266:24: error: '::logf' has not been declared
  return (::logf(val) / ::logf(base));
                        ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::floor(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:273:9: error: '::floorf' has not been declared
  return ::floorf(val);
         ^
../../../../AndroidNativeLib/Core/math.h: In static member function 'static T Math<T>::ceil(T) [with T = float]':
../../../../AndroidNativeLib/Core/math.h:280:9: error: '::ceilf' has not been declared
  return ::ceilf(val);
....
....
....

I have a header file called “Math.h” in my Core library and ndk-build confusing about names and looking for standart “fabs”, “sqrt”, “sinf”, “cosf” declarations in my Math.h header file. You can handle this issue simply by renaming your header files :)

I have tested this configuration and modifications on ndk-r10d and ndk-r11c and think it would work also on any ndk between these two versions. If you don’t have a specific issue about your project, “ndk-build” process will be completed succesfully :)

I have worked on g++ compiler and google test for running unit tests of my huge c++ code base on MAC-OS-X operating system and integrating on Jenkins server as well. I have learned many things after some investigation and now I think this information can be useful for the people suffering due to same topic.

Using .so files built by android ndk

First of all, my huge c++ code base is used in one of our top games as ndk built .so file and you know this is also a c++ library. It looks reasonable to use this prepared .so file for compiling with google test library and run unit tests, but as far as I see it is impossible. (If there is anyone who can achieve this, please write me!) Here is my stackoverflow topic about this issue :

http://stackoverflow.com/questions/37571476/compiling-with-g-via-linking-so-file-built-by-android-ndk

g++, gcc and GoogleTest configuration as 32-bit

After trying to use .so file, I have decided to compile my code base with g++ compiler with 32-bit option, because I have compiled my code base with 32-bit option with ndk so far and I don’t want to waste my time with some casting, including etc. issues. I assume you already are familiar with GoogleTest and g++, cmake compile concepts. You need gtest-all and gtest-main libraries built on GoogleTest library. You can use the following command to prepare 32-bit google test (For more information about google test)

cmake <YOUR_GOOGLE_TEST_ROOT_DIRECTORY> -DCMAKE_BUILD_TYPE=release32

“CMAKE_BUILD_TYPE=release32” option forces the make process to use 32-bit option. After that you need to compile and obtain object files for gtest-all.cc and gtest_main.cc with 32-bit configuration :

g++ -isystem <YOUR_GOOGLE_TEST_ROOT_DIRECTORY>/include -I./ -pthread -c <YOUR_GOOGLE_TEST_ROOT_DIRECTORY>/src/gtest-all.cc -m32
g++ -isystem <YOUR_GOOGLE_TEST_ROOT_DIRECTORY>/include -I./ -pthread -c <YOUR_GOOGLE_TEST_ROOT_DIRECTORY>/src/gtest_main.cc -m32

“-m32” option here makes the magic for you and compiles with 32-bit option.

Now you can build archive files for using on compiling process of your unit tests.

ar rvs libgtest.a gtest-all.o
ar rvs libgtest_main.a gtest_main.o

Remaining part is just compiling my code base with the libraries libgtest.a and libgtest_main.a and creating an executable file which include all my unit tests. Next week I am gonna publish a blog post like “Google test tutorial” which will be include a simple code base and some unit tests.

One of the most powerful features of android platform is push notifications which you can keep your users informed about new features of your apps or show them some special offers. This service is called as “Amazon Device Messaging(ADM)” on Amazon side.

I assume you already have integrated ADM into your application and trying to test push notifications on your Amazon device. Ok, let’s see those push notifications. We have two “.sh” files which include curl commands for getting access token and sending push notification to your registered device.

Getting Access Token

Firstly you need an access token for sending push notification. Save the following codes as “adm_getAccessToken-test.sh”.

#CLIENT_ID & CLIENT_SECRET parameters are application specific!!!
#You can get from Amazon Developer Console :)!!!
CLIENT_ID=amzn1.application-oa2-client.a...3
CLIENT_SECRET=f69c219247459c141...d1589c88b888eed7b
curl -X POST -H "Cache-Control: no-cache" -H "Postman-Token: e902b849-6578-9c43-92b4-6c55f2e246e9" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials&scope=messaging%3Apush&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET" https://api.amazon.com/auth/O2/token

Here we have two parameters as “CLIENT_ID” and “CLIENT_SECRET”. You can learn your application specific “CLIENT_SECRET” and “CLIENT_ID” from your Amazon Developer Console page.

After replacing these two parameters with your application and device information, you can run this “adm_getAccessToken-test.sh” or copy/paste it into your console. If everything goes well, you will obtain an access token in the result as follows.

{"access_token":"Atc|MQEBIM0Dc27MHx928R3chgdJg8M9QfoefieqnamEN_RZ72psemXLI0M_oFt2w_pXjCE5FFiLTrB2l9B6BU1JxNEXbqV9KV3mLp9RjPS8JID2-jT6XD76KQzP1mHvisQKwrkxrzTc1lV0zOtVkhC5xFVES0pu_aH6VU9Q7plfqR-JEKb0q...nRCzzpYpF2l-iHBnTNF0v4bPNwCTU3ywPGPZVzv0I","scope":"messaging:push","token_type":"bearer","expires_in":3600}

Sending Push Notification

After getting access token, you are ready to send push notification. Save the following codes as “adm_sendPush-test.sh”.

#ACCESS_TOKEN is obtained using adm_getAccessToken-test.sh
#REGISTER_ID is from adb logs.
ACCESS_TOKEN="Atc|MQEBIEshY-...76ouqKrndpvMw2YDHZ--oP6HIGgUgrLqGkI9wx0"
REGISTER_ID="amzn1.adm-registration.v2...M2b3c9PQ"
curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -H "X-Amzn-Type-Version: com.amazon.device.messaging.ADMMessage@1.0" -H "Accept: application/json" -H "X-Amzn-Accept-Type: com.amazon.device.messaging.ADMSendResult@1.0" -H "Cache-Control: no-cache" -H "Postman-Token: c7be00c4-232c-251e-3091-8e846214c3cd" -d '{
  "data":{"message":"Your message","title":"Amazon Push Message Title","tickerText":"Ticker ticker amazon"}
}' https://api.amazon.com/messaging/registrations/$REGISTER_ID/messages

You should obtain “REGISTER_ID” from adb logs after registering to ADM. Now you can run “adm_sendPush-test.sh” or copy/paste it into your console for sending push notification. If everything goes well, you will see a push notification on your amazon device.

In previous week, I have published this blog post about creating a git submodule as a new git repository by preserving commit history.

After this change in one of our games, it was necessary to update our compile and build jobs defined on jenkins service in our build machine. When you configure your jenkins job, you will see “Additional Behaviours” option in your build section as follows :

Click on the Add button and select “Advanced sub-modules behaviours” option.

Now the following section has been added into your build area and you should select “Recursively update submodules” checkbox.

Ok, everything seems ok but when you build your job, you will see some error messages about git credentials as follows :

Started by user Fuat Coskun
[EnvInject] - Loading node environment variables.
Building remotely on mobile-slave (mac-os) in workspace /Users/admin/Jenkins/workspace/Game-Compile-With-Submodule
...
FATAL: Command "git submodule update --init --recursive" returned status code 1:
stdout: 
stderr: Cloning into 'Sources/AndroidNativeLib'...
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/peakgames/AndroidNativeLib/'
Clone of 'https://github.com/peakgames/AndroidNativeLib' into submodule path 'Sources/AndroidNativeLib' failed

hudson.plugins.git.GitException: Command "git submodule update --init --recursive" returned status code 1:
stdout: 
stderr: Cloning into 'Sources/AndroidNativeLib'...
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/peakgames/AndroidNativeLib/'
Clone of 'https://github.com/peakgames/AndroidNativeLib' into submodule path 'Sources/AndroidNativeLib' failed

	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:1591)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$500(CliGitAPIImpl.java:86)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$6.execute(CliGitAPIImpl.java:893)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$1.call(RemoteGitImpl.java:152)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$1.call(RemoteGitImpl.java:145)
	at hudson.remoting.UserRequest.perform(UserRequest.java:118)
	at hudson.remoting.UserRequest.perform(UserRequest.java:48)
	at hudson.remoting.Request$2.run(Request.java:328)
	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at hudson.remoting.Engine$1$1.run(Engine.java:63)
	at java.lang.Thread.run(Thread.java:745)
	at ......remote call to mobile-slave(Native Method)
	at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1361)
	at hudson.remoting.UserResponse.retrieve(UserRequest.java:221)
	at hudson.remoting.Channel.call(Channel.java:753)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler.execute(RemoteGitImpl.java:145)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler.invoke(RemoteGitImpl.java:131)
	at com.sun.proxy.$Proxy63.execute(Unknown Source)
	at hudson.plugins.git.extensions.impl.SubmoduleOption.onCheckoutCompleted(SubmoduleOption.java:83)
	at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1047)
	at hudson.scm.SCM.checkout(SCM.java:485)
	at hudson.model.AbstractProject.checkout(AbstractProject.java:1276)
	at hudson.model.AbstractBuild$AbstractBuildExecution.defaultCheckout(AbstractBuild.java:610)
	at jenkins.scm.SCMCheckoutStrategy.checkout(SCMCheckoutStrategy.java:86)
	at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:532)
	at hudson.model.Run.execute(Run.java:1744)
	at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
	at hudson.model.ResourceController.execute(ResourceController.java:98)
	at hudson.model.Executor.run(Executor.java:374)
Finished: FAILURE

I know you expect that the same username and password will be used while cloning the submodule, but jenkins won’t be able to do this due to this bug which is reported and still open.

The easiest workaround for this issue is that entering your own credentials manually during the first time cloning for your jenkins job. You can see the directory that jenkins created for your job in your error message :

/Users/admin/Jenkins/workspace/Game-Compile-With-Submodule

Go to this directory and run those commands for initializing your submodule for the first time :

git submodule init
git submodule update

Now cloning process is over and you can run your jenkins job successfully. It won’t ask your credentials again, but please remember that you should apply same steps again if you create a new jenkins job with a git submodule.

Challenge of the last week for me was creating a git submodule without losing any information about commit history for one of our games. Creating a submodule is a straight job which has no difficulty. But if you change any file’s directory by using “mv” or “git mv” command, all the commit history is lost. Now, I will explain how to create git submodule lossless.

My directory structure at the beginning was looking like this:

Here Core, Drivers, Engine and Libs directories include some source code files which have been used by another game also. We have decided to sync those libraries under a submodule and I have created an empty github reopsitory called AndroidNativeLib for storing the submodule later on.

I will use Sources directory as target directory for creating a new git repository by preserving history, then I will remove unnecessary directories App, Breakpad and GoogleTest. Finally I will push remaining Core, Engine, Drivers and Libs directories with “.git” hidden folder which hold the commit history and other configuration.

Creating New Repository By Preserving History

Let’s start the journey :

I have used Git Bash for git operations on Windows. You can use terminal on Linux or Mac as you wish.

1. Root directory of the game is “Game” folder you can see on the screenshot above. Go to the root directory.

2. Ensure that you don’t have any unstaged changes. I suggest you have a clean new repository without any modified files.

3. Run the following command for creating a new repository from Sources directory in the root on master branch.

git filter-branch --prune-empty --subdirectory-filter Sources master

This was a filter-branch command which you can find more information about many other filter-branch command types here. After this, rewrite process will be started and all the commits will be rewrited for the source codes under Sources directory. You will see messages like below after rewriting process completed :

Rewrite 5adef2baf54d91ce9ba572b9e5a370d8addd9dcd (1546/1546)
Ref 'refs/heads/master' was rewritten

You should see that your root directory only contains the files & folders under target directory. (Sources folder as below for me)

4. Our new repository with history has been created but still points to our game repository. Now we need to remove remote repo definitions. Firstly, list existing remotes.</b>

git remote -v

As result, name of the remotes defined are on the left side (here it is “origin”) :

origin  https://github.com/peakgames/...
origin  https://github.com/peakgames/...

5. Now remove remotes :

git remote rm origin

6. Add new remote as pointing your new empty repository (AndroidNativeLib for me)

git remote add origin https://github.com/peakgames/AndroidNativeLib.git

7. We can commit and push everything to our new repository.

git push origin .

Now you can check your new repository on github and check history of source files.

Creating and Linking Submodule

Now we have a new repository ant we want to link this as a git submodule to our project. I will create a submodule called AndroidNativeLib just same as my library repository name.

1. Go to the directory you want to add submodule and run the following command. (For me it’s Game/Sources)

git submodule add https://github.com/peakgames/AndroidNativeLib

After that, a new file .gitmodules created in the root of your repository which includes submodule information :

[submodule "Sources/AndroidNativeLib"]
    path = Sources/AndroidNativeLib
    url = https://github.com/peakgames/AndroidNativeLib

You can check this document for getting more information about submodules.

2. Commit & push everyting created under your main repository. Now you will be able to route to your submodule on github by clicking the link generated for you as below :

That’s all. Now we have a submodule including common libraries with existing commit history and it’s is also a different git repository :)