We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Incorrect SDK variable in build.xml with pygame bootstrap and direct p4a invocation
This issue is a follow-up to Issue #681 (opened and closed two days ago).  Please see that for additional context (ie, install environment, dependency resolution, etc). I'm attempting still to manually create an apk by directly invoking p4a as follows:

  p4a apk --sdk_dir /opt/android-sdk-linux \
          --ndk_dir /opt/android-ndk-r10e \
          --android_api 15 --ndk_ver r10e-rc4 \
          --private /root/HelloWorld \
          --package=org.example.helloworld \
          --name="HelloWorld" --version=0.5 \
          --bootstrap=pygame --requirements=sdl,python2 \
          --dist_name=helloworld

P4a (or, more specifically, python-sh) is now properly resolving "ant"; however, ant is failing due to an error in the build.xml file:

  Buildfile: /root/.local/share/python-for-android/dists/helloworld/build.xml   

  BUILD FAILED  
  /root/.local/share/python-for-android/dists/helloworld/build.xml:18: Cannot find /opt/android-sdk/tools/ant/build.xml imported from /root/.local/share/python-for-android/dists/helloworld/build.xml 

Specifically, my dist's build.xml seems to be trying to import the Android SDK's build.xml from the wrong fully canonicalized file location.  Above, note that it looks for it in:

  /opt/android-sdk/tools/ant/build.xml

However, the p4a invocation clearly passes the SDK directory parameter as:

  /opt/android-sdk-linux

Somehow, p4a is going from "/opt/android-sdk-linux" to "/opt/android-sdk" and thus failing to find the file.

After some digging, I note that this is really due to use of the pygame bootstrap; more specifically, "/root/.local/share/python-for-android/dists/helloworld/build.xml" includes "/root/.local/share/python-for-android/dists/helloworld/local.properties", which itself contains the incorrect SDK directory parameter ("/opt/android-sdk", rather than "/opt/android-sdk-linux").

If we look at "/usr/local/lib/python2.7/dist-packages/pythonforandroid/bootstraps/pygame/**init**.py", we see this code snippet:

  shprint(sh.cp, '-a', join(src_path, 'local.properties'), '.')

So, the pygame bootstrap is simply copying the default "local.properties" (as in the git repo for python-for-android) into my particular dist.  I'm assuming that the intention here is that the "local.properties" file is supposed to be a fallback default location for SDK directory, and that my command line parameter ("--sdk_dir /opt/android-sdk-linux" above) at p4a invocation should supersede this default.  Clearly, that's not happening.

In fact, though, if I manually change the "local.properties" file to match the correct SDK directory, everything works fine.  Also, this bug is NOT triggered with the SDL2 bootstrap (though that triggers yet another bug), and it also is NOT triggered when the toolchain is invoked by buildozer (with "android_new" target).  Still, there's a bug somewhere here (even if only a documentation / dependency bug), and I'd like to resolve it, so things work properly with p4a invoked directly.

