fix merge conflicts
This commit is contained in:
commit
3d8f6879ce
42 changed files with 3481 additions and 1176 deletions
25
.deepsource.toml
Normal file
25
.deepsource.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
version = 1
|
||||
|
||||
test_patterns = ["tests/**"]
|
||||
|
||||
[[analyzers]]
|
||||
name = "python"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
runtime_version = "3.x.x"
|
||||
|
||||
|
||||
[[analyzers]]
|
||||
name = "docker"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
dockerfile_paths = [
|
||||
"dockerfile_dev",
|
||||
"dockerfile_prod"
|
||||
]
|
||||
|
||||
[[analyzers]]
|
||||
name = "ruby"
|
||||
enabled = true
|
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,7 +1,6 @@
|
|||
<!--
|
||||
The issue tracker is a tool to address bugs.
|
||||
Please use the #kivy IRC channel on freenode or Stack Overflow for
|
||||
support questions, more information at https://github.com/kivy/buildozer#support
|
||||
For support questions, please use: https://github.com/kivy/buildozer#support
|
||||
|
||||
Before opening a new issue, make sure you do the following:
|
||||
* check that your issue isn't already filed: https://github.com/kivy/buildozer/issues
|
||||
|
@ -15,8 +14,7 @@ Before opening a new issue, make sure you do the following:
|
|||
|
||||
* Python:
|
||||
* OS:
|
||||
* Kivy:
|
||||
* Cython:
|
||||
* Buildozer:
|
||||
|
||||
### Description
|
||||
|
||||
|
|
19
.github/support.yml
vendored
Normal file
19
.github/support.yml
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Configuration for support-requests - https://github.com/dessant/support-requests
|
||||
|
||||
# Label used to mark issues as support requests
|
||||
supportLabel: support
|
||||
# Comment to post on issues marked as support requests. Add a link
|
||||
# to a support page, or set to `false` to disable
|
||||
supportComment: >
|
||||
:wave: @{issue-author}, we use the issue tracker exclusively for bug reports
|
||||
and feature requests. However, this issue appears to be a support request.
|
||||
Please use our [support channels](https://github.com/kivy/buildozer#support)
|
||||
to get help with the project.
|
||||
|
||||
|
||||
Let us know if this comment was made in error, and we'll be happy
|
||||
to reopen the issue.
|
||||
# Whether to close issues marked as support requests
|
||||
close: true
|
||||
# Whether to lock issues marked as support requests
|
||||
lock: false
|
40
.github/workflows/android.yml
vendored
Normal file
40
.github/workflows/android.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
on: [push, pull_request]
|
||||
name: Android
|
||||
jobs:
|
||||
Integration:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- 'ubuntu-latest'
|
||||
- 'macOs-latest'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup environment
|
||||
run: |
|
||||
pip install -e .
|
||||
pip install Cython
|
||||
- run: buildozer --help
|
||||
- run: buildozer init
|
||||
- name: SDK, NDK and p4a download
|
||||
run: |
|
||||
sed -i.bak "s/# android.accept_sdk_license = False/android.accept_sdk_license = True/" buildozer.spec
|
||||
sed -i.bak "s/#p4a.branch = master/p4a.branch = develop/" buildozer.spec
|
||||
buildozer android p4a -- --help
|
||||
# Install OS specific dependencies
|
||||
- name: Install Linux dependencies
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: sudo apt -y install automake
|
||||
- name: Install macOS dependencies
|
||||
if: matrix.os == 'macOS-latest'
|
||||
run: |
|
||||
brew install automake
|
||||
sudo ln -sfn /usr/local/opt/openssl /usr/local/ssl
|
||||
- name: buildozer android debug
|
||||
run: |
|
||||
touch main.py
|
||||
buildozer android debug
|
24
.github/workflows/ios.yml
vendored
Normal file
24
.github/workflows/ios.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
on: [push, pull_request]
|
||||
name: iOS
|
||||
jobs:
|
||||
Integration:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup environment
|
||||
run: |
|
||||
pip install -e .
|
||||
pip install Cython cookiecutter pbxproj
|
||||
- run: buildozer --help
|
||||
- run: buildozer init
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install autoconf automake libtool pkg-config
|
||||
- name: buildozer ios debug
|
||||
run: |
|
||||
touch main.py
|
||||
buildozer ios debug
|
25
.github/workflows/pypi-release.yml
vendored
Normal file
25
.github/workflows/pypi-release.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
name: PyPI release
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
pypi_release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade setuptools wheel twine
|
||||
- name: Build
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
twine check dist/*
|
||||
- name: Publish package
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
uses: pypa/gh-action-pypi-publish@v1.1.0
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_password }}
|
60
.github/workflows/test_python.yml
vendored
Normal file
60
.github/workflows/test_python.yml
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
on: [push, pull_request]
|
||||
name: Tests
|
||||
jobs:
|
||||
Tests:
|
||||
name: base
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
- '3.6'
|
||||
- '3.7'
|
||||
- '3.8'
|
||||
os:
|
||||
- 'ubuntu-latest'
|
||||
- 'macOs-latest'
|
||||
architecture:
|
||||
- 'x64'
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
|
||||
- name: Requirements
|
||||
run: |
|
||||
pip install -U coveralls setuptools tox>=2.0
|
||||
- name: Tox
|
||||
run: tox
|
||||
- name: Coveralls
|
||||
env:
|
||||
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COVERALLS_SERVICE_NAME: github
|
||||
run: coveralls
|
||||
|
||||
Docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Docker build
|
||||
run: docker build --tag=kivy/buildozer .
|
||||
- name: Docker run
|
||||
run: docker run kivy/buildozer --version
|
||||
|
||||
Python2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 2.7
|
||||
- uses: actions/checkout@v2
|
||||
- name: Try Python 2 install
|
||||
run: |
|
||||
# we don't want the build to fail with the exit 1 so we catch with "||"
|
||||
python2 -m pip install -e . 2> error.log || echo Failing as expected
|
||||
cat error.log
|
||||
grep "Unsupported Python version" error.log
|
509
CHANGELOG.md
509
CHANGELOG.md
|
@ -1,5 +1,510 @@
|
|||
# Change Log
|
||||
|
||||
|
||||
## [1.2.0](https://github.com/kivy/buildozer/tree/1.2.0) (2020-05-30)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/1.1.0...1.2.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Bumps to latest Cython version [\#1132](https://github.com/kivy/buildozer/pull/1132) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Also integration test on macOS [\#1131](https://github.com/kivy/buildozer/pull/1131) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Tests android.numeric\_version config [\#1129](https://github.com/kivy/buildozer/pull/1129) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Refactored the TargetAndroid tests [\#1127](https://github.com/kivy/buildozer/pull/1127) ([pavelsof](https://github.com/pavelsof))
|
||||
- Adds p4a --numeric-version support [\#1126](https://github.com/kivy/buildozer/pull/1126) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Linter fixes and README.md update [\#1118](https://github.com/kivy/buildozer/pull/1118) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Removes Python 2 constructions [\#1114](https://github.com/kivy/buildozer/pull/1114) ([AndreMiras](https://github.com/AndreMiras))
|
||||
|
||||
## [1.1.0](https://github.com/kivy/buildozer/tree/1.1.0) (2020-05-18)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/1.0...1.1.0)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- [Docker image] SSLError("Can't connect to HTTPS URL because the SSL module is not available.") [\#1096](https://github.com/kivy/buildozer/issues/1096)
|
||||
- NameError: name 'raw\_input' is not defined [\#1070](https://github.com/kivy/buildozer/issues/1070)
|
||||
- Setup coverage testing [\#1058](https://github.com/kivy/buildozer/issues/1058)
|
||||
- AttributeError: 'function' object has no attribute 'glob' [\#1044](https://github.com/kivy/buildozer/issues/1044)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Pygallary [\#1109](https://github.com/kivy/buildozer/issues/1109)
|
||||
- Buildozer compilation ERROR: No matching distribution found for hostpython2 (from -r requirements.txt (line 2)) [\#1104](https://github.com/kivy/buildozer/issues/1104)
|
||||
- Circular errors with Java version and Android SDK [\#1103](https://github.com/kivy/buildozer/issues/1103)
|
||||
- APK not running on Android 10? [\#1102](https://github.com/kivy/buildozer/issues/1102)
|
||||
- Buildozer command fails: Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate [\#1095](https://github.com/kivy/buildozer/issues/1095)
|
||||
- Command Failed Error [\#1092](https://github.com/kivy/buildozer/issues/1092)
|
||||
- APK Can't be install (package can't be install in android) [\#1091](https://github.com/kivy/buildozer/issues/1091)
|
||||
- buildozer Install python 3.8.1 [\#1090](https://github.com/kivy/buildozer/issues/1090)
|
||||
- i have weak reference error while using python 3.8 [\#1089](https://github.com/kivy/buildozer/issues/1089)
|
||||
- buildozer is choosing odd venv, and using a different python? [\#1080](https://github.com/kivy/buildozer/issues/1080)
|
||||
- Fatal Python error: init\_fs\_encoding: failed to get the Python codec of the filesystem encoding [\#1076](https://github.com/kivy/buildozer/issues/1076)
|
||||
- Buildozer just wont compile my app [\#1074](https://github.com/kivy/buildozer/issues/1074)
|
||||
- Autoreconf not found? [\#1072](https://github.com/kivy/buildozer/issues/1072)
|
||||
- error while buildozer android debug deploy run [\#1064](https://github.com/kivy/buildozer/issues/1064)
|
||||
- Syntax error in Kivy and KivyMD dependencies file when using Buildozer to compile KivyMD app [\#1051](https://github.com/kivy/buildozer/issues/1051)
|
||||
- Adding CFFI as a Buildozer requirement breaks the Android build [\#1050](https://github.com/kivy/buildozer/issues/1050)
|
||||
- Is buildozer compatible with Python 3.7 [\#1048](https://github.com/kivy/buildozer/issues/1048)
|
||||
- Could not resolve org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0 [\#1042](https://github.com/kivy/buildozer/issues/1042)
|
||||
- Error while running buildozer android debug deploy [\#1038](https://github.com/kivy/buildozer/issues/1038)
|
||||
- cant able to build apk on linux with python3 [\#1033](https://github.com/kivy/buildozer/issues/1033)
|
||||
- Keystore was tampered with, or password was incorrect [\#1028](https://github.com/kivy/buildozer/issues/1028)
|
||||
- Windows support to build Android APK [\#1022](https://github.com/kivy/buildozer/issues/1022)
|
||||
- How to make third party site-packages 'requests' run on Android [\#1021](https://github.com/kivy/buildozer/issues/1021)
|
||||
- Crash on buildozer android debug command. Command failed: /usr/bin/python -m pythonforandroid.toolchain [\#1017](https://github.com/kivy/buildozer/issues/1017)
|
||||
- Build failed: Couldn't find executable for CC [\#1014](https://github.com/kivy/buildozer/issues/1014)
|
||||
- Cloning Error of python-for-android [\#1008](https://github.com/kivy/buildozer/issues/1008)
|
||||
- checking whether the C compiler works... no [\#1007](https://github.com/kivy/buildozer/issues/1007)
|
||||
- Kivy :How to ask for storage permission when app starts [\#1004](https://github.com/kivy/buildozer/issues/1004)
|
||||
- Buildozer :No module named 'numpy.core.\_multiarray\_umath' [\#1002](https://github.com/kivy/buildozer/issues/1002)
|
||||
- Kivy app Crashes while import openpyxl [\#1001](https://github.com/kivy/buildozer/issues/1001)
|
||||
- Warning when i run "buildozer -v android debug" [\#982](https://github.com/kivy/buildozer/issues/982)
|
||||
- sdkmanager is notinstalled [\#927](https://github.com/kivy/buildozer/issues/927)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update README.md [\#1111](https://github.com/kivy/buildozer/pull/1111) ([tshirtman](https://github.com/tshirtman))
|
||||
- Fixes Docker apt cache missed [\#1107](https://github.com/kivy/buildozer/pull/1107) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Adds libssl-dev to the install dependencies [\#1106](https://github.com/kivy/buildozer/pull/1106) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Automatically publish to PyPI upon tagging [\#1105](https://github.com/kivy/buildozer/pull/1105) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fix punctuation and typo in README.md [\#1101](https://github.com/kivy/buildozer/pull/1101) ([hematogender](https://github.com/hematogender))
|
||||
- Build integration test [\#1100](https://github.com/kivy/buildozer/pull/1100) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fixes missing libssl-dev dependency [\#1099](https://github.com/kivy/buildozer/pull/1099) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Drops Python 2 support [\#1094](https://github.com/kivy/buildozer/pull/1094) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Checks SDK, NDK and p4a get downloaded on first run [\#1093](https://github.com/kivy/buildozer/pull/1093) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Integration testing [\#1083](https://github.com/kivy/buildozer/pull/1083) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Also tests against macOS platform [\#1078](https://github.com/kivy/buildozer/pull/1078) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fix NameError with Python 3 and iOS target [\#1071](https://github.com/kivy/buildozer/pull/1071) ([lerela](https://github.com/lerela))
|
||||
- Unit tests TargetAndroid.build\_package() [\#1069](https://github.com/kivy/buildozer/pull/1069) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Dedicated Docker build/run job [\#1068](https://github.com/kivy/buildozer/pull/1068) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- F841: local variable is assigned to but never used [\#1066](https://github.com/kivy/buildozer/pull/1066) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- PEP8 organisation and fixes [\#1065](https://github.com/kivy/buildozer/pull/1065) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fixes coveralls.io on pull requests [\#1063](https://github.com/kivy/buildozer/pull/1063) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Coveralls TOKEN is only available on branch master [\#1062](https://github.com/kivy/buildozer/pull/1062) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Starts unit testing buildozer/targets/android.py [\#1061](https://github.com/kivy/buildozer/pull/1061) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Setup coverage testing [\#1060](https://github.com/kivy/buildozer/pull/1060) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fix Dockerfile dependencies [\#1053](https://github.com/kivy/buildozer/pull/1053) ([Sirfanas](https://github.com/Sirfanas))
|
||||
- Updates default buildozer.spec NDK from 17c to 19b [\#1041](https://github.com/kivy/buildozer/pull/1041) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fix config typo in default.spec [\#1026](https://github.com/kivy/buildozer/pull/1026) ([touilleMan](https://github.com/touilleMan))
|
||||
- Android gradle build: fix apk name [\#1025](https://github.com/kivy/buildozer/pull/1025) ([SomberNight](https://github.com/SomberNight))
|
||||
|
||||
## [1.0](https://github.com/kivy/buildozer/tree/1.0) (2019-12-22)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/0.39...1.0)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Accept license terms prompt is not visible [\#916](https://github.com/kivy/buildozer/issues/916)
|
||||
- Unable to build release. File "/usr/lib/python3.6/shutil.py", line 96, in copyfile with open\(src, 'rb'\) as fsrc: IOError: \[Errno 2\] No such file or directory: [\#851](https://github.com/kivy/buildozer/issues/851)
|
||||
- error: cannot find -lpython3.7 [\#842](https://github.com/kivy/buildozer/issues/842)
|
||||
- android.accept\_sdk\_license may misbehave [\#816](https://github.com/kivy/buildozer/issues/816)
|
||||
- Python3 error with pexpect [\#221](https://github.com/kivy/buildozer/issues/221)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Sup Req : Buildozer debug does not complete - Error threading.py, sh.py, etc.. [\#1000](https://github.com/kivy/buildozer/issues/1000)
|
||||
- Buildozer failed to execute the last command [\#999](https://github.com/kivy/buildozer/issues/999)
|
||||
- Android fullscreen mode: cannot hide status bar! [\#989](https://github.com/kivy/buildozer/issues/989)
|
||||
- buildozer uses wrong python version and disrespects requirement versions [\#988](https://github.com/kivy/buildozer/issues/988)
|
||||
- The version of Kivy installed on this system is too old. [\#987](https://github.com/kivy/buildozer/issues/987)
|
||||
- Failed to download any source lists! [\#986](https://github.com/kivy/buildozer/issues/986)
|
||||
- Aidl cannot be executed error buildozer [\#984](https://github.com/kivy/buildozer/issues/984)
|
||||
- buildozer debug error "\[WARNING\]" when i run buildozer andriod debug [\#980](https://github.com/kivy/buildozer/issues/980)
|
||||
- Building kivy app with python3 requirement gives "No compiled python is present to zip, skipping." warning and "Unable to import kivy.\_clock. Have you perhaps forgotten to compile kivy? ..." error when run on android device. [\#977](https://github.com/kivy/buildozer/issues/977)
|
||||
- Java And Python-for-android toolchain errors [\#975](https://github.com/kivy/buildozer/issues/975)
|
||||
- buildozer + python3 [\#973](https://github.com/kivy/buildozer/issues/973)
|
||||
- Error while running ".buildozer.../native-build/python -OO -m compileall -b -f /.../app [\#972](https://github.com/kivy/buildozer/issues/972)
|
||||
- buildozer fails with kivymd link [\#968](https://github.com/kivy/buildozer/issues/968)
|
||||
- ndk\_platform doesn't exist: /home/rr/android-ndk-r20/platforms/android-20/arch-arm [\#966](https://github.com/kivy/buildozer/issues/966)
|
||||
- Paused at Installing/updating SDK platform tools if necessary [\#965](https://github.com/kivy/buildozer/issues/965)
|
||||
- java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema [\#962](https://github.com/kivy/buildozer/issues/962)
|
||||
- please add aidl into Dockerfile [\#960](https://github.com/kivy/buildozer/issues/960)
|
||||
- Missing \_ctypes module [\#955](https://github.com/kivy/buildozer/issues/955)
|
||||
- Kivy-Buildozer release version doesnt upload google store [\#953](https://github.com/kivy/buildozer/issues/953)
|
||||
- buildozer using wrong kivy version [\#943](https://github.com/kivy/buildozer/issues/943)
|
||||
- buildozer ndk-api=21 error [\#942](https://github.com/kivy/buildozer/issues/942)
|
||||
- app crash [\#939](https://github.com/kivy/buildozer/issues/939)
|
||||
- ERROR: JAVA\_HOME is set to an invalid directory: /usr/lib/jvm/java-8-oracle [\#929](https://github.com/kivy/buildozer/issues/929)
|
||||
- no-issue [\#926](https://github.com/kivy/buildozer/issues/926)
|
||||
- can't find file to patch toggle\_jpg\_png\_webp.patch [\#921](https://github.com/kivy/buildozer/issues/921)
|
||||
- No matching distribution found for io [\#915](https://github.com/kivy/buildozer/issues/915)
|
||||
- Error: No matching distribution found for io\(from -r requirements.txt \(line 5\)\) [\#914](https://github.com/kivy/buildozer/issues/914)
|
||||
- I'm also experiencing the same issue, using macOS 10.14.3 and no Docker -- just plain Buildozer from the PyPi repo. What is the recommended course of action to fix this? [\#913](https://github.com/kivy/buildozer/issues/913)
|
||||
- app crash [\#911](https://github.com/kivy/buildozer/issues/911)
|
||||
- warnings while building apk using buildozer [\#910](https://github.com/kivy/buildozer/issues/910)
|
||||
- buildozer error please help me!! [\#906](https://github.com/kivy/buildozer/issues/906)
|
||||
- My application does not open in android but if it works in geany, help please. [\#903](https://github.com/kivy/buildozer/issues/903)
|
||||
- \[Docker image\] Can't compile apk: /bin/tar ... "Cannot utime: Operation not permitted" [\#902](https://github.com/kivy/buildozer/issues/902)
|
||||
- Fails to call numpy fft on android [\#899](https://github.com/kivy/buildozer/issues/899)
|
||||
- Command failed: /usr/bin/python3 -m pythonforandroid.toolchain [\#898](https://github.com/kivy/buildozer/issues/898)
|
||||
- error: C compiler cannot create executables [\#897](https://github.com/kivy/buildozer/issues/897)
|
||||
- stopped at "Installing/updating SDK platform tools if necessary" [\#896](https://github.com/kivy/buildozer/issues/896)
|
||||
- ValueError: Tried to access ndk\_ver but it has not been set - this should not happen, something went wrong! [\#893](https://github.com/kivy/buildozer/issues/893)
|
||||
- Buildozer not installing from custom source folders [\#892](https://github.com/kivy/buildozer/issues/892)
|
||||
- Error with build requirements PIL \(Python 3\) [\#890](https://github.com/kivy/buildozer/issues/890)
|
||||
- rocker plants.cvs -an active -r -p rco.png [\#889](https://github.com/kivy/buildozer/issues/889)
|
||||
- rocker plants.cvs -an active -r -p rco.png [\#888](https://github.com/kivy/buildozer/issues/888)
|
||||
- rocker plants.cvs -an active -r -p rco.png [\#887](https://github.com/kivy/buildozer/issues/887)
|
||||
- rocker plants.cvs -an active -r -p rco.png [\#886](https://github.com/kivy/buildozer/issues/886)
|
||||
- rocker plants.cvs -an active -r -p rco.png [\#885](https://github.com/kivy/buildozer/issues/885)
|
||||
- host=arm-linux-androideabi [\#884](https://github.com/kivy/buildozer/issues/884)
|
||||
- Buildozer has attribute errors and will not run [\#883](https://github.com/kivy/buildozer/issues/883)
|
||||
- buildozer on osx not working [\#879](https://github.com/kivy/buildozer/issues/879)
|
||||
- Android API Issue [\#877](https://github.com/kivy/buildozer/issues/877)
|
||||
- What is the way to add folders and files? [\#875](https://github.com/kivy/buildozer/issues/875)
|
||||
- Buildozer Error [\#874](https://github.com/kivy/buildozer/issues/874)
|
||||
- Problem with "Unpacking sdl2\_image" and "Parent module 'pythonforandroid.recipes' not found" [\#872](https://github.com/kivy/buildozer/issues/872)
|
||||
- buildozer android debug deploy is stuck [\#870](https://github.com/kivy/buildozer/issues/870)
|
||||
- running autoreconf -vif [\#866](https://github.com/kivy/buildozer/issues/866)
|
||||
- Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema [\#862](https://github.com/kivy/buildozer/issues/862)
|
||||
- Can not build x86 APK file [\#861](https://github.com/kivy/buildozer/issues/861)
|
||||
- But then a lot more issues, deep in the weeds now. [\#858](https://github.com/kivy/buildozer/issues/858)
|
||||
- Create tests for PR fix bug when logcat value which cannot be decode to utf-8 [\#857](https://github.com/kivy/buildozer/issues/857)
|
||||
- Can't Cythonize pyjnius: TypeError: can't pickle Argument objects [\#850](https://github.com/kivy/buildozer/issues/850)
|
||||
- buildozer -h complains about NoneType target [\#849](https://github.com/kivy/buildozer/issues/849)
|
||||
- Building failes at compiling openssl\[armeabi-v7a\] [\#841](https://github.com/kivy/buildozer/issues/841)
|
||||
- Applying patches for libffi\[armeabi-v7a\] [\#840](https://github.com/kivy/buildozer/issues/840)
|
||||
- Errors while running buildozer android debug deploy [\#832](https://github.com/kivy/buildozer/issues/832)
|
||||
- "Command failed" when running "buildozer android debug deploy run" [\#829](https://github.com/kivy/buildozer/issues/829)
|
||||
- Build Python3 for Android with Azure-keyvault and merest [\#828](https://github.com/kivy/buildozer/issues/828)
|
||||
- Outdated Android NDK download URL in Kivy Virtual Machine [\#827](https://github.com/kivy/buildozer/issues/827)
|
||||
- App crashes on startup [\#826](https://github.com/kivy/buildozer/issues/826)
|
||||
- I found the origin of the problem mentioned in issue \#694 \(Aidl not found\) [\#824](https://github.com/kivy/buildozer/issues/824)
|
||||
- download\(\) is not CI log friendly [\#823](https://github.com/kivy/buildozer/issues/823)
|
||||
- Application stuck in portrait mode [\#820](https://github.com/kivy/buildozer/issues/820)
|
||||
- Orientation landscape when set to portrait [\#818](https://github.com/kivy/buildozer/issues/818)
|
||||
- Certain python requirements fail due to `\_ctypes` [\#815](https://github.com/kivy/buildozer/issues/815)
|
||||
- Running buildozer help crashes [\#813](https://github.com/kivy/buildozer/issues/813)
|
||||
- \[Buildozer 0.40.dev0, Buildozer 0.39\] AttributeError: 'Buildozer' object has no attribute 'translate\_target' [\#812](https://github.com/kivy/buildozer/issues/812)
|
||||
- Version number failing to be added to apk [\#810](https://github.com/kivy/buildozer/issues/810)
|
||||
- Virtual machine out of date [\#764](https://github.com/kivy/buildozer/issues/764)
|
||||
- Docker doesn't build [\#751](https://github.com/kivy/buildozer/issues/751)
|
||||
- Buildozer exit code on recipe fail [\#674](https://github.com/kivy/buildozer/issues/674)
|
||||
- not able to release apk in release mode - build failed [\#363](https://github.com/kivy/buildozer/issues/363)
|
||||
- Issue with NDK r11b [\#308](https://github.com/kivy/buildozer/issues/308)
|
||||
- Feature: Create a compat.py for correct PY3 support and implement it [\#300](https://github.com/kivy/buildozer/issues/300)
|
||||
- Curl missing in KivyVM [\#296](https://github.com/kivy/buildozer/issues/296)
|
||||
- Virtual machine image could have better support for international keyboards [\#295](https://github.com/kivy/buildozer/issues/295)
|
||||
- Virtual machine image does not have enough disk space [\#294](https://github.com/kivy/buildozer/issues/294)
|
||||
- Not quite an issue, just some dependency stuff [\#247](https://github.com/kivy/buildozer/issues/247)
|
||||
- \# Command failed: ./distribute.sh -m "kivy" -d "stapp" [\#204](https://github.com/kivy/buildozer/issues/204)
|
||||
- Command ./distribute.sh failed -- no buildozer.spec found when it exists [\#203](https://github.com/kivy/buildozer/issues/203)
|
||||
- buildozer -v android debug : Compile fails at fcntlmodule.c [\#196](https://github.com/kivy/buildozer/issues/196)
|
||||
- Build errors on OSX 10.10 \(for android\) [\#165](https://github.com/kivy/buildozer/issues/165)
|
||||
- Feature Request: Vagrantfile [\#154](https://github.com/kivy/buildozer/issues/154)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Feature GitHub actions [\#1005](https://github.com/kivy/buildozer/pull/1005) ([tito](https://github.com/tito))
|
||||
- Fixes test\_p4a\_recommended\_android\_ndk\_found\(\) mocking [\#983](https://github.com/kivy/buildozer/pull/983) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fixes packaging for current p4a develop branch [\#978](https://github.com/kivy/buildozer/pull/978) ([misl6](https://github.com/misl6))
|
||||
- Updates install instructions and troubleshooting [\#976](https://github.com/kivy/buildozer/pull/976) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- fix: show output of sdk update if auto\_accept\_license is false [\#970](https://github.com/kivy/buildozer/pull/970) ([tshirtman](https://github.com/tshirtman))
|
||||
- Add libs only for current arch [\#969](https://github.com/kivy/buildozer/pull/969) ([misl6](https://github.com/misl6))
|
||||
- Rename final apk with arch in the name [\#967](https://github.com/kivy/buildozer/pull/967) ([tito](https://github.com/tito))
|
||||
- Code improvements around NDK download [\#961](https://github.com/kivy/buildozer/pull/961) ([inclement](https://github.com/inclement))
|
||||
- Separate build per android.arch [\#957](https://github.com/kivy/buildozer/pull/957) ([tito](https://github.com/tito))
|
||||
- spec file: cast paths in source.exclude\_dirs to lowercase [\#956](https://github.com/kivy/buildozer/pull/956) ([SomberNight](https://github.com/SomberNight))
|
||||
- added cmake to requirements [\#950](https://github.com/kivy/buildozer/pull/950) ([mcroni](https://github.com/mcroni))
|
||||
- Add ability to get p4a's recommended android's NDK version [\#947](https://github.com/kivy/buildozer/pull/947) ([opacam](https://github.com/opacam))
|
||||
- New feature: allow to use a p4a fork [\#940](https://github.com/kivy/buildozer/pull/940) ([opacam](https://github.com/opacam))
|
||||
- Minor linter fix [\#937](https://github.com/kivy/buildozer/pull/937) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Update installation.rst [\#936](https://github.com/kivy/buildozer/pull/936) ([yairlempert](https://github.com/yairlempert))
|
||||
- clarify overriding of config tokens [\#935](https://github.com/kivy/buildozer/pull/935) ([brentpicasso](https://github.com/brentpicasso))
|
||||
- Extend add\_libs to arm64-v8a [\#934](https://github.com/kivy/buildozer/pull/934) ([misl6](https://github.com/misl6))
|
||||
- Doc/installation updates [\#932](https://github.com/kivy/buildozer/pull/932) ([tshirtman](https://github.com/tshirtman))
|
||||
- customizability options [\#919](https://github.com/kivy/buildozer/pull/919) ([zworkb](https://github.com/zworkb))
|
||||
- disable orientation and window option for service\_only bootstrap [\#912](https://github.com/kivy/buildozer/pull/912) ([zworkb](https://github.com/zworkb))
|
||||
- Unit test unicode decode on command output, fixes \#857 [\#905](https://github.com/kivy/buildozer/pull/905) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Made sure to print all lines of license question by always flushing [\#904](https://github.com/kivy/buildozer/pull/904) ([inclement](https://github.com/inclement))
|
||||
- Exits with error code on build exception, fixes \#674 [\#882](https://github.com/kivy/buildozer/pull/882) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Download Apache ANT at the same path as the buildozer.spec android.ant\_path option [\#860](https://github.com/kivy/buildozer/pull/860) ([robertpro](https://github.com/robertpro))
|
||||
- Fix for bug when logcat value which cannot be decode to utf-8 [\#856](https://github.com/kivy/buildozer/pull/856) ([Draqun](https://github.com/Draqun))
|
||||
- Changes default log level to debug \(2\) [\#855](https://github.com/kivy/buildozer/pull/855) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Handles unknown command/target error gracefully, closes \#812 [\#853](https://github.com/kivy/buildozer/pull/853) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Updates system requirements needed to build recipes [\#852](https://github.com/kivy/buildozer/pull/852) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Various Dockerfile improvements [\#848](https://github.com/kivy/buildozer/pull/848) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Support p4a uses-library argument [\#846](https://github.com/kivy/buildozer/pull/846) ([pax0r](https://github.com/pax0r))
|
||||
- Removed reference to Kivy VM [\#845](https://github.com/kivy/buildozer/pull/845) ([Megalex42](https://github.com/Megalex42))
|
||||
- Removes extra log\_env\(\) call [\#843](https://github.com/kivy/buildozer/pull/843) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- add missing android arch to spec file [\#839](https://github.com/kivy/buildozer/pull/839) ([OptimusGREEN](https://github.com/OptimusGREEN))
|
||||
- feat: make unzip quiet [\#836](https://github.com/kivy/buildozer/pull/836) ([mkg20001](https://github.com/mkg20001))
|
||||
- fix: drop release-unsigned from release output path [\#835](https://github.com/kivy/buildozer/pull/835) ([mkg20001](https://github.com/mkg20001))
|
||||
- Add ci\_mode to toggle download progress [\#833](https://github.com/kivy/buildozer/pull/833) ([mkg20001](https://github.com/mkg20001))
|
||||
- Unit test logger [\#831](https://github.com/kivy/buildozer/pull/831) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- refactor auto accept license [\#822](https://github.com/kivy/buildozer/pull/822) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Unit tests buildozer --help command, refs \#813 [\#821](https://github.com/kivy/buildozer/pull/821) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Use getbooldefault\(\) for boolean, fixes \#806 [\#817](https://github.com/kivy/buildozer/pull/817) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Update the issue template [\#814](https://github.com/kivy/buildozer/pull/814) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Show envs when run2 [\#802](https://github.com/kivy/buildozer/pull/802) ([maho](https://github.com/maho))
|
||||
|
||||
## [0.39](https://github.com/kivy/buildozer/tree/0.39) (2019-02-04)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/0.38...0.39)
|
||||
|
||||
## [0.38](https://github.com/kivy/buildozer/tree/0.38) (2019-02-03)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/0.36...0.38)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- TypeError: read\(\) takes exactly 2 arguments \(3 given\) [\#793](https://github.com/kivy/buildozer/issues/793)
|
||||
- TypeError: read\(\) takes exactly 2 arguments \(3 given\) [\#792](https://github.com/kivy/buildozer/issues/792)
|
||||
- AttributeError: 'str' object has no attribute 'decode' [\#756](https://github.com/kivy/buildozer/issues/756)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Openssl compilation fails, '\_\_atomic' undefined [\#800](https://github.com/kivy/buildozer/issues/800)
|
||||
- --ndk-api appears twice [\#798](https://github.com/kivy/buildozer/issues/798)
|
||||
- Error in toolchain.py and argument --ndk-api 9 [\#797](https://github.com/kivy/buildozer/issues/797)
|
||||
- Target ndk-api is 19, but the \*\*python3 recipe supports only 21\*\* [\#796](https://github.com/kivy/buildozer/issues/796)
|
||||
- Add support for --frameworks on iOS [\#790](https://github.com/kivy/buildozer/issues/790)
|
||||
- Hello World impossible: checking whether the C compiler works... no [\#785](https://github.com/kivy/buildozer/issues/785)
|
||||
- Buildozer 0.37 UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 [\#782](https://github.com/kivy/buildozer/issues/782)
|
||||
- APK Crashes on start with no obvious cause [\#779](https://github.com/kivy/buildozer/issues/779)
|
||||
- Outdated Android NDK download URL in Kivy Virtual Machine [\#778](https://github.com/kivy/buildozer/issues/778)
|
||||
- Buildozer "gradlew failed!" [\#777](https://github.com/kivy/buildozer/issues/777)
|
||||
- Conflicting documentation Python2 versus Python3 [\#774](https://github.com/kivy/buildozer/issues/774)
|
||||
- No valid --ndk-api received, using the default of 0 = min\(android-api=0, default ndk-api=21\) [\#772](https://github.com/kivy/buildozer/issues/772)
|
||||
- `default.spec` specifies `python3` but also incompatible NDK and API settings [\#770](https://github.com/kivy/buildozer/issues/770)
|
||||
- Error: minsdk argument does not match the api that is compiled against [\#768](https://github.com/kivy/buildozer/issues/768)
|
||||
- Need to support sensorLandscape [\#762](https://github.com/kivy/buildozer/issues/762)
|
||||
- minsdk argument does not match the api that is compiled against [\#761](https://github.com/kivy/buildozer/issues/761)
|
||||
- Need to be able to specify the NDK API target [\#758](https://github.com/kivy/buildozer/issues/758)
|
||||
- Buildozer cannot import name pythran\_is\_numpy\_func\_supported [\#753](https://github.com/kivy/buildozer/issues/753)
|
||||
- Python3 recipe not building, error with self.ctx.python\_recipe [\#752](https://github.com/kivy/buildozer/issues/752)
|
||||
- compile error [\#744](https://github.com/kivy/buildozer/issues/744)
|
||||
- APK build failed "ndk\_platform doesn't exist" \(Python3.6; android.api = 27\) [\#742](https://github.com/kivy/buildozer/issues/742)
|
||||
- Logo Design Proposal [\#734](https://github.com/kivy/buildozer/issues/734)
|
||||
- `android clean` not working \(FileNotFoundError: \[Errno 2\] No such file or directory\) [\#732](https://github.com/kivy/buildozer/issues/732)
|
||||
- Can't Make an APK via Buildozer [\#712](https://github.com/kivy/buildozer/issues/712)
|
||||
- App build Failed [\#707](https://github.com/kivy/buildozer/issues/707)
|
||||
- ERROR: /home/kivy/.buildozer/android/platform/apache-ant-1.9.4/bin/ant failed! [\#706](https://github.com/kivy/buildozer/issues/706)
|
||||
- APK using txt file in main.py issue. [\#704](https://github.com/kivy/buildozer/issues/704)
|
||||
- "Copying APK" fails because of wrong path used [\#699](https://github.com/kivy/buildozer/issues/699)
|
||||
- Cannot build [\#697](https://github.com/kivy/buildozer/issues/697)
|
||||
- Fail on build [\#692](https://github.com/kivy/buildozer/issues/692)
|
||||
- Cannot build "Hello World" APK [\#687](https://github.com/kivy/buildozer/issues/687)
|
||||
- Error when building an android APK using Kivy [\#684](https://github.com/kivy/buildozer/issues/684)
|
||||
- can't get audio stream from a server [\#683](https://github.com/kivy/buildozer/issues/683)
|
||||
- Continuous integration testing [\#679](https://github.com/kivy/buildozer/issues/679)
|
||||
- Post build fails because copying built apk fails [\#671](https://github.com/kivy/buildozer/issues/671)
|
||||
- Buildozer can't compile for Android on Manjaro Linux [\#670](https://github.com/kivy/buildozer/issues/670)
|
||||
- Icon/Logo Proposal [\#669](https://github.com/kivy/buildozer/issues/669)
|
||||
- Buildozer cant compile platform Ubuntu 16.04 [\#668](https://github.com/kivy/buildozer/issues/668)
|
||||
- Buildozer gets stuck at unpacking kivy [\#667](https://github.com/kivy/buildozer/issues/667)
|
||||
- Kivy window [\#666](https://github.com/kivy/buildozer/issues/666)
|
||||
- Failed building wheel for pyaudio [\#665](https://github.com/kivy/buildozer/issues/665)
|
||||
- Buildozer compilation gets stuck [\#663](https://github.com/kivy/buildozer/issues/663)
|
||||
- IOError: \[Errno 2\] No such file or directory: u'/home/samurai-girl/python2/.buildozer/android/platform/build/dists/test/build/outputs/apk/test-debug.apk' [\#662](https://github.com/kivy/buildozer/issues/662)
|
||||
- Unable to build \_ctypes.so [\#660](https://github.com/kivy/buildozer/issues/660)
|
||||
- error while packaging for android on macOS [\#659](https://github.com/kivy/buildozer/issues/659)
|
||||
- Command failed: /usr/bin/python2 -m pythonforandroid.toolchain [\#658](https://github.com/kivy/buildozer/issues/658)
|
||||
- Cannot build apk with buildozer android debug [\#656](https://github.com/kivy/buildozer/issues/656)
|
||||
- How to correctly build an APK package with Python 3? [\#655](https://github.com/kivy/buildozer/issues/655)
|
||||
- SDK does not have any Build Tools installed. [\#652](https://github.com/kivy/buildozer/issues/652)
|
||||
- Error building Kivy app with opencv\(and numpy\) - raise CommandNotFoundError\(path\) [\#651](https://github.com/kivy/buildozer/issues/651)
|
||||
- FileNotFoundError: \[Errno 2\] [\#649](https://github.com/kivy/buildozer/issues/649)
|
||||
- The python3crystax recipe can only be built when using the CrystaX NDK. Exiting. [\#648](https://github.com/kivy/buildozer/issues/648)
|
||||
- build apk : error can not find the build/output folder [\#647](https://github.com/kivy/buildozer/issues/647)
|
||||
- help me building cryptography [\#646](https://github.com/kivy/buildozer/issues/646)
|
||||
- sslv3 alert handshake failure on Addroid [\#643](https://github.com/kivy/buildozer/issues/643)
|
||||
- Opening Android SDK Manager to download "Google Repository" and "Google Play services" [\#642](https://github.com/kivy/buildozer/issues/642)
|
||||
- kivy python host failed [\#641](https://github.com/kivy/buildozer/issues/641)
|
||||
- python.host failed [\#640](https://github.com/kivy/buildozer/issues/640)
|
||||
- Kivy Crashing [\#638](https://github.com/kivy/buildozer/issues/638)
|
||||
- .so lib files missing debug symbols [\#637](https://github.com/kivy/buildozer/issues/637)
|
||||
- Kivy app doesn't run [\#634](https://github.com/kivy/buildozer/issues/634)
|
||||
- "\* daemon not running. starting it now on port 5037 \* \* daemon started successfully \*" [\#633](https://github.com/kivy/buildozer/issues/633)
|
||||
- FileNotFoundError: \[Errno 2\] No such file or directory: '/home/alex/Documents/pengame/.buildozer/android/platform/build/dists/helloworldapp/build/outputs/apk/helloworldapp-debug.apk' [\#632](https://github.com/kivy/buildozer/issues/632)
|
||||
- Compiling Kivy app to apk fails with a pip error [\#631](https://github.com/kivy/buildozer/issues/631)
|
||||
- ERROR: /home/ubuntu/.buildozer/android/platform/apache-ant-1.9.4/bin/ant failed! [\#625](https://github.com/kivy/buildozer/issues/625)
|
||||
- Build error when building Kivy app [\#624](https://github.com/kivy/buildozer/issues/624)
|
||||
- buildozer debug is not running this error is showing [\#622](https://github.com/kivy/buildozer/issues/622)
|
||||
- unexpected e\_machine: 3 [\#621](https://github.com/kivy/buildozer/issues/621)
|
||||
- buildozer matplotlib [\#617](https://github.com/kivy/buildozer/issues/617)
|
||||
- IOError: \[Errno 2\] No such file or directory: u'/Users/gauravgupta/kivy/.buildozer/android/platform/build/dists/myellipse/build/outputs/apk/myellipse-debug.apk' [\#613](https://github.com/kivy/buildozer/issues/613)
|
||||
- Build failing in final ANT stage [\#610](https://github.com/kivy/buildozer/issues/610)
|
||||
- Cannot build apk [\#606](https://github.com/kivy/buildozer/issues/606)
|
||||
- Installing buildozer for Python 3 failed [\#604](https://github.com/kivy/buildozer/issues/604)
|
||||
- FileNotFoundError at end of build when copying APK file. [\#602](https://github.com/kivy/buildozer/issues/602)
|
||||
- BUILD FAILED [\#601](https://github.com/kivy/buildozer/issues/601)
|
||||
- Error with buildozer [\#591](https://github.com/kivy/buildozer/issues/591)
|
||||
- ImportError: No module named Cython.Distutils While running buildozer android debug [\#587](https://github.com/kivy/buildozer/issues/587)
|
||||
- python 2.7 compile with NDK 15c [\#584](https://github.com/kivy/buildozer/issues/584)
|
||||
- Problem upgrade to newest version [\#583](https://github.com/kivy/buildozer/issues/583)
|
||||
- Simple Kivy test app can't compile to android apk [\#581](https://github.com/kivy/buildozer/issues/581)
|
||||
- Apple Watch Support [\#574](https://github.com/kivy/buildozer/issues/574)
|
||||
- Skip error or better error message: requirements with extra comma [\#562](https://github.com/kivy/buildozer/issues/562)
|
||||
- failed to build numpy on Mac [\#557](https://github.com/kivy/buildozer/issues/557)
|
||||
- p4a.source\_dir set and android clean --\> crash [\#556](https://github.com/kivy/buildozer/issues/556)
|
||||
- Kivy python android build error? [\#555](https://github.com/kivy/buildozer/issues/555)
|
||||
- python3 import networkx needs lib2to3 but cannot be imported [\#554](https://github.com/kivy/buildozer/issues/554)
|
||||
- buildozer android debug deploy run ERROR [\#550](https://github.com/kivy/buildozer/issues/550)
|
||||
- App Crashes [\#541](https://github.com/kivy/buildozer/issues/541)
|
||||
- Requirements: Requests, Ssl [\#539](https://github.com/kivy/buildozer/issues/539)
|
||||
- Error: Aidl cannot be executed [\#532](https://github.com/kivy/buildozer/issues/532)
|
||||
- Kivy and Beautifulsoup with Buildozer fail on Python 3. [\#529](https://github.com/kivy/buildozer/issues/529)
|
||||
- I'm having similar problem [\#528](https://github.com/kivy/buildozer/issues/528)
|
||||
- Awkward error while building apk [\#526](https://github.com/kivy/buildozer/issues/526)
|
||||
- The "android" command is deprecated [\#519](https://github.com/kivy/buildozer/issues/519)
|
||||
- Kivy: Permission denied \(when running buildozer android on Mac OS X\) [\#517](https://github.com/kivy/buildozer/issues/517)
|
||||
- Extraction of "Kivy2.7z" failed [\#516](https://github.com/kivy/buildozer/issues/516)
|
||||
- buildozer still download ndk from wrong path [\#506](https://github.com/kivy/buildozer/issues/506)
|
||||
- android-new landscape error on restart [\#482](https://github.com/kivy/buildozer/issues/482)
|
||||
- Add possibility to choose pip version for modules in the requirements section [\#475](https://github.com/kivy/buildozer/issues/475)
|
||||
- Bulldozer android\_new fails when ffmpeg is added to the requirements: No C Compiler found! [\#463](https://github.com/kivy/buildozer/issues/463)
|
||||
- CalledProcessError: Command '\['python', 'package\_app.py', '--displayname=Music Favorites'\]' returned non-zero exit status 1 [\#448](https://github.com/kivy/buildozer/issues/448)
|
||||
- \[Errno 13\] Permission denied; Buildozer on Flask Server [\#445](https://github.com/kivy/buildozer/issues/445)
|
||||
- Error while compiling a kivy app for android \(undefined reference to 'SDL\_main' collect2: error: ld returned 1 exit status\) [\#438](https://github.com/kivy/buildozer/issues/438)
|
||||
- AsyncImage not loading in .apk [\#433](https://github.com/kivy/buildozer/issues/433)
|
||||
- Big Bug, ORMs cant find sqlite3.so [\#426](https://github.com/kivy/buildozer/issues/426)
|
||||
- cp: cannot stat '~/.buildozer/android/platform/python-for-android/src/libs/armeabi/\*.so': No such file or directory [\#422](https://github.com/kivy/buildozer/issues/422)
|
||||
- using android\_new causes missing packages errors [\#420](https://github.com/kivy/buildozer/issues/420)
|
||||
- Buildozer fails with "Command '\['ant', 'debug'\]' returned non-zero exit status 1" [\#419](https://github.com/kivy/buildozer/issues/419)
|
||||
- Buildozer fails to build when ffmpeg is added [\#418](https://github.com/kivy/buildozer/issues/418)
|
||||
- Build on arm64 android [\#412](https://github.com/kivy/buildozer/issues/412)
|
||||
- Building with "android\_new" target fails due to missing architecture on pythonforandroid.toolchain apk [\#407](https://github.com/kivy/buildozer/issues/407)
|
||||
- Command '\['ant', 'debug'\]' returned non-zero exit status 1 when building PIL library [\#406](https://github.com/kivy/buildozer/issues/406)
|
||||
- Android, Pygame backend: buildozer android debug deploy run tries to launch wrong Activity [\#401](https://github.com/kivy/buildozer/issues/401)
|
||||
- AttributeError: 'NoneType' object has no attribute 'splitlines' [\#400](https://github.com/kivy/buildozer/issues/400)
|
||||
- Pyzmq import fails on Android with python2 / kivy 1.9 / cython 0.23 [\#397](https://github.com/kivy/buildozer/issues/397)
|
||||
- Python 3: \# Aidl cannot be executed AttributeError: 'module' object has no attribute 'maxint' [\#392](https://github.com/kivy/buildozer/issues/392)
|
||||
- subprocess.CalledProcessError [\#391](https://github.com/kivy/buildozer/issues/391)
|
||||
- python.host could not find platform independent libraries [\#390](https://github.com/kivy/buildozer/issues/390)
|
||||
- Buildozer android\_new fails [\#388](https://github.com/kivy/buildozer/issues/388)
|
||||
- toolchain.py: error: argument --private is required [\#384](https://github.com/kivy/buildozer/issues/384)
|
||||
- Android fails on running Kivy apk [\#381](https://github.com/kivy/buildozer/issues/381)
|
||||
- ImportError: No module named plyer with android\_new as a target [\#379](https://github.com/kivy/buildozer/issues/379)
|
||||
- buildozer -v android debug runs into problem [\#376](https://github.com/kivy/buildozer/issues/376)
|
||||
- subprocess.CalledProcessError [\#372](https://github.com/kivy/buildozer/issues/372)
|
||||
- Can't install Pillow , return errors [\#371](https://github.com/kivy/buildozer/issues/371)
|
||||
- failed to load ctypes as android app built on OSX [\#368](https://github.com/kivy/buildozer/issues/368)
|
||||
- old\_toolchain not shows images [\#367](https://github.com/kivy/buildozer/issues/367)
|
||||
- Buildozer deployment dlopen failed libSDL2.so has unexpected e\_machine: 40 [\#365](https://github.com/kivy/buildozer/issues/365)
|
||||
- Rebuild only selected packages [\#226](https://github.com/kivy/buildozer/issues/226)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Updated README for Python 3 [\#809](https://github.com/kivy/buildozer/pull/809) ([inclement](https://github.com/inclement))
|
||||
- Update README.md to add opencollective [\#808](https://github.com/kivy/buildozer/pull/808) ([tito](https://github.com/tito))
|
||||
- Made buildozer respect user sdk dir when accessing sdkmanager [\#807](https://github.com/kivy/buildozer/pull/807) ([inclement](https://github.com/inclement))
|
||||
- Removed android\_old and updated SDK management to work with current SDK [\#806](https://github.com/kivy/buildozer/pull/806) ([inclement](https://github.com/inclement))
|
||||
- Removed redundant --ndk-api argument and fixed default value [\#805](https://github.com/kivy/buildozer/pull/805) ([inclement](https://github.com/inclement))
|
||||
- Update for p4a master [\#803](https://github.com/kivy/buildozer/pull/803) ([inclement](https://github.com/inclement))
|
||||
- Unit tests read spec file, refs \#793 [\#799](https://github.com/kivy/buildozer/pull/799) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Support the --add-frameworks flag in kivy-ios [\#795](https://github.com/kivy/buildozer/pull/795) ([hackalog](https://github.com/hackalog))
|
||||
- Introduces CI and tox testing, fixes \#679 [\#794](https://github.com/kivy/buildozer/pull/794) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fix python 2 crash when reading config file [\#791](https://github.com/kivy/buildozer/pull/791) ([etc0de](https://github.com/etc0de))
|
||||
- Handle buildozer.spec with unicode chars [\#789](https://github.com/kivy/buildozer/pull/789) ([guysoft](https://github.com/guysoft))
|
||||
- Specify GitHub branches in buildozer.spec [\#787](https://github.com/kivy/buildozer/pull/787) ([hackalog](https://github.com/hackalog))
|
||||
- Fixes minor comment typo introduced in \#759 [\#786](https://github.com/kivy/buildozer/pull/786) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Docker from current git [\#775](https://github.com/kivy/buildozer/pull/775) ([maho](https://github.com/maho))
|
||||
- Fix output directory for gradle [\#766](https://github.com/kivy/buildozer/pull/766) ([wo01](https://github.com/wo01))
|
||||
- support sensorLandscape mode. resolves \#762 [\#763](https://github.com/kivy/buildozer/pull/763) ([brentpicasso](https://github.com/brentpicasso))
|
||||
- allow specifying of Android NDK API. Resolves \#758 [\#759](https://github.com/kivy/buildozer/pull/759) ([brentpicasso](https://github.com/brentpicasso))
|
||||
- Update cython version from the docs [\#757](https://github.com/kivy/buildozer/pull/757) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- fix android sdk/ndk information link [\#755](https://github.com/kivy/buildozer/pull/755) ([avere001](https://github.com/avere001))
|
||||
- this allows to build with ndk 17c \(and other recent-ish ones\) [\#754](https://github.com/kivy/buildozer/pull/754) ([tshirtman](https://github.com/tshirtman))
|
||||
- fix ndk URLs [\#747](https://github.com/kivy/buildozer/pull/747) ([zworkb](https://github.com/zworkb))
|
||||
|
||||
## [0.36](https://github.com/kivy/buildozer/tree/0.36) (2018-11-21)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/0.35...0.36)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Error in debug, install platform, Indexerror. [\#731](https://github.com/kivy/buildozer/issues/731)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Buildozer looking for nonexistent script [\#749](https://github.com/kivy/buildozer/issues/749)
|
||||
- Can not build APK file with buildozer. UnicodeDecodeError [\#746](https://github.com/kivy/buildozer/issues/746)
|
||||
- CrystaX no longer the preferred NDK for Python3 [\#745](https://github.com/kivy/buildozer/issues/745)
|
||||
- AKP build fails \(android.py line 524\) [\#738](https://github.com/kivy/buildozer/issues/738)
|
||||
- Buildozer 0.35 with IndexError: list index out of range on Mac OS [\#737](https://github.com/kivy/buildozer/issues/737)
|
||||
- cannot build pyjnius for armeabi-v7a [\#735](https://github.com/kivy/buildozer/issues/735)
|
||||
- I can't package my app the way i always did. [\#733](https://github.com/kivy/buildozer/issues/733)
|
||||
- OSError: \[Errno 18\] Invalid cross-device link [\#644](https://github.com/kivy/buildozer/issues/644)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Correctly write out a sub-process's `stdout` when using Python 3. [\#743](https://github.com/kivy/buildozer/pull/743) ([dbrnz](https://github.com/dbrnz))
|
||||
- Explicitly run `pip3` when using Python 3 [\#741](https://github.com/kivy/buildozer/pull/741) ([dbrnz](https://github.com/dbrnz))
|
||||
- workaround for working in WSL [\#740](https://github.com/kivy/buildozer/pull/740) ([tshirtman](https://github.com/tshirtman))
|
||||
- Allow for `install\_reqs` line having whitespace at start. [\#736](https://github.com/kivy/buildozer/pull/736) ([dbrnz](https://github.com/dbrnz))
|
||||
- Fix Support config file name [\#730](https://github.com/kivy/buildozer/pull/730) ([dessant](https://github.com/dessant))
|
||||
|
||||
## [0.35](https://github.com/kivy/buildozer/tree/0.35) (2018-10-24)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/0.34...0.35)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Buildozer should not regex/hack install\_reqs [\#722](https://github.com/kivy/buildozer/issues/722)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Command failed: /usr/bin/python -m pythonforandroid.toolchain create... [\#727](https://github.com/kivy/buildozer/issues/727)
|
||||
- buildozer fails at installing platfrom [\#726](https://github.com/kivy/buildozer/issues/726)
|
||||
- Unable to build APK [\#725](https://github.com/kivy/buildozer/issues/725)
|
||||
- Buildozer APK not working: OS X, Docker, or fresh Ubuntu 16.04 [\#723](https://github.com/kivy/buildozer/issues/723)
|
||||
- gcc Segmentation Fault [\#720](https://github.com/kivy/buildozer/issues/720)
|
||||
- Error debugging for android [\#719](https://github.com/kivy/buildozer/issues/719)
|
||||
- ndk\_platform doesn't exist \(when switching to API = 28\) [\#717](https://github.com/kivy/buildozer/issues/717)
|
||||
- FileNotFoundError: \[Errno 2\] \(SOLVED\) - It was Encoding Error [\#715](https://github.com/kivy/buildozer/issues/715)
|
||||
- SDL\_JAVA\_PACKAGE\_PATH error? [\#714](https://github.com/kivy/buildozer/issues/714)
|
||||
- Python3Crystax instructions in README [\#710](https://github.com/kivy/buildozer/issues/710)
|
||||
- Bug or support request? [\#708](https://github.com/kivy/buildozer/issues/708)
|
||||
- build requirement failed [\#701](https://github.com/kivy/buildozer/issues/701)
|
||||
- I am using Virtual Machine provided in the official kivy website for building android APK, this is the part of log file [\#696](https://github.com/kivy/buildozer/issues/696)
|
||||
- App minimizes instantly after launching. [\#695](https://github.com/kivy/buildozer/issues/695)
|
||||
- Aidl not detected [\#694](https://github.com/kivy/buildozer/issues/694)
|
||||
- python 3 ssl [\#690](https://github.com/kivy/buildozer/issues/690)
|
||||
- Is there something like multiprocessing? [\#685](https://github.com/kivy/buildozer/issues/685)
|
||||
- Kivy in pyCharm [\#682](https://github.com/kivy/buildozer/issues/682)
|
||||
- Toolchain error. Help,please! [\#678](https://github.com/kivy/buildozer/issues/678)
|
||||
- virtual machine does not compile apk Fails with errors [\#677](https://github.com/kivy/buildozer/issues/677)
|
||||
- An error in Buildozer Apk \(Python Kivy\) Help PLZ! [\#676](https://github.com/kivy/buildozer/issues/676)
|
||||
- App crashes on android but works fine in idle window using buildozer [\#675](https://github.com/kivy/buildozer/issues/675)
|
||||
- Pyjnius exception Adbuddiz class not found [\#661](https://github.com/kivy/buildozer/issues/661)
|
||||
- Buildozer failed to execute the last command \#/usr/bin/python3 -m pythonforandroid.toolchain create --dist\_name=blueb --bootstrap=sdl2 --requirements=python3crystax,kivy --arch x86 --copy-libs --color=always --storage-dir=/home/jp/Desktop/BlueB/.buildozer/android/platform/build [\#654](https://github.com/kivy/buildozer/issues/654)
|
||||
- java.lang.ClassNotFoundException: sun.misc.BASE64Encoder [\#639](https://github.com/kivy/buildozer/issues/639)
|
||||
- IOError: \[Errno 2\] No such file or directory: [\#636](https://github.com/kivy/buildozer/issues/636)
|
||||
- App crashes with aws boto3 [\#635](https://github.com/kivy/buildozer/issues/635)
|
||||
- APK Immediately Closes After Opening in Debug, Release, and Zipaligned & Signed Versions [\#629](https://github.com/kivy/buildozer/issues/629)
|
||||
- Using Python/Buildozer to compile Kivy for Android [\#628](https://github.com/kivy/buildozer/issues/628)
|
||||
- "configure: error: C compiler cannot create executables See `config.log' for more details" \(\# Command failed: ./distribute.sh -m "kivy" -d "pollygot"\) [\#627](https://github.com/kivy/buildozer/issues/627)
|
||||
- "OSError: \[Errno 30\] Read-only file system" \(\# Command failed: virtualenv --python=python2.7 ./venv\) [\#626](https://github.com/kivy/buildozer/issues/626)
|
||||
- Java compiling issue: buildozer uses obsolete source value 1.5 [\#619](https://github.com/kivy/buildozer/issues/619)
|
||||
- Cloning into 'python-for-android-new-toolchain'... [\#618](https://github.com/kivy/buildozer/issues/618)
|
||||
- Failed to build application: 'WindowInfoX11' is not a type identifier [\#616](https://github.com/kivy/buildozer/issues/616)
|
||||
- Sudo issue\[closed\] [\#615](https://github.com/kivy/buildozer/issues/615)
|
||||
- buildozer-vm-2 installed from scratch ABENDS [\#611](https://github.com/kivy/buildozer/issues/611)
|
||||
- ASCII decode problem [\#608](https://github.com/kivy/buildozer/issues/608)
|
||||
- error: could not delete 'build/lib.linux-x86\_64-2.7/buildozer/targets/android.py': Permission denied [\#607](https://github.com/kivy/buildozer/issues/607)
|
||||
- APK Build Failing with Python 3.6 [\#605](https://github.com/kivy/buildozer/issues/605)
|
||||
- IOError: \[Errno 2\] No such file or directory: u'/home/kivy/buildozer/.buildozer/android/platform/build/... [\#603](https://github.com/kivy/buildozer/issues/603)
|
||||
- Feature Request: Dockerfile or image in dockerhub [\#589](https://github.com/kivy/buildozer/issues/589)
|
||||
- Buildozer debug error. [\#545](https://github.com/kivy/buildozer/issues/545)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix \#645 [\#729](https://github.com/kivy/buildozer/pull/729) ([tito](https://github.com/tito))
|
||||
- Enable Support app [\#728](https://github.com/kivy/buildozer/pull/728) ([dessant](https://github.com/dessant))
|
||||
- Updates p4a deps parsing [\#724](https://github.com/kivy/buildozer/pull/724) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Improved error handling if p4a setup.py can't be read [\#721](https://github.com/kivy/buildozer/pull/721) ([inclement](https://github.com/inclement))
|
||||
- Various spelling corrections [\#718](https://github.com/kivy/buildozer/pull/718) ([Zen-CODE](https://github.com/Zen-CODE))
|
||||
- Updates Python 3 install instructions, fixes \#710 [\#711](https://github.com/kivy/buildozer/pull/711) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Remove obsolete sh package dependency [\#705](https://github.com/kivy/buildozer/pull/705) ([Cheaterman](https://github.com/Cheaterman))
|
||||
- Changes how is\_gradle\_build is detected. [\#700](https://github.com/kivy/buildozer/pull/700) ([rammie](https://github.com/rammie))
|
||||
- Cleans installation docs [\#689](https://github.com/kivy/buildozer/pull/689) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Adds issue template with basic required info [\#688](https://github.com/kivy/buildozer/pull/688) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- buildozer Dockerfile, fixes \#589 [\#681](https://github.com/kivy/buildozer/pull/681) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Removes few unused variables [\#680](https://github.com/kivy/buildozer/pull/680) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- Fixed a typo pointed out by AndreMiras [\#664](https://github.com/kivy/buildozer/pull/664) ([inclement](https://github.com/inclement))
|
||||
- Updates installation.rst with Ubuntu 18.04 instructions [\#657](https://github.com/kivy/buildozer/pull/657) ([AndreMiras](https://github.com/AndreMiras))
|
||||
- fix prerelease version [\#653](https://github.com/kivy/buildozer/pull/653) ([marceloneil](https://github.com/marceloneil))
|
||||
- allow setting launchMode for the main activity in the manifest [\#650](https://github.com/kivy/buildozer/pull/650) ([SomberNight](https://github.com/SomberNight))
|
||||
- Fixes Invalid cross-device link [\#645](https://github.com/kivy/buildozer/pull/645) ([robertpro](https://github.com/robertpro))
|
||||
- Quote --storage-dir value [\#630](https://github.com/kivy/buildozer/pull/630) ([ghost](https://github.com/ghost))
|
||||
- Allow adding Java activities to the manifest [\#612](https://github.com/kivy/buildozer/pull/612) ([bauerj](https://github.com/bauerj))
|
||||
- add comment re p4a.port in default.spec [\#600](https://github.com/kivy/buildozer/pull/600) ([replabrobin](https://github.com/replabrobin))
|
||||
- Spelling [\#592](https://github.com/kivy/buildozer/pull/592) ([jsoref](https://github.com/jsoref))
|
||||
|
||||
## [0.34](https://github.com/kivy/buildozer/tree/0.34) (2017-12-15)
|
||||
[Full Changelog](https://github.com/kivy/buildozer/compare/0.33...0.34)
|
||||
|
||||
|
@ -64,7 +569,7 @@
|
|||
- Fix old toolchain index error [\#576](https://github.com/kivy/buildozer/pull/576) ([Zen-CODE](https://github.com/Zen-CODE))
|
||||
- Some fixes in old android target [\#572](https://github.com/kivy/buildozer/pull/572) ([rnixx](https://github.com/rnixx))
|
||||
- Removed --sdk argument for p4a [\#571](https://github.com/kivy/buildozer/pull/571) ([inclement](https://github.com/inclement))
|
||||
- Update specifications.rst [\#560](https://github.com/kivy/buildozer/pull/560) ([saltycraig](https://github.com/saltycraig))
|
||||
- Update specifications.rst [\#560](https://github.com/kivy/buildozer/pull/560) ([crajun](https://github.com/crajun))
|
||||
- Changed p4a directory name for current toolchain [\#527](https://github.com/kivy/buildozer/pull/527) ([inclement](https://github.com/inclement))
|
||||
- Update android.py, updated recreate the project.properties section [\#525](https://github.com/kivy/buildozer/pull/525) ([mokhoo](https://github.com/mokhoo))
|
||||
- Fix unicode coding error in android build target [\#518](https://github.com/kivy/buildozer/pull/518) ([jamalex](https://github.com/jamalex))
|
||||
|
@ -565,7 +1070,6 @@
|
|||
- Clarified wording in README [\#75](https://github.com/kivy/buildozer/pull/75) ([inclement](https://github.com/inclement))
|
||||
- Check for package name starting with number [\#65](https://github.com/kivy/buildozer/pull/65) ([inclement](https://github.com/inclement))
|
||||
- \[FIX\] Detect 32/64 bit on Windows, to download Android NDK [\#62](https://github.com/kivy/buildozer/pull/62) ([alanjds](https://github.com/alanjds))
|
||||
- Add ability to choose python-for-android directory [\#60](https://github.com/kivy/buildozer/pull/60) ([inclement](https://github.com/inclement))
|
||||
- Added --private and --dir Android storage option [\#58](https://github.com/kivy/buildozer/pull/58) ([brousch](https://github.com/brousch))
|
||||
- Added a 'serve' command to serve bin/ over SimpleHTTPServer [\#49](https://github.com/kivy/buildozer/pull/49) ([brousch](https://github.com/brousch))
|
||||
|
||||
|
@ -582,6 +1086,7 @@
|
|||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add ability to choose python-for-android directory [\#60](https://github.com/kivy/buildozer/pull/60) ([inclement](https://github.com/inclement))
|
||||
- Update default Android NDK to r9 [\#53](https://github.com/kivy/buildozer/pull/53) ([brousch](https://github.com/brousch))
|
||||
- Added android.wakelock option [\#51](https://github.com/kivy/buildozer/pull/51) ([brousch](https://github.com/brousch))
|
||||
- Fixed another 'Unknown' typo [\#48](https://github.com/kivy/buildozer/pull/48) ([brousch](https://github.com/brousch))
|
||||
|
|
72
Dockerfile
72
Dockerfile
|
@ -1,38 +1,69 @@
|
|||
# Dockerfile for providing buildozer
|
||||
#
|
||||
# Build with:
|
||||
# docker build --tag=buildozer .
|
||||
# docker build --tag=kivy/buildozer .
|
||||
#
|
||||
# In order to give the container access to your current working directory
|
||||
# it must be mounted using the --volume option.
|
||||
# Run with (e.g. `buildozer --version`):
|
||||
# docker run --volume "$(pwd)":/home/user/hostcwd buildozer --version
|
||||
# docker run \
|
||||
# --volume "$HOME/.buildozer":/home/user/.buildozer \
|
||||
# --volume "$PWD":/home/user/hostcwd \
|
||||
# kivy/buildozer --version
|
||||
#
|
||||
# Or for interactive shell:
|
||||
# docker run --volume "$(pwd)":/home/user/hostcwd --entrypoint /bin/bash -it --rm buildozer
|
||||
FROM ubuntu:18.04
|
||||
# docker run --interactive --tty --rm \
|
||||
# --volume "$HOME/.buildozer":/home/user/.buildozer \
|
||||
# --volume "$PWD":/home/user/hostcwd \
|
||||
# --entrypoint /bin/bash \
|
||||
# kivy/buildozer
|
||||
#
|
||||
# If you get a `PermissionError` on `/home/user/.buildozer/cache`,
|
||||
# try updating the permissions from the host with:
|
||||
# sudo chown $USER -R ~/.buildozer
|
||||
# Or simply recreate the directory from the host with:
|
||||
# rm -rf ~/.buildozer && mkdir ~/.buildozer
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ENV USER="user"
|
||||
ENV HOME_DIR="/home/${USER}"
|
||||
ENV WORK_DIR="${HOME_DIR}/hostcwd" \
|
||||
SRC_DIR="${HOME_DIR}/src" \
|
||||
PATH="${HOME_DIR}/.local/bin:${PATH}"
|
||||
|
||||
# configures locale
|
||||
RUN apt update -qq > /dev/null && \
|
||||
apt install -qq --yes --no-install-recommends \
|
||||
RUN apt update -qq > /dev/null \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt install -qq --yes --no-install-recommends \
|
||||
locales && \
|
||||
locale-gen en_US.UTF-8
|
||||
ENV LANG="en_US.UTF-8" \
|
||||
LANGUAGE="en_US.UTF-8" \
|
||||
LC_ALL="en_US.UTF-8"
|
||||
|
||||
# installs system dependencies (required to setup all the tools)
|
||||
RUN apt install -qq --yes --no-install-recommends \
|
||||
sudo python-pip python-setuptools file
|
||||
|
||||
# https://buildozer.readthedocs.io/en/latest/installation.html#android-on-ubuntu-18-04-64bit
|
||||
RUN dpkg --add-architecture i386 && apt update -qq > /dev/null && \
|
||||
apt install -qq --yes --no-install-recommends \
|
||||
build-essential ccache git libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 \
|
||||
libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 python2.7 \
|
||||
python2.7-dev openjdk-8-jdk unzip zlib1g-dev zlib1g:i386
|
||||
# system requirements to build most of the recipes
|
||||
RUN apt update -qq > /dev/null \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt install -qq --yes --no-install-recommends \
|
||||
autoconf \
|
||||
automake \
|
||||
build-essential \
|
||||
ccache \
|
||||
cmake \
|
||||
gettext \
|
||||
git \
|
||||
libffi-dev \
|
||||
libltdl-dev \
|
||||
libssl-dev \
|
||||
libtool \
|
||||
openjdk-13-jdk \
|
||||
patch \
|
||||
pkg-config \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
sudo \
|
||||
unzip \
|
||||
zip \
|
||||
zlib1g-dev
|
||||
|
||||
# prepares non root env
|
||||
RUN useradd --create-home --shell /bin/bash ${USER}
|
||||
|
@ -42,14 +73,9 @@ RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
|||
|
||||
USER ${USER}
|
||||
WORKDIR ${WORK_DIR}
|
||||
COPY --chown=user:user . ${SRC_DIR}
|
||||
|
||||
# installs buildozer and dependencies
|
||||
RUN pip install --user Cython==0.25.2 buildozer
|
||||
# calling buildozer adb command should trigger SDK/NDK first install and update
|
||||
# but it requires a buildozer.spec file
|
||||
RUN cd /tmp/ && buildozer init && buildozer android adb -- version && cd -
|
||||
# fixes source and target JDK version, refs https://github.com/kivy/buildozer/issues/625
|
||||
RUN sed s/'name="java.source" value="1.5"'/'name="java.source" value="7"'/ -i ${HOME_DIR}/.buildozer/android/platform/android-sdk-20/tools/ant/build.xml
|
||||
RUN sed s/'name="java.target" value="1.5"'/'name="java.target" value="7"'/ -i ${HOME_DIR}/.buildozer/android/platform/android-sdk-20/tools/ant/build.xml
|
||||
RUN pip3 install --user --upgrade Cython==0.29.19 wheel pip virtualenv ${SRC_DIR}
|
||||
|
||||
ENTRYPOINT ["buildozer"]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
include *COPYING
|
||||
include *CHANGELOG.md
|
||||
include *README.md
|
||||
recursive-include buildozer *.spec
|
||||
|
|
220
README.md
Normal file
220
README.md
Normal file
|
@ -0,0 +1,220 @@
|
|||
Buildozer
|
||||
=========
|
||||
|
||||
[![Tests](https://github.com/kivy/buildozer/workflows/Tests/badge.svg)](https://github.com/kivy/buildozer/actions?query=workflow%3ATests)
|
||||
[![Android](https://github.com/kivy/buildozer/workflows/Android/badge.svg)](https://github.com/kivy/buildozer/actions?query=workflow%3AAndroid)
|
||||
[![iOS](https://github.com/kivy/buildozer/workflows/iOS/badge.svg)](https://github.com/kivy/buildozer/actions?query=workflow%3AiOS)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/kivy/buildozer/badge.svg)](https://coveralls.io/github/kivy/buildozer)
|
||||
[![Backers on Open Collective](https://opencollective.com/kivy/backers/badge.svg)](#backers)
|
||||
[![Sponsors on Open Collective](https://opencollective.com/kivy/sponsors/badge.svg)](#sponsors)
|
||||
|
||||
Buildozer is a tool for creating application packages easily.
|
||||
|
||||
The goal is to have one "buildozer.spec" file in your app directory, describing
|
||||
your application requirements and settings such as title, icon, included modules
|
||||
etc. Buildozer will use that spec to create a package for Android, iOS, Windows,
|
||||
OSX and/or Linux.
|
||||
|
||||
Buildozer currently supports packaging for Android via the [python-for-android](https://github.com/kivy/python-for-android/)
|
||||
project, and for iOS via the kivy-ios project. iOS and OSX are still under work.
|
||||
|
||||
For Android, buildozer will automatically download and prepare the
|
||||
build dependencies. For more information, see
|
||||
[Android-SDK-NDK-Information](https://github.com/kivy/kivy/wiki/Android-SDK-NDK-Information).
|
||||
Note that only Python 3 is supported.
|
||||
|
||||
Note that this tool has nothing to do with the eponymous online build service
|
||||
[buildozer.io](https://buildozer.io).
|
||||
|
||||
## Installing Buildozer with target Python 3 (default):
|
||||
|
||||
- Install buildozer:
|
||||
|
||||
# via pip (latest stable, recommended)
|
||||
# if you use a virtualenv, don't use the `--user` option
|
||||
pip install --user buildozer
|
||||
|
||||
# latest dev version
|
||||
# if you use a virtualenv, don't use the `--user` option
|
||||
pip install --user https://github.com/kivy/buildozer/archive/master.zip
|
||||
|
||||
# git clone, for working on buildozer
|
||||
git clone https://github.com/kivy/buildozer
|
||||
cd buildozer
|
||||
python setup.py build
|
||||
pip install -e .
|
||||
|
||||
- Check buildozer is in your path
|
||||
|
||||
`which buildozer`
|
||||
# if there is no result, and you installed with --user, add this line at the end of your `~/.bashrc` file.
|
||||
export PATH=~/.local/bin/:$PATH
|
||||
# and then run
|
||||
. ~/.bashrc
|
||||
|
||||
- Go into your application directory and run:
|
||||
|
||||
buildozer init
|
||||
# edit the buildozer.spec, then
|
||||
buildozer android debug deploy run
|
||||
|
||||
|
||||
## Buildozer Docker image
|
||||
|
||||
A Dockerfile is available to use buildozer through a Docker environment.
|
||||
|
||||
- Build with:
|
||||
|
||||
docker build --tag=buildozer .
|
||||
|
||||
- Run with:
|
||||
|
||||
docker run --volume "$(pwd)":/home/user/hostcwd buildozer --version
|
||||
|
||||
|
||||
## Buildozer GitHub action
|
||||
|
||||
Use [ArtemSBulgakov/buildozer-action@v1](https://github.com/ArtemSBulgakov/buildozer-action)
|
||||
to build your packages automatically on push or pull request.
|
||||
See [full workflow example](https://github.com/ArtemSBulgakov/buildozer-action#full-workflow).
|
||||
|
||||
|
||||
## Examples of Buildozer commands
|
||||
|
||||
```
|
||||
# buildozer target command
|
||||
buildozer android clean
|
||||
buildozer android update
|
||||
buildozer android deploy
|
||||
buildozer android debug
|
||||
buildozer android release
|
||||
|
||||
# or all in one (compile in debug, deploy on device)
|
||||
buildozer android debug deploy
|
||||
|
||||
# set the default command if nothing set
|
||||
buildozer setdefault android debug deploy run
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
Usage:
|
||||
buildozer [--profile <name>] [--verbose] [target] <command>...
|
||||
buildozer --version
|
||||
|
||||
Available targets:
|
||||
android Android target, based on python-for-android project
|
||||
ios iOS target, based on kivy-ios project
|
||||
|
||||
Global commands (without target):
|
||||
distclean Clean the whole Buildozer environment
|
||||
help Show the Buildozer help
|
||||
init Create an initial buildozer.spec in the current directory
|
||||
serve Serve the bin directory via SimpleHTTPServer
|
||||
setdefault Set the default command to run when no arguments are given
|
||||
version Show the Buildozer version
|
||||
|
||||
Target commands:
|
||||
clean Clean the target environment
|
||||
update Update the target dependencies
|
||||
debug Build the application in debug mode
|
||||
release Build the application in release mode
|
||||
deploy Deploy the application on the device
|
||||
run Run the application on the device
|
||||
serve Serve the bin directory via SimpleHTTPServer
|
||||
|
||||
Target "ios" commands:
|
||||
list_identities List the available identities to use for signing.
|
||||
xcode Open the xcode project.
|
||||
|
||||
Target "android" commands:
|
||||
adb Run adb from the Android SDK. Args must come after --, or
|
||||
use --alias to make an alias
|
||||
logcat Show the log from the device
|
||||
p4a Run p4a commands. Args must come after --, or use --alias
|
||||
to make an alias
|
||||
```
|
||||
|
||||
|
||||
## `buildozer.spec`
|
||||
|
||||
See [buildozer/default.spec](https://raw.github.com/kivy/buildozer/master/buildozer/default.spec) for an up-to-date spec file.
|
||||
|
||||
|
||||
## Default config
|
||||
|
||||
You can override the value of *any* `buildozer.spec` config token by
|
||||
setting an appropriate environment variable. These are all of the
|
||||
form ``$SECTION_TOKEN``, where SECTION is the config file section and
|
||||
TOKEN is the config token to override. Dots are replaced by
|
||||
underscores.
|
||||
|
||||
For example, here are some config tokens from the [app] section of the
|
||||
config, along with the environment variables that would override them.
|
||||
|
||||
- ``title`` -> ``$APP_TITLE``
|
||||
- ``package.name`` -> ``$APP_PACKAGE_NAME``
|
||||
- ``p4a.source_dir`` -> ``$APP_P4A_SOURCE_DIR``
|
||||
|
||||
## Support
|
||||
|
||||
If you need assistance, you can ask for help on our mailing list:
|
||||
|
||||
* User Group : https://groups.google.com/group/kivy-users
|
||||
* Email : kivy-users@googlegroups.com
|
||||
|
||||
Discord channel:
|
||||
|
||||
Server : https://chat.kivy.org
|
||||
Channel : #support
|
||||
|
||||
For [debugging on Android](https://python-for-android.readthedocs.io/en/stable/troubleshooting/?highlight=adb#debugging-on-android), don't hesitate to use ADB to get logs of your application.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
We love pull requests and discussing novel ideas. Check out our
|
||||
[contribution guide](https://kivy.org/docs/contribute.html) and
|
||||
feel free to improve buildozer.
|
||||
|
||||
The following mailing list and IRC channel are used exclusively for
|
||||
discussions about developing the Kivy framework and its sister projects:
|
||||
|
||||
* Dev Group : https://groups.google.com/group/kivy-dev
|
||||
* Email : kivy-dev@googlegroups.com
|
||||
|
||||
We also have a Discord channel:
|
||||
|
||||
* Server : https://chat.kivy.org
|
||||
* Channel : #support
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Buildozer is released under the terms of the MIT License. Please refer to the
|
||||
LICENSE file.
|
||||
|
||||
|
||||
## Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/kivy#backer)]
|
||||
|
||||
<a href="https://opencollective.com/kivy#backers" target="_blank"><img src="https://opencollective.com/kivy/backers.svg?width=890"></a>
|
||||
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/kivy#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/kivy/sponsor/0/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/1/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/2/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/3/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/4/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/5/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/6/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/7/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/8/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/kivy/sponsor/9/website" target="_blank"><img src="https://opencollective.com/kivy/sponsor/9/avatar.svg"></a>
|
248
README.rst
248
README.rst
|
@ -1,248 +0,0 @@
|
|||
Buildozer
|
||||
=========
|
||||
|
||||
Buildozer is a tool for creating application packages easily.
|
||||
|
||||
The goal is to have one "buildozer.spec" file in your app directory, describing
|
||||
your application requirements and settings such as title, icon, included modules
|
||||
etc. Buildozer will use that spec to create a package for Android, iOS, Windows,
|
||||
OSX and/or Linux.
|
||||
|
||||
Buildozer currently supports packaging for Android via the `python-for-android
|
||||
<http://github.com/kivy/python-for-android/>`_
|
||||
project, and for iOS via the kivy-ios project. iOS and OSX are still under work.
|
||||
|
||||
For Android: please have a look at `Android-SDK-NDK-Informations
|
||||
<https://github.com/kivy/kivy/wiki/Android-SDK-NDK-Informations>`_. Please note that
|
||||
the default SDK/NDK coded in Buildozer works for target Python 2.
|
||||
For target Python 3 see `Installing Buildozer with target Python 3 (CrystaX)
|
||||
<#installing-buildozer-with-target-python-3-crystax>`_.
|
||||
For host Python, both versions are seamlessly supported.
|
||||
|
||||
We provide a ready-to-use `Virtual Machine for Virtualbox <https://kivy.org/#download>`_.
|
||||
|
||||
Note that this tool has nothing to do with the eponymous online build service
|
||||
`buildozer.io <http://buildozer.io />`_.
|
||||
|
||||
Installing Buildozer with target Python 2 (default):
|
||||
----------------------------------------------------
|
||||
|
||||
#. Install buildozer::
|
||||
|
||||
# via pip (latest stable, recommended)
|
||||
sudo pip install buildozer
|
||||
|
||||
# latest dev version
|
||||
sudo pip install https://github.com/kivy/buildozer/archive/master.zip
|
||||
|
||||
# git clone, for working on buildozer
|
||||
git clone https://github.com/kivy/buildozer
|
||||
cd buildozer
|
||||
python setup.py build
|
||||
sudo pip install -e .
|
||||
|
||||
#. Go into your application directory and run::
|
||||
|
||||
buildozer init
|
||||
# edit the buildozer.spec, then
|
||||
buildozer android debug deploy run
|
||||
|
||||
Installing Buildozer with target Python 3 (CrystaX):
|
||||
----------------------------------------------------
|
||||
|
||||
After following the steps above to install buildozer and generate the default spec file,
|
||||
you need to setup Crystax NDK as described below.
|
||||
|
||||
#. Download and extract the Crystax NDK somewhere (~/.buildozer/crystax-ndk is one option): https://www.crystax.net/en/download
|
||||
|
||||
#. Make sure the following lines are in your buildozer.spec file.::
|
||||
|
||||
# Require python3crystax:
|
||||
requirements = python3crystax,kivy
|
||||
|
||||
# Point to the directory where you extracted the crystax-ndk:
|
||||
android.ndk_path = <Your install path here. Use ~ for home DIR>
|
||||
|
||||
#. Finally, build, deploy and run the app on your phone::
|
||||
|
||||
buildozer android debug deploy run
|
||||
|
||||
|
||||
|
||||
Buildozer Docker image
|
||||
----------------------
|
||||
|
||||
A Dockerfile is available to use buildozer through a Docker environment.
|
||||
|
||||
#. Build with::
|
||||
|
||||
docker build --tag=buildozer .
|
||||
|
||||
#. Run with::
|
||||
|
||||
docker run --volume "$(pwd)":/home/user/hostcwd buildozer --version
|
||||
|
||||
|
||||
Examples of Buildozer commands:
|
||||
--------------------------------
|
||||
|
||||
::
|
||||
|
||||
# buildozer target command
|
||||
buildozer android clean
|
||||
buildozer android update
|
||||
buildozer android deploy
|
||||
buildozer android debug
|
||||
buildozer android release
|
||||
|
||||
# or all in one (compile in debug, deploy on device)
|
||||
buildozer android debug deploy
|
||||
|
||||
# set the default command if nothing set
|
||||
buildozer setdefault android debug deploy run
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
::
|
||||
|
||||
Usage:
|
||||
buildozer [--profile <name>] [--verbose] [target] <command>...
|
||||
buildozer --version
|
||||
|
||||
Available targets:
|
||||
android Android target, based on python-for-android project
|
||||
ios iOS target, based on kivy-ios project
|
||||
android_old Android target, based on python-for-android project (old toolchain)
|
||||
|
||||
Global commands (without target):
|
||||
distclean Clean the whole Buildozer environment.
|
||||
help Show the Buildozer help.
|
||||
init Create a initial buildozer.spec in the current directory
|
||||
serve Serve the bin directory via SimpleHTTPServer
|
||||
setdefault Set the default command to run when no arguments are given
|
||||
version Show the Buildozer version
|
||||
|
||||
Target commands:
|
||||
clean Clean the target environment
|
||||
update Update the target dependencies
|
||||
debug Build the application in debug mode
|
||||
release Build the application in release mode
|
||||
deploy Deploy the application on the device
|
||||
run Run the application on the device
|
||||
serve Serve the bin directory via SimpleHTTPServer
|
||||
|
||||
Target "android_old" commands:
|
||||
adb Run adb from the Android SDK. Args must come after --, or
|
||||
use --alias to make an alias
|
||||
logcat Show the log from the device
|
||||
|
||||
Target "ios" commands:
|
||||
list_identities List the available identities to use for signing.
|
||||
xcode Open the xcode project.
|
||||
|
||||
Target "android" commands:
|
||||
adb Run adb from the Android SDK. Args must come after --, or
|
||||
use --alias to make an alias
|
||||
logcat Show the log from the device
|
||||
p4a Run p4a commands. Args must come after --, or use --alias
|
||||
to make an alias
|
||||
|
||||
|
||||
|
||||
buildozer.spec
|
||||
--------------
|
||||
|
||||
See `buildozer/default.spec <https://raw.github.com/kivy/buildozer/master/buildozer/default.spec>`_ for an up-to-date spec file.
|
||||
|
||||
|
||||
Default config
|
||||
--------------
|
||||
|
||||
You can override the value of *any* buildozer.spec config token by
|
||||
setting an appropriate environment variable. These are all of the
|
||||
form ``$SECTION_TOKEN``, where SECTION is the config file section and
|
||||
TOKEN is the config token to override. Dots are replaced by
|
||||
underscores.
|
||||
|
||||
For example, here are some config tokens from the [app] section of the
|
||||
config, along with the environment variables that would override them.
|
||||
|
||||
- ``title`` -> ``$APP_TITLE``
|
||||
- ``package.name`` -> ``$APP_PACKAGE_NAME``
|
||||
- ``p4a.source_dir`` -> ``$APP_P4A_SOURCE_DIR``
|
||||
|
||||
Buildozer Virtual Machine
|
||||
-------------------------
|
||||
|
||||
The current virtual machine (available via https://kivy.org/downloads/) allow
|
||||
you to have a ready to use vm for building android application.
|
||||
|
||||
Using shared folders
|
||||
++++++++++++++++++++
|
||||
|
||||
If the Virtualbox Guest tools are outdated, install the latest one:
|
||||
|
||||
- in the Virtualbox: `Devices` -> `Install Guest Additions CD images`
|
||||
- in the guest/linux: Go to the cdrom and run the installer
|
||||
- reboot the vm
|
||||
|
||||
VirtualBox filesystem doesn't support symlink anymore (don't
|
||||
try the setextradata solution, it doesn't work.). So you must
|
||||
do the build outside the shared folder. One solution:
|
||||
|
||||
- `sudo mkdir /build`
|
||||
- `sudo chown kivy /build`
|
||||
- In your buildozer.spec, section `[buildozer]`, set `build_dir = /build/buildozer-myapp`
|
||||
|
||||
Using your devices via the VM
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
There is a little icon on the bottom left that represent an USB plug.
|
||||
Select it, and select your android device on it. Then you can check:
|
||||
|
||||
- `buildozer android adb -- devices`
|
||||
|
||||
If it doesn't, use Google. They are so many differents way / issues
|
||||
depending your phone that Google will be your only source of
|
||||
information, not us :)
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
If you need assistance, you can ask for help on our mailing list:
|
||||
|
||||
* User Group : https://groups.google.com/group/kivy-users
|
||||
* Email : kivy-users@googlegroups.com
|
||||
|
||||
We also have an IRC channel:
|
||||
|
||||
* Server : irc.freenode.net
|
||||
* Port : 6667, 6697 (SSL only)
|
||||
* Channel : #kivy
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
We love pull requests and discussing novel ideas. Check out our
|
||||
`contribution guide <http://kivy.org/docs/contribute.html>`_ and
|
||||
feel free to improve buildozer.
|
||||
|
||||
The following mailing list and IRC channel are used exclusively for
|
||||
discussions about developing the Kivy framework and its sister projects:
|
||||
|
||||
* Dev Group : https://groups.google.com/group/kivy-dev
|
||||
* Email : kivy-dev@googlegroups.com
|
||||
|
||||
IRC channel:
|
||||
|
||||
* Server : irc.freenode.net
|
||||
* Port : 6667, 6697 (SSL only)
|
||||
* Channel : #kivy-dev
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Buildozer is released under the terms of the MIT License. Please refer to the
|
||||
LICENSE file.
|
|
@ -6,30 +6,29 @@ Generic Python packager for Android / iOS. Desktop later.
|
|||
|
||||
'''
|
||||
|
||||
__version__ = '0.35dev'
|
||||
__version__ = '1.2.0.dev0'
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import zipfile
|
||||
import select
|
||||
import codecs
|
||||
import textwrap
|
||||
import warnings
|
||||
from buildozer.jsonstore import JsonStore
|
||||
from sys import stdout, stderr, exit
|
||||
from re import search
|
||||
from os.path import join, exists, dirname, realpath, splitext, expanduser
|
||||
from subprocess import Popen, PIPE
|
||||
from os import environ, unlink, rename, walk, sep, listdir, makedirs
|
||||
from subprocess import Popen, PIPE, TimeoutExpired
|
||||
from os import environ, unlink, walk, sep, listdir, makedirs
|
||||
from copy import copy
|
||||
from shutil import copyfile, rmtree, copytree
|
||||
from shutil import copyfile, rmtree, copytree, move
|
||||
from fnmatch import fnmatch
|
||||
try:
|
||||
from urllib.request import FancyURLopener
|
||||
from configparser import SafeConfigParser
|
||||
except ImportError:
|
||||
from urllib import FancyURLopener
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
from pprint import pformat
|
||||
|
||||
from urllib.request import FancyURLopener
|
||||
from configparser import ConfigParser
|
||||
try:
|
||||
import fcntl
|
||||
except ImportError:
|
||||
|
@ -41,7 +40,7 @@ try:
|
|||
colorama.init()
|
||||
|
||||
RESET_SEQ = colorama.Fore.RESET + colorama.Style.RESET_ALL
|
||||
COLOR_SEQ = lambda x: x
|
||||
COLOR_SEQ = lambda x: x # noqa: E731
|
||||
BOLD_SEQ = ''
|
||||
if sys.platform == 'win32':
|
||||
BLACK = colorama.Fore.BLACK + colorama.Style.DIM
|
||||
|
@ -54,7 +53,7 @@ try:
|
|||
except ImportError:
|
||||
if sys.platform != 'win32':
|
||||
RESET_SEQ = "\033[0m"
|
||||
COLOR_SEQ = lambda x: "\033[1;{}m".format(30 + x)
|
||||
COLOR_SEQ = lambda x: "\033[1;{}m".format(30 + x) # noqa: E731
|
||||
BOLD_SEQ = "\033[1m"
|
||||
BLACK = 0
|
||||
RED = 1
|
||||
|
@ -71,13 +70,14 @@ except ImportError:
|
|||
LOG_LEVELS_C = (RED, BLUE, BLACK)
|
||||
LOG_LEVELS_T = 'EID'
|
||||
SIMPLE_HTTP_SERVER_PORT = 8000
|
||||
IS_PY3 = sys.version_info[0] >= 3
|
||||
|
||||
|
||||
class ChromeDownloader(FancyURLopener):
|
||||
version = (
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 '
|
||||
'(KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36')
|
||||
|
||||
|
||||
urlretrieve = ChromeDownloader().retrieve
|
||||
|
||||
|
||||
|
@ -97,20 +97,23 @@ class BuildozerCommandException(BuildozerException):
|
|||
pass
|
||||
|
||||
|
||||
class Buildozer(object):
|
||||
class Buildozer:
|
||||
|
||||
ERROR = 0
|
||||
INFO = 1
|
||||
DEBUG = 2
|
||||
|
||||
standard_cmds = ('distclean', 'update', 'debug', 'release',
|
||||
'deploy', 'run', 'serve')
|
||||
|
||||
def __init__(self, filename='buildozer.spec', target=None):
|
||||
super(Buildozer, self).__init__()
|
||||
self.log_level = 1
|
||||
self.log_level = 2
|
||||
self.environ = {}
|
||||
self.specfilename = filename
|
||||
self.state = None
|
||||
self.build_id = None
|
||||
self.config_profile = ''
|
||||
self.config = SafeConfigParser(allow_no_value=True)
|
||||
self.config = ConfigParser(allow_no_value=True)
|
||||
self.config.optionxform = lambda value: value
|
||||
self.config.getlist = self._get_config_list
|
||||
self.config.getlistvalues = self._get_config_list_values
|
||||
|
@ -119,7 +122,7 @@ class Buildozer(object):
|
|||
self.config.getrawdefault = self._get_config_raw_default
|
||||
|
||||
if exists(filename):
|
||||
self.config.read(filename)
|
||||
self.config.read(filename, "utf-8")
|
||||
self.check_configuration_tokens()
|
||||
|
||||
# Check all section/tokens for env vars, and replace the
|
||||
|
@ -128,18 +131,10 @@ class Buildozer(object):
|
|||
|
||||
try:
|
||||
self.log_level = int(self.config.getdefault(
|
||||
'buildozer', 'log_level', '1'))
|
||||
except:
|
||||
'buildozer', 'log_level', '2'))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
build_dir = self.config.getdefault('buildozer', 'builddir', None)
|
||||
if build_dir:
|
||||
# for backwards compatibility, append .buildozer to builddir
|
||||
build_dir = join(build_dir, '.buildozer')
|
||||
self.build_dir = self.config.getdefault('buildozer', 'build_dir', build_dir)
|
||||
|
||||
if self.build_dir:
|
||||
self.build_dir = realpath(join(self.root_dir, self.build_dir))
|
||||
self.user_bin_dir = self.config.getdefault('buildozer', 'bin_dir', None)
|
||||
if self.user_bin_dir:
|
||||
self.user_bin_dir = realpath(join(self.root_dir, self.user_bin_dir))
|
||||
|
@ -152,10 +147,9 @@ class Buildozer(object):
|
|||
def set_target(self, target):
|
||||
'''Set the target to use (one of buildozer.targets, such as "android")
|
||||
'''
|
||||
target = self.translate_target(target)
|
||||
self.targetname = target
|
||||
m = __import__('buildozer.targets.{0}'.format(target),
|
||||
fromlist=['buildozer'])
|
||||
fromlist=['buildozer'])
|
||||
self.target = m.get_target(self)
|
||||
self.check_build_layout()
|
||||
self.check_configuration_tokens()
|
||||
|
@ -178,7 +172,6 @@ class Buildozer(object):
|
|||
self.info('Check application requirements')
|
||||
self.check_application_requirements()
|
||||
|
||||
self.info('Check garden requirements')
|
||||
self.check_garden_requirements()
|
||||
|
||||
self.info('Compile platform')
|
||||
|
@ -228,13 +221,19 @@ class Buildozer(object):
|
|||
print('{} {}'.format(LOG_LEVELS_T[level], msg))
|
||||
|
||||
def debug(self, msg):
|
||||
self.log(2, msg)
|
||||
self.log(self.DEBUG, msg)
|
||||
|
||||
def log_env(self, level, env):
|
||||
"""dump env into debug logger in readable format"""
|
||||
self.log(level, "ENVIRONMENT:")
|
||||
for k, v in env.items():
|
||||
self.log(level, " {} = {}".format(k, pformat(v)))
|
||||
|
||||
def info(self, msg):
|
||||
self.log(1, msg)
|
||||
self.log(self.INFO, msg)
|
||||
|
||||
def error(self, msg):
|
||||
self.log(0, msg)
|
||||
self.log(self.ERROR, msg)
|
||||
|
||||
#
|
||||
# Internal check methods
|
||||
|
@ -254,7 +253,7 @@ class Buildozer(object):
|
|||
|
||||
def cmd(self, command, **kwargs):
|
||||
# prepare the environ, based on the system + our own env
|
||||
env = copy(environ)
|
||||
env = environ.copy()
|
||||
env.update(self.environ)
|
||||
|
||||
# prepare the process
|
||||
|
@ -270,15 +269,18 @@ class Buildozer(object):
|
|||
get_stderr = kwargs.pop('get_stderr', False)
|
||||
break_on_error = kwargs.pop('break_on_error', True)
|
||||
sensible = kwargs.pop('sensible', False)
|
||||
run_condition = kwargs.pop('run_condition', None)
|
||||
quiet = kwargs.pop('quiet', False)
|
||||
|
||||
if not sensible:
|
||||
self.debug('Run {0!r}'.format(command))
|
||||
else:
|
||||
if type(command) in (list, tuple):
|
||||
self.debug('Run {0!r} ...'.format(command[0]))
|
||||
if not quiet:
|
||||
if not sensible:
|
||||
self.debug('Run {0!r}'.format(command))
|
||||
else:
|
||||
self.debug('Run {0!r} ...'.format(command.split()[0]))
|
||||
self.debug('Cwd {}'.format(kwargs.get('cwd')))
|
||||
if isinstance(command, (list, tuple)):
|
||||
self.debug('Run {0!r} ...'.format(command[0]))
|
||||
else:
|
||||
self.debug('Run {0!r} ...'.format(command.split()[0]))
|
||||
self.debug('Cwd {}'.format(kwargs.get('cwd')))
|
||||
|
||||
# open the process
|
||||
if sys.platform == 'win32':
|
||||
|
@ -298,9 +300,9 @@ class Buildozer(object):
|
|||
|
||||
ret_stdout = [] if get_stdout else None
|
||||
ret_stderr = [] if get_stderr else None
|
||||
while True:
|
||||
while not run_condition or run_condition():
|
||||
try:
|
||||
readx = select.select([fd_stdout, fd_stderr], [], [])[0]
|
||||
readx = select.select([fd_stdout, fd_stderr], [], [], 1)[0]
|
||||
except select.error:
|
||||
break
|
||||
if fd_stdout in readx:
|
||||
|
@ -310,10 +312,7 @@ class Buildozer(object):
|
|||
if get_stdout:
|
||||
ret_stdout.append(chunk)
|
||||
if show_output:
|
||||
if IS_PY3:
|
||||
stdout.write(str(chunk))
|
||||
else:
|
||||
stdout.write(chunk)
|
||||
stdout.write(chunk.decode('utf-8', 'replace'))
|
||||
if fd_stderr in readx:
|
||||
chunk = process.stderr.read()
|
||||
if not chunk:
|
||||
|
@ -321,20 +320,24 @@ class Buildozer(object):
|
|||
if get_stderr:
|
||||
ret_stderr.append(chunk)
|
||||
if show_output:
|
||||
if IS_PY3:
|
||||
stderr.write(chunk.decode('utf-8'))
|
||||
else:
|
||||
stderr.write(chunk)
|
||||
stderr.write(chunk.decode('utf-8', 'replace'))
|
||||
|
||||
stdout.flush()
|
||||
stderr.flush()
|
||||
stdout.flush()
|
||||
stderr.flush()
|
||||
|
||||
try:
|
||||
process.communicate(
|
||||
timeout=(1 if run_condition and not run_condition() else None)
|
||||
)
|
||||
except TimeoutExpired:
|
||||
pass
|
||||
|
||||
process.communicate()
|
||||
if process.returncode != 0 and break_on_error:
|
||||
self.error('Command failed: {0}'.format(command))
|
||||
self.log_env(self.ERROR, kwargs['env'])
|
||||
self.error('')
|
||||
self.error('Buildozer failed to execute the last command')
|
||||
if self.log_level <= 1:
|
||||
if self.log_level <= self.INFO:
|
||||
self.error('If the error is not obvious, please raise the log_level to 2')
|
||||
self.error('and retry the latest command.')
|
||||
else:
|
||||
|
@ -343,10 +346,12 @@ class Buildozer(object):
|
|||
self.error('raising an issue with buildozer itself.')
|
||||
self.error('In case of a bug report, please add a full log with log_level = 2')
|
||||
raise BuildozerCommandException()
|
||||
|
||||
if ret_stdout:
|
||||
ret_stdout = b''.join(ret_stdout)
|
||||
if ret_stderr:
|
||||
ret_stderr = b''.join(ret_stderr)
|
||||
|
||||
return (ret_stdout.decode('utf-8', 'ignore') if ret_stdout else None,
|
||||
ret_stderr.decode('utf-8') if ret_stderr else None,
|
||||
process.returncode)
|
||||
|
@ -355,7 +360,7 @@ class Buildozer(object):
|
|||
from pexpect import spawnu
|
||||
|
||||
# prepare the environ, based on the system + our own env
|
||||
env = copy(environ)
|
||||
env = environ.copy()
|
||||
env.update(self.environ)
|
||||
|
||||
# prepare the process
|
||||
|
@ -365,10 +370,7 @@ class Buildozer(object):
|
|||
show_output = kwargs.pop('show_output')
|
||||
|
||||
if show_output:
|
||||
if IS_PY3:
|
||||
kwargs['logfile'] = codecs.getwriter('utf8')(stdout.buffer)
|
||||
else:
|
||||
kwargs['logfile'] = codecs.getwriter('utf8')(stdout)
|
||||
kwargs['logfile'] = codecs.getwriter('utf8')(stdout.buffer)
|
||||
|
||||
if not sensible:
|
||||
self.debug('Run (expect) {0!r}'.format(command))
|
||||
|
@ -403,13 +405,13 @@ class Buildozer(object):
|
|||
adderror('[app] One of "version" or "version.regex" must be set')
|
||||
if version and version_regex:
|
||||
adderror('[app] Conflict between "version" and "version.regex"'
|
||||
', only one can be used.')
|
||||
', only one can be used.')
|
||||
if version_regex and not get('app', 'version.filename', ''):
|
||||
adderror('[app] "version.filename" is missing'
|
||||
', required by "version.regex"')
|
||||
', required by "version.regex"')
|
||||
|
||||
orientation = get('app', 'orientation', 'landscape')
|
||||
if orientation not in ('landscape', 'portrait', 'all'):
|
||||
if orientation not in ('landscape', 'portrait', 'all', 'sensorLandscape'):
|
||||
adderror('[app] "orientation" have an invalid value')
|
||||
|
||||
if errors:
|
||||
|
@ -479,9 +481,9 @@ class Buildozer(object):
|
|||
return
|
||||
|
||||
# remove all the requirements that the target can compile
|
||||
onlyname = lambda x: x.split('==')[0]
|
||||
onlyname = lambda x: x.split('==')[0] # noqa: E731
|
||||
requirements = [x for x in requirements if onlyname(x) not in
|
||||
target_available_packages]
|
||||
target_available_packages]
|
||||
|
||||
if requirements and hasattr(sys, 'real_prefix'):
|
||||
e = self.error
|
||||
|
@ -492,10 +494,12 @@ class Buildozer(object):
|
|||
exit(1)
|
||||
|
||||
# did we already installed the libs ?
|
||||
if exists(self.applibs_dir) and \
|
||||
self.state.get('cache.applibs', '') == requirements:
|
||||
self.debug('Application requirements already installed, pass')
|
||||
return
|
||||
if (
|
||||
exists(self.applibs_dir) and
|
||||
self.state.get('cache.applibs', '') == requirements
|
||||
):
|
||||
self.debug('Application requirements already installed, pass')
|
||||
return
|
||||
|
||||
# recreate applibs
|
||||
self.rmdir(self.applibs_dir)
|
||||
|
@ -516,51 +520,17 @@ class Buildozer(object):
|
|||
cwd=self.buildozer_dir)
|
||||
|
||||
def check_garden_requirements(self):
|
||||
'''Ensure required garden packages are available to be included.
|
||||
'''
|
||||
garden_requirements = self.config.getlist('app',
|
||||
'garden_requirements', '')
|
||||
|
||||
# have we installed the garden packages?
|
||||
if exists(self.gardenlibs_dir) and \
|
||||
self.state.get('cache.gardenlibs', '') == garden_requirements:
|
||||
self.debug('Garden requirements already installed, pass')
|
||||
return
|
||||
|
||||
# we're going to reinstall all the garden libs.
|
||||
self.rmdir(self.gardenlibs_dir)
|
||||
|
||||
# but if we don't have requirements, or if the user removed everything,
|
||||
# don't do anything.
|
||||
if not garden_requirements:
|
||||
self.state['cache.gardenlibs'] = garden_requirements
|
||||
return
|
||||
|
||||
self._ensure_virtualenv()
|
||||
self.cmd('pip install Kivy-Garden==0.1.1', env=self.env_venv)
|
||||
|
||||
# recreate gardenlibs
|
||||
self.mkdir(self.gardenlibs_dir)
|
||||
|
||||
for requirement in garden_requirements:
|
||||
self._install_garden_package(requirement)
|
||||
|
||||
# save gardenlibs state
|
||||
self.state['cache.gardenlibs'] = garden_requirements
|
||||
|
||||
def _install_garden_package(self, package):
|
||||
self._ensure_virtualenv()
|
||||
self.debug('Install garden package {} in buildozer_dir'.format(package))
|
||||
self.cmd('garden install --app {}'.format(package),
|
||||
env=self.env_venv,
|
||||
cwd=self.buildozer_dir)
|
||||
'garden_requirements', '')
|
||||
if garden_requirements:
|
||||
warnings.warn("`garden_requirements` settings is deprecated, use `requirements` instead", DeprecationWarning)
|
||||
|
||||
def _ensure_virtualenv(self):
|
||||
if hasattr(self, 'venv'):
|
||||
return
|
||||
self.venv = join(self.buildozer_dir, 'venv')
|
||||
if not self.file_exists(self.venv):
|
||||
self.cmd('virtualenv --python=python2.7 ./venv',
|
||||
self.cmd('python3 -m venv ./venv',
|
||||
cwd=self.buildozer_dir)
|
||||
|
||||
# read virtualenv output and parse it
|
||||
|
@ -613,7 +583,7 @@ class Buildozer(object):
|
|||
if not os.path.isdir(os.path.dirname(target)):
|
||||
self.error(('Rename {0} to {1} fails because {2} is not a '
|
||||
'directory').format(source, target, target))
|
||||
rename(source, target)
|
||||
move(source, target)
|
||||
|
||||
def file_copy(self, source, target, cwd=None):
|
||||
if cwd:
|
||||
|
@ -624,10 +594,6 @@ class Buildozer(object):
|
|||
|
||||
def file_extract(self, archive, cwd=None):
|
||||
if archive.endswith('.tgz') or archive.endswith('.tar.gz'):
|
||||
# XXX tarfile doesn't work for NDK-r8c :(
|
||||
#tf = tarfile.open(archive, 'r:*')
|
||||
#tf.extractall(path=cwd)
|
||||
#tf.close()
|
||||
self.cmd('tar xzf {0}'.format(archive), cwd=cwd)
|
||||
return
|
||||
|
||||
|
@ -638,12 +604,12 @@ class Buildozer(object):
|
|||
|
||||
if archive.endswith('.bin'):
|
||||
# To process the bin files for linux and darwin systems
|
||||
self.cmd('chmod a+x {0}'.format(archive),cwd=cwd)
|
||||
self.cmd('./{0}'.format(archive),cwd=cwd)
|
||||
self.cmd('chmod a+x {0}'.format(archive), cwd=cwd)
|
||||
self.cmd('./{0}'.format(archive), cwd=cwd)
|
||||
return
|
||||
|
||||
if archive.endswith('.zip'):
|
||||
self.cmd('unzip {}'.format(join(cwd, archive)), cwd=cwd)
|
||||
self.cmd('unzip -q {}'.format(join(cwd, archive)), cwd=cwd)
|
||||
return
|
||||
|
||||
raise Exception('Unhandled extraction for type {0}'.format(archive))
|
||||
|
@ -674,8 +640,9 @@ class Buildozer(object):
|
|||
else:
|
||||
progression = '{0:.2f}%'.format(
|
||||
index * blksize * 100. / float(size))
|
||||
stdout.write('- Download {}\r'.format(progression))
|
||||
stdout.flush()
|
||||
if "CI" not in environ:
|
||||
stdout.write('- Download {}\r'.format(progression))
|
||||
stdout.flush()
|
||||
|
||||
url = url + filename
|
||||
if cwd:
|
||||
|
@ -725,12 +692,11 @@ class Buildozer(object):
|
|||
def build_application(self):
|
||||
self._copy_application_sources()
|
||||
self._copy_application_libs()
|
||||
self._copy_garden_libs()
|
||||
self._add_sitecustomize()
|
||||
|
||||
def _copy_application_sources(self):
|
||||
# XXX clean the inclusion/exclusion algo.
|
||||
source_dir = realpath(self.config.getdefault('app', 'source.dir', '.'))
|
||||
source_dir = realpath(expanduser(self.config.getdefault('app', 'source.dir', '.')))
|
||||
include_exts = self.config.getlist('app', 'source.include_exts', '')
|
||||
exclude_exts = self.config.getlist('app', 'source.exclude_exts', '')
|
||||
exclude_dirs = self.config.getlist('app', 'source.exclude_dirs', '')
|
||||
|
@ -740,11 +706,17 @@ class Buildozer(object):
|
|||
'')
|
||||
app_dir = self.app_dir
|
||||
|
||||
include_exts = [ext.lower() for ext in include_exts]
|
||||
exclude_exts = [ext.lower() for ext in exclude_exts]
|
||||
exclude_dirs = [dir.lower() for dir in exclude_dirs]
|
||||
exclude_patterns = [pat.lower() for pat in exclude_patterns]
|
||||
include_patterns = [pat.lower() for pat in include_patterns]
|
||||
|
||||
self.debug('Copy application source from {}'.format(source_dir))
|
||||
|
||||
rmtree(self.app_dir)
|
||||
|
||||
for root, dirs, files in walk(source_dir):
|
||||
for root, dirs, files in walk(source_dir, followlinks=True):
|
||||
# avoid hidden directory
|
||||
if True in [x.startswith('.') for x in root.split(sep)]:
|
||||
continue
|
||||
|
@ -805,7 +777,7 @@ class Buildozer(object):
|
|||
# TODO more filters
|
||||
basename, ext = splitext(fn)
|
||||
if ext:
|
||||
ext = ext[1:]
|
||||
ext = ext[1:].lower()
|
||||
if include_exts and ext not in include_exts:
|
||||
continue
|
||||
if exclude_exts and ext in exclude_exts:
|
||||
|
@ -826,17 +798,12 @@ class Buildozer(object):
|
|||
# copy also the libs
|
||||
copytree(self.applibs_dir, join(self.app_dir, '_applibs'))
|
||||
|
||||
def _copy_garden_libs(self):
|
||||
if exists(self.gardenlibs_dir):
|
||||
copytree(self.gardenlibs_dir, join(self.app_dir, 'libs'))
|
||||
|
||||
def _add_sitecustomize(self):
|
||||
copyfile(join(dirname(__file__), 'sitecustomize.py'),
|
||||
join(self.app_dir, 'sitecustomize.py'))
|
||||
|
||||
main_py = join(self.app_dir, 'service', 'main.py')
|
||||
if not self.file_exists(main_py):
|
||||
#self.error('Unable to patch main_py to add applibs directory.')
|
||||
return
|
||||
|
||||
header = (b'import sys, os; '
|
||||
|
@ -853,16 +820,33 @@ class Buildozer(object):
|
|||
'''Return a "valid" name from a name with lot of invalid chars
|
||||
(allowed characters: a-z, A-Z, 0-9, -, _)
|
||||
'''
|
||||
return re.sub('[^a-zA-Z0-9_\-]', '_', name)
|
||||
return re.sub(r'[^a-zA-Z0-9_\-]', '_', name)
|
||||
|
||||
@property
|
||||
def root_dir(self):
|
||||
return realpath(dirname(self.specfilename))
|
||||
return realpath(expanduser(dirname(self.specfilename)))
|
||||
|
||||
@property
|
||||
def user_build_dir(self):
|
||||
"""The user-provided build dir, if any."""
|
||||
# Check for a user-provided build dir
|
||||
# Check the (deprecated) builddir token, for backwards compatibility
|
||||
build_dir = self.config.getdefault('buildozer', 'builddir', None)
|
||||
if build_dir is not None:
|
||||
# for backwards compatibility, append .buildozer to builddir
|
||||
build_dir = join(build_dir, '.buildozer')
|
||||
build_dir = self.config.getdefault('buildozer', 'build_dir', build_dir)
|
||||
|
||||
if build_dir is not None:
|
||||
build_dir = realpath(join(self.root_dir, expanduser(build_dir)))
|
||||
|
||||
return build_dir
|
||||
|
||||
@property
|
||||
def buildozer_dir(self):
|
||||
if self.build_dir:
|
||||
return self.build_dir
|
||||
'''The directory in which to run the app build.'''
|
||||
if self.user_build_dir is not None:
|
||||
return self.user_build_dir
|
||||
return join(self.root_dir, '.buildozer')
|
||||
|
||||
@property
|
||||
|
@ -883,10 +867,6 @@ class Buildozer(object):
|
|||
def applibs_dir(self):
|
||||
return join(self.buildozer_dir, 'applibs')
|
||||
|
||||
@property
|
||||
def gardenlibs_dir(self):
|
||||
return join(self.buildozer_dir, 'libs')
|
||||
|
||||
@property
|
||||
def global_buildozer_dir(self):
|
||||
return join(expanduser('~'), '.buildozer')
|
||||
|
@ -911,28 +891,10 @@ class Buildozer(object):
|
|||
return package_name
|
||||
return '{}.{}'.format(package_domain, package_name)
|
||||
|
||||
|
||||
#
|
||||
# command line invocation
|
||||
#
|
||||
|
||||
def translate_target(self, target, inverse=False):
|
||||
# FIXME at some point, refactor to remove completely android old toolchain
|
||||
if inverse:
|
||||
if target == "android":
|
||||
target = "android_old"
|
||||
elif target == "android_new":
|
||||
target = "android"
|
||||
else:
|
||||
if target == "android":
|
||||
target = "android_new"
|
||||
elif target == "android_new":
|
||||
self.error("ERROR: The target android_new is now android")
|
||||
exit(1)
|
||||
elif target == "android_old":
|
||||
target = "android"
|
||||
return target
|
||||
|
||||
def targets(self):
|
||||
for fn in listdir(join(dirname(__file__), 'targets')):
|
||||
if fn.startswith('.') or fn.startswith('__'):
|
||||
|
@ -943,7 +905,7 @@ class Buildozer(object):
|
|||
try:
|
||||
m = __import__('buildozer.targets.{0}'.format(target),
|
||||
fromlist=['buildozer'])
|
||||
yield self.translate_target(target, inverse=True), m
|
||||
yield target, m
|
||||
except NotImplementedError:
|
||||
pass
|
||||
except:
|
||||
|
@ -973,8 +935,7 @@ class Buildozer(object):
|
|||
|
||||
if not meth.__doc__:
|
||||
continue
|
||||
doc = [x for x in
|
||||
meth.__doc__.strip().splitlines()][0].strip()
|
||||
doc = list(meth.__doc__.strip().splitlines())[0].strip()
|
||||
print(' {0:<18} {1}'.format(name, doc))
|
||||
|
||||
print('')
|
||||
|
@ -1051,8 +1012,8 @@ class Buildozer(object):
|
|||
|
||||
# maybe it's a target?
|
||||
targets = [x[0] for x in self.targets()]
|
||||
if self.translate_target(command, inverse=True) not in targets:
|
||||
print('Unknown command/target {}'.format(self.translate_target(command, inverse=True)))
|
||||
if command not in targets:
|
||||
print('Unknown command/target {}'.format(command))
|
||||
exit(1)
|
||||
|
||||
self.set_target(command)
|
||||
|
@ -1062,11 +1023,6 @@ class Buildozer(object):
|
|||
'''If effective user id is 0, display a warning and require
|
||||
user input to continue (or to cancel)'''
|
||||
|
||||
if IS_PY3:
|
||||
input_func = input
|
||||
else:
|
||||
input_func = raw_input
|
||||
|
||||
warn_on_root = self.config.getdefault('buildozer', 'warn_on_root', '1')
|
||||
try:
|
||||
euid = os.geteuid() == 0
|
||||
|
@ -1079,7 +1035,7 @@ class Buildozer(object):
|
|||
print('\033[91mThis is \033[1mnot\033[0m \033[91mrecommended, and may lead to problems later.\033[0m')
|
||||
cont = None
|
||||
while cont not in ('y', 'n'):
|
||||
cont = input_func('Are you sure you want to continue [y/n]? ')
|
||||
cont = input('Are you sure you want to continue [y/n]? ')
|
||||
|
||||
if cont == 'n':
|
||||
sys.exit()
|
||||
|
@ -1104,6 +1060,23 @@ class Buildozer(object):
|
|||
return
|
||||
rmtree(self.global_buildozer_dir)
|
||||
|
||||
def cmd_appclean(self, *args):
|
||||
'''Clean the .buildozer folder in the app directory.
|
||||
|
||||
This command specifically refuses to delete files in a
|
||||
user-specified build directory, to avoid accidentally deleting
|
||||
more than the user intends.
|
||||
'''
|
||||
if self.user_build_dir is not None:
|
||||
self.error(
|
||||
('Failed: build_dir is specified as {} in the buildozer config. `appclean` will '
|
||||
'not attempt to delete files in a user-specified build directory.').format(self.user_build_dir))
|
||||
elif exists(self.buildozer_dir):
|
||||
self.info('Deleting {}'.format(self.buildozer_dir))
|
||||
rmtree(self.buildozer_dir)
|
||||
else:
|
||||
self.error('{} already deleted, skipping.'.format(self.buildozer_dir))
|
||||
|
||||
def cmd_help(self, *args):
|
||||
'''Show the Buildozer help.
|
||||
'''
|
||||
|
@ -1169,15 +1142,13 @@ class Buildozer(object):
|
|||
value, section_base, profile))
|
||||
self.config.set(section_base, name, value)
|
||||
|
||||
|
||||
|
||||
def _get_config_list_values(self, *args, **kwargs):
|
||||
kwargs['with_values'] = True
|
||||
return self._get_config_list(*args, **kwargs)
|
||||
|
||||
def _get_config_list(self, section, token, default=None, with_values=False):
|
||||
# monkey-patch method for ConfigParser
|
||||
# get a key as a list of string, seperated from the comma
|
||||
# get a key as a list of string, separated from the comma
|
||||
|
||||
# check if an env var exists that should replace the file config
|
||||
set_config_token_from_env(section, token, self.config)
|
||||
|
@ -1246,6 +1217,7 @@ def set_config_from_envs(config):
|
|||
for token in config.options(section):
|
||||
set_config_token_from_env(section, token, config)
|
||||
|
||||
|
||||
def set_config_token_from_env(section, token, config):
|
||||
'''Given a config section and token, checks for an appropriate
|
||||
environment variable. If the variable exists, sets the config entry to
|
||||
|
|
|
@ -22,7 +22,7 @@ source.include_exts = py,png,jpg,kv,atlas
|
|||
#source.exclude_exts = spec
|
||||
|
||||
# (list) List of directory to exclude (let empty to not exclude anything)
|
||||
#source.exclude_dirs = tests, bin
|
||||
#source.exclude_dirs = tests, bin, venv
|
||||
|
||||
# (list) List of exclusions using pattern matching
|
||||
#source.exclude_patterns = license,images/*/*.jpg
|
||||
|
@ -35,23 +35,20 @@ version = 0.1
|
|||
# version.filename = %(source.dir)s/main.py
|
||||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = kivy
|
||||
# comma separated e.g. requirements = sqlite3,kivy
|
||||
requirements = python3,kivy
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
# requirements.source.kivy = ../../kivy
|
||||
|
||||
# (list) Garden requirements
|
||||
#garden_requirements =
|
||||
|
||||
# (str) Presplash of the application
|
||||
#presplash.filename = %(source.dir)s/data/presplash.png
|
||||
|
||||
# (str) Icon of the application
|
||||
#icon.filename = %(source.dir)s/data/icon.png
|
||||
|
||||
# (str) Supported orientation (one of landscape, portrait or all)
|
||||
# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
|
||||
orientation = portrait
|
||||
|
||||
# (list) List of service to declare
|
||||
|
@ -77,27 +74,43 @@ osx.kivy_version = 1.9.1
|
|||
# (bool) Indicate if the application should be fullscreen or not
|
||||
fullscreen = 0
|
||||
|
||||
# (string) Presplash background color (for new android toolchain)
|
||||
# (string) Presplash background color (for android toolchain)
|
||||
# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
|
||||
# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
|
||||
# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
|
||||
# olive, purple, silver, teal.
|
||||
#android.presplash_color = #FFFFFF
|
||||
|
||||
# (string) Presplash animation using Lottie format.
|
||||
# see https://lottiefiles.com/ for examples and https://airbnb.design/lottie/
|
||||
# for general documentation.
|
||||
# Lottie files can be created using various tools, like Adobe After Effect or Synfig.
|
||||
#android.presplash_lottie = "path/to/lottie/file.json"
|
||||
|
||||
# (str) Adaptive icon of the application (used if Android API level is 26+ at runtime)
|
||||
#icon.adaptive_foreground.filename = %(source.dir)s/data/icon_fg.png
|
||||
#icon.adaptive_background.filename = %(source.dir)s/data/icon_bg.png
|
||||
|
||||
# (list) Permissions
|
||||
#android.permissions = INTERNET
|
||||
|
||||
# (int) Android API to use
|
||||
#android.api = 19
|
||||
# (list) features (adds uses-feature -tags to manifest)
|
||||
#android.features = android.hardware.usb.host
|
||||
|
||||
# (int) Minimum API required
|
||||
#android.minapi = 9
|
||||
# (int) Target Android API, should be as high as possible.
|
||||
#android.api = 27
|
||||
|
||||
# (int) Minimum API your APK will support.
|
||||
#android.minapi = 21
|
||||
|
||||
# (int) Android SDK version to use
|
||||
#android.sdk = 20
|
||||
|
||||
# (str) Android NDK version to use
|
||||
#android.ndk = 9c
|
||||
#android.ndk = 19b
|
||||
|
||||
# (int) Android NDK API to use. This is the minimum API your app will support, it should usually match android.minapi.
|
||||
#android.ndk_api = 21
|
||||
|
||||
# (bool) Use --private data storage (True) or --dir public storage (False)
|
||||
#android.private_storage = True
|
||||
|
@ -116,8 +129,33 @@ fullscreen = 0
|
|||
# when an update is due and you just want to test/build your package
|
||||
# android.skip_update = False
|
||||
|
||||
# (bool) If True, then automatically accept SDK license
|
||||
# agreements. This is intended for automation only. If set to False,
|
||||
# the default, you will be shown the license when first running
|
||||
# buildozer.
|
||||
# android.accept_sdk_license = False
|
||||
|
||||
# (str) Android entry point, default is ok for Kivy-based app
|
||||
#android.entrypoint = org.renpy.android.PythonActivity
|
||||
#android.entrypoint = org.kivy.android.PythonActivity
|
||||
|
||||
# (str) Full name including package path of the Java class that implements Android Activity
|
||||
# use that parameter together with android.entrypoint to set custom Java class instead of PythonActivity
|
||||
#android.activity_class_name = org.kivy.android.PythonActivity
|
||||
|
||||
# (str) Extra xml to write directly inside the <manifest> element of AndroidManifest.xml
|
||||
# use that parameter to provide a filename from where to load your custom XML code
|
||||
#android.extra_manifest_xml = ./src/android/extra_manifest.xml
|
||||
|
||||
# (str) Extra xml to write directly inside the <manifest><application> tag of AndroidManifest.xml
|
||||
# use that parameter to provide a filename from where to load your custom XML arguments:
|
||||
#android.extra_manifest_application_arguments = ./src/android/extra_manifest_application_arguments.xml
|
||||
|
||||
# (str) Full name including package path of the Java class that implements Python Service
|
||||
# use that parameter to set custom Java class instead of PythonService
|
||||
#android.service_class_name = org.kivy.android.PythonService
|
||||
|
||||
# (str) Android app theme, default is ok for Kivy-based app
|
||||
# android.apptheme = "@android:style/Theme.NoTitleBar"
|
||||
|
||||
# (list) Pattern to whitelist for the whole project
|
||||
#android.whitelist =
|
||||
|
@ -138,19 +176,36 @@ fullscreen = 0
|
|||
# directory containing the files)
|
||||
#android.add_src =
|
||||
|
||||
# (list) Android AAR archives to add (currently works only with sdl2_gradle
|
||||
# bootstrap)
|
||||
# (list) Android AAR archives to add
|
||||
#android.add_aars =
|
||||
|
||||
# (list) Gradle dependencies to add (currently works only with sdl2_gradle
|
||||
# bootstrap)
|
||||
# (list) Gradle dependencies to add
|
||||
#android.gradle_dependencies =
|
||||
|
||||
# (list) Java classes to add as activities to the manifest.
|
||||
#android.add_activites = com.example.ExampleActivity
|
||||
# (bool) Enable AndroidX support. Enable when 'android.gradle_dependencies'
|
||||
# contains an 'androidx' package, or any package from Kotlin source.
|
||||
# android.enable_androidx requires android.api >= 28
|
||||
#android.enable_androidx = False
|
||||
|
||||
# (str) python-for-android branch to use, defaults to stable
|
||||
#p4a.branch = stable
|
||||
# (list) add java compile options
|
||||
# this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
|
||||
# see https://developer.android.com/studio/write/java8-support for further information
|
||||
# android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8"
|
||||
|
||||
# (list) Gradle repositories to add {can be necessary for some android.gradle_dependencies}
|
||||
# please enclose in double quotes
|
||||
# e.g. android.gradle_repositories = "maven { url 'https://kotlin.bintray.com/ktor' }"
|
||||
#android.add_gradle_repositories =
|
||||
|
||||
# (list) packaging options to add
|
||||
# see https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html
|
||||
# can be necessary to solve conflicts in gradle_dependencies
|
||||
# please enclose in double quotes
|
||||
# e.g. android.add_packaging_options = "exclude 'META-INF/common.kotlin_module'", "exclude 'META-INF/*.kotlin_module'"
|
||||
#android.add_packaging_options =
|
||||
|
||||
# (list) Java classes to add as activities to the manifest.
|
||||
#android.add_activities = com.example.ExampleActivity
|
||||
|
||||
# (str) OUYA Console category. Should be one of GAME or APP
|
||||
# If you leave this blank, OUYA support will not be enabled
|
||||
|
@ -165,9 +220,10 @@ fullscreen = 0
|
|||
# (str) launchMode to set for the main activity
|
||||
#android.manifest.launch_mode = standard
|
||||
|
||||
# (list) Android additionnal libraries to copy into libs/armeabi
|
||||
# (list) Android additional libraries to copy into libs/armeabi
|
||||
#android.add_libs_armeabi = libs/android/*.so
|
||||
#android.add_libs_armeabi_v7a = libs/android-v7/*.so
|
||||
#android.add_libs_arm64_v8a = libs/android-v8/*.so
|
||||
#android.add_libs_x86 = libs/android-x86/*.so
|
||||
#android.add_libs_mips = libs/android-mips/*.so
|
||||
|
||||
|
@ -182,19 +238,59 @@ fullscreen = 0
|
|||
# project.properties automatically.)
|
||||
#android.library_references =
|
||||
|
||||
# (list) Android shared libraries which will be added to AndroidManifest.xml using <uses-library> tag
|
||||
#android.uses_library =
|
||||
|
||||
# (str) Android logcat filters to use
|
||||
#android.logcat_filters = *:S python:D
|
||||
|
||||
# (bool) Android logcat only display log for activity's pid
|
||||
#android.logcat_pid_only = False
|
||||
|
||||
# (str) Android additional adb arguments
|
||||
#android.adb_args = -H host.docker.internal
|
||||
|
||||
# (bool) Copy library instead of making a libpymodules.so
|
||||
#android.copy_libs = 1
|
||||
|
||||
# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86
|
||||
# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
|
||||
android.arch = armeabi-v7a
|
||||
|
||||
# (int) overrides automatic versionCode computation (used in build.gradle)
|
||||
# this is not the same as app version and should only be edited if you know what you're doing
|
||||
# android.numeric_version = 1
|
||||
|
||||
# (bool) enables Android auto backup feature (Android API >=23)
|
||||
android.allow_backup = True
|
||||
|
||||
# (str) XML file for custom backup rules (see official auto backup documentation)
|
||||
# android.backup_rules =
|
||||
|
||||
# (str) If you need to insert variables into your AndroidManifest.xml file,
|
||||
# you can do so with the manifestPlaceholders property.
|
||||
# This property takes a map of key-value pairs. (via a string)
|
||||
# Usage example : android.manifest_placeholders = [myCustomUrl:\"org.kivy.customurl\"]
|
||||
# android.manifest_placeholders = [:]
|
||||
|
||||
# (bool) disables the compilation of py to pyc/pyo files when packaging
|
||||
# android.no-compile-pyo = True
|
||||
|
||||
#
|
||||
# Python for android (p4a) specific
|
||||
#
|
||||
|
||||
# (str) python-for-android URL to use for checkout
|
||||
#p4a.url =
|
||||
|
||||
# (str) python-for-android fork to use in case if p4a.url is not specified, defaults to upstream (kivy)
|
||||
#p4a.fork = kivy
|
||||
|
||||
# (str) python-for-android branch to use, defaults to master
|
||||
#p4a.branch = master
|
||||
|
||||
# (str) python-for-android specific commit to use, defaults to HEAD, must be within p4a.branch
|
||||
#p4a.commit = HEAD
|
||||
|
||||
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
|
||||
#p4a.source_dir =
|
||||
|
||||
|
@ -210,6 +306,13 @@ android.arch = armeabi-v7a
|
|||
# (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
|
||||
#p4a.port =
|
||||
|
||||
# Control passing the --use-setup-py vs --ignore-setup-py to p4a
|
||||
# "in the future" --use-setup-py is going to be the default behaviour in p4a, right now it is not
|
||||
# Setting this to false will pass --ignore-setup-py, true will pass --use-setup-py
|
||||
# NOTE: this is general setuptools integration, having pyproject.toml is enough, no need to generate
|
||||
# setup.py if you're using Poetry, but you need to add "toml" to source.include_exts.
|
||||
#p4a.setup_py = false
|
||||
|
||||
|
||||
#
|
||||
# iOS specific
|
||||
|
@ -217,19 +320,50 @@ android.arch = armeabi-v7a
|
|||
|
||||
# (str) Path to a custom kivy-ios folder
|
||||
#ios.kivy_ios_dir = ../kivy-ios
|
||||
# Alternately, specify the URL and branch of a git checkout:
|
||||
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
|
||||
ios.kivy_ios_branch = master
|
||||
|
||||
# Another platform dependency: ios-deploy
|
||||
# Uncomment to use a custom checkout
|
||||
#ios.ios_deploy_dir = ../ios_deploy
|
||||
# Or specify URL and branch
|
||||
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
|
||||
ios.ios_deploy_branch = 1.10.0
|
||||
|
||||
# (bool) Whether or not to sign the code
|
||||
ios.codesign.allowed = false
|
||||
|
||||
# (str) Name of the certificate to use for signing the debug version
|
||||
# Get a list of available identities: buildozer ios list_identities
|
||||
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
|
||||
|
||||
# (str) The development team to use for signing the debug version
|
||||
#ios.codesign.development_team.debug = <hexstring>
|
||||
|
||||
# (str) Name of the certificate to use for signing the release version
|
||||
#ios.codesign.release = %(ios.codesign.debug)s
|
||||
|
||||
# (str) The development team to use for signing the release version
|
||||
#ios.codesign.development_team.release = <hexstring>
|
||||
|
||||
# (str) URL pointing to .ipa file to be installed
|
||||
# This option should be defined along with `display_image_url` and `full_size_image_url` options.
|
||||
#ios.manifest.app_url =
|
||||
|
||||
# (str) URL pointing to an icon (57x57px) to be displayed during download
|
||||
# This option should be defined along with `app_url` and `full_size_image_url` options.
|
||||
#ios.manifest.display_image_url =
|
||||
|
||||
# (str) URL pointing to a large icon (512x512px) to be used by iTunes
|
||||
# This option should be defined along with `app_url` and `display_image_url` options.
|
||||
#ios.manifest.full_size_image_url =
|
||||
|
||||
|
||||
[buildozer]
|
||||
|
||||
# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
|
||||
log_level = 1
|
||||
log_level = 2
|
||||
|
||||
# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
|
||||
warn_on_root = 1
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
"""
|
||||
Replacement for shelve, using json.
|
||||
This is currently needed to correctly support db between Python 2 and 3.
|
||||
This was needed to correctly support db between Python 2 and 3.
|
||||
"""
|
||||
|
||||
__all__ = ["JsonStore"]
|
||||
|
||||
import io
|
||||
import sys
|
||||
from json import load, dump, dumps
|
||||
from json import load, dump
|
||||
from os.path import exists
|
||||
|
||||
IS_PY3 = sys.version_info[0] >= 3
|
||||
|
||||
class JsonStore(object):
|
||||
class JsonStore:
|
||||
|
||||
def __init__(self, filename):
|
||||
super(JsonStore, self).__init__()
|
||||
self.filename = filename
|
||||
self.data = {}
|
||||
if exists(filename):
|
||||
|
@ -46,11 +43,5 @@ class JsonStore(object):
|
|||
return self.data.keys()
|
||||
|
||||
def sync(self):
|
||||
# http://stackoverflow.com/questions/12309269/write-json-data-to-file-in-python/14870531#14870531
|
||||
if IS_PY3:
|
||||
with open(self.filename, 'w') as fd:
|
||||
dump(self.data, fd, ensure_ascii=False)
|
||||
else:
|
||||
with io.open(self.filename, 'w', encoding='utf-8') as fd:
|
||||
fd.write(unicode(dumps(self.data, ensure_ascii=False)))
|
||||
|
||||
with open(self.filename, 'w') as fd:
|
||||
dump(self.data, fd, ensure_ascii=False)
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
|
||||
class Infinity(object):
|
||||
class Infinity:
|
||||
|
||||
def __repr__(self):
|
||||
return "Infinity"
|
||||
|
@ -43,10 +41,11 @@ class Infinity(object):
|
|||
def __neg__(self):
|
||||
return NegativeInfinity
|
||||
|
||||
|
||||
Infinity = Infinity()
|
||||
|
||||
|
||||
class NegativeInfinity(object):
|
||||
class NegativeInfinity:
|
||||
|
||||
def __repr__(self):
|
||||
return "-Infinity"
|
||||
|
@ -75,4 +74,5 @@ class NegativeInfinity(object):
|
|||
def __neg__(self):
|
||||
return Infinity
|
||||
|
||||
|
||||
NegativeInfinity = NegativeInfinity()
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import collections
|
||||
import itertools
|
||||
import re
|
||||
|
@ -49,7 +47,7 @@ class InvalidVersion(ValueError):
|
|||
"""
|
||||
|
||||
|
||||
class _BaseVersion(object):
|
||||
class _BaseVersion:
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._key)
|
||||
|
@ -164,6 +162,7 @@ def _legacy_cmpkey(version):
|
|||
|
||||
return epoch, parts
|
||||
|
||||
|
||||
# Deliberately not anchored to the start and end of the string, to make it
|
||||
# easier for 3rd party code to reuse
|
||||
VERSION_PATTERN = r"""
|
||||
|
@ -334,7 +333,7 @@ def _parse_letter_version(letter, number):
|
|||
return letter, int(number)
|
||||
|
||||
|
||||
_local_version_seperators = re.compile(r"[\._-]")
|
||||
_local_version_separators = re.compile(r"[\._-]")
|
||||
|
||||
|
||||
def _parse_local_version(local):
|
||||
|
@ -344,7 +343,7 @@ def _parse_local_version(local):
|
|||
if local is not None:
|
||||
return tuple(
|
||||
part.lower() if not part.isdigit() else int(part)
|
||||
for part in _local_version_seperators.split(local)
|
||||
for part in _local_version_separators.split(local)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@ def main():
|
|||
except BuildozerCommandException:
|
||||
# don't show the exception in the command line. The log already show
|
||||
# the command failed.
|
||||
pass
|
||||
sys.exit(1)
|
||||
except BuildozerException as error:
|
||||
Buildozer().error('%s' % error)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -21,13 +21,9 @@ from sys import stdout, stdin, exit
|
|||
from select import select
|
||||
from os.path import join, expanduser, realpath, exists, splitext
|
||||
from os import makedirs, walk, getcwd
|
||||
try:
|
||||
from configparser import SafeConfigParser
|
||||
except ImportError:
|
||||
from ConfigParser import SafeConfigParser
|
||||
from configparser import ConfigParser
|
||||
try:
|
||||
import termios
|
||||
import tty
|
||||
has_termios = True
|
||||
except ImportError:
|
||||
has_termios = False
|
||||
|
@ -131,7 +127,7 @@ class BuildozerRemote(Buildozer):
|
|||
self.package_full_name)
|
||||
self.debug('Remote build directory: {}'.format(self.remote_build_dir))
|
||||
self._ssh_mkdir(self.remote_build_dir)
|
||||
self._ssh_sync(__path__[0])
|
||||
self._ssh_sync(__path__[0]) # noqa: F821 undefined name
|
||||
|
||||
def _sync_application_sources(self):
|
||||
self.info('Synchronize application sources')
|
||||
|
@ -139,7 +135,7 @@ class BuildozerRemote(Buildozer):
|
|||
|
||||
# create custom buildozer.spec
|
||||
self.info('Create custom buildozer.spec')
|
||||
config = SafeConfigParser()
|
||||
config = ConfigParser()
|
||||
config.read('buildozer.spec')
|
||||
config.set('app', 'source.dir', 'app')
|
||||
|
||||
|
@ -159,7 +155,7 @@ class BuildozerRemote(Buildozer):
|
|||
self.remote_build_dir,
|
||||
'--verbose' if self.log_level == 2 else '',
|
||||
' '.join(args),
|
||||
)
|
||||
)
|
||||
self._ssh_command(cmd)
|
||||
|
||||
def _ssh_mkdir(self, *args):
|
||||
|
@ -177,10 +173,10 @@ class BuildozerRemote(Buildozer):
|
|||
|
||||
def _ssh_sync(self, directory, mode='put'):
|
||||
self.debug('Syncing {} directory'.format(directory))
|
||||
directory = realpath(directory)
|
||||
directory = realpath(expanduser(directory))
|
||||
base_strip = directory.rfind('/')
|
||||
if mode == 'get':
|
||||
local_dir = join(directory,'bin')
|
||||
local_dir = join(directory, 'bin')
|
||||
remote_dir = join(self.remote_build_dir, 'bin')
|
||||
if not exists(local_dir):
|
||||
makedirs(local_dir)
|
||||
|
@ -200,9 +196,6 @@ class BuildozerRemote(Buildozer):
|
|||
|
||||
def _ssh_command(self, command):
|
||||
self.debug('Execute remote command {}'.format(command))
|
||||
#shell = self._ssh_client.invoke_shell()
|
||||
#shell.sendall(command)
|
||||
#shell.sendall('\nexit\n')
|
||||
transport = self._ssh_client.get_transport()
|
||||
channel = transport.open_session()
|
||||
try:
|
||||
|
@ -220,8 +213,6 @@ class BuildozerRemote(Buildozer):
|
|||
def _posix_shell(self, chan):
|
||||
oldtty = termios.tcgetattr(stdin)
|
||||
try:
|
||||
#tty.setraw(stdin.fileno())
|
||||
#tty.setcbreak(stdin.fileno())
|
||||
chan.settimeout(0.0)
|
||||
|
||||
while True:
|
||||
|
@ -234,7 +225,6 @@ class BuildozerRemote(Buildozer):
|
|||
break
|
||||
stdout.write(x)
|
||||
stdout.flush()
|
||||
#print len(x), repr(x)
|
||||
except socket.timeout:
|
||||
pass
|
||||
if stdin in r:
|
||||
|
@ -246,7 +236,7 @@ class BuildozerRemote(Buildozer):
|
|||
termios.tcsetattr(stdin, termios.TCSADRAIN, oldtty)
|
||||
|
||||
# thanks to Mike Looijmans for this code
|
||||
def _windows_shell(self,chan):
|
||||
def _windows_shell(self, chan):
|
||||
import threading
|
||||
|
||||
stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")
|
||||
|
@ -274,6 +264,7 @@ class BuildozerRemote(Buildozer):
|
|||
# user hit ^Z or F6
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
BuildozerRemote().run_command(sys.argv[1:])
|
||||
|
@ -282,5 +273,6 @@ def main():
|
|||
except BuildozerException as error:
|
||||
Buildozer().error('%s' % error)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from sys import exit
|
||||
import os
|
||||
from os.path import join
|
||||
|
||||
|
||||
def no_config(f):
|
||||
|
@ -7,9 +8,8 @@ def no_config(f):
|
|||
return f
|
||||
|
||||
|
||||
class Target(object):
|
||||
class Target:
|
||||
def __init__(self, buildozer):
|
||||
super(Target, self).__init__()
|
||||
self.buildozer = buildozer
|
||||
self.build_mode = 'debug'
|
||||
self.platform_update = False
|
||||
|
@ -147,3 +147,117 @@ class Target(object):
|
|||
|
||||
def cmd_serve(self, *args):
|
||||
self.buildozer.cmd_serve()
|
||||
|
||||
def path_or_git_url(self, repo, owner='kivy', branch='master',
|
||||
url_format='https://github.com/{owner}/{repo}.git',
|
||||
platform=None,
|
||||
squash_hyphen=True):
|
||||
"""Get source location for a git checkout
|
||||
|
||||
This method will check the `buildozer.spec` for the keys:
|
||||
{repo}_dir
|
||||
{repo}_url
|
||||
{repo}_branch
|
||||
|
||||
and use them to determine the source location for a git checkout.
|
||||
|
||||
If a `platform` is specified, {platform}.{repo} will be used
|
||||
as the base for the buildozer key
|
||||
|
||||
`{repo}_dir` specifies a custom checkout location
|
||||
(relative to `buildozer.root_dir`). If present, `path` will be
|
||||
set to this value and `url`, `branch` will be set to None,
|
||||
None. Otherwise, `{repo}_url` and `{repo}_branch` will be
|
||||
examined.
|
||||
|
||||
If no keys are present, the kwargs will be used to create
|
||||
a sensible default URL and branch.
|
||||
|
||||
:Parameters:
|
||||
`repo`: str (required)
|
||||
name of repository to fetch. Used both for buildozer
|
||||
keys ({platform}.{repo}_dir|_url|_branch) and in building
|
||||
default git URL
|
||||
`branch`: str (default 'master')
|
||||
Specific branch to retrieve if none specified in
|
||||
buildozer.spec.
|
||||
`owner`: str
|
||||
owner of repo.
|
||||
`platform`: str or None
|
||||
platform prefix to use when retrieving `buildozer.spec`
|
||||
keys. If specified, key names will be {platform}.{repo}
|
||||
instead of just {repo}
|
||||
`squash_hyphen`: boolean
|
||||
if True, change '-' to '_' when looking for
|
||||
keys in buildozer.spec. This lets us keep backwards
|
||||
compatibility with old buildozer.spec files
|
||||
`url_format`: format string
|
||||
Used to construct default git URL.
|
||||
can use {repo} {owner} and {branch} if needed.
|
||||
|
||||
:Returns:
|
||||
A Tuple (path, url, branch) where
|
||||
`path`
|
||||
Path to a custom git checkout. If specified,
|
||||
both `url` and `branch` will be None
|
||||
`url`
|
||||
URL of git repository from where code should be
|
||||
checked-out
|
||||
`branch`
|
||||
branch name (or tag) that should be used for the
|
||||
check-out.
|
||||
|
||||
"""
|
||||
if squash_hyphen:
|
||||
key = repo.replace('-', '_')
|
||||
else:
|
||||
key = repo
|
||||
if platform:
|
||||
key = "{}.{}".format(platform, key)
|
||||
config = self.buildozer.config
|
||||
path = config.getdefault('app', '{}_dir'.format(key), None)
|
||||
|
||||
if path is not None:
|
||||
path = join(self.buildozer.root_dir, path)
|
||||
url = None
|
||||
branch = None
|
||||
else:
|
||||
branch = config.getdefault('app', '{}_branch'.format(key), branch)
|
||||
default_url = url_format.format(owner=owner, repo=repo, branch=branch)
|
||||
url = config.getdefault('app', '{}_url'.format(key), default_url)
|
||||
if branch != 'master':
|
||||
url = "--branch {} {}".format(branch, url)
|
||||
return path, url, branch
|
||||
|
||||
def install_or_update_repo(self, repo, **kwargs):
|
||||
"""Install or update a git repository into the platform directory.
|
||||
|
||||
This will clone the contents of a git repository to
|
||||
`buildozer.platform_dir`. The location of this repo can be
|
||||
specified via URL and branch name, or via a custom (local)
|
||||
directory name.
|
||||
|
||||
:Parameters:
|
||||
**kwargs:
|
||||
Any valid arguments for :meth:`path_or_git_url`
|
||||
|
||||
:Returns:
|
||||
fully qualified path to updated git repo
|
||||
"""
|
||||
cmd = self.buildozer.cmd
|
||||
install_dir = join(self.buildozer.platform_dir, repo)
|
||||
custom_dir, clone_url, clone_branch = self.path_or_git_url(repo, **kwargs)
|
||||
if not self.buildozer.file_exists(install_dir):
|
||||
if custom_dir:
|
||||
cmd('mkdir -p "{}"'.format(install_dir))
|
||||
cmd('cp -a "{}"/* "{}"/'.format(custom_dir, install_dir))
|
||||
else:
|
||||
cmd('git clone {}'.format(clone_url),
|
||||
cwd=self.buildozer.platform_dir)
|
||||
elif self.platform_update:
|
||||
if custom_dir:
|
||||
cmd('cp -a "{}"/* "{}"/'.format(custom_dir, install_dir))
|
||||
else:
|
||||
cmd('git clean -dxf', cwd=install_dir)
|
||||
cmd('git pull origin {}'.format(clone_branch), cwd=install_dir)
|
||||
return install_dir
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,208 +0,0 @@
|
|||
# coding=utf-8
|
||||
'''
|
||||
Android target, based on python-for-android project
|
||||
'''
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from buildozer import USE_COLOR
|
||||
from buildozer.targets.android import TargetAndroid
|
||||
from os.path import join, expanduser, realpath
|
||||
|
||||
|
||||
class TargetAndroidNew(TargetAndroid):
|
||||
targetname = 'android'
|
||||
p4a_branch = "stable"
|
||||
p4a_directory = "python-for-android-new-toolchain"
|
||||
p4a_apk_cmd = "apk --debug --bootstrap="
|
||||
extra_p4a_args = ''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TargetAndroidNew, self).__init__(*args, **kwargs)
|
||||
self._build_dir = join(self.buildozer.platform_dir, 'build')
|
||||
executable = sys.executable or 'python'
|
||||
self._p4a_cmd = '{} -m pythonforandroid.toolchain '.format(executable)
|
||||
self._p4a_bootstrap = self.buildozer.config.getdefault(
|
||||
'app', 'p4a.bootstrap', 'sdl2')
|
||||
self.p4a_apk_cmd += self._p4a_bootstrap
|
||||
color = 'always' if USE_COLOR else 'never'
|
||||
self.extra_p4a_args = ' --color={} --storage-dir="{}"'.format(
|
||||
color, self._build_dir)
|
||||
hook = self.buildozer.config.getdefault("app", "p4a.hook", None)
|
||||
if hook is not None:
|
||||
self.extra_p4a_args += ' --hook={}'.format(realpath(hook))
|
||||
port = self.buildozer.config.getdefault('app', 'p4a.port', None)
|
||||
if port is not None:
|
||||
self.extra_p4a_args += ' --port={}'.format(port)
|
||||
|
||||
def _p4a(self, cmd, **kwargs):
|
||||
if not hasattr(self, "pa_dir"):
|
||||
self.pa_dir = join(self.buildozer.platform_dir, self.p4a_directory)
|
||||
kwargs.setdefault('cwd', self.pa_dir)
|
||||
return self.buildozer.cmd(self._p4a_cmd + cmd + self.extra_p4a_args, **kwargs)
|
||||
|
||||
def get_available_packages(self):
|
||||
return True
|
||||
|
||||
def compile_platform(self):
|
||||
app_requirements = self.buildozer.config.getlist(
|
||||
'app', 'requirements', '')
|
||||
dist_name = self.buildozer.config.get('app', 'package.name')
|
||||
local_recipes = self.get_local_recipes_dir()
|
||||
requirements = ','.join(app_requirements)
|
||||
options = []
|
||||
|
||||
source_dirs = {
|
||||
'P4A_{}_DIR'.format(name[20:]): realpath(expanduser(value))
|
||||
for name, value in self.buildozer.config.items('app')
|
||||
if name.startswith('requirements.source.')
|
||||
}
|
||||
if source_dirs:
|
||||
self.buildozer.environ.update(source_dirs)
|
||||
self.buildozer.info('Using custom source dirs:\n {}'.format(
|
||||
'\n '.join(['{} = {}'.format(k, v)
|
||||
for k, v in source_dirs.items()])))
|
||||
|
||||
if self.buildozer.config.getbooldefault('app', 'android.copy_libs', True):
|
||||
options.append("--copy-libs")
|
||||
# support for recipes in a local directory within the project
|
||||
if local_recipes:
|
||||
options.append('--local-recipes')
|
||||
options.append(local_recipes)
|
||||
available_modules = self._p4a(
|
||||
"create --dist_name={} --bootstrap={} --requirements={} --arch {} {}".format(
|
||||
dist_name, self._p4a_bootstrap, requirements,
|
||||
self.buildozer.config.getdefault('app', 'android.arch', "armeabi-v7a"), " ".join(options)),
|
||||
get_stdout=True)[0]
|
||||
|
||||
def get_dist_dir(self, dist_name):
|
||||
return join(self._build_dir, 'dists', dist_name)
|
||||
|
||||
def get_local_recipes_dir(self):
|
||||
local_recipes = self.buildozer.config.getdefault('app', 'p4a.local_recipes')
|
||||
return realpath(expanduser(local_recipes)) if local_recipes else None
|
||||
|
||||
def execute_build_package(self, build_cmd):
|
||||
# wrapper from previous old_toolchain to new toolchain
|
||||
dist_name = self.buildozer.config.get('app', 'package.name')
|
||||
local_recipes = self.get_local_recipes_dir()
|
||||
cmd = [self.p4a_apk_cmd, "--dist_name", dist_name]
|
||||
for args in build_cmd:
|
||||
option, values = args[0], args[1:]
|
||||
if option == "debug":
|
||||
continue
|
||||
elif option == "release":
|
||||
cmd.append("--release")
|
||||
if self.check_p4a_sign_env(True):
|
||||
cmd.append("--sign")
|
||||
continue
|
||||
if option == "--window":
|
||||
cmd.append("--window")
|
||||
elif option == "--sdk":
|
||||
cmd.append("--android_api")
|
||||
cmd.extend(values)
|
||||
else:
|
||||
cmd.extend(args)
|
||||
|
||||
# support for presplash background color
|
||||
presplash_color = self.buildozer.config.getdefault('app', 'android.presplash_color', None)
|
||||
if presplash_color:
|
||||
cmd.append('--presplash-color')
|
||||
cmd.append("'{}'".format(presplash_color))
|
||||
|
||||
# support for services
|
||||
services = self.buildozer.config.getlist('app', 'services', [])
|
||||
for service in services:
|
||||
cmd.append("--service")
|
||||
cmd.append(service)
|
||||
|
||||
# support for copy-libs
|
||||
if self.buildozer.config.getbooldefault('app', 'android.copy_libs', True):
|
||||
cmd.append("--copy-libs")
|
||||
|
||||
# support for recipes in a local directory within the project
|
||||
if local_recipes:
|
||||
cmd.append('--local-recipes')
|
||||
cmd.append(local_recipes)
|
||||
|
||||
# support for blacklist/whitelist filename
|
||||
whitelist_src = self.buildozer.config.getdefault('app', 'android.whitelist_src', None)
|
||||
blacklist_src = self.buildozer.config.getdefault('app', 'android.blacklist_src', None)
|
||||
if whitelist_src:
|
||||
cmd.append('--whitelist')
|
||||
cmd.append(realpath(whitelist_src))
|
||||
if blacklist_src:
|
||||
cmd.append('--blacklist')
|
||||
cmd.append(realpath(blacklist_src))
|
||||
|
||||
# support for aars
|
||||
aars = self.buildozer.config.getlist('app', 'android.add_aars', [])
|
||||
for aar in aars:
|
||||
cmd.append('--add-aar')
|
||||
cmd.append(realpath(aar))
|
||||
|
||||
# support for gradle dependencies
|
||||
gradle_dependencies = self.buildozer.config.getlist('app', 'android.gradle_dependencies', [])
|
||||
for gradle_dependency in gradle_dependencies:
|
||||
cmd.append('--depend')
|
||||
cmd.append(gradle_dependency)
|
||||
|
||||
cmd.append('--arch')
|
||||
cmd.append(self.buildozer.config.getdefault('app', 'android.arch', "armeabi-v7a"))
|
||||
|
||||
cmd = " ".join(cmd)
|
||||
self._p4a(cmd)
|
||||
|
||||
def get_release_mode(self):
|
||||
if self.check_p4a_sign_env():
|
||||
return "release"
|
||||
return "release-unsigned"
|
||||
|
||||
def check_p4a_sign_env(self, error=False):
|
||||
keys = ["KEYALIAS", "KEYSTORE_PASSWD", "KEYSTORE", "KEYALIAS_PASSWD"]
|
||||
check = True
|
||||
for key in keys:
|
||||
key = "P4A_RELEASE_{}".format(key)
|
||||
if key not in os.environ:
|
||||
if error:
|
||||
self.buildozer.error(
|
||||
("Asking for release but {} is missing"
|
||||
"--sign will not be passed").format(key))
|
||||
check = False
|
||||
return check
|
||||
|
||||
def cmd_run(self, *args):
|
||||
entrypoint = self.buildozer.config.getdefault(
|
||||
'app', 'android.entrypoint')
|
||||
if not entrypoint:
|
||||
self.buildozer.config.set('app', 'android.entrypoint', 'org.kivy.android.PythonActivity')
|
||||
return super(TargetAndroidNew, self).cmd_run(*args)
|
||||
|
||||
def cmd_p4a(self, *args):
|
||||
'''
|
||||
Run p4a commands. Args must come after --, or
|
||||
use --alias to make an alias
|
||||
'''
|
||||
self.check_requirements()
|
||||
self.install_platform()
|
||||
args = args[0]
|
||||
if args and args[0] == '--alias':
|
||||
print('To set up p4a in this shell session, execute:')
|
||||
print(' alias p4a=$(buildozer {} p4a --alias 2>&1 >/dev/null)'
|
||||
.format(self.targetname))
|
||||
sys.stderr.write('PYTHONPATH={} {}\n'.format(self.pa_dir, self._p4a_cmd))
|
||||
else:
|
||||
self._p4a(' '.join(args) if args else '')
|
||||
|
||||
def cmd_clean(self, *args):
|
||||
'''
|
||||
Clean the build and distribution
|
||||
'''
|
||||
self._p4a("clean_builds")
|
||||
self._p4a("clean_dists")
|
||||
|
||||
|
||||
def get_target(buildozer):
|
||||
buildozer.targetname = "android"
|
||||
return TargetAndroidNew(buildozer)
|
|
@ -3,15 +3,13 @@ iOS target, based on kivy-ios project
|
|||
'''
|
||||
|
||||
import sys
|
||||
if sys.platform != 'darwin':
|
||||
raise NotImplementedError('Windows platform not yet working for Android')
|
||||
|
||||
import plistlib
|
||||
from buildozer import BuildozerCommandException
|
||||
from buildozer.target import Target, no_config
|
||||
from os.path import join, basename, expanduser, realpath
|
||||
from getpass import getpass
|
||||
|
||||
|
||||
PHP_TEMPLATE = '''
|
||||
<?php
|
||||
// credits goes to http://jeffreysambells.com/2010/06/22/ios-wireless-app-distribution
|
||||
|
@ -58,10 +56,22 @@ li { padding: 1em; }
|
|||
</html>
|
||||
'''
|
||||
|
||||
|
||||
class TargetIos(Target):
|
||||
targetname = "ios"
|
||||
|
||||
def __init__(self, buildozer):
|
||||
super().__init__(buildozer)
|
||||
executable = sys.executable or 'python'
|
||||
self._toolchain_cmd = f"{executable} toolchain.py "
|
||||
self._xcodebuild_cmd = "xcodebuild "
|
||||
# set via install_platform()
|
||||
self.ios_dir = None
|
||||
self.ios_deploy_dir = None
|
||||
|
||||
def check_requirements(self):
|
||||
if sys.platform != "darwin":
|
||||
raise NotImplementedError("Only macOS is supported for iOS target")
|
||||
checkbin = self.buildozer.checkbin
|
||||
cmd = self.buildozer.cmd
|
||||
|
||||
|
@ -91,35 +101,36 @@ class TargetIos(Target):
|
|||
self.buildozer.debug(' -> found {0}'.format(xcode))
|
||||
|
||||
def install_platform(self):
|
||||
cmd = self.buildozer.cmd
|
||||
self.ios_dir = ios_dir = join(self.buildozer.platform_dir, 'kivy-ios')
|
||||
custom_kivy_ios = self.buildozer.config.getdefault('app', 'ios.kivy_ios_dir')
|
||||
if custom_kivy_ios:
|
||||
custom_kivy_ios = join(self.buildozer.root_dir, custom_kivy_ios)
|
||||
if not self.buildozer.file_exists(ios_dir):
|
||||
if custom_kivy_ios:
|
||||
cmd('mkdir -p "{}"'.format(ios_dir))
|
||||
cmd('cp -a "{}"/* "{}"/'.format(custom_kivy_ios, ios_dir))
|
||||
else:
|
||||
cmd('git clone https://github.com/kivy/kivy-ios',
|
||||
cwd=self.buildozer.platform_dir)
|
||||
elif self.platform_update:
|
||||
if custom_kivy_ios:
|
||||
cmd('cp -a "{}"/* "{}"/'.format(custom_kivy_ios, ios_dir))
|
||||
else:
|
||||
cmd('git clean -dxf', cwd=ios_dir)
|
||||
cmd('git pull origin master', cwd=ios_dir)
|
||||
"""
|
||||
Clones `kivy/kivy-ios` and `phonegap/ios-deploy` then sets `ios_dir`
|
||||
and `ios_deploy_dir` accordingly.
|
||||
"""
|
||||
self.ios_dir = self.install_or_update_repo('kivy-ios', platform='ios')
|
||||
self.ios_deploy_dir = self.install_or_update_repo('ios-deploy',
|
||||
platform='ios',
|
||||
branch='1.7.0',
|
||||
owner='phonegap')
|
||||
|
||||
self.ios_deploy_dir = ios_deploy_dir = join(self.buildozer.platform_dir,
|
||||
'ios-deploy')
|
||||
if not self.buildozer.file_exists(ios_deploy_dir):
|
||||
cmd('git clone --branch 1.7.0 https://github.com/phonegap/ios-deploy',
|
||||
cwd=self.buildozer.platform_dir)
|
||||
def toolchain(self, cmd, **kwargs):
|
||||
kwargs.setdefault('cwd', self.ios_dir)
|
||||
return self.buildozer.cmd(self._toolchain_cmd + cmd, **kwargs)
|
||||
|
||||
def xcodebuild(self, *args, **kwargs):
|
||||
return self.buildozer.cmd(self._xcodebuild_cmd + ' '.join(arg for arg in args if arg is not None), **kwargs)
|
||||
|
||||
@property
|
||||
def code_signing_allowed(self):
|
||||
allowed = self.buildozer.config.getboolean("app", "ios.codesign.allowed")
|
||||
allowed = "YES" if allowed else "NO"
|
||||
return f"CODE_SIGNING_ALLOWED={allowed}"
|
||||
|
||||
@property
|
||||
def code_signing_development_team(self):
|
||||
team = self.buildozer.config.getdefault("app", f"ios.codesign.development_team.{self.build_mode}", None)
|
||||
return f"DEVELOPMENT_TEAM={team}" if team else None
|
||||
|
||||
def get_available_packages(self):
|
||||
available_modules = self.buildozer.cmd(
|
||||
'./toolchain.py recipes --compact',
|
||||
cwd=self.ios_dir, get_stdout=True)[0]
|
||||
available_modules = self.toolchain("recipes --compact", get_stdout=True)[0]
|
||||
return available_modules.splitlines()[0].split()
|
||||
|
||||
def compile_platform(self):
|
||||
|
@ -131,7 +142,7 @@ class TargetIos(Target):
|
|||
|
||||
# we need to extract the requirements that kivy-ios knows about
|
||||
available_modules = self.get_available_packages()
|
||||
onlyname = lambda x: x.split('==')[0]
|
||||
onlyname = lambda x: x.split('==')[0] # noqa: E731 do not assign a lambda expression, use a def
|
||||
ios_requirements = [x for x in app_requirements if onlyname(x) in
|
||||
available_modules]
|
||||
|
||||
|
@ -156,11 +167,10 @@ class TargetIos(Target):
|
|||
return
|
||||
|
||||
modules_str = ' '.join(ios_requirements)
|
||||
self.buildozer.cmd('./toolchain.py build {}'.format(modules_str),
|
||||
cwd=self.ios_dir)
|
||||
self.toolchain(f"build {modules_str}")
|
||||
|
||||
if not self.buildozer.file_exists(self.ios_deploy_dir, 'ios-deploy'):
|
||||
self.buildozer.cmd('make ios-deploy', cwd=self.ios_deploy_dir)
|
||||
self.xcodebuild(cwd=self.ios_deploy_dir)
|
||||
|
||||
self.buildozer.state['ios.requirements'] = ios_requirements
|
||||
self.buildozer.state.sync()
|
||||
|
@ -180,22 +190,25 @@ class TargetIos(Target):
|
|||
app_name = self.buildozer.namify(self.buildozer.config.get('app',
|
||||
'package.name'))
|
||||
|
||||
ios_frameworks = self.buildozer.config.getlist('app', 'ios.frameworks', '')
|
||||
frameworks_cmd = ''
|
||||
for framework in ios_frameworks:
|
||||
frameworks_cmd += '--add-framework={} '.format(framework)
|
||||
|
||||
self.app_project_dir = join(self.ios_dir, '{0}-ios'.format(app_name.lower()))
|
||||
if not self.buildozer.file_exists(self.app_project_dir):
|
||||
self.buildozer.cmd('./toolchain.py create {0} {1}'.format(
|
||||
app_name, self.buildozer.app_dir),
|
||||
cwd=self.ios_dir)
|
||||
cmd = f"create {frameworks_cmd}{app_name} {self.buildozer.app_dir}"
|
||||
else:
|
||||
self.buildozer.cmd('./toolchain.py update {0}-ios'.format(
|
||||
app_name),
|
||||
cwd=self.ios_dir)
|
||||
cmd = f"update {frameworks_cmd}{app_name}-ios"
|
||||
self.toolchain(cmd)
|
||||
|
||||
# fix the plist
|
||||
plist_fn = '{}-Info.plist'.format(app_name.lower())
|
||||
plist_rfn = join(self.app_project_dir, plist_fn)
|
||||
version = self.buildozer.get_version()
|
||||
self.buildozer.info('Update Plist {}'.format(plist_fn))
|
||||
plist = plistlib.readPlist(plist_rfn)
|
||||
with open(plist_rfn, 'rb') as f:
|
||||
plist = plistlib.load(f)
|
||||
plist['CFBundleIdentifier'] = self._get_package()
|
||||
plist['CFBundleShortVersionString'] = version
|
||||
plist['CFBundleVersion'] = '{}.{}'.format(version,
|
||||
|
@ -204,12 +217,37 @@ class TargetIos(Target):
|
|||
# add icons
|
||||
self._create_icons()
|
||||
|
||||
# ok, write the modified plist.
|
||||
plistlib.writePlist(plist, plist_rfn)
|
||||
# Generate OTA distribution manifest if `app_url`, `display_image_url` and `full_size_image_url` are defined.
|
||||
app_url = self.buildozer.config.getdefault("app", "ios.manifest.app_url", None)
|
||||
display_image_url = self.buildozer.config.getdefault("app", "ios.manifest.display_image_url", None)
|
||||
full_size_image_url = self.buildozer.config.getdefault("app", "ios.manifest.full_size_image_url", None)
|
||||
|
||||
mode = 'Debug' if self.build_mode == 'debug' else 'Release'
|
||||
self.buildozer.cmd('xcodebuild -configuration {} ENABLE_BITCODE=NO clean build'.format(mode),
|
||||
cwd=self.app_project_dir)
|
||||
if any((app_url, display_image_url, full_size_image_url)):
|
||||
|
||||
if not all((app_url, display_image_url, full_size_image_url)):
|
||||
self.buildozer.error("Options ios.manifest.app_url, ios.manifest.display_image_url"
|
||||
" and ios.manifest.full_size_image_url should be defined all together")
|
||||
return
|
||||
|
||||
plist['manifest'] = {
|
||||
'appURL': app_url,
|
||||
'displayImageURL': display_image_url,
|
||||
'fullSizeImageURL': full_size_image_url,
|
||||
}
|
||||
|
||||
# ok, write the modified plist.
|
||||
with open(plist_rfn, 'wb') as f:
|
||||
plistlib.dump(plist, f)
|
||||
|
||||
mode = self.build_mode.capitalize()
|
||||
self.xcodebuild(
|
||||
f'-configuration {mode}',
|
||||
'-allowProvisioningUpdates',
|
||||
'ENABLE_BITCODE=NO',
|
||||
self.code_signing_allowed,
|
||||
self.code_signing_development_team,
|
||||
'clean build',
|
||||
cwd=self.app_project_dir)
|
||||
ios_app_dir = '{app_lower}-ios/build/{mode}-iphoneos/{app_lower}.app'.format(
|
||||
app_lower=app_name.lower(), mode=mode)
|
||||
self.buildozer.state['ios:latestappdir'] = ios_app_dir
|
||||
|
@ -234,27 +272,24 @@ class TargetIos(Target):
|
|||
self.buildozer.rmdir(intermediate_dir)
|
||||
|
||||
self.buildozer.info('Creating archive...')
|
||||
self.buildozer.cmd((
|
||||
'/usr/bin/xcodebuild'
|
||||
' -alltargets'
|
||||
' -configuration {mode}'
|
||||
' -scheme {scheme}'
|
||||
' -archivePath "{xcarchive}"'
|
||||
' archive'
|
||||
' ENABLE_BITCODE=NO'
|
||||
).format(mode=mode, xcarchive=xcarchive, scheme=app_name.lower()),
|
||||
self.xcodebuild(
|
||||
'-alltargets',
|
||||
f'-configuration {mode}',
|
||||
f'-scheme {app_name.lower()}',
|
||||
f'-archivePath "{xcarchive}"',
|
||||
'archive',
|
||||
'ENABLE_BITCODE=NO',
|
||||
self.code_signing_development_team,
|
||||
cwd=build_dir)
|
||||
|
||||
self.buildozer.info('Creating IPA...')
|
||||
self.buildozer.cmd((
|
||||
'/usr/bin/xcodebuild'
|
||||
' -exportArchive'
|
||||
' -exportFormat IPA'
|
||||
' -archivePath "{xcarchive}"'
|
||||
' -exportPath "{ipa}"'
|
||||
' CODE_SIGN_IDENTITY={ioscodesign}'
|
||||
' ENABLE_BITCODE=NO'
|
||||
).format(xcarchive=xcarchive, ipa=ipa_tmp, ioscodesign=ioscodesign),
|
||||
self.xcodebuild(
|
||||
'-exportArchive',
|
||||
f'-archivePath "{xcarchive}"',
|
||||
f'-exportOptionsPlist "{plist_rfn}"',
|
||||
f'-exportPath "{ipa_tmp}"',
|
||||
f'CODE_SIGN_IDENTITY={ioscodesign}',
|
||||
'ENABLE_BITCODE=NO',
|
||||
cwd=build_dir)
|
||||
|
||||
self.buildozer.info('Moving IPA to bin...')
|
||||
|
@ -266,14 +301,12 @@ class TargetIos(Target):
|
|||
self.buildozer.state['ios:latestipa'] = ipa
|
||||
self.buildozer.state['ios:latestmode'] = self.build_mode
|
||||
|
||||
self._create_index()
|
||||
|
||||
def cmd_deploy(self, *args):
|
||||
super(TargetIos, self).cmd_deploy(*args)
|
||||
super().cmd_deploy(*args)
|
||||
self._run_ios_deploy(lldb=False)
|
||||
|
||||
def cmd_run(self, *args):
|
||||
super(TargetIos, self).cmd_run(*args)
|
||||
super().cmd_run(*args)
|
||||
self._run_ios_deploy(lldb=True)
|
||||
|
||||
def cmd_xcode(self, *args):
|
||||
|
@ -316,17 +349,13 @@ class TargetIos(Target):
|
|||
self.buildozer.error('Icon {} does not exists'.format(icon_fn))
|
||||
return
|
||||
|
||||
self.buildozer.cmd('./toolchain.py icon {} {}'.format(
|
||||
self.app_project_dir, icon_fn),
|
||||
cwd=self.ios_dir)
|
||||
|
||||
def _create_index(self):
|
||||
# TODO
|
||||
pass
|
||||
self.toolchain(f"icon {self.app_project_dir} {icon_fn}")
|
||||
|
||||
def check_configuration_tokens(self):
|
||||
errors = []
|
||||
config = self.buildozer.config
|
||||
if not config.getboolean('app', 'ios.codesign.allowed'):
|
||||
return
|
||||
identity_debug = config.getdefault('app', 'ios.codesign.debug', '')
|
||||
identity_release = config.getdefault('app', 'ios.codesign.release',
|
||||
identity_debug)
|
||||
|
@ -345,8 +374,7 @@ class TargetIos(Target):
|
|||
elif identity_release not in available_identities:
|
||||
errors.append('[app] identity "{}" not found. '
|
||||
'Check with list_identities'.format(identity_release))
|
||||
|
||||
super(TargetIos, self).check_configuration_tokens(errors)
|
||||
super().check_configuration_tokens(errors)
|
||||
|
||||
@no_config
|
||||
def cmd_list_identities(self, *args):
|
||||
|
@ -396,10 +424,10 @@ class TargetIos(Target):
|
|||
if not error:
|
||||
correct = True
|
||||
break
|
||||
self.error('Invalid keychain password')
|
||||
self.buildozer.error('Invalid keychain password')
|
||||
|
||||
if not correct:
|
||||
self.error('Unable to unlock the keychain, exiting.')
|
||||
self.buildozer.error('Unable to unlock the keychain, exiting.')
|
||||
raise BuildozerCommandException()
|
||||
|
||||
# maybe user want to save it for further reuse?
|
||||
|
@ -410,7 +438,7 @@ class TargetIos(Target):
|
|||
|
||||
save = None
|
||||
while save is None:
|
||||
q = raw_input('Do you want to save the password (Y/n): ')
|
||||
q = input('Do you want to save the password (Y/n): ')
|
||||
if q in ('', 'Y'):
|
||||
save = True
|
||||
elif q == 'n':
|
||||
|
@ -420,7 +448,8 @@ class TargetIos(Target):
|
|||
|
||||
if save:
|
||||
with open(password_file, 'wb') as fd:
|
||||
fd.write(password)
|
||||
fd.write(password.encode())
|
||||
|
||||
|
||||
def get_target(buildozer):
|
||||
return TargetIos(buildozer)
|
||||
|
|
|
@ -6,26 +6,10 @@ import sys
|
|||
if sys.platform != 'darwin':
|
||||
raise NotImplementedError('This will only work on osx')
|
||||
|
||||
#Global variables
|
||||
|
||||
#Global imports
|
||||
import traceback
|
||||
import os
|
||||
import io
|
||||
from pipes import quote
|
||||
from sys import platform, executable
|
||||
from buildozer import BuildozerException
|
||||
from buildozer import IS_PY3
|
||||
from buildozer.target import Target
|
||||
from os import environ
|
||||
from os.path import (exists, join, realpath, expanduser,
|
||||
basename, relpath, abspath, dirname)
|
||||
from shutil import copyfile
|
||||
from glob import glob
|
||||
from os.path import exists, join, abspath, dirname
|
||||
from subprocess import check_call, check_output
|
||||
|
||||
from buildozer.libs.version import parse
|
||||
|
||||
|
||||
class TargetOSX(Target):
|
||||
targetname = "osx"
|
||||
|
@ -33,9 +17,9 @@ class TargetOSX(Target):
|
|||
def ensure_sdk(self):
|
||||
self.buildozer.info('Check if kivy-sdk-packager exists')
|
||||
if exists(
|
||||
join(self.buildozer.platform_dir, 'kivy-sdk-packager-master')):
|
||||
join(self.buildozer.platform_dir, 'kivy-sdk-packager-master')):
|
||||
self.buildozer.info(
|
||||
'kivy-sdk-packager found at '\
|
||||
'kivy-sdk-packager found at '
|
||||
'{}'.format(self.buildozer.platform_dir))
|
||||
return
|
||||
|
||||
|
@ -62,16 +46,16 @@ class TargetOSX(Target):
|
|||
self.buildozer.info('Downloading kivy...')
|
||||
status_code = check_output(
|
||||
('curl', '-L', '--write-out', '%{http_code}', '-o', 'Kivy{}.dmg'.format(py_branch),
|
||||
'http://kivy.org/downloads/{}/Kivy-{}-osx-python{}.dmg'\
|
||||
'https://kivy.org/downloads/{}/Kivy-{}-osx-python{}.dmg'
|
||||
.format(current_kivy_vers, current_kivy_vers, py_branch)),
|
||||
cwd=cwd)
|
||||
|
||||
if status_code == "404":
|
||||
self.buildozer.error(
|
||||
"Unable to download the Kivy App. Check osx.kivy_version in your buildozer.spec, and verify "
|
||||
"Kivy servers are accessible. http://kivy.org/downloads/")
|
||||
"Kivy servers are accessible. https://kivy.org/downloads/")
|
||||
check_call(("rm", "Kivy{}.dmg".format(py_branch)), cwd=cwd)
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
self.buildozer.info('Extracting and installing Kivy...')
|
||||
check_call(('hdiutil', 'attach', cwd + '/Kivy{}.dmg'.format(py_branch)))
|
||||
|
@ -92,8 +76,6 @@ class TargetOSX(Target):
|
|||
else:
|
||||
self.download_kivy(kivy_app_dir, py_branch)
|
||||
|
||||
return
|
||||
|
||||
def check_requirements(self):
|
||||
self.ensure_sdk()
|
||||
self.ensure_kivyapp()
|
||||
|
@ -106,7 +88,7 @@ class TargetOSX(Target):
|
|||
len(errors)))
|
||||
for error in errors:
|
||||
print(error)
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
# check
|
||||
|
||||
def build_package(self):
|
||||
|
@ -114,7 +96,6 @@ class TargetOSX(Target):
|
|||
|
||||
bc = self.buildozer.config
|
||||
bcg = bc.get
|
||||
bcgl = bc.getlist
|
||||
package_name = bcg('app', 'package.name')
|
||||
domain = bcg('app', 'package.domain')
|
||||
title = bcg('app', 'title')
|
||||
|
@ -124,7 +105,7 @@ class TargetOSX(Target):
|
|||
author = bc.getdefault('app', 'author', '')
|
||||
|
||||
self.buildozer.info('Create {}.app'.format(package_name))
|
||||
cwd = join(self.buildozer.platform_dir,'kivy-sdk-packager-master', 'osx')
|
||||
cwd = join(self.buildozer.platform_dir, 'kivy-sdk-packager-master', 'osx')
|
||||
# remove kivy from app_deps
|
||||
app_deps = [a for a in app_deps.split('\n') if not a.startswith('#') and a not in ['kivy', '']]
|
||||
|
||||
|
@ -141,7 +122,6 @@ class TargetOSX(Target):
|
|||
'--bundlename={}'.format(title),
|
||||
'--bundleid={}'.format(domain),
|
||||
'--bundleversion={}'.format(version),
|
||||
#'--deps={}'.format(','.join(app_deps)),
|
||||
'--displayname={}'.format(title)
|
||||
]
|
||||
if icon:
|
||||
|
@ -159,10 +139,10 @@ class TargetOSX(Target):
|
|||
self.buildozer.info('{}.dmg created'.format(package_name))
|
||||
self.buildozer.info('moving {}.dmg to bin.'.format(package_name))
|
||||
binpath = join(
|
||||
self.buildozer.build_dir or
|
||||
self.buildozer.user_build_dir or
|
||||
dirname(abspath(self.buildozer.specfilename)), 'bin')
|
||||
check_output(
|
||||
('cp', '-a', package_name+'.dmg', binpath),
|
||||
('cp', '-a', package_name + '.dmg', binpath),
|
||||
cwd=cwd)
|
||||
self.buildozer.info('All Done!')
|
||||
|
||||
|
@ -176,7 +156,7 @@ class TargetOSX(Target):
|
|||
#
|
||||
self.buildozer.environ.update({
|
||||
'PACKAGES_PATH': self.buildozer.global_packages_dir,
|
||||
})
|
||||
})
|
||||
|
||||
def get_custom_commands(self):
|
||||
result = []
|
||||
|
@ -195,7 +175,7 @@ class TargetOSX(Target):
|
|||
if not args:
|
||||
self.buildozer.error('Missing target command')
|
||||
self.buildozer.usage()
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
result = []
|
||||
last_command = []
|
||||
|
@ -209,7 +189,7 @@ class TargetOSX(Target):
|
|||
if not last_command:
|
||||
self.buildozer.error('Argument passed without a command')
|
||||
self.buildozer.usage()
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
last_command.append(arg)
|
||||
if last_command:
|
||||
result.append(last_command)
|
||||
|
@ -220,7 +200,7 @@ class TargetOSX(Target):
|
|||
command, args = item[0], item[1:]
|
||||
if not hasattr(self, 'cmd_{0}'.format(command)):
|
||||
self.buildozer.error('Unknown command {0}'.format(command))
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
func = getattr(self, 'cmd_{0}'.format(command))
|
||||
|
||||
|
@ -264,4 +244,3 @@ class TargetOSX(Target):
|
|||
|
||||
def get_target(buildozer):
|
||||
return TargetOSX(buildozer)
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ torrent:
|
|||
mktorrent \
|
||||
-a ${TORRENT_ANNOUNCE} \
|
||||
-o output-kivy-buildozer-vm/kivy-buildozer-vm.torrent \
|
||||
-w http://txzone.net/files/torrents/${PACKAGE_FILENAME} \
|
||||
-w https://txzone.net/files/torrents/${PACKAGE_FILENAME} \
|
||||
-v output-kivy-buildozer-vm/${PACKAGE_FILENAME}
|
||||
|
||||
upload:
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
download the Android SDK/NDK (automatically done), and during the first
|
||||
compilation.
|
||||
<br/>
|
||||
It is preferrable to add a <a href="#sharefolder">share a folder
|
||||
It is preferable to add a <a href="#sharefolder"> share a folder
|
||||
</a> between your host and the VM, then build from there.<br/>
|
||||
|
||||
By the time we shipped the VM and you using it, you may need to
|
||||
|
@ -83,7 +83,7 @@ build_dir = /build/buildozer-myapp</pre>
|
|||
<h2 id="update-buildozer">Update buildozer</h2>
|
||||
<p>
|
||||
The buildozer version you have may be outdated, as well as the dependencies.
|
||||
The best is to regulary update buildozer:
|
||||
The best is to regularly update buildozer:
|
||||
<pre>sudo pip install -U buildozer</pre>
|
||||
</p>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# an error when using the android sdk:
|
||||
# "Can't read cryptographic policy directory: unlimited"
|
||||
|
||||
wget http://bootstrap.pypa.io/get-pip.py
|
||||
wget https://bootstrap.pypa.io/get-pip.py
|
||||
python get-pip.py
|
||||
rm get-pip.py
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ BUILDDIR = build
|
|||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from https://www.sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
|
|
|
@ -56,7 +56,7 @@ if errorlevel 9009 (
|
|||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Write your own recipe
|
|||
|
||||
A recipe allows you to compile libraries / python extension for the mobile.
|
||||
Most of the time, the default compilation instructions doesn't work for the
|
||||
target, as ARM compiler / Android NDK introduce specifities that the library
|
||||
target, as ARM compiler / Android NDK introduce specificities that the library
|
||||
you want doesn't handle correctly, and you'll need to patch. Also, because the
|
||||
Android platform cannot load more than 64 inline dynamic libraries, we have a
|
||||
mechanism to bundle all of them in one to ensure you'll not hit this
|
||||
|
@ -15,10 +15,10 @@ limitation.
|
|||
|
||||
To test your own recipe via Buildozer, you need to:
|
||||
|
||||
#. Fork `Python for Android <http://github.com/kivy/python-for-android>`_, and
|
||||
#. Fork `Python for Android <https://github.com/kivy/python-for-android>`_, and
|
||||
clone your own version (this will allow easy contribution later)::
|
||||
|
||||
git clone http://github.com/YOURNAME/python-for-android
|
||||
git clone https://github.com/YOURNAME/python-for-android
|
||||
|
||||
#. Change your `buildozer.spec` to reference your version::
|
||||
|
||||
|
@ -44,6 +44,6 @@ include it in the python-for-android project, by issuing a Pull Request:
|
|||
|
||||
git push origin master
|
||||
|
||||
#. Go to `http://github.com/YOURNAME/python-for-android`, and you should see
|
||||
#. Go to `https://github.com/YOURNAME/python-for-android`, and you should see
|
||||
your new branch and a button "Pull Request" on it. Use it, write a
|
||||
description about what you did, and Send!
|
||||
|
|
|
@ -1,38 +1,132 @@
|
|||
|
||||
Installation
|
||||
============
|
||||
|
||||
Buildozer itself doesn't depend on any library, and works on Python 2.7 and >=
|
||||
3.3. Depending the platform you want to target, you might need more tools
|
||||
installed. Buildozer tries to give you hints or tries to install few things for
|
||||
Buildozer itself doesn't depend on any library Python >= 3.3.
|
||||
Depending the platform you want to target, you might need more tools installed.
|
||||
Buildozer tries to give you hints or tries to install few things for
|
||||
you, but it doesn't cover every situation.
|
||||
|
||||
First, install the buildozer project with::
|
||||
|
||||
pip install --upgrade buildozer
|
||||
pip3 install --user --upgrade buildozer
|
||||
|
||||
Targeting Android
|
||||
-----------------
|
||||
|
||||
If you target Android, you must install at least Cython, few build libs, and a
|
||||
Java SDK. Some binaries of the Android SDK are still in 32 bits, so you need
|
||||
few 32bits libraries available:
|
||||
|
||||
Android on Ubuntu 18.04 (64bit)
|
||||
Android on Ubuntu 20.04 (64bit)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
(expected to work as well in later version, but only regularly tested in the latest LTS)
|
||||
|
||||
::
|
||||
|
||||
sudo pip install --upgrade cython==0.21
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update
|
||||
sudo apt install build-essential ccache git libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 python2.7 python2.7-dev openjdk-8-jdk unzip zlib1g-dev zlib1g:i386
|
||||
sudo apt install -y git zip unzip openjdk-13-jdk python3-pip autoconf libtool pkg-config zlib1g-dev libncurses5-dev libncursesw5-dev libtinfo5 cmake libffi-dev libssl-dev
|
||||
pip3 install --user --upgrade Cython==0.29.19 virtualenv # the --user should be removed if you do this in a venv
|
||||
|
||||
Android on Ubuntu 16.04 (64bit)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# add the following line at the end of your ~/.bashrc file
|
||||
export PATH=$PATH:~/.local/bin/
|
||||
|
||||
Android on Windows 10
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To use buildozer in Windows 10 you need first to enable Windows Subsystem for Linux (WSL) and install a Linux distribution: https://docs.microsoft.com/en-us/windows/wsl/install-win10.
|
||||
|
||||
These instructions were tested with WSL 1 and Ubuntu 18.04 LTS.
|
||||
|
||||
After installing WSL and Ubuntu in your Windows 10 machine, open Ubuntu and do this:
|
||||
|
||||
1) Run the commands listed on the previous section (Android in Ubuntu 18.04 (64-bit).
|
||||
2) Run the following commands:
|
||||
|
||||
::
|
||||
|
||||
sudo pip install --upgrade cython==0.21
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential ccache git libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 python2.7 python2.7-dev openjdk-8-jdk unzip zlib1g-dev zlib1g:i386
|
||||
# Use here the python version you need
|
||||
sudo apt install -y python3.7-venv
|
||||
# Create a folder for buildozer. For example: C:\buildozer
|
||||
mkdir /mnt/c/buildozer
|
||||
cd /mnt/c/buildozer
|
||||
python3.7 -m venv venv-buildozer
|
||||
source venv/bin/activate
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install --upgrade wheel
|
||||
python -m pip install --upgrade cython
|
||||
python -m pip install --upgrade virtualenv
|
||||
python -m pip install --upgrade buildozer
|
||||
# Restart your WSL terminal to enable the path change
|
||||
|
||||
Windows Subsystem for Linux does not have direct access to USB. Due to this, you need to install the Windows version of ADB (Android Debug Bridge):
|
||||
|
||||
- Go to https://developer.android.com/studio/releases/platform-tools and click on "Download SDK Platform-Tools for Windows".
|
||||
|
||||
- Unzip the downloaded file to a new folder. For example, "C:\\platform-tools".
|
||||
|
||||
Before Using Buildozer
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you wish, clone your code to a new folder, where the build process will run.
|
||||
|
||||
You don't need to create a virtualenv for your code requirements. But just add these requirements to a configuration file called buildozer.spec as you will see in the following sections.
|
||||
|
||||
Before running buildozer in your code folder, remember to go into the buildozer folder and activate the buildozer virtualenv.
|
||||
|
||||
Android on macOS
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
brew install openssl
|
||||
sudo ln -sfn /usr/local/opt/openssl /usr/local/ssl
|
||||
brew install pkg-config autoconf automake
|
||||
python3 -m pip install --user --upgrade Cython==0.29.19 virtualenv # the --user should be removed if you do this in a venv
|
||||
|
||||
# add the following line at the end of your `~/.bashrc` file
|
||||
export PATH=$PATH:~/Library/Python/3.7/bin
|
||||
|
||||
|
||||
TroubleShooting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Buildozer stuck on "Installing/updating SDK platform tools if necessary"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Press "y" then enter to continue, the license acceptance system is silently waiting for your input
|
||||
|
||||
|
||||
Aidl not found, please install it.
|
||||
""""""""""""""""""""""""""""""""""
|
||||
|
||||
Buildozer didn't install a necessary package
|
||||
|
||||
::
|
||||
|
||||
~/.buildozer/android/platform/android-sdk/tools/bin/sdkmanager "build-tools;29.0.0"
|
||||
|
||||
Then press "y" then enter to accept the license.
|
||||
|
||||
|
||||
python-for-android related errors
|
||||
"""""""""""""""""""""""""""""""""
|
||||
See the dedicated `p4a troubleshooting documentation
|
||||
<https://python-for-android.readthedocs.io/en/latest/troubleshooting/>`_.
|
||||
|
||||
|
||||
Targeting IOS
|
||||
-------------
|
||||
|
||||
Install XCode and command line tools (through the AppStore)
|
||||
|
||||
|
||||
Install homebrew (https://brew.sh)
|
||||
|
||||
::
|
||||
|
||||
brew install pkg-config sdl2 sdl2_image sdl2_ttf sdl2_mixer gstreamer autoconf automake
|
||||
|
||||
|
||||
Install pip and virtualenv
|
||||
|
||||
::
|
||||
|
||||
python3 -m pip install --user --upgrade pip virtualenv kivy-ios
|
||||
|
|
|
@ -8,7 +8,7 @@ Init and build for Android
|
|||
|
||||
#. Buildozer will try to guess the version of your application, by searching a
|
||||
line like `__version__ = "1.0.3"` in your `main.py`. Ensure you have one at
|
||||
the start of your application. It is not mandatory but heavilly advised.
|
||||
the start of your application. It is not mandatory but heavily advised.
|
||||
|
||||
#. Create a `buildozer.spec` file, with::
|
||||
|
||||
|
@ -26,7 +26,7 @@ Init and build for Android
|
|||
The first build will be slow, as it will download the Android SDK, NDK, and
|
||||
others tools needed for the compilation.
|
||||
Don't worry, thoses files will be saved in a global directory and will be
|
||||
shared accross the different project you'll manage with Buildozer.
|
||||
shared across the different project you'll manage with Buildozer.
|
||||
|
||||
#. At the end, you should have an APK file in the `bin/` directory.
|
||||
|
||||
|
@ -60,6 +60,40 @@ To save the logcat output into a file named `my_log.txt` (the file will appear i
|
|||
|
||||
buildozer -v android debug deploy run logcat > my_log.txt
|
||||
|
||||
To see your running application's print() messages and python's error messages, use:
|
||||
|
||||
::
|
||||
|
||||
buildozer -v android deploy run logcat | grep python
|
||||
|
||||
Run my application from Windows 10
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Plug your Android device on a USB port.
|
||||
|
||||
- Open Windows PowerShell, go into the folder where you installed the Windows version of ADB, and activate the ADB daemon. When the daemon is started you must see a number besides the word "device" meaning your device was correctly detected. In case of trouble, try another USB port or USB cable.
|
||||
|
||||
::
|
||||
|
||||
cd C:\platform-tools\
|
||||
.\adb.exe devices
|
||||
|
||||
- Open the Linux distribution you installed on Windows Subsystem for Linux (WSL) and proceed with the deploy commands:
|
||||
|
||||
::
|
||||
|
||||
buildozer -v android deploy run
|
||||
|
||||
It is important to notice that Windows ADB and Buildozer installed ADB must be the same version. To check the versions, open PowerShell and type:
|
||||
|
||||
::
|
||||
|
||||
cd C:\platform-tools\
|
||||
.\adb.exe version
|
||||
wsl
|
||||
cd ~/.buildozer/android/platform/android-sdk/platform-tools/
|
||||
./adb version
|
||||
|
||||
Install on non-connected devices
|
||||
--------------------------------
|
||||
|
||||
|
|
|
@ -98,16 +98,6 @@ Section [app]
|
|||
the compilation here. If you want to make it work, contribute to the
|
||||
Python-for-android project by creating a recipe. See :doc:`contribute`.
|
||||
|
||||
- `garden_requirements`: List, Garden packages to include.
|
||||
|
||||
Add here the list of Kivy's garden packages to include. For example::
|
||||
|
||||
garden_requirements = graph
|
||||
|
||||
Please note that if it doesn't work, it might be because of the garden
|
||||
package itself. Refer to the author of the package if he already tested
|
||||
it on your target platform, not us.
|
||||
|
||||
- `presplash.filename`: String, loading screen of your application.
|
||||
|
||||
Presplash is the image shown on the device during application loading.
|
||||
|
|
38
setup.py
38
setup.py
|
@ -2,6 +2,7 @@
|
|||
Buildozer
|
||||
'''
|
||||
|
||||
import sys
|
||||
from setuptools import setup
|
||||
from os.path import dirname, join
|
||||
import codecs
|
||||
|
@ -11,6 +12,21 @@ import io
|
|||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
CURRENT_PYTHON = sys.version_info[:2]
|
||||
REQUIRED_PYTHON = (3, 6)
|
||||
|
||||
# This check and everything above must remain compatible with Python 2.7.
|
||||
if CURRENT_PYTHON < REQUIRED_PYTHON:
|
||||
sys.stderr.write("""
|
||||
==========================
|
||||
Unsupported Python version
|
||||
==========================
|
||||
This version of buildozer requires Python {}.{}, but you're trying to
|
||||
install it on Python {}.{}.
|
||||
""".format(*(REQUIRED_PYTHON + CURRENT_PYTHON)))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def find_version(*file_paths):
|
||||
# Open in Latin-1 so that we avoid encoding errors.
|
||||
|
@ -28,7 +44,7 @@ def find_version(*file_paths):
|
|||
|
||||
|
||||
curdir = dirname(__file__)
|
||||
with io.open(join(curdir, "README.rst"), encoding="utf-8") as fd:
|
||||
with io.open(join(curdir, "README.md"), encoding="utf-8") as fd:
|
||||
readme = fd.read()
|
||||
with io.open(join(curdir, "CHANGELOG.md"), encoding="utf-8") as fd:
|
||||
changelog = fd.read()
|
||||
|
@ -38,27 +54,25 @@ setup(
|
|||
version=find_version('buildozer', '__init__.py'),
|
||||
description='Generic Python packager for Android / iOS and Desktop',
|
||||
long_description=readme + "\n\n" + changelog,
|
||||
long_description_content_type='text/markdown',
|
||||
author='Mathieu Virbel',
|
||||
author_email='mat@kivy.org',
|
||||
url='http://github.com/kivy/buildozer',
|
||||
url='https://github.com/kivy/buildozer',
|
||||
license='MIT',
|
||||
packages=[
|
||||
'buildozer', 'buildozer.targets', 'buildozer.libs', 'buildozer.scripts'
|
||||
],
|
||||
],
|
||||
package_data={'buildozer': ['default.spec']},
|
||||
include_package_data=True,
|
||||
install_requires=['pexpect', 'virtualenv'],
|
||||
install_requires=['pexpect', 'virtualenv', 'sh'],
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta', 'Intended Audience :: Developers',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'Topic :: Software Development :: Build Tools',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5'
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
|
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
0
tests/scripts/__init__.py
Normal file
0
tests/scripts/__init__.py
Normal file
26
tests/scripts/test_client.py
Normal file
26
tests/scripts/test_client.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import sys
|
||||
import unittest
|
||||
from buildozer import BuildozerCommandException
|
||||
from buildozer.scripts import client
|
||||
from unittest import mock
|
||||
|
||||
|
||||
class TestClient(unittest.TestCase):
|
||||
|
||||
def test_run_command_called(self):
|
||||
"""
|
||||
Checks Buildozer.run_command() is being called with arguments from command line.
|
||||
"""
|
||||
with mock.patch('buildozer.Buildozer.run_command') as m_run_command:
|
||||
client.main()
|
||||
assert m_run_command.call_args_list == [mock.call(sys.argv[1:])]
|
||||
|
||||
def test_exit_code(self):
|
||||
"""
|
||||
Makes sure the CLI exits with error code on BuildozerCommandException, refs #674.
|
||||
"""
|
||||
with mock.patch('buildozer.Buildozer.run_command') as m_run_command:
|
||||
m_run_command.side_effect = BuildozerCommandException()
|
||||
with self.assertRaises(SystemExit) as context:
|
||||
client.main()
|
||||
assert context.exception.code == 1
|
394
tests/targets/test_android.py
Normal file
394
tests/targets/test_android.py
Normal file
|
@ -0,0 +1,394 @@
|
|||
import os
|
||||
import tempfile
|
||||
from six import StringIO
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from buildozer.targets.android import TargetAndroid
|
||||
from tests.targets.utils import (
|
||||
init_buildozer,
|
||||
patch_buildozer,
|
||||
patch_buildozer_checkbin,
|
||||
patch_buildozer_cmd,
|
||||
patch_buildozer_file_exists,
|
||||
)
|
||||
|
||||
|
||||
def patch_buildozer_cmd_expect():
|
||||
return patch_buildozer("cmd_expect")
|
||||
|
||||
|
||||
def patch_buildozer_download():
|
||||
return patch_buildozer("download")
|
||||
|
||||
|
||||
def patch_buildozer_file_extract():
|
||||
return patch_buildozer("file_extract")
|
||||
|
||||
|
||||
def patch_os_isfile():
|
||||
return mock.patch("os.path.isfile")
|
||||
|
||||
|
||||
def patch_target_android(method):
|
||||
return mock.patch(
|
||||
"buildozer.targets.android.TargetAndroid.{method}".format(method=method)
|
||||
)
|
||||
|
||||
|
||||
def patch_platform(platform):
|
||||
return mock.patch("buildozer.targets.android.platform", platform)
|
||||
|
||||
|
||||
def init_target(temp_dir, options=None):
|
||||
buildozer = init_buildozer(temp_dir, "android", options)
|
||||
return TargetAndroid(buildozer)
|
||||
|
||||
|
||||
def call_build_package(target_android):
|
||||
"""
|
||||
Call the build_package() method of the tested TargetAndroid instance,
|
||||
patching the functions that would otherwise produce side-effects.
|
||||
|
||||
Return the mocked execute_build_package() method of the TargetAndroid
|
||||
instance so that tests can easily check which command-line arguments
|
||||
would be passed on to python-for-android's toolchain.
|
||||
"""
|
||||
buildozer = target_android.buildozer
|
||||
expected_dist_dir = (
|
||||
'{buildozer_dir}/android/platform/build-armeabi-v7a/dists/myapp__armeabi-v7a'.format(
|
||||
buildozer_dir=buildozer.buildozer_dir)
|
||||
)
|
||||
|
||||
with patch_target_android('_update_libraries_references') as m_update_libraries_references, \
|
||||
patch_target_android('_generate_whitelist') as m_generate_whitelist, \
|
||||
mock.patch('buildozer.targets.android.TargetAndroid.execute_build_package') as m_execute_build_package, \
|
||||
mock.patch('buildozer.targets.android.copyfile') as m_copyfile, \
|
||||
mock.patch('buildozer.targets.android.os.listdir') as m_listdir:
|
||||
m_listdir.return_value = ['30.0.0-rc2']
|
||||
target_android.build_package()
|
||||
|
||||
assert m_listdir.call_count == 1
|
||||
assert m_update_libraries_references.call_args_list == [
|
||||
mock.call(expected_dist_dir)
|
||||
]
|
||||
assert m_generate_whitelist.call_args_list == [mock.call(expected_dist_dir)]
|
||||
assert m_copyfile.call_args_list == [
|
||||
mock.call(
|
||||
'{expected_dist_dir}/bin/MyApplication-0.1-debug.apk'.format(
|
||||
expected_dist_dir=expected_dist_dir
|
||||
),
|
||||
'{bin_dir}/myapp-0.1-armeabi-v7a-debug.apk'.format(bin_dir=buildozer.bin_dir),
|
||||
)
|
||||
]
|
||||
return m_execute_build_package
|
||||
|
||||
|
||||
class TestTargetAndroid:
|
||||
|
||||
def setup_method(self):
|
||||
"""
|
||||
Create a temporary directory that will contain the spec file and will
|
||||
serve as the root_dir.
|
||||
"""
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
|
||||
def tear_method(self):
|
||||
"""
|
||||
Remove the temporary directory created in self.setup_method.
|
||||
"""
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def test_init(self):
|
||||
"""Tests init defaults."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
buildozer = target_android.buildozer
|
||||
assert target_android._arch == "armeabi-v7a"
|
||||
assert target_android._build_dir.endswith(
|
||||
".buildozer/android/platform/build-armeabi-v7a"
|
||||
)
|
||||
assert target_android._p4a_bootstrap == "sdl2"
|
||||
assert target_android._p4a_cmd.endswith(
|
||||
"python -m pythonforandroid.toolchain "
|
||||
)
|
||||
assert target_android.build_mode == "debug"
|
||||
assert (
|
||||
target_android.extra_p4a_args == (
|
||||
' --color=always'
|
||||
' --storage-dir="{buildozer_dir}/android/platform/build-armeabi-v7a" --ndk-api=21 --ignore-setup-py'.format(
|
||||
buildozer_dir=buildozer.buildozer_dir)
|
||||
)
|
||||
)
|
||||
assert target_android.p4a_apk_cmd == "apk --debug --bootstrap=sdl2"
|
||||
assert target_android.platform_update is False
|
||||
|
||||
def test_init_positional_buildozer(self):
|
||||
"""Positional `buildozer` argument is required."""
|
||||
with pytest.raises(TypeError) as ex_info:
|
||||
TargetAndroid()
|
||||
assert ex_info.value.args == (
|
||||
"__init__() missing 1 required positional argument: 'buildozer'",
|
||||
)
|
||||
|
||||
def test_sdkmanager(self):
|
||||
"""Tests the _sdkmanager() method."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
kwargs = {}
|
||||
with patch_buildozer_cmd() as m_cmd, patch_buildozer_cmd_expect() as m_cmd_expect, patch_os_isfile() as m_isfile:
|
||||
m_isfile.return_value = True
|
||||
assert m_cmd.return_value == target_android._sdkmanager(**kwargs)
|
||||
assert m_cmd.call_count == 1
|
||||
assert m_cmd_expect.call_count == 0
|
||||
assert m_isfile.call_count == 1
|
||||
kwargs = {"return_child": True}
|
||||
with patch_buildozer_cmd() as m_cmd, patch_buildozer_cmd_expect() as m_cmd_expect, patch_os_isfile() as m_isfile:
|
||||
m_isfile.return_value = True
|
||||
assert m_cmd_expect.return_value == target_android._sdkmanager(
|
||||
**kwargs
|
||||
)
|
||||
assert m_cmd.call_count == 0
|
||||
assert m_cmd_expect.call_count == 1
|
||||
assert m_isfile.call_count == 1
|
||||
|
||||
def test_check_requirements(self):
|
||||
"""Basic tests for the check_requirements() method."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
buildozer = target_android.buildozer
|
||||
assert not hasattr(target_android, "adb_cmd")
|
||||
assert not hasattr(target_android, "javac_cmd")
|
||||
assert "PATH" not in buildozer.environ
|
||||
with patch_buildozer_checkbin() as m_checkbin:
|
||||
target_android.check_requirements()
|
||||
assert m_checkbin.call_args_list == [
|
||||
mock.call("Git (git)", "git"),
|
||||
mock.call("Cython (cython)", "cython"),
|
||||
mock.call("Java compiler (javac)", "javac"),
|
||||
mock.call("Java keytool (keytool)", "keytool"),
|
||||
]
|
||||
assert target_android.adb_cmd.endswith(
|
||||
".buildozer/android/platform/android-sdk/platform-tools/adb"
|
||||
)
|
||||
assert target_android.javac_cmd == "javac"
|
||||
assert target_android.keytool_cmd == "keytool"
|
||||
assert "PATH" in buildozer.environ
|
||||
|
||||
def test_check_configuration_tokens(self):
|
||||
"""Basic tests for the check_configuration_tokens() method."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
with mock.patch(
|
||||
"buildozer.targets.android.Target.check_configuration_tokens"
|
||||
) as m_check_configuration_tokens:
|
||||
target_android.check_configuration_tokens()
|
||||
assert m_check_configuration_tokens.call_args_list == [mock.call([])]
|
||||
|
||||
@pytest.mark.parametrize("platform", ["linux", "darwin"])
|
||||
def test_install_android_sdk(self, platform):
|
||||
"""Basic tests for the _install_android_sdk() method."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
with patch_buildozer_file_exists() as m_file_exists, patch_buildozer_download() as m_download:
|
||||
m_file_exists.return_value = True
|
||||
sdk_dir = target_android._install_android_sdk()
|
||||
assert m_file_exists.call_args_list == [
|
||||
mock.call(target_android.android_sdk_dir)
|
||||
]
|
||||
assert m_download.call_args_list == []
|
||||
assert sdk_dir.endswith(".buildozer/android/platform/android-sdk")
|
||||
with patch_buildozer_file_exists() as m_file_exists, \
|
||||
patch_buildozer_download() as m_download, \
|
||||
patch_buildozer_file_extract() as m_file_extract, \
|
||||
patch_platform(platform):
|
||||
m_file_exists.return_value = False
|
||||
sdk_dir = target_android._install_android_sdk()
|
||||
assert m_file_exists.call_args_list == [
|
||||
mock.call(target_android.android_sdk_dir)
|
||||
]
|
||||
platform_map = {"linux": "linux", "darwin": "mac"}
|
||||
platform = platform_map[platform]
|
||||
archive = "commandlinetools-{platform}-6514223_latest.zip".format(platform=platform)
|
||||
assert m_download.call_args_list == [
|
||||
mock.call(
|
||||
"https://dl.google.com/android/repository/",
|
||||
archive,
|
||||
cwd=mock.ANY,
|
||||
)
|
||||
]
|
||||
assert m_file_extract.call_args_list == [mock.call(archive, cwd=mock.ANY)]
|
||||
assert sdk_dir.endswith(".buildozer/android/platform/android-sdk")
|
||||
|
||||
def test_build_package(self):
|
||||
"""Basic tests for the build_package() method."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
buildozer = target_android.buildozer
|
||||
m_execute_build_package = call_build_package(target_android)
|
||||
assert m_execute_build_package.call_args_list == [
|
||||
mock.call(
|
||||
[
|
||||
("--name", "'My Application'"),
|
||||
("--version", "0.1"),
|
||||
("--package", "org.test.myapp"),
|
||||
("--minsdk", "21"),
|
||||
("--ndk-api", "21"),
|
||||
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=buildozer.buildozer_dir)),
|
||||
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
||||
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
||||
("--orientation", "portrait"),
|
||||
("--window",),
|
||||
("debug",),
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_numeric_version(self):
|
||||
"""The `android.numeric_version` config should be passed to `build_package()`."""
|
||||
target_android = init_target(self.temp_dir, {
|
||||
"android.numeric_version": "1234"
|
||||
})
|
||||
buildozer = target_android.buildozer
|
||||
m_execute_build_package = call_build_package(target_android)
|
||||
assert m_execute_build_package.call_args_list == [
|
||||
mock.call(
|
||||
[
|
||||
("--name", "'My Application'"),
|
||||
("--version", "0.1"),
|
||||
("--package", "org.test.myapp"),
|
||||
("--minsdk", "21"),
|
||||
("--ndk-api", "21"),
|
||||
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=buildozer.buildozer_dir)),
|
||||
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
||||
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
||||
("--orientation", "portrait"),
|
||||
("--window",),
|
||||
("--numeric-version", "1234"),
|
||||
("debug",),
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_build_package_intent_filters(self):
|
||||
"""
|
||||
The build_package() method should honour the manifest.intent_filters
|
||||
config option.
|
||||
"""
|
||||
filters_path = os.path.join(self.temp_dir.name, 'filters.xml')
|
||||
|
||||
with open(filters_path, 'w') as f:
|
||||
f.write('<?xml version="1.0" encoding="utf-8"?>')
|
||||
|
||||
target_android = init_target(self.temp_dir, {
|
||||
'android.manifest.intent_filters': 'filters.xml'
|
||||
})
|
||||
buildozer = target_android.buildozer
|
||||
m_execute_build_package = call_build_package(target_android)
|
||||
|
||||
assert m_execute_build_package.call_args_list == [
|
||||
mock.call(
|
||||
[
|
||||
('--name', "'My Application'"),
|
||||
('--version', '0.1'),
|
||||
('--package', 'org.test.myapp'),
|
||||
('--minsdk', '21'),
|
||||
('--ndk-api', '21'),
|
||||
('--private', '{buildozer_dir}/android/app'.format(buildozer_dir=buildozer.buildozer_dir)),
|
||||
('--android-entrypoint', 'org.kivy.android.PythonActivity'),
|
||||
('--android-apptheme', '@android:style/Theme.NoTitleBar'),
|
||||
('--orientation', 'portrait'),
|
||||
('--window',),
|
||||
('--intent-filters', os.path.realpath(filters_path)),
|
||||
('debug',),
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_allow_backup(self):
|
||||
"""The `android.allow_backup` config should be passed to `build_package()`."""
|
||||
target_android = init_target(self.temp_dir, {
|
||||
"android.allow_backup": "false"
|
||||
})
|
||||
buildozer = target_android.buildozer
|
||||
m_execute_build_package = call_build_package(target_android)
|
||||
assert m_execute_build_package.call_args_list == [
|
||||
mock.call(
|
||||
[
|
||||
("--name", "'My Application'"),
|
||||
("--version", "0.1"),
|
||||
("--package", "org.test.myapp"),
|
||||
("--minsdk", "21"),
|
||||
("--ndk-api", "21"),
|
||||
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=buildozer.buildozer_dir)),
|
||||
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
||||
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
||||
("--orientation", "portrait"),
|
||||
("--window",),
|
||||
("--allow-backup", "false"),
|
||||
("debug",),
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_backup_rules(self):
|
||||
"""The `android.backup_rules` config should be passed to `build_package()`."""
|
||||
target_android = init_target(self.temp_dir, {
|
||||
"android.backup_rules": "backup_rules.xml"
|
||||
})
|
||||
buildozer = target_android.buildozer
|
||||
m_execute_build_package = call_build_package(target_android)
|
||||
assert m_execute_build_package.call_args_list == [
|
||||
mock.call(
|
||||
[
|
||||
("--name", "'My Application'"),
|
||||
("--version", "0.1"),
|
||||
("--package", "org.test.myapp"),
|
||||
("--minsdk", "21"),
|
||||
("--ndk-api", "21"),
|
||||
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=buildozer.buildozer_dir)),
|
||||
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
||||
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
||||
("--orientation", "portrait"),
|
||||
("--window",),
|
||||
("--backup-rules", "{root_dir}/backup_rules.xml".format(root_dir=buildozer.root_dir)),
|
||||
("debug",),
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_install_platform_p4a_clone_url(self):
|
||||
"""The `p4a.url` config should be used for cloning p4a before the `p4a.fork` option."""
|
||||
target_android = init_target(self.temp_dir, {
|
||||
'p4a.url': 'https://custom-p4a-url/p4a.git',
|
||||
'p4a.fork': 'myfork',
|
||||
})
|
||||
|
||||
with patch_buildozer_cmd() as m_cmd, mock.patch('buildozer.targets.android.open') as m_open:
|
||||
m_open.return_value = StringIO('install_reqs = []') # to stub setup.py parsing
|
||||
target_android._install_p4a()
|
||||
|
||||
assert mock.call(
|
||||
'git clone -b master --single-branch https://custom-p4a-url/p4a.git python-for-android',
|
||||
cwd=mock.ANY) in m_cmd.call_args_list
|
||||
|
||||
def test_install_platform_p4a_clone_fork(self):
|
||||
"""The `p4a.fork` config should be used for cloning p4a."""
|
||||
target_android = init_target(self.temp_dir, {
|
||||
'p4a.fork': 'fork'
|
||||
})
|
||||
|
||||
with patch_buildozer_cmd() as m_cmd, mock.patch('buildozer.targets.android.open') as m_open:
|
||||
m_open.return_value = StringIO('install_reqs = []') # to stub setup.py parsing
|
||||
target_android._install_p4a()
|
||||
|
||||
assert mock.call(
|
||||
'git clone -b master --single-branch https://github.com/fork/python-for-android.git python-for-android',
|
||||
cwd=mock.ANY) in m_cmd.call_args_list
|
||||
|
||||
def test_install_platform_p4a_clone_default(self):
|
||||
"""The default URL should be used for cloning p4a if no config options `p4a.url` and `p4a.fork` are set."""
|
||||
target_android = init_target(self.temp_dir)
|
||||
|
||||
with patch_buildozer_cmd() as m_cmd, mock.patch('buildozer.targets.android.open') as m_open:
|
||||
m_open.return_value = StringIO('install_reqs = []') # to stub setup.py parsing
|
||||
target_android._install_p4a()
|
||||
|
||||
assert mock.call(
|
||||
'git clone -b master --single-branch https://github.com/kivy/python-for-android.git python-for-android',
|
||||
cwd=mock.ANY) in m_cmd.call_args_list
|
215
tests/targets/test_ios.py
Normal file
215
tests/targets/test_ios.py
Normal file
|
@ -0,0 +1,215 @@
|
|||
import sys
|
||||
import tempfile
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from buildozer import BuildozerCommandException
|
||||
from buildozer.targets.ios import TargetIos
|
||||
from tests.targets.utils import (
|
||||
init_buildozer,
|
||||
patch_buildozer_checkbin,
|
||||
patch_buildozer_cmd,
|
||||
patch_buildozer_error,
|
||||
patch_buildozer_file_exists,
|
||||
)
|
||||
|
||||
|
||||
def patch_target_ios(method):
|
||||
return mock.patch("buildozer.targets.ios.TargetIos.{method}".format(method=method))
|
||||
|
||||
|
||||
def init_target(temp_dir, options=None):
|
||||
buildozer = init_buildozer(temp_dir, "ios", options)
|
||||
return TargetIos(buildozer)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform != "darwin", reason="Only macOS is supported for target iOS"
|
||||
)
|
||||
class TestTargetIos:
|
||||
def setup_method(self):
|
||||
"""
|
||||
Create a temporary directory that will contain the spec file and will
|
||||
serve as the root_dir.
|
||||
"""
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
|
||||
def tear_method(self):
|
||||
"""
|
||||
Remove the temporary directory created in self.setup_method.
|
||||
"""
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def test_init(self):
|
||||
"""Tests init defaults."""
|
||||
target = init_target(self.temp_dir)
|
||||
assert target.targetname == "ios"
|
||||
assert target.code_signing_allowed == "CODE_SIGNING_ALLOWED=NO"
|
||||
assert target.build_mode == "debug"
|
||||
assert target.platform_update is False
|
||||
|
||||
def test_check_requirements(self):
|
||||
"""Basic tests for the check_requirements() method."""
|
||||
target = init_target(self.temp_dir)
|
||||
buildozer = target.buildozer
|
||||
assert not hasattr(target, "adb_cmd")
|
||||
assert not hasattr(target, "javac_cmd")
|
||||
assert "PATH" not in buildozer.environ
|
||||
with patch_buildozer_checkbin() as m_checkbin:
|
||||
target.check_requirements()
|
||||
assert m_checkbin.call_args_list == [
|
||||
mock.call("Xcode xcodebuild", "xcodebuild"),
|
||||
mock.call("Xcode xcode-select", "xcode-select"),
|
||||
mock.call("Git git", "git"),
|
||||
mock.call("Cython cython", "cython"),
|
||||
mock.call("pkg-config", "pkg-config"),
|
||||
mock.call("autoconf", "autoconf"),
|
||||
mock.call("automake", "automake"),
|
||||
mock.call("libtool", "libtool"),
|
||||
]
|
||||
assert target._toolchain_cmd.endswith("toolchain.py ")
|
||||
assert target._xcodebuild_cmd == "xcodebuild "
|
||||
|
||||
def test_check_configuration_tokens(self):
|
||||
"""Basic tests for the check_configuration_tokens() method."""
|
||||
target = init_target(self.temp_dir, {"ios.codesign.allowed": "yes"})
|
||||
with mock.patch(
|
||||
"buildozer.targets.android.Target.check_configuration_tokens"
|
||||
) as m_check_configuration_tokens, mock.patch(
|
||||
"buildozer.targets.ios.TargetIos._get_available_identities"
|
||||
) as m_get_available_identities:
|
||||
target.check_configuration_tokens()
|
||||
assert m_get_available_identities.call_args_list == [mock.call()]
|
||||
assert m_check_configuration_tokens.call_args_list == [
|
||||
mock.call(
|
||||
[
|
||||
'[app] "ios.codesign.debug" key missing, you must give a certificate name to use.',
|
||||
'[app] "ios.codesign.release" key missing, you must give a certificate name to use.',
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_get_available_packages(self):
|
||||
"""Checks the toolchain `recipes --compact` output is parsed correctly to return recipe list."""
|
||||
target = init_target(self.temp_dir)
|
||||
with patch_target_ios("toolchain") as m_toolchain:
|
||||
m_toolchain.return_value = ("hostpython3 kivy pillow python3 sdl2", None, 0)
|
||||
available_packages = target.get_available_packages()
|
||||
assert m_toolchain.call_args_list == [
|
||||
mock.call("recipes --compact", get_stdout=True)
|
||||
]
|
||||
assert available_packages == [
|
||||
"hostpython3",
|
||||
"kivy",
|
||||
"pillow",
|
||||
"python3",
|
||||
"sdl2",
|
||||
]
|
||||
|
||||
def test_install_platform(self):
|
||||
"""Checks `install_platform()` calls clone commands and sets `ios_dir` and `ios_deploy_dir` attributes."""
|
||||
target = init_target(self.temp_dir)
|
||||
assert target.ios_dir is None
|
||||
assert target.ios_deploy_dir is None
|
||||
with patch_buildozer_cmd() as m_cmd:
|
||||
target.install_platform()
|
||||
assert m_cmd.call_args_list == [
|
||||
mock.call("git clone https://github.com/kivy/kivy-ios", cwd=mock.ANY),
|
||||
mock.call(
|
||||
"git clone --branch 1.10.0 https://github.com/phonegap/ios-deploy",
|
||||
cwd=mock.ANY,
|
||||
),
|
||||
]
|
||||
assert target.ios_dir.endswith(".buildozer/ios/platform/kivy-ios")
|
||||
assert target.ios_deploy_dir.endswith(".buildozer/ios/platform/ios-deploy")
|
||||
|
||||
def test_compile_platform(self):
|
||||
"""Checks the `toolchain build` command is called on the ios requirements."""
|
||||
target = init_target(self.temp_dir)
|
||||
target.ios_deploy_dir = "/ios/deploy/dir"
|
||||
# fmt: off
|
||||
with patch_target_ios("get_available_packages") as m_get_available_packages, \
|
||||
patch_target_ios("toolchain") as m_toolchain, \
|
||||
patch_buildozer_file_exists() as m_file_exists:
|
||||
m_get_available_packages.return_value = ["hostpython3", "python3"]
|
||||
m_file_exists.return_value = True
|
||||
target.compile_platform()
|
||||
# fmt: on
|
||||
assert m_get_available_packages.call_args_list == [mock.call()]
|
||||
assert m_toolchain.call_args_list == [mock.call("build python3")]
|
||||
assert m_file_exists.call_args_list == [
|
||||
mock.call(target.ios_deploy_dir, "ios-deploy")
|
||||
]
|
||||
|
||||
def test_get_package(self):
|
||||
"""Checks default package values and checks it can be overridden."""
|
||||
# default value
|
||||
target = init_target(self.temp_dir)
|
||||
package = target._get_package()
|
||||
assert package == "org.test.myapp"
|
||||
# override
|
||||
target = init_target(
|
||||
self.temp_dir,
|
||||
{"package.domain": "com.github.kivy", "package.name": "buildozer"},
|
||||
)
|
||||
package = target._get_package()
|
||||
assert package == "com.github.kivy.buildozer"
|
||||
|
||||
def test_unlock_keychain_wrong_password(self):
|
||||
"""A `BuildozerCommandException` should be raised on wrong password 3 times."""
|
||||
target = init_target(self.temp_dir)
|
||||
# fmt: off
|
||||
with mock.patch("buildozer.targets.ios.getpass") as m_getpass, \
|
||||
patch_buildozer_cmd() as m_cmd, \
|
||||
pytest.raises(BuildozerCommandException):
|
||||
m_getpass.return_value = "password"
|
||||
# the `security unlock-keychain` command returned an error
|
||||
# hence we'll get prompted to enter the password
|
||||
m_cmd.return_value = (None, None, 123)
|
||||
target._unlock_keychain()
|
||||
# fmt: on
|
||||
assert m_getpass.call_args_list == [
|
||||
mock.call("Password to unlock the default keychain:"),
|
||||
mock.call("Password to unlock the default keychain:"),
|
||||
mock.call("Password to unlock the default keychain:"),
|
||||
]
|
||||
|
||||
def test_build_package_no_signature(self):
|
||||
"""Code signing is currently required to go through final `xcodebuild` steps."""
|
||||
target = init_target(self.temp_dir)
|
||||
target.ios_dir = "/ios/dir"
|
||||
# fmt: off
|
||||
with patch_target_ios("_unlock_keychain") as m_unlock_keychain, \
|
||||
patch_buildozer_error() as m_error, \
|
||||
mock.patch("buildozer.targets.ios.plistlib.readPlist") as m_readplist, \
|
||||
mock.patch("buildozer.targets.ios.plistlib.writePlist") as m_writeplist, \
|
||||
patch_buildozer_cmd() as m_cmd:
|
||||
m_readplist.return_value = {}
|
||||
target.build_package()
|
||||
# fmt: on
|
||||
assert m_unlock_keychain.call_args_list == [mock.call()]
|
||||
assert m_error.call_args_list == [
|
||||
mock.call(
|
||||
"Cannot create the IPA package without signature. "
|
||||
'You must fill the "ios.codesign.debug" token.'
|
||||
)
|
||||
]
|
||||
assert m_readplist.call_args_list == [
|
||||
mock.call("/ios/dir/myapp-ios/myapp-Info.plist")
|
||||
]
|
||||
assert m_writeplist.call_args_list == [
|
||||
mock.call(
|
||||
{
|
||||
"CFBundleIdentifier": "org.test.myapp",
|
||||
"CFBundleShortVersionString": "0.1",
|
||||
"CFBundleVersion": "0.1.None",
|
||||
},
|
||||
"/ios/dir/myapp-ios/myapp-Info.plist",
|
||||
)
|
||||
]
|
||||
assert m_cmd.call_args_list == [mock.call(mock.ANY, cwd=target.ios_dir), mock.call(
|
||||
"xcodebuild -configuration Debug -allowProvisioningUpdates ENABLE_BITCODE=NO "
|
||||
"CODE_SIGNING_ALLOWED=NO clean build",
|
||||
cwd="/ios/dir/myapp-ios",
|
||||
)]
|
66
tests/targets/utils.py
Normal file
66
tests/targets/utils.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
import os
|
||||
import re
|
||||
from unittest import mock
|
||||
|
||||
import buildozer as buildozer_module
|
||||
from buildozer import Buildozer
|
||||
|
||||
|
||||
def patch_buildozer(method):
|
||||
return mock.patch("buildozer.Buildozer.{method}".format(method=method))
|
||||
|
||||
|
||||
def patch_buildozer_cmd():
|
||||
return patch_buildozer("cmd")
|
||||
|
||||
|
||||
def patch_buildozer_checkbin():
|
||||
return patch_buildozer("checkbin")
|
||||
|
||||
|
||||
def patch_buildozer_file_exists():
|
||||
return patch_buildozer("file_exists")
|
||||
|
||||
|
||||
def patch_buildozer_error():
|
||||
return patch_buildozer("error")
|
||||
|
||||
|
||||
def default_specfile_path():
|
||||
return os.path.join(os.path.dirname(buildozer_module.__file__), "default.spec")
|
||||
|
||||
|
||||
def init_buildozer(temp_dir, target, options=None):
|
||||
"""
|
||||
Create a buildozer.spec file in the temporary directory and init the
|
||||
Buildozer instance.
|
||||
|
||||
The optional argument can be used to overwrite the config options in
|
||||
the buildozer.spec file, e.g.:
|
||||
|
||||
init_buildozer({'title': 'Test App'})
|
||||
|
||||
will replace line 4 of the default spec file.
|
||||
"""
|
||||
if options is None:
|
||||
options = {}
|
||||
|
||||
spec_path = os.path.join(temp_dir.name, "buildozer.spec")
|
||||
|
||||
with open(default_specfile_path()) as f:
|
||||
default_spec = f.readlines()
|
||||
|
||||
spec = []
|
||||
for line in default_spec:
|
||||
if line.strip():
|
||||
match = re.search(r"[#\s]?([0-9a-z_.]+)", line)
|
||||
key = match and match.group(1)
|
||||
if key in options:
|
||||
line = "{} = {}\n".format(key, options[key])
|
||||
|
||||
spec.append(line)
|
||||
|
||||
with open(spec_path, "w") as f:
|
||||
f.writelines(spec)
|
||||
|
||||
return Buildozer(filename=spec_path, target=target)
|
243
tests/test_buildozer.py
Normal file
243
tests/test_buildozer.py
Normal file
|
@ -0,0 +1,243 @@
|
|||
import re
|
||||
import os
|
||||
import codecs
|
||||
import unittest
|
||||
import buildozer as buildozer_module
|
||||
from buildozer import Buildozer
|
||||
from six import StringIO
|
||||
import tempfile
|
||||
from unittest import mock
|
||||
|
||||
from buildozer.targets.android import (
|
||||
TargetAndroid, DEFAULT_ANDROID_NDK_VERSION, MSG_P4A_RECOMMENDED_NDK_ERROR
|
||||
)
|
||||
|
||||
|
||||
class TestBuildozer(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Creates a temporary spec file containing the content of the default.spec.
|
||||
"""
|
||||
self.specfile = tempfile.NamedTemporaryFile(suffix='.spec', delete=False)
|
||||
self.specfilename = self.specfile.name
|
||||
default_spec = codecs.open(self.default_specfile_path(), encoding='utf-8')
|
||||
self.specfile.write(default_spec.read().encode('utf-8'))
|
||||
self.specfile.close()
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
Deletes the temporary spec file.
|
||||
"""
|
||||
os.unlink(self.specfile.name)
|
||||
|
||||
@staticmethod
|
||||
def default_specfile_path():
|
||||
return os.path.join(
|
||||
os.path.dirname(buildozer_module.__file__),
|
||||
'default.spec')
|
||||
|
||||
@staticmethod
|
||||
def file_re_sub(filepath, pattern, replace):
|
||||
"""
|
||||
Helper method for inplace file regex editing.
|
||||
"""
|
||||
with open(filepath) as f:
|
||||
file_content = f.read()
|
||||
file_content = re.sub(pattern, replace, file_content)
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(file_content)
|
||||
|
||||
@classmethod
|
||||
def set_specfile_log_level(cls, specfilename, log_level):
|
||||
"""
|
||||
Helper method for setting `log_level` in a given `specfilename`.
|
||||
"""
|
||||
pattern = 'log_level = [0-9]'
|
||||
replace = 'log_level = {}'.format(log_level)
|
||||
cls.file_re_sub(specfilename, pattern, replace)
|
||||
buildozer = Buildozer(specfilename)
|
||||
assert buildozer.log_level == log_level
|
||||
|
||||
def test_buildozer_base(self):
|
||||
"""
|
||||
Basic test making sure the Buildozer object can be instantiated.
|
||||
"""
|
||||
buildozer = Buildozer()
|
||||
assert buildozer.specfilename == 'buildozer.spec'
|
||||
# spec file doesn't have to exist
|
||||
assert os.path.exists(buildozer.specfilename) is False
|
||||
|
||||
def test_buildozer_read_spec(self):
|
||||
"""
|
||||
Initializes Buildozer object from existing spec file.
|
||||
"""
|
||||
buildozer = Buildozer(filename=self.default_specfile_path())
|
||||
assert os.path.exists(buildozer.specfilename) is True
|
||||
|
||||
def test_buildozer_help(self):
|
||||
"""
|
||||
Makes sure the help gets display with no error, refs:
|
||||
https://github.com/kivy/buildozer/issues/813
|
||||
"""
|
||||
buildozer = Buildozer()
|
||||
with mock.patch('sys.stdout', new_callable=StringIO) as mock_stdout:
|
||||
buildozer.usage()
|
||||
assert 'Usage:' in mock_stdout.getvalue()
|
||||
|
||||
def test_log_get_set(self):
|
||||
"""
|
||||
Tests reading and setting log level from spec file.
|
||||
"""
|
||||
# the default log level value is known
|
||||
buildozer = Buildozer('does_not_exist.spec')
|
||||
assert buildozer.log_level == 2
|
||||
# sets log level to 1 on the spec file
|
||||
self.set_specfile_log_level(self.specfile.name, 1)
|
||||
buildozer = Buildozer(self.specfile.name)
|
||||
assert buildozer.log_level == 1
|
||||
|
||||
def test_log_print(self):
|
||||
"""
|
||||
Checks logger prints different info depending on log level.
|
||||
"""
|
||||
# sets log level to 1 in the spec file
|
||||
self.set_specfile_log_level(self.specfile.name, 1)
|
||||
buildozer = Buildozer(self.specfile.name)
|
||||
assert buildozer.log_level == 1
|
||||
# at this level, debug messages shouldn't not be printed
|
||||
with mock.patch('sys.stdout', new_callable=StringIO) as mock_stdout:
|
||||
buildozer.debug('debug message')
|
||||
buildozer.info('info message')
|
||||
buildozer.error('error message')
|
||||
# using `in` keyword rather than `==` because of bash color prefix/suffix
|
||||
assert 'debug message' not in mock_stdout.getvalue()
|
||||
assert 'info message' in mock_stdout.getvalue()
|
||||
assert 'error message' in mock_stdout.getvalue()
|
||||
# sets log level to 2 in the spec file
|
||||
self.set_specfile_log_level(self.specfile.name, 2)
|
||||
buildozer = Buildozer(self.specfile.name)
|
||||
assert buildozer.log_level == 2
|
||||
# at this level all message types should be printed
|
||||
with mock.patch('sys.stdout', new_callable=StringIO) as mock_stdout:
|
||||
buildozer.debug('debug message')
|
||||
buildozer.info('info message')
|
||||
buildozer.error('error message')
|
||||
assert 'debug message' in mock_stdout.getvalue()
|
||||
assert 'info message' in mock_stdout.getvalue()
|
||||
assert 'error message' in mock_stdout.getvalue()
|
||||
|
||||
def test_run_command_unknown(self):
|
||||
"""
|
||||
Makes sure the unknown command/target is handled gracefully, refs:
|
||||
https://github.com/kivy/buildozer/issues/812
|
||||
"""
|
||||
buildozer = Buildozer()
|
||||
command = 'foobar'
|
||||
args = [command, 'debug']
|
||||
with mock.patch('sys.stdout', new_callable=StringIO) as mock_stdout:
|
||||
with self.assertRaises(SystemExit):
|
||||
buildozer.run_command(args)
|
||||
assert mock_stdout.getvalue() == 'Unknown command/target {}\n'.format(command)
|
||||
|
||||
def test_android_ant_path(self):
|
||||
"""
|
||||
Verify that the selected ANT path is being used from the spec file
|
||||
"""
|
||||
my_ant_path = '/my/ant/path'
|
||||
|
||||
buildozer = Buildozer(filename=self.default_specfile_path(), target='android')
|
||||
buildozer.config.set('app', 'android.ant_path', my_ant_path) # Set ANT path
|
||||
target = TargetAndroid(buildozer=buildozer)
|
||||
|
||||
# Mock first run
|
||||
with mock.patch('buildozer.Buildozer.download') as download, \
|
||||
mock.patch('buildozer.Buildozer.file_extract') as m_file_extract, \
|
||||
mock.patch('os.makedirs'):
|
||||
ant_path = target._install_apache_ant()
|
||||
assert m_file_extract.call_args_list == [mock.call(mock.ANY, cwd='/my/ant/path')]
|
||||
assert ant_path == my_ant_path
|
||||
assert download.call_args_list == [
|
||||
mock.call("https://archive.apache.org/dist/ant/binaries/", mock.ANY, cwd=my_ant_path)]
|
||||
# Mock ant already installed
|
||||
with mock.patch.object(Buildozer, 'file_exists', return_value=True):
|
||||
ant_path = target._install_apache_ant()
|
||||
assert ant_path == my_ant_path
|
||||
|
||||
def test_cmd_unicode_decode(self):
|
||||
"""
|
||||
Verifies Buildozer.cmd() can properly handle non-unicode outputs.
|
||||
refs: https://github.com/kivy/buildozer/issues/857
|
||||
"""
|
||||
buildozer = Buildozer()
|
||||
command = 'uname'
|
||||
kwargs = {
|
||||
'show_output': True,
|
||||
'get_stdout': True,
|
||||
'get_stderr': True,
|
||||
}
|
||||
command_output = b'\x80 cannot decode \x80'
|
||||
# showing the point that we can't decode it
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
command_output.decode('utf-8')
|
||||
with mock.patch('buildozer.Popen') as m_popen, \
|
||||
mock.patch('buildozer.select') as m_select, \
|
||||
mock.patch('buildozer.stdout') as m_stdout:
|
||||
m_select.select().__getitem__.return_value = [0]
|
||||
# makes sure fcntl.fcntl() gets what it expects so it doesn't crash
|
||||
m_popen().stdout.fileno.return_value = 0
|
||||
m_popen().stderr.fileno.return_value = 2
|
||||
# Buildozer.cmd() is iterating through command output "chunk" until
|
||||
# one chunk is None
|
||||
m_popen().stdout.read.side_effect = [command_output, None]
|
||||
m_popen().returncode = 0
|
||||
stdout, stderr, returncode = buildozer.cmd(command, **kwargs)
|
||||
# when get_stdout is True, the command output also gets returned
|
||||
assert stdout == command_output.decode('utf-8', 'ignore')
|
||||
assert stderr is None
|
||||
assert returncode == 0
|
||||
# Python2 and Python3 have different approaches for decoding the output
|
||||
assert m_stdout.write.call_args_list == [
|
||||
mock.call(command_output.decode('utf-8', 'replace'))
|
||||
]
|
||||
|
||||
def test_p4a_recommended_ndk_version_default_value(self):
|
||||
self.set_specfile_log_level(self.specfile.name, 1)
|
||||
buildozer = Buildozer(self.specfile.name, 'android')
|
||||
assert buildozer.target.p4a_recommended_ndk_version is None
|
||||
|
||||
def test_p4a_recommended_android_ndk_error(self):
|
||||
self.set_specfile_log_level(self.specfile.name, 1)
|
||||
buildozer = Buildozer(self.specfile.name, 'android')
|
||||
|
||||
with mock.patch('sys.stdout', new_callable=StringIO) as mock_stdout:
|
||||
ndk_version = buildozer.target.p4a_recommended_android_ndk
|
||||
assert MSG_P4A_RECOMMENDED_NDK_ERROR in mock_stdout.getvalue()
|
||||
# and we should get the default android's ndk version of buildozer
|
||||
assert ndk_version == DEFAULT_ANDROID_NDK_VERSION
|
||||
|
||||
@mock.patch('buildozer.targets.android.os.path.isfile')
|
||||
@mock.patch('buildozer.targets.android.os.path.exists')
|
||||
@mock.patch('buildozer.targets.android.open', create=True)
|
||||
def test_p4a_recommended_android_ndk_found(
|
||||
self, mock_open, mock_exists, mock_isfile
|
||||
):
|
||||
self.set_specfile_log_level(self.specfile.name, 1)
|
||||
buildozer = Buildozer(self.specfile.name, 'android')
|
||||
expected_ndk = '19b'
|
||||
recommended_line = 'RECOMMENDED_NDK_VERSION = {expected_ndk}\n'.format(
|
||||
expected_ndk=expected_ndk)
|
||||
mock_open.return_value = StringIO(recommended_line)
|
||||
ndk_version = buildozer.target.p4a_recommended_android_ndk
|
||||
p4a_dir = os.path.join(
|
||||
buildozer.platform_dir, buildozer.target.p4a_directory_name)
|
||||
mock_open.assert_called_once_with(
|
||||
os.path.join(p4a_dir, "pythonforandroid", "recommendations.py"), 'r'
|
||||
)
|
||||
assert ndk_version == expected_ndk
|
||||
|
||||
# now test that we only read one time p4a file, so we call again to
|
||||
# `p4a_recommended_android_ndk` and we should still have one call to `open`
|
||||
# file, the performed above
|
||||
ndk_version = buildozer.target.p4a_recommended_android_ndk
|
||||
mock_open.assert_called_once()
|
32
tox.ini
Normal file
32
tox.ini
Normal file
|
@ -0,0 +1,32 @@
|
|||
[tox]
|
||||
envlist = pep8,py3
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
pytest
|
||||
py3: coverage
|
||||
commands = pytest tests/
|
||||
|
||||
[testenv:py3]
|
||||
# for py3 env we will get code coverage
|
||||
commands =
|
||||
coverage run --branch --source=buildozer -m pytest {posargs:tests/}
|
||||
coverage report -m
|
||||
|
||||
[testenv:pep8]
|
||||
deps = flake8
|
||||
commands = flake8 buildozer/ tests/
|
||||
|
||||
[flake8]
|
||||
ignore =
|
||||
E121, # continuation line under-indented for hanging indent
|
||||
E122, # continuation line missing indentation or outdented
|
||||
E126, # continuation line over-indented for hanging indent
|
||||
E127, # continuation line over-indented for visual indent
|
||||
E128, # continuation line under-indented for visual indent
|
||||
E131, # continuation line unaligned for hanging indent
|
||||
E402, # module level import not at top of file
|
||||
E501, # line too long
|
||||
E722, # do not use bare 'except'
|
||||
W503, # line break before binary operator
|
||||
W504 # line break after binary operator
|
Loading…
Reference in a new issue