Thanks!


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pythonforandroid/bootstraps/pygame/__init__.py`
Content:
```
1 from pythonforandroid.toolchain import Bootstrap, shprint, current_directory, info, warning, ArchARM, info_main
2 from os.path import join, exists
3 from os import walk
4 import glob
5 import sh
6 
7 
8 class PygameBootstrap(Bootstrap):
9     name = 'pygame'
10 
11     recipe_depends = ['hostpython2', 'python2', 'pyjnius', 'sdl', 'pygame',
12                       'android', 'kivy']
13 
14     def run_distribute(self):
15         info_main('# Creating Android project from build and {} bootstrap'.format(
16             self.name))
17 
18         # src_path = join(self.ctx.root_dir, 'bootstrap_templates',
19         #                 self.name)
20         src_path = join(self.bootstrap_dir, 'build')
21 
22         arch = self.ctx.archs[0]
23         if len(self.ctx.archs) > 1:
24             raise ValueError('built for more than one arch, but bootstrap cannot handle that yet')
25         info('Bootstrap running with arch {}'.format(arch))
26 
27         with current_directory(self.dist_dir):
28 
29             info('Creating initial layout')
30             for dirname in ('assets', 'bin', 'private', 'res', 'templates'):
31                 if not exists(dirname):
32                     shprint(sh.mkdir, dirname)
33 
34             info('Copying default files')
35             shprint(sh.cp, '-a', join(self.build_dir, 'project.properties'), '.')
36             shprint(sh.cp, '-a', join(src_path, 'local.properties'), '.')
37             shprint(sh.cp, '-a', join(src_path, 'build.py'), '.')
38             shprint(sh.cp, '-a', join(src_path, 'buildlib'), '.')
39             shprint(sh.cp, '-a', join(src_path, 'src'), '.')
40             shprint(sh.cp, '-a', join(src_path, 'templates'), '.')
41             shprint(sh.cp, '-a', join(src_path, 'res'), '.')
42             shprint(sh.cp, '-a', join(src_path, 'blacklist.txt'), '.')
43             shprint(sh.cp, '-a', join(src_path, 'whitelist.txt'), '.')
44 
45             info('Copying python distribution')
46             hostpython = sh.Command(self.ctx.hostpython)
47             # AND: This *doesn't* need to be in arm env?
48             try:
49                 shprint(hostpython, '-OO', '-m', 'compileall', self.ctx.get_python_install_dir(),
50                         _tail=10, _filterout="^Listing")
51             except sh.ErrorReturnCode:
52                 pass
53             if not exists('python-install'):
54                 shprint(sh.cp, '-a', self.ctx.get_python_install_dir(), './python-install')
55 
56             self.distribute_libs(arch, [join(self.build_dir, 'libs', arch.arch), self.ctx.get_libs_dir(arch.arch)]);
57             self.distribute_aars(arch)
58             self.distribute_javaclasses(self.ctx.javaclass_dir)
59 
60             info('Filling private directory')
61             if not exists(join('private', 'lib')):
62                 shprint(sh.cp, '-a', join('python-install', 'lib'), 'private')
63             shprint(sh.mkdir, '-p', join('private', 'include', 'python2.7'))
64 
65             # AND: Copylibs stuff should go here
66             shprint(sh.mv, join('libs', arch.arch, 'libpymodules.so'), 'private/')
67             shprint(sh.cp, join('python-install', 'include' , 'python2.7', 'pyconfig.h'), join('private', 'include', 'python2.7/'))
68 
69             info('Removing some unwanted files')
70             shprint(sh.rm, '-f', join('private', 'lib', 'libpython2.7.so'))
71             shprint(sh.rm, '-rf', join('private', 'lib', 'pkgconfig'))
72 
73             with current_directory(join(self.dist_dir, 'private', 'lib', 'python2.7')):
74                 # shprint(sh.xargs, 'rm', sh.grep('-E', '*\.(py|pyx|so\.o|so\.a|so\.libs)$', sh.find('.')))
75                 removes = []
76                 for dirname, something, filens in walk('.'):
77                     for filename in filens:
78                         for suffix in ('py', 'pyc', 'so.o', 'so.a', 'so.libs'):
79                             if filename.endswith(suffix):
80                                 removes.append(filename)
81                 shprint(sh.rm, '-f', *removes)
82 
83                 info('Deleting some other stuff not used on android')
84                 # To quote the original distribute.sh, 'well...'
85                 # shprint(sh.rm, '-rf', 'ctypes')
86                 shprint(sh.rm, '-rf', 'lib2to3')
87                 shprint(sh.rm, '-rf', 'idlelib')
88                 for filename in glob.glob('config/libpython*.a'):
89                     shprint(sh.rm, '-f', filename)
90                 shprint(sh.rm, '-rf', 'config/python.o')
91                 shprint(sh.rm, '-rf', 'lib-dynload/_ctypes_test.so')
92                 shprint(sh.rm, '-rf', 'lib-dynload/_testcapi.so')
93 
94 
95         self.strip_libraries(arch)
96         super(PygameBootstrap, self).run_distribute()
97 
98 bootstrap = PygameBootstrap()
99
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pythonforandroid/bootstraps/pygame/__init__.py b/pythonforandroid/bootstraps/pygame/__init__.py
--- a/pythonforandroid/bootstraps/pygame/__init__.py
+++ b/pythonforandroid/bootstraps/pygame/__init__.py
@@ -33,7 +33,6 @@
 
             info('Copying default files')
             shprint(sh.cp, '-a', join(self.build_dir, 'project.properties'), '.')
-            shprint(sh.cp, '-a', join(src_path, 'local.properties'), '.')
             shprint(sh.cp, '-a', join(src_path, 'build.py'), '.')
             shprint(sh.cp, '-a', join(src_path, 'buildlib'), '.')
             shprint(sh.cp, '-a', join(src_path, 'src'), '.')
@@ -42,6 +41,9 @@
             shprint(sh.cp, '-a', join(src_path, 'blacklist.txt'), '.')
             shprint(sh.cp, '-a', join(src_path, 'whitelist.txt'), '.')
 
+            with open('local.properties', 'w') as fileh:
+                fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))
+
             info('Copying python distribution')
             hostpython = sh.Command(self.ctx.hostpython)
             # AND: This *doesn't* need to be in arm env?

{"golden_diff": "diff --git a/pythonforandroid/bootstraps/pygame/__init__.py b/pythonforandroid/bootstraps/pygame/__init__.py\n--- a/pythonforandroid/bootstraps/pygame/__init__.py\n+++ b/pythonforandroid/bootstraps/pygame/__init__.py\n@@ -33,7 +33,6 @@\n \n             info('Copying default files')\n             shprint(sh.cp, '-a', join(self.build_dir, 'project.properties'), '.')\n-            shprint(sh.cp, '-a', join(src_path, 'local.properties'), '.')\n             shprint(sh.cp, '-a', join(src_path, 'build.py'), '.')\n             shprint(sh.cp, '-a', join(src_path, 'buildlib'), '.')\n             shprint(sh.cp, '-a', join(src_path, 'src'), '.')\n@@ -42,6 +41,9 @@\n             shprint(sh.cp, '-a', join(src_path, 'blacklist.txt'), '.')\n             shprint(sh.cp, '-a', join(src_path, 'whitelist.txt'), '.')\n \n+            with open('local.properties', 'w') as fileh:\n+                fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))\n+\n             info('Copying python distribution')\n             hostpython = sh.Command(self.ctx.hostpython)\n             # AND: This *doesn't* need to be in arm env?\n", "issue": "Incorrect SDK variable in build.xml with pygame bootstrap and direct p4a invocation\nThis issue is a follow-up to Issue #681 (opened and closed two days ago).  Please see that for additional context (ie, install environment, dependency resolution, etc). I'm attempting still to manually create an apk by directly invoking p4a as follows:\n\n  p4a apk --sdk_dir /opt/android-sdk-linux \\\n          --ndk_dir /opt/android-ndk-r10e \\\n          --android_api 15 --ndk_ver r10e-rc4 \\\n          --private /root/HelloWorld \\\n          --package=org.example.helloworld \\\n          --name=\"HelloWorld\" --version=0.5 \\\n          --bootstrap=pygame --requirements=sdl,python2 \\\n          --dist_name=helloworld\n\nP4a (or, more specifically, python-sh) is now properly resolving \"ant\"; however, ant is failing due to an error in the build.xml file:\n\n  Buildfile: /root/.local/share/python-for-android/dists/helloworld/build.xml   \n\n  BUILD FAILED  \n  /root/.local/share/python-for-android/dists/helloworld/build.xml:18: Cannot find /opt/android-sdk/tools/ant/build.xml imported from /root/.local/share/python-for-android/dists/helloworld/build.xml \n\nSpecifically, my dist's build.xml seems to be trying to import the Android SDK's build.xml from the wrong fully canonicalized file location.  Above, note that it looks for it in:\n\n  /opt/android-sdk/tools/ant/build.xml\n\nHowever, the p4a invocation clearly passes the SDK directory parameter as:\n\n  /opt/android-sdk-linux\n\nSomehow, p4a is going from \"/opt/android-sdk-linux\" to \"/opt/android-sdk\" and thus failing to find the file.\n\nAfter some digging, I note that this is really due to use of the pygame bootstrap; more specifically, \"/root/.local/share/python-for-android/dists/helloworld/build.xml\" includes \"/root/.local/share/python-for-android/dists/helloworld/local.properties\", which itself contains the incorrect SDK directory parameter (\"/opt/android-sdk\", rather than \"/opt/android-sdk-linux\").\n\nIf we look at \"/usr/local/lib/python2.7/dist-packages/pythonforandroid/bootstraps/pygame/**init**.py\", we see this code snippet:\n\n  shprint(sh.cp, '-a', join(src_path, 'local.properties'), '.')\n\nSo, the pygame bootstrap is simply copying the default \"local.properties\" (as in the git repo for python-for-android) into my particular dist.  I'm assuming that the intention here is that the \"local.properties\" file is supposed to be a fallback default location for SDK directory, and that my command line parameter (\"--sdk_dir /opt/android-sdk-linux\" above) at p4a invocation should supersede this default.  Clearly, that's not happening.\n\nIn fact, though, if I manually change the \"local.properties\" file to match the correct SDK directory, everything works fine.  Also, this bug is NOT triggered with the SDL2 bootstrap (though that triggers yet another bug), and it also is NOT triggered when the toolchain is invoked by buildozer (with \"android_new\" target).  Still, there's a bug somewhere here (even if only a documentation / dependency bug), and I'd like to resolve it, so things work properly with p4a invoked directly.\n\nThanks!\n\n", "before_files": [{"content": "from pythonforandroid.toolchain import Bootstrap, shprint, current_directory, info, warning, ArchARM, info_main\nfrom os.path import join, exists\nfrom os import walk\nimport glob\nimport sh\n\n\nclass PygameBootstrap(Bootstrap):\n    name = 'pygame'\n\n    recipe_depends = ['hostpython2', 'python2', 'pyjnius', 'sdl', 'pygame',\n                      'android', 'kivy']\n\n    def run_distribute(self):\n        info_main('# Creating Android project from build and {} bootstrap'.format(\n            self.name))\n\n        # src_path = join(self.ctx.root_dir, 'bootstrap_templates',\n        #                 self.name)\n        src_path = join(self.bootstrap_dir, 'build')\n\n        arch = self.ctx.archs[0]\n        if len(self.ctx.archs) > 1:\n            raise ValueError('built for more than one arch, but bootstrap cannot handle that yet')\n        info('Bootstrap running with arch {}'.format(arch))\n\n        with current_directory(self.dist_dir):\n\n            info('Creating initial layout')\n            for dirname in ('assets', 'bin', 'private', 'res', 'templates'):\n                if not exists(dirname):\n                    shprint(sh.mkdir, dirname)\n\n            info('Copying default files')\n            shprint(sh.cp, '-a', join(self.build_dir, 'project.properties'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'local.properties'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'build.py'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'buildlib'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'src'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'templates'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'res'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'blacklist.txt'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'whitelist.txt'), '.')\n\n            info('Copying python distribution')\n            hostpython = sh.Command(self.ctx.hostpython)\n            # AND: This *doesn't* need to be in arm env?\n            try:\n                shprint(hostpython, '-OO', '-m', 'compileall', self.ctx.get_python_install_dir(),\n                        _tail=10, _filterout=\"^Listing\")\n            except sh.ErrorReturnCode:\n                pass\n            if not exists('python-install'):\n                shprint(sh.cp, '-a', self.ctx.get_python_install_dir(), './python-install')\n\n            self.distribute_libs(arch, [join(self.build_dir, 'libs', arch.arch), self.ctx.get_libs_dir(arch.arch)]);\n            self.distribute_aars(arch)\n            self.distribute_javaclasses(self.ctx.javaclass_dir)\n\n            info('Filling private directory')\n            if not exists(join('private', 'lib')):\n                shprint(sh.cp, '-a', join('python-install', 'lib'), 'private')\n            shprint(sh.mkdir, '-p', join('private', 'include', 'python2.7'))\n\n            # AND: Copylibs stuff should go here\n            shprint(sh.mv, join('libs', arch.arch, 'libpymodules.so'), 'private/')\n            shprint(sh.cp, join('python-install', 'include' , 'python2.7', 'pyconfig.h'), join('private', 'include', 'python2.7/'))\n\n            info('Removing some unwanted files')\n            shprint(sh.rm, '-f', join('private', 'lib', 'libpython2.7.so'))\n            shprint(sh.rm, '-rf', join('private', 'lib', 'pkgconfig'))\n\n            with current_directory(join(self.dist_dir, 'private', 'lib', 'python2.7')):\n                # shprint(sh.xargs, 'rm', sh.grep('-E', '*\\.(py|pyx|so\\.o|so\\.a|so\\.libs)$', sh.find('.')))\n                removes = []\n                for dirname, something, filens in walk('.'):\n                    for filename in filens:\n                        for suffix in ('py', 'pyc', 'so.o', 'so.a', 'so.libs'):\n                            if filename.endswith(suffix):\n                                removes.append(filename)\n                shprint(sh.rm, '-f', *removes)\n\n                info('Deleting some other stuff not used on android')\n                # To quote the original distribute.sh, 'well...'\n                # shprint(sh.rm, '-rf', 'ctypes')\n                shprint(sh.rm, '-rf', 'lib2to3')\n                shprint(sh.rm, '-rf', 'idlelib')\n                for filename in glob.glob('config/libpython*.a'):\n                    shprint(sh.rm, '-f', filename)\n                shprint(sh.rm, '-rf', 'config/python.o')\n                shprint(sh.rm, '-rf', 'lib-dynload/_ctypes_test.so')\n                shprint(sh.rm, '-rf', 'lib-dynload/_testcapi.so')\n\n\n        self.strip_libraries(arch)\n        super(PygameBootstrap, self).run_distribute()\n\nbootstrap = PygameBootstrap()\n", "path": "pythonforandroid/bootstraps/pygame/__init__.py"}], "after_files": [{"content": "from pythonforandroid.toolchain import Bootstrap, shprint, current_directory, info, warning, ArchARM, info_main\nfrom os.path import join, exists\nfrom os import walk\nimport glob\nimport sh\n\n\nclass PygameBootstrap(Bootstrap):\n    name = 'pygame'\n\n    recipe_depends = ['hostpython2', 'python2', 'pyjnius', 'sdl', 'pygame',\n                      'android', 'kivy']\n\n    def run_distribute(self):\n        info_main('# Creating Android project from build and {} bootstrap'.format(\n            self.name))\n\n        # src_path = join(self.ctx.root_dir, 'bootstrap_templates',\n        #                 self.name)\n        src_path = join(self.bootstrap_dir, 'build')\n\n        arch = self.ctx.archs[0]\n        if len(self.ctx.archs) > 1:\n            raise ValueError('built for more than one arch, but bootstrap cannot handle that yet')\n        info('Bootstrap running with arch {}'.format(arch))\n\n        with current_directory(self.dist_dir):\n\n            info('Creating initial layout')\n            for dirname in ('assets', 'bin', 'private', 'res', 'templates'):\n                if not exists(dirname):\n                    shprint(sh.mkdir, dirname)\n\n            info('Copying default files')\n            shprint(sh.cp, '-a', join(self.build_dir, 'project.properties'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'build.py'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'buildlib'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'src'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'templates'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'res'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'blacklist.txt'), '.')\n            shprint(sh.cp, '-a', join(src_path, 'whitelist.txt'), '.')\n\n            with open('local.properties', 'w') as fileh:\n                fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))\n\n            info('Copying python distribution')\n            hostpython = sh.Command(self.ctx.hostpython)\n            # AND: This *doesn't* need to be in arm env?\n            try:\n                shprint(hostpython, '-OO', '-m', 'compileall', self.ctx.get_python_install_dir(),\n                        _tail=10, _filterout=\"^Listing\")\n            except sh.ErrorReturnCode:\n                pass\n            if not exists('python-install'):\n                shprint(sh.cp, '-a', self.ctx.get_python_install_dir(), './python-install')\n\n            self.distribute_libs(arch, [join(self.build_dir, 'libs', arch.arch), self.ctx.get_libs_dir(arch.arch)]);\n            self.distribute_aars(arch)\n            self.distribute_javaclasses(self.ctx.javaclass_dir)\n\n            info('Filling private directory')\n            if not exists(join('private', 'lib')):\n                shprint(sh.cp, '-a', join('python-install', 'lib'), 'private')\n            shprint(sh.mkdir, '-p', join('private', 'include', 'python2.7'))\n\n            # AND: Copylibs stuff should go here\n            shprint(sh.mv, join('libs', arch.arch, 'libpymodules.so'), 'private/')\n            shprint(sh.cp, join('python-install', 'include' , 'python2.7', 'pyconfig.h'), join('private', 'include', 'python2.7/'))\n\n            info('Removing some unwanted files')\n            shprint(sh.rm, '-f', join('private', 'lib', 'libpython2.7.so'))\n            shprint(sh.rm, '-rf', join('private', 'lib', 'pkgconfig'))\n\n            with current_directory(join(self.dist_dir, 'private', 'lib', 'python2.7')):\n                # shprint(sh.xargs, 'rm', sh.grep('-E', '*\\.(py|pyx|so\\.o|so\\.a|so\\.libs)$', sh.find('.')))\n                removes = []\n                for dirname, something, filens in walk('.'):\n                    for filename in filens:\n                        for suffix in ('py', 'pyc', 'so.o', 'so.a', 'so.libs'):\n                            if filename.endswith(suffix):\n                                removes.append(filename)\n                shprint(sh.rm, '-f', *removes)\n\n                info('Deleting some other stuff not used on android')\n                # To quote the original distribute.sh, 'well...'\n                # shprint(sh.rm, '-rf', 'ctypes')\n                shprint(sh.rm, '-rf', 'lib2to3')\n                shprint(sh.rm, '-rf', 'idlelib')\n                for filename in glob.glob('config/libpython*.a'):\n                    shprint(sh.rm, '-f', filename)\n                shprint(sh.rm, '-rf', 'config/python.o')\n                shprint(sh.rm, '-rf', 'lib-dynload/_ctypes_test.so')\n                shprint(sh.rm, '-rf', 'lib-dynload/_testcapi.so')\n\n\n        self.strip_libraries(arch)\n        super(PygameBootstrap, self).run_distribute()\n\nbootstrap = PygameBootstrap()\n", "path": "pythonforandroid/bootstraps/pygame/__init__.py"}]}