Merge branch 'master' into 1266-slippy
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,6 +16,7 @@
|
||||
/test/build
|
||||
/test/node_modules
|
||||
/test/fixtures/*/*_actual.*
|
||||
/test/fixtures/database/*.db
|
||||
/include/mbgl/shader/shaders.hpp
|
||||
/src/shader/shaders_gl.cpp
|
||||
/src/shader/shaders_gles2.cpp
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -12,7 +12,7 @@
|
||||
|
||||
[submodule "test/ios/KIF"]
|
||||
path = test/ios/KIF
|
||||
url = https://github.com/mapbox/KIF.git
|
||||
url = https://github.com/kif-framework/KIF.git
|
||||
|
||||
[submodule "platform/ios/vendor/SMCalloutView"]
|
||||
path = platform/ios/vendor/SMCalloutView
|
||||
|
||||
2
.mason
2
.mason
Submodule .mason updated: 03869fd11e...c43967404c
146
.travis.yml
146
.travis.yml
@@ -1,95 +1,99 @@
|
||||
language: cpp
|
||||
language: android
|
||||
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: linux
|
||||
include:
|
||||
- os: linux
|
||||
env: CONFIG=release MASON_PLATFORM=android MASON_ANDROID_ABI=arm-v7 TESTMUNK=yes
|
||||
compiler: clang
|
||||
env: FLAVOR=linux CXX=g++-4.8 BUILDTYPE=Release
|
||||
addons:
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'gdb', 'g++-4.8', 'gcc-4.8', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ]
|
||||
- os: linux
|
||||
env: CONFIG=debug MASON_PLATFORM=android MASON_ANDROID_ABI=arm-v7 TESTMUNK=no
|
||||
compiler: clang
|
||||
env: FLAVOR=linux CXX=clang++ BUILDTYPE=Debug
|
||||
addons:
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'gdb', 'libgcc-4.8-dev', 'libstdc++-4.8-dev', 'libstdc++6', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ]
|
||||
- os: linux
|
||||
env: CONFIG=release MASON_PLATFORM=android MASON_ANDROID_ABI=arm-v5 TESTMUNK=no
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: CONFIG=release MASON_PLATFORM=android MASON_ANDROID_ABI=arm-v8 TESTMUNK=no
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: CONFIG=release MASON_PLATFORM=android MASON_ANDROID_ABI=x86 TESTMUNK=no
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: CONFIG=release MASON_PLATFORM=android MASON_ANDROID_ABI=mips TESTMUNK=no
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: CONFIG=release MASON_PLATFORM=android MASON_ANDROID_ABI=mips-64 TESTMUNK=no
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: BUILDTYPE=Release JOBS=16
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: BUILDTYPE=Debug JOBS=16
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: BUILDTYPE=Release JOBS=8
|
||||
compiler: gcc
|
||||
env: FLAVOR=linux CXX=clang++ BUILDTYPE=Release
|
||||
addons:
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'gdb', 'libgcc-4.8-dev', 'libstdc++-4.8-dev', 'libstdc++6', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ]
|
||||
- os: osx
|
||||
env: BUILDTYPE=Debug JOBS=8 MASON_PLATFORM=osx
|
||||
compiler: clang
|
||||
env: FLAVOR=osx BUILDTYPE=Debug
|
||||
- os: osx
|
||||
env: BUILDTYPE=Release JOBS=8 MASON_PLATFORM=ios
|
||||
compiler: clang
|
||||
env: FLAVOR=ios BUILDTYPE=Release
|
||||
- os: linux
|
||||
env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Release
|
||||
android:
|
||||
components: [ 'build-tools-22.0.0', 'android-22', 'extra' ]
|
||||
addons:
|
||||
apt:
|
||||
packages: [ 'lib32stdc++6' ]
|
||||
- os: linux
|
||||
env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Debug
|
||||
android:
|
||||
components: [ 'build-tools-22.0.0', 'android-22', 'extra' ]
|
||||
addons:
|
||||
apt:
|
||||
packages: [ 'lib32stdc++6' ]
|
||||
- os: linux
|
||||
env: FLAVOR=android ANDROID_ABI=arm-v8 BUILDTYPE=Release
|
||||
android:
|
||||
components: [ 'build-tools-22.0.0', 'android-22', 'extra' ]
|
||||
addons:
|
||||
apt:
|
||||
packages: [ 'lib32stdc++6' ]
|
||||
- os: linux
|
||||
env: FLAVOR=android ANDROID_ABI=x86 BUILDTYPE=Release
|
||||
android:
|
||||
components: [ 'build-tools-22.0.0', 'android-22', 'extra' ]
|
||||
addons:
|
||||
apt:
|
||||
packages: [ 'lib32stdc++6' ]
|
||||
- os: linux
|
||||
env: FLAVOR=android ANDROID_ABI=mips BUILDTYPE=Release
|
||||
android:
|
||||
components: [ 'build-tools-22.0.0', 'android-22', 'extra' ]
|
||||
addons:
|
||||
apt:
|
||||
packages: [ 'lib32stdc++6' ]
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "MZHblLZXG/jWf2w0ZFlxCLDwx2qtGgRDODQyg1BR7JIuMz6AtWv8XR/sUczWLbiABCL0a/NzJF1g4v2pI7X69IntcjOdIABBgTh7++6+1TJ0Kp8viEltb55nQG3lHy/R6fOaI7Pj9tuCX0PCRtGA5C/fGnodLGEjy3RVOJ09ln0="
|
||||
- secure: "KaSQbhgjtV7ZCkesHmvrNsbQVjk5SPfGKB1VkWenRGYhLF45HpSRNwSxMQddZ566Pg7qIFgF1iWl/B0QW3B6AWL5WmzQ5AOJgwS876pNIc/UT7ubMPtgAtjpvw1bQvQP3B8MrB+3OE5c6tD+a3LhR9krV//dOsfErR5Yy+3Mbkc="
|
||||
- ANDROID_BUILD_INSTANCE_PROFILE: arn:aws:iam::234858372212:instance-profile/android-gl-build/travis/instance-profile/travis-mapbox-gl-native-AndroidInstanceProfile-13EA815DD8IQ9
|
||||
- secure: "RiBIBfVhhaMjU5ksuwJO3shdvG9FpinBjdSv4co9jg9171SR8edNriedHjVKSIeBhSGNmZmX+twS3dJS/By6tl/LKh9sTynA+ZAYYljkE7jn881B/gMrlYvdAA6og5KvkhV1/0iJWlhuZrMTkhpDR200iLgg3EWBhWjltzmDW/I="
|
||||
- secure: "CHBiUM60TolDbQnn+4IRA/tvOKwKs3g9EDvv8YHSJMg3FuHmjKQkprBasvxf3hnTXg4WLZEubmeDcyJ6RRzPP5mMSr/hksYl0pSjj/6TUecE5fHPVVeN7txVqkpOBf9i45Y+iBUQMjBb1NnDK3pHXxpnAs1Q/pe7vReErj4GF1U="
|
||||
- LD_LIBRARY_PATH: '/usr/local/lib'
|
||||
- TERM: dumb
|
||||
# begin iOS code signing
|
||||
- secure: "I6Iu75X1E+js5tzijtKi1EGtIuBcA4/25nDYe0svV4HAtujY71ZJZ4eB6355CKhFXpLXrF3i7eKVX3v+zWS0QROPEWacgsqsvNg+Ba9cnznW/faUSOYekCfhzWd/6reYDM7KzKAQwSUHLk9JIWK/kkmi4r+vVJK7h+tjPllK5YA="
|
||||
- IOS_APP_NAME="Mapbox GL"
|
||||
- 'IOS_DEVELOPER_NAME="iPhone Distribution: Mapbox, Inc."'
|
||||
- IOS_PROFILE_NAME="ios-in-house"
|
||||
- secure: "nQqSM8rd7OHtV4MqmNqVnkrVHqxKqQsaWRYk4/nPdhbeVWtTtkk0df711LrF1TUtbEPEewHxYUvTZ/UXmwJNeoKdzTHavI8hnatRkgjyxGERPn1il1Otelht9I+LQQHf+plrpRjVWBrNIW0Zox1B3cqn6d3NglpbXrEQ2EjYGNA="
|
||||
# end iOS code signing
|
||||
|
||||
before_install:
|
||||
- if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then sudo service mysql stop; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then sudo service postgresql stop; fi
|
||||
- source ./scripts/local_mason.sh
|
||||
- source ./scripts/travis_helper.sh
|
||||
- source ./scripts/install_node.sh
|
||||
- source ./scripts/flags.sh
|
||||
- ./scripts/travis_before_install.sh
|
||||
- if [[ ${TRAVIS_OS_NAME} == "linux" && ${MASON_PLATFORM} != "android" ]]; then export LD_LIBRARY_PATH=`mason prefix mesa 10.4.3`/lib; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == "linux" && ${MASON_PLATFORM} != "android" ]]; then glxinfo; fi
|
||||
- TERM: dumb
|
||||
# AWS
|
||||
- secure: "MZHblLZXG/jWf2w0ZFlxCLDwx2qtGgRDODQyg1BR7JIuMz6AtWv8XR/sUczWLbiABCL0a/NzJF1g4v2pI7X69IntcjOdIABBgTh7++6+1TJ0Kp8viEltb55nQG3lHy/R6fOaI7Pj9tuCX0PCRtGA5C/fGnodLGEjy3RVOJ09ln0="
|
||||
- secure: "KaSQbhgjtV7ZCkesHmvrNsbQVjk5SPfGKB1VkWenRGYhLF45HpSRNwSxMQddZ566Pg7qIFgF1iWl/B0QW3B6AWL5WmzQ5AOJgwS876pNIc/UT7ubMPtgAtjpvw1bQvQP3B8MrB+3OE5c6tD+a3LhR9krV//dOsfErR5Yy+3Mbkc="
|
||||
# Access Token
|
||||
- secure: "RiBIBfVhhaMjU5ksuwJO3shdvG9FpinBjdSv4co9jg9171SR8edNriedHjVKSIeBhSGNmZmX+twS3dJS/By6tl/LKh9sTynA+ZAYYljkE7jn881B/gMrlYvdAA6og5KvkhV1/0iJWlhuZrMTkhpDR200iLgg3EWBhWjltzmDW/I="
|
||||
# Testmunk
|
||||
- secure: "CHBiUM60TolDbQnn+4IRA/tvOKwKs3g9EDvv8YHSJMg3FuHmjKQkprBasvxf3hnTXg4WLZEubmeDcyJ6RRzPP5mMSr/hksYl0pSjj/6TUecE5fHPVVeN7txVqkpOBf9i45Y+iBUQMjBb1NnDK3pHXxpnAs1Q/pe7vReErj4GF1U="
|
||||
# iOS code signing
|
||||
- secure: "I6Iu75X1E+js5tzijtKi1EGtIuBcA4/25nDYe0svV4HAtujY71ZJZ4eB6355CKhFXpLXrF3i7eKVX3v+zWS0QROPEWacgsqsvNg+Ba9cnznW/faUSOYekCfhzWd/6reYDM7KzKAQwSUHLk9JIWK/kkmi4r+vVJK7h+tjPllK5YA="
|
||||
- IOS_APP_NAME="Mapbox GL"
|
||||
- 'IOS_DEVELOPER_NAME="iPhone Distribution: Mapbox, Inc."'
|
||||
- IOS_PROFILE_NAME="ios-in-house"
|
||||
- secure: "nQqSM8rd7OHtV4MqmNqVnkrVHqxKqQsaWRYk4/nPdhbeVWtTtkk0df711LrF1TUtbEPEewHxYUvTZ/UXmwJNeoKdzTHavI8hnatRkgjyxGERPn1il1Otelht9I+LQQHf+plrpRjVWBrNIW0Zox1B3cqn6d3NglpbXrEQ2EjYGNA="
|
||||
- KIF_SCREENSHOTS="${TRAVIS_BUILD_DIR}/screenshots"
|
||||
|
||||
install:
|
||||
- ulimit -c
|
||||
|
||||
before_script:
|
||||
# Set the core file limit to unlimited so a core file is generated upon crash
|
||||
- ulimit -c unlimited -S
|
||||
# begin iOS code signing
|
||||
- openssl aes-256-cbc -k "$IOS_ENCRYPTION_SECRET" -in scripts/ios_travis/ios-in-house.mobileprovision.enc -d -a -out scripts/ios_travis/ios-in-house.mobileprovision
|
||||
- openssl aes-256-cbc -k "$IOS_ENCRYPTION_SECRET" -in scripts/ios_travis/ios-dist.cer.enc -d -a -out scripts/ios_travis/ios-dist.cer
|
||||
- openssl aes-256-cbc -k "$IOS_ENCRYPTION_SECRET" -in scripts/ios_travis/ios-dist.p12.enc -d -a -out scripts/ios_travis/ios-dist.p12
|
||||
- ./scripts/ios_travis/add-key.sh
|
||||
# end iOS code signing
|
||||
- ./scripts/${FLAVOR}/install.sh
|
||||
|
||||
script:
|
||||
- ./scripts/travis_script.sh
|
||||
- ./scripts/${FLAVOR}/run.sh
|
||||
|
||||
after_script:
|
||||
- ./scripts/ios_travis/remove-key.sh
|
||||
after_failure:
|
||||
- "[ -f scripts/${FLAVOR}/run.sh ] && scripts/${FLAVOR}/run.sh"
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
secure: HHQYr7sF8M1SzoWSqgKVYtwAgGdLLCyTMsQjFhEEQNYO92ZwURE5s03qWTGH5k8+4Yqn26yrXt3NztLC4JIOpcGervN2mSZyq4dZgFTcWEd61igw0qwSenlwvFfbE1ASK/KYCzfyn9MIfHN+ovwLoRxXZkPwinKDvl3DXjBaFNg=
|
||||
|
||||
git:
|
||||
submodules: false
|
||||
|
||||
148
Makefile
148
Makefile
@@ -4,10 +4,16 @@ PREFIX ?= /usr/local
|
||||
ANDROID_ABI ?= arm-v7
|
||||
|
||||
ifeq ($(shell uname -s), Darwin)
|
||||
HOST ?= osx
|
||||
HOST = osx
|
||||
HEADLESS = cgl
|
||||
JOBS ?= $(shell sysctl -n hw.ncpu)
|
||||
endif
|
||||
HOST ?= linux
|
||||
|
||||
ifeq ($(shell uname -s), Linux)
|
||||
HOST = linux
|
||||
JOBS ?= $(shell grep --count processor /proc/cpuinfo)
|
||||
endif
|
||||
|
||||
JOBS ?= 1
|
||||
|
||||
all: mbgl
|
||||
@@ -25,52 +31,53 @@ config/%.gypi: configure
|
||||
styles/styles:
|
||||
git submodule update --init styles
|
||||
|
||||
ifeq ($(shell uname -s), Darwin)
|
||||
SMCalloutView:
|
||||
git submodule update --init platform/ios/vendor/SMCalloutView
|
||||
else
|
||||
SMCalloutView:
|
||||
endif
|
||||
|
||||
KIF:
|
||||
git submodule update --init test/ios/KIF
|
||||
|
||||
|
||||
#### Build files ###############################################################
|
||||
|
||||
.PRECIOUS: Makefile/project
|
||||
Makefile/project: config/$(HOST).gypi styles/styles SMCalloutView
|
||||
deps/run_gyp gyp/$(HOST).gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f make
|
||||
|
||||
.PRECIOUS: Xcode/project
|
||||
Xcode/project: config/$(HOST).gypi styles/styles SMCalloutView
|
||||
deps/run_gyp gyp/$(HOST).gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f xcode
|
||||
|
||||
|
||||
#### Library builds ############################################################
|
||||
|
||||
.PRECIOUS: Makefile/mbgl
|
||||
Makefile/mbgl: config/$(HOST).gypi styles/styles SMCalloutView
|
||||
deps/run_gyp mbgl.gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f make
|
||||
|
||||
mbgl: Makefile/mbgl
|
||||
mbgl: Makefile/project
|
||||
$(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) everything
|
||||
|
||||
standalone: Makefile/mbgl
|
||||
standalone: Makefile/project
|
||||
LINK=`pwd`/gyp/link.py $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) standalone
|
||||
|
||||
install: Makefile/mbgl
|
||||
install: Makefile/project
|
||||
LINK=`pwd`/gyp/link.py $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) install
|
||||
|
||||
.PRECIOUS: Xcode/mbgl
|
||||
Xcode/mbgl: config/$(HOST).gypi styles/styles SMCalloutView
|
||||
deps/run_gyp mbgl.gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f xcode
|
||||
|
||||
##### Test builds ##############################################################
|
||||
|
||||
.PRECIOUS: Makefile/test
|
||||
Makefile/test: test/test.gyp config/$(HOST).gypi styles/styles SMCalloutView
|
||||
deps/run_gyp test/test.gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f make
|
||||
|
||||
.PHONY: test
|
||||
test: Makefile/test
|
||||
test: Makefile/project
|
||||
$(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) test
|
||||
|
||||
test-%: test
|
||||
./scripts/run_tests.sh "build/$(HOST)/$(BUILDTYPE)/test" --gtest_filter=$*
|
||||
|
||||
|
||||
.PRECIOUS: Xcode/test
|
||||
Xcode/test: test/test.gyp config/osx.gypi styles/styles SMCalloutView
|
||||
deps/run_gyp test/test.gyp $(CONFIG_osx) $(LIBS_osx) --generator-output=./build/osx -f xcode
|
||||
|
||||
.PHONY: lproj lbuild run-xlinux
|
||||
xtest-proj: Xcode/test
|
||||
open ./build/osx/test/test.xcodeproj
|
||||
|
||||
xtest: Xcode/test
|
||||
xcodebuild -project ./build/osx/test/test.xcodeproj -configuration $(BUILDTYPE) -target test -jobs $(JOBS)
|
||||
.PHONY: xtest
|
||||
xtest: XCPRETTY := $(shell ./scripts/xcpretty.sh)
|
||||
xtest: Xcode/project
|
||||
xcodebuild -project ./build/osx/gyp/osx.xcodeproj -configuration $(BUILDTYPE) -target test -jobs $(JOBS) $(XCPRETTY)
|
||||
|
||||
xtest-%: xtest
|
||||
./scripts/run_tests.sh "build/osx/Build/Products/$(BUILDTYPE)/test" --gtest_filter=$*
|
||||
@@ -78,31 +85,23 @@ xtest-%: xtest
|
||||
|
||||
#### Mac OS X application builds ###############################################
|
||||
|
||||
.PRECIOUS: Makefile/osx
|
||||
Makefile/osx: macosx/mapboxgl-app.gyp config/osx.gypi styles/styles
|
||||
deps/run_gyp macosx/mapboxgl-app.gyp $(CONFIG_osx) $(LIBS_osx) --generator-output=./build/osx -f make
|
||||
|
||||
.PHONY: osx run-osx
|
||||
osx: Makefile/osx
|
||||
osx: Makefile/project
|
||||
$(MAKE) -C build/osx BUILDTYPE=$(BUILDTYPE) osxapp
|
||||
|
||||
run-osx: osx
|
||||
"build/osx/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL"
|
||||
|
||||
|
||||
.PRECIOUS: Xcode/osx
|
||||
Xcode/osx: macosx/mapboxgl-app.gyp config/osx.gypi styles/styles
|
||||
deps/run_gyp macosx/mapboxgl-app.gyp $(CONFIG_osx) $(LIBS_osx) --generator-output=./build/osx -f xcode
|
||||
|
||||
.PHONY: xosx-proj xosx run-xosx
|
||||
xosx-proj: Xcode/osx
|
||||
open ./build/osx/macosx/mapboxgl-app.xcodeproj
|
||||
xosx-proj: Xcode/project
|
||||
open ./build/osx/gyp/osx.xcodeproj
|
||||
|
||||
xosx: Xcode/osx
|
||||
xcodebuild -project ./build/osx/macosx/mapboxgl-app.xcodeproj -configuration $(BUILDTYPE) -target osxapp -jobs $(JOBS)
|
||||
xosx: XCPRETTY := $(shell ./scripts/xcpretty.sh)
|
||||
xosx: Xcode/project
|
||||
xcodebuild -project ./build/osx/gyp/osx.xcodeproj -configuration $(BUILDTYPE) -target osxapp -jobs $(JOBS) $(XCPRETTY)
|
||||
|
||||
run-xosx: xosx
|
||||
"build/osx/Build/Products/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL"
|
||||
"gyp/build/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL"
|
||||
|
||||
# Legacy name
|
||||
xproj: xosx-proj
|
||||
@@ -112,21 +111,29 @@ xproj: xosx-proj
|
||||
#### iOS application builds ####################################################
|
||||
|
||||
.PRECIOUS: Xcode/ios
|
||||
Xcode/ios: ios/app/mapboxgl-app.gyp config/ios.gypi styles/styles SMCalloutView
|
||||
deps/run_gyp ios/app/mapboxgl-app.gyp $(CONFIG_ios) $(LIBS_ios) --generator-output=./build/ios -f xcode
|
||||
Xcode/ios: gyp/ios.gyp config/ios.gypi styles/styles SMCalloutView
|
||||
deps/run_gyp gyp/ios.gyp $(CONFIG_ios) $(LIBS_ios) --generator-output=./build/ios -f xcode
|
||||
|
||||
.PHONY: ios-proj ios isim ipackage
|
||||
ios-proj: Xcode/ios
|
||||
open ./build/ios/ios/app/mapboxgl-app.xcodeproj
|
||||
open ./build/ios/gyp/ios.xcodeproj
|
||||
|
||||
ios: XCPRETTY := $(shell ./scripts/xcpretty.sh)
|
||||
ios: Xcode/ios
|
||||
xcodebuild -sdk iphoneos ARCHS="arm64 armv7 armv7s" PROVISIONING_PROFILE="2b532944-bf3d-4bf4-aa6c-a81676984ae8" -project ./build/ios/ios/app/mapboxgl-app.xcodeproj -configuration Release -target iosapp -jobs $(JOBS)
|
||||
xcodebuild -sdk iphoneos ARCHS="arm64 armv7 armv7s" PROVISIONING_PROFILE="2b532944-bf3d-4bf4-aa6c-a81676984ae8" -project ./build/ios/gyp/ios.xcodeproj -configuration Release -target iosapp -jobs $(JOBS) $(XCPRETTY)
|
||||
|
||||
isim: XCPRETTY := $(shell ./scripts/xcpretty.sh)
|
||||
isim: Xcode/ios
|
||||
xcodebuild -sdk iphonesimulator ARCHS="x86_64 i386" -project ./build/ios/ios/app/mapboxgl-app.xcodeproj -configuration Debug -target iosapp -jobs $(JOBS)
|
||||
xcodebuild -sdk iphonesimulator ARCHS="x86_64 i386" -project ./build/ios/gyp/ios.xcodeproj -configuration Debug -target iosapp -jobs $(JOBS) $(XCPRETTY)
|
||||
|
||||
ipackage: clean Xcode/ios
|
||||
./scripts/package_ios.sh
|
||||
./scripts/ios/package.sh
|
||||
|
||||
ipackage-sim: clean Xcode/ios
|
||||
./scripts/ios/package.sh sim
|
||||
|
||||
itest: ipackage-sim KIF
|
||||
./scripts/ios/test.sh
|
||||
|
||||
# Legacy name
|
||||
iproj: ios-proj
|
||||
@@ -134,34 +141,20 @@ iproj: ios-proj
|
||||
|
||||
#### Linux application builds ##################################################
|
||||
|
||||
.PRECIOUS: Makefile/linux
|
||||
Makefile/linux: linux/mapboxgl-app.gyp config/$(HOST).gypi styles/styles
|
||||
deps/run_gyp linux/mapboxgl-app.gyp $(CONFIG_$(HOST)) $(LIBS_linux) --generator-output=./build/$(HOST) -f make
|
||||
|
||||
.PHONY: linux run-linux
|
||||
linux: Makefile/linux
|
||||
linux: Makefile/project
|
||||
$(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) linuxapp
|
||||
|
||||
run-linux: linux
|
||||
(cd build/$(HOST)/$(BUILDTYPE) && ./mapbox-gl)
|
||||
|
||||
|
||||
.PRECIOUS: Xcode/linux
|
||||
Xcode/linux: linux/mapboxgl-app.gyp config/osx.gypi styles/styles
|
||||
deps/run_gyp linux/mapboxgl-app.gyp $(CONFIG_osx) $(LIBS_linux) --generator-output=./build/osx -f xcode
|
||||
|
||||
.PHONY: lproj lbuild run-xlinux
|
||||
xlinux-proj: Xcode/linux
|
||||
open ./build/osx/linux/mapboxgl-app.xcodeproj
|
||||
|
||||
xlinux: Xcode/linux
|
||||
xcodebuild -project ./build/osx/linux/mapboxgl-app.xcodeproj -configuration $(BUILDTYPE) -target linuxapp
|
||||
.PHONY: xlinux run-xlinux
|
||||
xlinux: XCPRETTY := $(shell ./scripts/xcpretty.sh)
|
||||
xlinux: Xcode/project
|
||||
xcodebuild -project ./build/osx/gyp/osx.xcodeproj -configuration $(BUILDTYPE) -target linuxapp -jobs $(JOBS) $(XCPRETTY)
|
||||
|
||||
run-xlinux: xlinux
|
||||
"build/osx/Build/Products/$(BUILDTYPE)/mapbox-gl"
|
||||
|
||||
# Legacy name
|
||||
lproj: xlinux-proj
|
||||
"gyp/build/$(BUILDTYPE)/mapbox-gl"
|
||||
|
||||
|
||||
#### Android libaries #########################################################
|
||||
@@ -193,22 +186,15 @@ android-deploy: $(ANDROID_ABIS)
|
||||
|
||||
android-project: android-lib
|
||||
|
||||
|
||||
##### Render builds ############################################################
|
||||
|
||||
.PRECIOUS: Makefile/render
|
||||
Makefile/render: bin/render.gyp config/$(HOST).gypi
|
||||
deps/run_gyp bin/render.gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f make
|
||||
|
||||
render: Makefile/render
|
||||
render: Makefile/project
|
||||
$(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) mbgl-render
|
||||
|
||||
.PRECIOUS: Xcode/render
|
||||
Xcode/render: bin/render.gyp config/osx.gypi styles/styles
|
||||
deps/run_gyp bin/render.gyp $(CONFIG_osx) $(LIBS_osx) --generator-output=./build/osx -f xcode
|
||||
|
||||
.PHONY: xrender-proj
|
||||
xrender-proj: Xcode/render
|
||||
open ./build/osx/bin/render.xcodeproj
|
||||
.PHONY: xrender run-xrender
|
||||
xrender: Xcode/project
|
||||
xcodebuild -project ./build/osx/gyp/osx.xcodeproj -configuration $(BUILDTYPE) -target mbgl-render -jobs $(JOBS)
|
||||
|
||||
|
||||
##### Maintenace operations ####################################################
|
||||
|
||||
11
README.md
11
README.md
@@ -49,7 +49,7 @@ Target OS X: 10.9+
|
||||
If you merely want to install the library for iOS and try it out as an Objective-C consumer:
|
||||
|
||||
0. Use [Homebrew](http://brew.sh/) to install Boost headers: `brew install boost`.
|
||||
1. Run `./scripts/package_ios.sh`. The packaging script will produce the statically-linked `libMapboxGL.a`, `MapboxGL.bundle` for resources, and a `Headers` folder.
|
||||
1. Run `make ipackage`. The packaging script will produce the statically-linked `libMapboxGL.a`, `MapboxGL.bundle` for resources, and a `Headers` folder.
|
||||
2. Copy the contents of `build/ios/pkg/static` into your project. It should happen automatically, but ensure that:
|
||||
- `Headers` is in your *Header Search Paths* (`HEADER_SEARCH_PATHS`) build setting.
|
||||
- `MapboxGL.bundle` is in your target's *Copy Bundle Resources* build phase.
|
||||
@@ -68,7 +68,9 @@ If you merely want to install the library for iOS and try it out as an Objective
|
||||
5. [Set the Mapbox API access token](#mapbox-api-access-tokens).
|
||||
6. `#import "MapboxGL.h"`
|
||||
|
||||
If you want to build from source and/or contribute to development of the project, run `make iproj`, which will create and open an Xcode project which can build the entire library from source as well as an Objective-C test app.
|
||||
If you want to build from source and/or contribute to development of the project, run `make iproj`, which will create and open an Xcode project which can build the entire library from source as well as an Objective-C test app. If you don't have an Apple Developer account, change the destination from "My Mac" to a simulator such as "iPhone 6" before you run and build the app.
|
||||
|
||||
You can also run `make itest` to run the included tests. Requires `brew install xcpretty`.
|
||||
|
||||
Target devices: iPhone 4S and above (5, 5c, 5s, 6, 6 Plus) and iPad 2 and above (3, 4, Mini, Air, Mini 2, Air 2).
|
||||
|
||||
@@ -84,6 +86,7 @@ Install GCC 4.8+ if you are running Ubuntu 13.10 or older. Alternatively, you ca
|
||||
sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-4.8 g++-4.8
|
||||
export CXX=g++-4.8
|
||||
|
||||
Ensure you have git and other build essentials:
|
||||
|
||||
@@ -108,10 +111,6 @@ Otherwise, you can just install
|
||||
|
||||
sudo apt-get install libboost-dev libboost-program-options-dev
|
||||
|
||||
Once you're done installing the build dependencies, you can get started by running
|
||||
|
||||
./configure
|
||||
|
||||
Then, you can then proceed to build the library:
|
||||
|
||||
git submodule update --init
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <cstdint>
|
||||
#include <cinttypes>
|
||||
#include <cassert>
|
||||
|
||||
#include <string>
|
||||
#include <locale>
|
||||
@@ -255,20 +256,6 @@ void JNICALL nativeDestroySurface(JNIEnv *env, jobject obj, jlong nativeMapViewP
|
||||
nativeMapView->destroySurface();
|
||||
}
|
||||
|
||||
void JNICALL nativeStart(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeStart");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
nativeMapView->start();
|
||||
}
|
||||
|
||||
void JNICALL nativeStop(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeStop");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
nativeMapView->stop();
|
||||
}
|
||||
|
||||
void JNICALL nativePause(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativePause");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
@@ -287,14 +274,7 @@ void JNICALL nativeUpdate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
nativeMapView->getMap().triggerUpdate();
|
||||
}
|
||||
|
||||
void JNICALL nativeTerminate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminate");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
nativeMapView->getMap().terminate();
|
||||
nativeMapView->getMap().update();
|
||||
}
|
||||
|
||||
void JNICALL nativeResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height,
|
||||
@@ -310,7 +290,7 @@ void JNICALL nativeResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint
|
||||
assert(fbWidth <= UINT16_MAX);
|
||||
assert(fbHeight <= UINT16_MAX);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
nativeMapView->resize(width, height, ratio, fbWidth, fbHeight);
|
||||
nativeMapView->getMap().resize(width, height, ratio);
|
||||
}
|
||||
|
||||
void JNICALL nativeRemoveClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) {
|
||||
@@ -927,9 +907,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
// NOTE: if you get java.lang.UnsatisfiedLinkError you likely forgot to set the size of the
|
||||
// array correctly (too large)
|
||||
std::array<JNINativeMethod, 62> methods = {{ // Can remove the extra brace in C++14
|
||||
const std::vector<JNINativeMethod> methods = {
|
||||
{"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
|
||||
reinterpret_cast<void *>(&nativeCreate)},
|
||||
{"nativeDestroy", "(J)V", reinterpret_cast<void *>(&nativeDestroy)},
|
||||
@@ -940,12 +918,9 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
{"nativeCreateSurface", "(JLandroid/view/Surface;)V",
|
||||
reinterpret_cast<void *>(&nativeCreateSurface)},
|
||||
{"nativeDestroySurface", "(J)V", reinterpret_cast<void *>(&nativeDestroySurface)},
|
||||
{"nativeStart", "(J)V", reinterpret_cast<void *>(&nativeStart)},
|
||||
{"nativeStop", "(J)V", reinterpret_cast<void *>(&nativeStop)},
|
||||
{"nativePause", "(J)V", reinterpret_cast<void *>(&nativePause)},
|
||||
{"nativeResume", "(J)V", reinterpret_cast<void *>(&nativeResume)},
|
||||
{"nativeUpdate", "(J)V", reinterpret_cast<void *>(&nativeUpdate)},
|
||||
{"nativeTerminate", "(J)V", reinterpret_cast<void *>(&nativeTerminate)},
|
||||
{"nativeResize", "(JIIFII)V",
|
||||
reinterpret_cast<void *>(static_cast<void JNICALL (
|
||||
*)(JNIEnv *, jobject, jlong, jint, jint, jfloat, jint, jint)>(&nativeResize))},
|
||||
@@ -1014,7 +989,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
{"nativeLatLngForProjectedMeters", "(JLcom/mapbox/mapboxgl/geometry/ProjectedMeters;)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast<void *>(&nativeLatLngForProjectedMeters)},
|
||||
{"nativePixelForLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Landroid/graphics/PointF;", reinterpret_cast<void *>(&nativePixelForLatLng)},
|
||||
{"nativeLatLngForPixel", "(JLandroid/graphics/PointF;)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast<void *>(&nativeLatLngForPixel)},
|
||||
}};
|
||||
};
|
||||
|
||||
if (env->RegisterNatives(nativeMapViewClass, methods.data(), methods.size()) < 0) {
|
||||
env->ExceptionDescribe();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
@@ -16,6 +17,7 @@
|
||||
#include <mbgl/platform/gl.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_once_t loadGLExtensions = PTHREAD_ONCE_INIT;
|
||||
|
||||
@@ -59,7 +61,7 @@ NativeMapView::NativeMapView(JNIEnv *env, jobject obj_)
|
||||
: mbgl::View(*this),
|
||||
fileCache(mbgl::android::cachePath + "/mbgl-cache.db"),
|
||||
fileSource(&fileCache),
|
||||
map(*this, fileSource) {
|
||||
map(*this, fileSource, MapMode::Continuous, true) {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::NativeMapView");
|
||||
|
||||
assert(env != nullptr);
|
||||
@@ -121,11 +123,11 @@ void NativeMapView::deactivate() {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::invalidate() {
|
||||
void NativeMapView::invalidate(std::function<void()> render) {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate");
|
||||
|
||||
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
|
||||
map.render();
|
||||
render();
|
||||
|
||||
if (!eglSwapBuffers(display, surface)) {
|
||||
mbgl::Log::Error(mbgl::Event::OpenGL, "eglSwapBuffers() returned error %d",
|
||||
@@ -576,23 +578,6 @@ EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[], EGLint numConfi
|
||||
return configId;
|
||||
}
|
||||
|
||||
void NativeMapView::start() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::start");
|
||||
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
initializeDisplay();
|
||||
}
|
||||
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
initializeContext();
|
||||
}
|
||||
|
||||
assert(display != EGL_NO_DISPLAY);
|
||||
assert(context != EGL_NO_CONTEXT);
|
||||
|
||||
map.start(true);
|
||||
}
|
||||
|
||||
void loadExtensions() {
|
||||
const GLubyte *str = glGetString(GL_EXTENSIONS);
|
||||
if (str == nullptr) {
|
||||
@@ -689,14 +674,6 @@ void loadExtensions() {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::stop() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::stop");
|
||||
|
||||
if ((display != EGL_NO_DISPLAY) && (context != EGL_NO_CONTEXT)) {
|
||||
map.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::pause(bool waitForPause) {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::pause %s",
|
||||
(waitForPause) ? "true" : "false");
|
||||
@@ -824,9 +801,5 @@ void NativeMapView::updateFps() {
|
||||
env = nullptr;
|
||||
}
|
||||
|
||||
void NativeMapView::resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight) {
|
||||
View::resize(width, height, ratio, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +419,6 @@ public class MapView extends SurfaceView {
|
||||
|
||||
mNativeMapView.initializeDisplay();
|
||||
mNativeMapView.initializeContext();
|
||||
mNativeMapView.start();
|
||||
}
|
||||
|
||||
// Called when we need to save instance state
|
||||
@@ -441,7 +440,6 @@ public class MapView extends SurfaceView {
|
||||
// Called when we need to clean up
|
||||
// Must be called from Activity onDestroy
|
||||
public void onDestroy() {
|
||||
mNativeMapView.stop();
|
||||
mNativeMapView.terminateContext();
|
||||
mNativeMapView.terminateDisplay();
|
||||
}
|
||||
|
||||
@@ -73,14 +73,6 @@ class NativeMapView {
|
||||
nativeDestroySurface(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
nativeStart(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
nativeStop(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
nativePause(mNativeMapViewPtr);
|
||||
}
|
||||
@@ -386,18 +378,12 @@ class NativeMapView {
|
||||
|
||||
private native void nativeDestroySurface(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStart(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStop(long nativeMapViewPtr);
|
||||
|
||||
private native void nativePause(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResume(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeUpdate(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeTerminate(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResize(long nativeMapViewPtr, int width,
|
||||
int height, float ratio, int fbWidth, int fbHeight);
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
export BUILDTYPE=Debug
|
||||
|
||||
./android/scripts/common.sh $1
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
export BUILDTYPE=Release
|
||||
|
||||
./android/scripts/common.sh $1
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
NAME=$1
|
||||
|
||||
case `uname -s` in
|
||||
'Darwin') export JOBS=`sysctl -n hw.ncpu` ;;
|
||||
'Linux') export JOBS=`nproc` ;;
|
||||
*) export JOBS=1 ;;
|
||||
esac
|
||||
|
||||
|
||||
export CC=clang CXX=clang++
|
||||
export MASON_PLATFORM=android
|
||||
|
||||
mkdir -p ./android/java/MapboxGLAndroidSDKTestApp/src/main/res/raw/
|
||||
echo "${MAPBOX_ACCESS_TOKEN}" >> ./android/java/MapboxGLAndroidSDKTestApp/src/main/res/raw/token.txt
|
||||
|
||||
make android -j$JOBS BUILDTYPE=$BUILDTYPE JOBS=$JOBS
|
||||
|
||||
S3_PREFIX=s3://mapbox/mapbox-gl-native/android/build/${NAME}
|
||||
APK_OUTPUTS=./android/java/MapboxGLAndroidSDKTestApp/build/outputs/apk
|
||||
|
||||
# Upload the shared object.
|
||||
aws s3 cp \
|
||||
./build/android-${ANDROID_ABI}/${BUILDTYPE}/lib.target/libmapbox-gl.so \
|
||||
${S3_PREFIX}/libmapbox-gl.so
|
||||
|
||||
# Upload either the debug or the release build
|
||||
if [ ${BUILDTYPE} == "Debug" ] ; then
|
||||
aws s3 cp \
|
||||
${APK_OUTPUTS}/MapboxGLAndroidSDKTestApp-debug.apk \
|
||||
${S3_PREFIX}/MapboxGLAndroidSDKTestApp-debug.apk
|
||||
elif [ ${BUILDTYPE} == "Release" ] ; then
|
||||
aws s3 cp \
|
||||
${APK_OUTPUTS}/MapboxGLAndroidSDKTestApp-release-unsigned.apk \
|
||||
${S3_PREFIX}/MapboxGLAndroidSDKTestApp-release-unsigned.apk
|
||||
fi
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
cwd=$(pwd)
|
||||
|
||||
region="us-east-1"
|
||||
region_ami="ami-022e0c6a"
|
||||
sleep=10
|
||||
instance_name="android-gl-build-$TRAVIS_REPO_SLUG-$TRAVIS_JOB_NUMBER"
|
||||
echo $ami_name
|
||||
|
||||
NAME=$TRAVIS_JOB_ID
|
||||
|
||||
user_data="#!/bin/bash
|
||||
cd /android
|
||||
git clone git://github.com/mapbox/mapbox-gl-native.git
|
||||
|
||||
pushd mapbox-gl-native
|
||||
if [[ $TRAVIS_PULL_REQUEST == 'false' ]]; then
|
||||
git checkout $TRAVIS_COMMIT
|
||||
else
|
||||
git fetch origin +refs/pull/$TRAVIS_PULL_REQUEST/merge:
|
||||
git checkout FETCH_HEAD
|
||||
fi
|
||||
git submodule update --init --recursive
|
||||
|
||||
export ANDROID_NDK_PATH=/android/android-ndk-r10d
|
||||
export JAVA_HOME=/android/jdk1.7.0_71
|
||||
export ANDROID_HOME=/android/android-sdk-linux
|
||||
export PATH=\$PATH:/android/jdk1.7.0_71/bin
|
||||
export MAPBOX_ACCESS_TOKEN=$MAPBOX_ACCESS_TOKEN
|
||||
export TESTMUNK_KEY=$TESTMUNK_KEY
|
||||
export TESTMUNK=$TESTMUNK
|
||||
export MASON_ANDROID_ABI=$MASON_ANDROID_ABI
|
||||
export ANDROID_ABI=$MASON_ANDROID_ABI
|
||||
|
||||
if ./android/scripts/build-$CONFIG.sh $NAME &>../build.log; then
|
||||
echo 'ANDROID BUILD PASSED'
|
||||
else
|
||||
echo 'ANDROID BUILD FAILED'
|
||||
fi
|
||||
popd
|
||||
|
||||
aws s3 cp --region us-east-1 build.log s3://mapbox/mapbox-gl-native/android/build/${NAME}/build-log.txt
|
||||
shutdown -P now"
|
||||
|
||||
id=$(aws ec2 run-instances \
|
||||
--region $region \
|
||||
--image-id $region_ami \
|
||||
--count 1 \
|
||||
--instance-type m3.large \
|
||||
--iam-instance-profile Arn="$ANDROID_BUILD_INSTANCE_PROFILE" \
|
||||
--instance-initiated-shutdown-behavior terminate \
|
||||
--user-data "$user_data" | jq -r '.Instances[0].InstanceId')
|
||||
|
||||
echo "Instance: $region $id"
|
||||
|
||||
sleep 10
|
||||
|
||||
result=$(aws ec2 create-tags --region $region --resources $id --tags "Key=Name,Value=$instance_name")
|
||||
|
||||
instance_status_terminated=$(aws ec2 describe-instances --region $region --instance-id $id | jq -r '.Reservations[0].Instances[0].State.Name')
|
||||
|
||||
until [ "$instance_status_terminated" = "terminated" ]; do
|
||||
instance_status_terminated=$(aws ec2 describe-instances --region $region --instance-id $id | jq -r '.Reservations[0].Instances[0].State.Name')
|
||||
echo "Instance terminating status $region $id: $instance_status_terminated"
|
||||
sleep $sleep
|
||||
done
|
||||
|
||||
echo "Build finished"
|
||||
|
||||
output=$(aws ec2 get-console-output --region $region --instance-id $id | jq -r '.Output')
|
||||
|
||||
aws s3 cp --region $region s3://mapbox/mapbox-gl-native/android/build/${NAME}/build-log.txt build.log
|
||||
cat build.log
|
||||
|
||||
if [[ $output == *"ANDROID BUILD PASSED"* ]]; then
|
||||
echo "ANDROID BUILD PASSED"
|
||||
exit 0
|
||||
else
|
||||
echo "ANDROID BUILD FAILED"
|
||||
exit 1
|
||||
fi
|
||||
@@ -83,7 +83,7 @@ int main(int argc, char *argv[]) {
|
||||
HeadlessView view;
|
||||
Map map(view, fileSource);
|
||||
|
||||
map.start(Map::Mode::Static);
|
||||
map.start(Map::Mode::Still);
|
||||
|
||||
// Set access token if present
|
||||
if (token.size()) {
|
||||
|
||||
@@ -31,32 +31,32 @@ LIBS_linux += -Dcache_lib=$(word 1,$(CACHE) sqlite)
|
||||
LIBS_linux += --depth=. -Goutput_dir=.
|
||||
|
||||
ANDROID_ABIS += android-lib-arm-v8
|
||||
ENV_android-arm-v8 = $(shell MASON_ANDROID_ABI=arm-v8 ./scripts/android_env.sh)
|
||||
ENV_android-arm-v8 = $(shell MASON_ANDROID_ABI=arm-v8 ./scripts/android/toolchain.sh)
|
||||
CONFIG_android-arm-v8 = -Dhost=android -Iconfig/android-arm-v8.gypi
|
||||
|
||||
ANDROID_ABIS += android-lib-arm-v7
|
||||
ENV_android-arm-v7 = $(shell MASON_ANDROID_ABI=arm-v7 ./scripts/android_env.sh)
|
||||
ENV_android-arm-v7 = $(shell MASON_ANDROID_ABI=arm-v7 ./scripts/android/toolchain.sh)
|
||||
CONFIG_android-arm-v7 = -Dhost=android -Iconfig/android-arm-v7.gypi
|
||||
|
||||
ANDROID_ABIS += android-lib-arm-v5
|
||||
ENV_android-arm-v5 = $(shell MASON_ANDROID_ABI=arm-v5 ./scripts/android_env.sh)
|
||||
ENV_android-arm-v5 = $(shell MASON_ANDROID_ABI=arm-v5 ./scripts/android/toolchain.sh)
|
||||
CONFIG_android-arm-v5 = -Dhost=android -Iconfig/android-arm-v5.gypi
|
||||
|
||||
ANDROID_ABIS += android-lib-x86
|
||||
ENV_android-x86 = $(shell MASON_ANDROID_ABI=x86 ./scripts/android_env.sh)
|
||||
ENV_android-x86 = $(shell MASON_ANDROID_ABI=x86 ./scripts/android/toolchain.sh)
|
||||
CONFIG_android-x86 = -Dhost=android -Iconfig/android-x86.gypi
|
||||
|
||||
# OpenSSL build is incomplete.
|
||||
# ANDROID_ABIS += android-lib-x86-64
|
||||
# ENV_android-x86-64 = $(shell MASON_ANDROID_ABI=x86-64 ./scripts/android_env.sh)
|
||||
# ENV_android-x86-64 = $(shell MASON_ANDROID_ABI=x86-64 ./scripts/android/toolchain.sh)
|
||||
# CONFIG_android-x86-64 = -Dhost=android -Iconfig/android-x86-64.gypi
|
||||
|
||||
ANDROID_ABIS += android-lib-mips
|
||||
ENV_android-mips = $(shell MASON_ANDROID_ABI=mips ./scripts/android_env.sh)
|
||||
ENV_android-mips = $(shell MASON_ANDROID_ABI=mips ./scripts/android/toolchain.sh)
|
||||
CONFIG_android-mips = -Dhost=android -Iconfig/android-mips.gypi
|
||||
|
||||
ANDROID_ABIS += android-lib-mips-64
|
||||
ENV_android-mips-64 = $(shell MASON_ANDROID_ABI=mips-64 ./scripts/android_env.sh)
|
||||
ENV_android-mips-64 = $(shell MASON_ANDROID_ABI=mips-64 ./scripts/android/toolchain.sh)
|
||||
CONFIG_android-mips-64 = -Dhost=android -Iconfig/android-mips-64.gypi
|
||||
|
||||
LIBS_android = -Dheadless_lib=none
|
||||
|
||||
5
configure
vendored
5
configure
vendored
@@ -15,7 +15,8 @@ function finish {
|
||||
trap finish EXIT
|
||||
|
||||
# Install mason
|
||||
. ./scripts/local_mason.sh
|
||||
git submodule update --init .mason
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
case ${MASON_PLATFORM} in
|
||||
'ios')
|
||||
@@ -44,7 +45,7 @@ case ${MASON_PLATFORM} in
|
||||
LIBCURL_VERSION=system
|
||||
LIBUV_VERSION=0.10.28
|
||||
ZLIB_VERSION=system
|
||||
BOOST_VERSION=system
|
||||
BOOST_VERSION=1.57.0
|
||||
NUNICODE_VERSION=1.5.1
|
||||
LIBZIP_VERSION=0.11.2
|
||||
;;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
export TRAVIS_OS_NAME=linux
|
||||
|
||||
cd build
|
||||
|
||||
source ./scripts/local_mason.sh
|
||||
mason install mesa 10.4.3
|
||||
export LD_LIBRARY_PATH=`mason prefix mesa 10.4.3`/lib
|
||||
|
||||
export DISPLAY=:99.0
|
||||
Xvfb :99 -ac -screen 0 1024x768x24 &
|
||||
|
||||
if [[ ${CXX} == "g++" ]]; then
|
||||
export CXX="g++-4.8"
|
||||
export CC="gcc-4.8"
|
||||
fi
|
||||
|
||||
source ./scripts/install_node.sh
|
||||
|
||||
make linux -j`nproc`
|
||||
make test-* -j`nproc`
|
||||
./scripts/compare_images.sh
|
||||
5
gyp/ios.gyp
Normal file
5
gyp/ios.gyp
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
'includes': [
|
||||
'../ios/app/mapboxgl-app.gypi',
|
||||
],
|
||||
}
|
||||
7
gyp/linux.gyp
Normal file
7
gyp/linux.gyp
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
'includes': [
|
||||
'../linux/mapboxgl-app.gypi',
|
||||
'../test/test.gypi',
|
||||
'../bin/render.gypi',
|
||||
],
|
||||
}
|
||||
8
gyp/osx.gyp
Normal file
8
gyp/osx.gyp
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
'includes': [
|
||||
'../macosx/mapboxgl-app.gypi',
|
||||
'../linux/mapboxgl-app.gypi',
|
||||
'../test/test.gypi',
|
||||
'../bin/render.gypi',
|
||||
],
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
'../include/mbgl/ios/MGLMapView.h',
|
||||
'../include/mbgl/ios/MGLMapView+IBAdditions.h',
|
||||
'../platform/ios/MGLMapView.mm',
|
||||
'../platform/ios/MGLFileCache.h',
|
||||
'../platform/ios/MGLFileCache.mm',
|
||||
'../include/mbgl/ios/MGLAnnotation.h',
|
||||
'../include/mbgl/ios/MGLUserLocation.h',
|
||||
'../platform/ios/MGLUserLocation_Private.h',
|
||||
@@ -31,6 +33,9 @@
|
||||
'../include/mbgl/ios/MGLMetricsLocationManager.h',
|
||||
'../platform/ios/MGLMetricsLocationManager.m',
|
||||
'../include/mbgl/ios/MGLTypes.h',
|
||||
'../platform/ios/NSBundle+MGLAdditions.h',
|
||||
'../platform/ios/NSBundle+MGLAdditions.m',
|
||||
'../platform/ios/NSException+MGLAdditions.h',
|
||||
'../platform/ios/NSProcessInfo+MGLAdditions.h',
|
||||
'../platform/ios/NSProcessInfo+MGLAdditions.m',
|
||||
'../platform/ios/NSString+MGLAdditions.h',
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
'hard_dependency': 1,
|
||||
'dependencies': [ 'touch_styles' ], # required for xcode http://openradar.appspot.com/7232149
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
['platform_lib == "osx" or platform_lib == "ios"', {
|
||||
'direct_dependent_settings': {
|
||||
'mac_bundle_resources': [ '../styles/styles' ],
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate() override;
|
||||
void invalidate(std::function<void()> render) override;
|
||||
|
||||
void notifyMapChange(mbgl::MapChange change, Duration delay = Duration::zero()) override;
|
||||
|
||||
@@ -39,17 +39,12 @@ public:
|
||||
void createSurface(ANativeWindow *window);
|
||||
void destroySurface();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void resume();
|
||||
void pause(bool waitForPause = false);
|
||||
|
||||
void enableFps(bool enable);
|
||||
void updateFps();
|
||||
|
||||
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
|
||||
|
||||
private:
|
||||
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);
|
||||
|
||||
|
||||
@@ -46,11 +46,6 @@ IB_DESIGNABLE
|
||||
|
||||
/** @name Managing Constraints */
|
||||
|
||||
/** A view controller whose top and bottom layout guides to use for proper setup of constraints in the map view internals.
|
||||
*
|
||||
* Certain components of the map view, such as the heading compass and the data attribution button, need to be aware of the view controller layout in order to avoid positioning content under a top navigation bar or a bottom toolbar. */
|
||||
@property (nonatomic, weak) IBOutlet UIViewController *viewControllerForLayoutGuides;
|
||||
|
||||
#pragma mark - Accessing Map Properties
|
||||
|
||||
/** @name Accessing Map Properties */
|
||||
|
||||
@@ -4,6 +4,7 @@ extern NSString *const MGLEventTypeMapLoad;
|
||||
extern NSString *const MGLEventTypeMapTap;
|
||||
extern NSString *const MGLEventTypeMapDragEnd;
|
||||
extern NSString *const MGLEventTypeLocation;
|
||||
extern NSString *const MGLEventTypeVisit;
|
||||
|
||||
extern NSString *const MGLEventKeyLatitude;
|
||||
extern NSString *const MGLEventKeyLongitude;
|
||||
@@ -16,6 +17,8 @@ extern NSString *const MGLEventKeyVerticalAccuracy;
|
||||
extern NSString *const MGLEventKeyPushEnabled;
|
||||
extern NSString *const MGLEventKeyEmailEnabled;
|
||||
extern NSString *const MGLEventKeyGestureID;
|
||||
extern NSString *const MGLEventKeyArrivalDate;
|
||||
extern NSString *const MGLEventKeyDepartureDate;
|
||||
|
||||
extern NSString *const MGLEventGestureSingleTap;
|
||||
extern NSString *const MGLEventGestureDoubleTap;
|
||||
@@ -25,13 +28,14 @@ extern NSString *const MGLEventGesturePanStart;
|
||||
extern NSString *const MGLEventGesturePinchStart;
|
||||
extern NSString *const MGLEventGestureRotateStart;
|
||||
|
||||
@interface MGLMapboxEvents : NSObject
|
||||
@interface MGLMapboxEvents : NSObject <NSURLSessionDelegate>
|
||||
|
||||
// You must call these methods from the main thread.
|
||||
//
|
||||
+ (void) setToken:(NSString *)token;
|
||||
+ (void) setAppName:(NSString *)appName;
|
||||
+ (void) setAppVersion:(NSString *)appVersion;
|
||||
+ (void) setAppBuildNumber:(NSString *)appBuildNumber;
|
||||
+ (void) pauseMetricsCollection;
|
||||
+ (void) resumeMetricsCollection;
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
// These methods can be called from any thread.
|
||||
//
|
||||
+ (instancetype)sharedManager;
|
||||
+ (void) startUpdatingLocation;
|
||||
+ (void) stopUpdatingLocation;
|
||||
- (void) startUpdatingLocation;
|
||||
- (void) stopUpdatingLocation;
|
||||
- (void) startMonitoringVisits;
|
||||
- (void) stopMonitoringVisits;
|
||||
|
||||
@end
|
||||
|
||||
@@ -54,11 +54,6 @@ public:
|
||||
// Only call this while the OpenGL context is exclusive to this thread.
|
||||
void performCleanup();
|
||||
|
||||
// #############################################################################################
|
||||
|
||||
// Request to terminate the environment.
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
unsigned id;
|
||||
FileSource& fileSource;
|
||||
@@ -67,9 +62,6 @@ private:
|
||||
std::vector<uint32_t> abandonedVAOs;
|
||||
std::vector<uint32_t> abandonedBuffers;
|
||||
std::vector<uint32_t> abandonedTextures;
|
||||
|
||||
public:
|
||||
uv_loop_t* const loop;
|
||||
};
|
||||
|
||||
class EnvironmentScope final {
|
||||
|
||||
@@ -1,96 +1,57 @@
|
||||
#ifndef MBGL_MAP_MAP
|
||||
#define MBGL_MAP_MAP
|
||||
|
||||
#include <mbgl/map/transform.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/map/update.hpp>
|
||||
#include <mbgl/map/mode.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/projection.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
#include <mbgl/util/vec.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <iosfwd>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace uv { class async; }
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Painter;
|
||||
class GlyphStore;
|
||||
class LayerDescription;
|
||||
class Sprite;
|
||||
class Style;
|
||||
class StyleLayer;
|
||||
class TexturePool;
|
||||
class FileSource;
|
||||
class View;
|
||||
class GlyphAtlas;
|
||||
class SpriteAtlas;
|
||||
class LineAtlas;
|
||||
class Environment;
|
||||
class EnvironmentScope;
|
||||
class AnnotationManager;
|
||||
class MapData;
|
||||
class Worker;
|
||||
class MapContext;
|
||||
class StillImage;
|
||||
|
||||
namespace util {
|
||||
template <class T> class Thread;
|
||||
}
|
||||
|
||||
class Map : private util::noncopyable {
|
||||
friend class View;
|
||||
|
||||
public:
|
||||
enum class Mode : uint8_t {
|
||||
None, // we're not doing any processing
|
||||
Continuous, // continually updating map
|
||||
Static, // a once-off static image.
|
||||
};
|
||||
|
||||
explicit Map(View&, FileSource&);
|
||||
explicit Map(View&, FileSource&,
|
||||
MapMode mode = MapMode::Continuous,
|
||||
bool startPaused = false);
|
||||
~Map();
|
||||
|
||||
// Start the map render thread. It is asynchronous.
|
||||
void start(bool startPaused = false, Mode mode = Mode::Continuous);
|
||||
inline void start(Mode renderMode) { start(false, renderMode); }
|
||||
|
||||
// Stop the map render thread. This call will block until the map rendering thread stopped.
|
||||
// The optional callback function will be invoked repeatedly until the map thread is stopped.
|
||||
// The callback function should wait until it is woken up again by view.notify(), otherwise
|
||||
// this will be a busy waiting loop.
|
||||
void stop(std::function<void ()> callback = std::function<void ()>());
|
||||
|
||||
// Pauses the render thread. The render thread will stop running but will not be terminated and will not lose state until resumed.
|
||||
void pause(bool waitForPause = false);
|
||||
|
||||
// Resumes a paused render thread
|
||||
void resume();
|
||||
|
||||
// Register a callback that will get called (on the render thread) when all resources have
|
||||
// been loaded and a complete render occurs.
|
||||
using StillImageCallback = std::function<void(std::unique_ptr<const StillImage>)>;
|
||||
void renderStill(StillImageCallback callback);
|
||||
|
||||
// Triggers a synchronous or asynchronous render.
|
||||
void renderSync();
|
||||
|
||||
// Unconditionally performs a render with the current map state. May only be called from the Map
|
||||
// thread.
|
||||
void render();
|
||||
void renderAsync();
|
||||
|
||||
// Notifies the Map thread that the state has changed and an update might be necessary.
|
||||
void triggerUpdate(Update = Update::Nothing);
|
||||
|
||||
// Triggers a render. Can be called from any thread.
|
||||
void triggerRender();
|
||||
|
||||
// Releases resources immediately
|
||||
void terminate();
|
||||
void update(Update update = Update::Nothing);
|
||||
|
||||
// Styling
|
||||
void addClass(const std::string&);
|
||||
@@ -134,18 +95,23 @@ public:
|
||||
double getBearing() const;
|
||||
void resetNorth();
|
||||
|
||||
// Size
|
||||
void resize(uint16_t width, uint16_t height, float ratio = 1);
|
||||
uint16_t getWidth() const;
|
||||
uint16_t getHeight() const;
|
||||
|
||||
// API
|
||||
void setAccessToken(const std::string &token);
|
||||
std::string getAccessToken() const;
|
||||
|
||||
// Projection
|
||||
inline void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const { Projection::getWorldBoundsMeters(sw, ne); }
|
||||
inline void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const { Projection::getWorldBoundsLatLng(sw, ne); }
|
||||
inline double getMetersPerPixelAtLatitude(const double lat, const double zoom) const { return Projection::getMetersPerPixelAtLatitude(lat, zoom); }
|
||||
inline const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const { return Projection::projectedMetersForLatLng(latLng); }
|
||||
inline const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const { return Projection::latLngForProjectedMeters(projectedMeters); }
|
||||
inline const vec2<double> pixelForLatLng(const LatLng latLng) const { return state.pixelForLatLng(latLng); }
|
||||
inline const LatLng latLngForPixel(const vec2<double> pixel) const { return state.latLngForPixel(pixel); }
|
||||
void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const;
|
||||
void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const;
|
||||
double getMetersPerPixelAtLatitude(const double lat, const double zoom) const;
|
||||
const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const;
|
||||
const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const;
|
||||
const vec2<double> pixelForLatLng(const LatLng latLng) const;
|
||||
const LatLng latLngForPixel(const vec2<double> pixel) const;
|
||||
|
||||
// Annotations
|
||||
void setDefaultPointAnnotationSymbol(const std::string&);
|
||||
@@ -160,7 +126,6 @@ public:
|
||||
|
||||
// Memory
|
||||
void setSourceTileCacheSize(size_t);
|
||||
size_t getSourceTileCacheSize() const { return sourceCacheSize; }
|
||||
void onLowMemory();
|
||||
|
||||
// Debug
|
||||
@@ -168,104 +133,9 @@ public:
|
||||
void toggleDebug();
|
||||
bool getDebug() const;
|
||||
|
||||
inline const TransformState &getState() const { return state; }
|
||||
TimePoint getTime() const;
|
||||
inline AnnotationManager& getAnnotationManager() const { return *annotationManager; }
|
||||
|
||||
private:
|
||||
// Runs the map event loop. ONLY run this function when you want to get render a single frame
|
||||
// with this map object. It will *not* spawn a separate thread and instead block until the
|
||||
// frame is completely rendered.
|
||||
void run();
|
||||
|
||||
// This may only be called by the View object.
|
||||
void resize(uint16_t width, uint16_t height, float ratio = 1);
|
||||
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
|
||||
|
||||
util::ptr<Sprite> getSprite();
|
||||
Worker& getWorker();
|
||||
|
||||
// Checks if render thread needs to pause
|
||||
void checkForPause();
|
||||
|
||||
// Setup
|
||||
void setup();
|
||||
|
||||
void updateTiles();
|
||||
|
||||
// Triggered by triggerUpdate();
|
||||
void update();
|
||||
|
||||
// Loads the style set in the data object. Called by Update::StyleInfo
|
||||
void reloadStyle();
|
||||
void loadStyleJSON(const std::string& json, const std::string& base);
|
||||
|
||||
// Prepares a map render by updating the tiles we need for the current view, as well as updating
|
||||
// the stylesheet.
|
||||
void prepare();
|
||||
|
||||
// Runs the function in the map thread.
|
||||
void invokeTask(std::function<void()>&&);
|
||||
template <typename Fn> auto invokeSyncTask(const Fn& fn) -> decltype(fn());
|
||||
|
||||
void processTasks();
|
||||
|
||||
void updateAnnotationTiles(const std::vector<TileID>&);
|
||||
|
||||
size_t sourceCacheSize;
|
||||
|
||||
Mode mode = Mode::None;
|
||||
|
||||
const std::unique_ptr<Environment> env;
|
||||
std::unique_ptr<EnvironmentScope> scope;
|
||||
View &view;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Worker> workers;
|
||||
std::thread thread;
|
||||
std::unique_ptr<uv::async> asyncTerminate;
|
||||
std::unique_ptr<uv::async> asyncUpdate;
|
||||
std::unique_ptr<uv::async> asyncInvoke;
|
||||
std::unique_ptr<uv::async> asyncRender;
|
||||
|
||||
bool terminating = false;
|
||||
bool pausing = false;
|
||||
bool isPaused = false;
|
||||
std::mutex mutexRun;
|
||||
std::condition_variable condRun;
|
||||
std::mutex mutexPause;
|
||||
std::condition_variable condPause;
|
||||
|
||||
// Used to signal that rendering completed.
|
||||
bool rendered = false;
|
||||
std::condition_variable condRendered;
|
||||
std::mutex mutexRendered;
|
||||
|
||||
// Stores whether the map thread has been stopped already.
|
||||
std::atomic_bool isStopped;
|
||||
|
||||
Transform transform;
|
||||
TransformState state;
|
||||
|
||||
FileSource& fileSource;
|
||||
|
||||
util::ptr<Style> style;
|
||||
std::unique_ptr<GlyphAtlas> glyphAtlas;
|
||||
util::ptr<GlyphStore> glyphStore;
|
||||
std::unique_ptr<SpriteAtlas> spriteAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
std::unique_ptr<LineAtlas> lineAtlas;
|
||||
util::ptr<TexturePool> texturePool;
|
||||
std::unique_ptr<Painter> painter;
|
||||
std::unique_ptr<AnnotationManager> annotationManager;
|
||||
|
||||
const std::unique_ptr<MapData> data;
|
||||
|
||||
std::atomic<UpdateType> updated;
|
||||
|
||||
std::mutex mutexTask;
|
||||
std::queue<std::function<void()>> tasks;
|
||||
StillImageCallback callback;
|
||||
const std::unique_ptr<util::Thread<MapContext>> context;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
15
include/mbgl/map/mode.hpp
Normal file
15
include/mbgl/map/mode.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef MBGL_MAP_MODE
|
||||
#define MBGL_MAP_MODE
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
enum class MapMode : uint8_t {
|
||||
Continuous, // continually updating map
|
||||
Still, // a once-off still image
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,6 @@ using UpdateType = uint32_t;
|
||||
|
||||
enum class Update : UpdateType {
|
||||
Nothing = 0,
|
||||
StyleInfo = 1 << 0,
|
||||
Debug = 1 << 1,
|
||||
DefaultTransitionDuration = 1 << 2,
|
||||
Classes = 1 << 3,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define MBGL_MAP_VIEW
|
||||
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <functional>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -39,13 +40,13 @@ public:
|
||||
|
||||
virtual void notify() = 0;
|
||||
|
||||
// Called from the render thread. The implementation must trigger a rerender.
|
||||
// (i.e. map->renderSync() or map->renderAsync() must be called as a result of this)
|
||||
virtual void invalidate() = 0;
|
||||
// Called from the render thread. The implementation should resize the framebuffer.
|
||||
virtual void resize(uint16_t width, uint16_t height, float pixelRatio);
|
||||
|
||||
// Called from the render (=GL) thread. Signals that the contents of the contents
|
||||
// may be discarded. The default is a no-op.
|
||||
virtual void discard();
|
||||
// Called from the render thread. The implementation must trigger a rerender.
|
||||
// (i.e. either the passed render() function for rendering immediately on the map thread,
|
||||
// or map->renderSync() from the main thread must be called as a result of this)
|
||||
virtual void invalidate(std::function<void()> render) = 0;
|
||||
|
||||
// Reads the pixel data from the current framebuffer. If your View implementation
|
||||
// doesn't support reading from the framebuffer, return a null pointer.
|
||||
@@ -58,10 +59,6 @@ public:
|
||||
MapChange change,
|
||||
Duration delay = Duration::zero());
|
||||
|
||||
protected:
|
||||
// Resizes the view
|
||||
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
|
||||
|
||||
protected:
|
||||
mbgl::Map *map = nullptr;
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate() override;
|
||||
void invalidate(std::function<void()> render) override;
|
||||
|
||||
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
static void onMouseClick(GLFWwindow *window, int button, int action, int modifiers);
|
||||
static void onMouseMove(GLFWwindow *window, double x, double y);
|
||||
|
||||
int run();
|
||||
void run();
|
||||
void fps();
|
||||
|
||||
public:
|
||||
|
||||
@@ -17,6 +17,7 @@ typedef XID GLXPbuffer;
|
||||
#include <mbgl/platform/gl.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -28,13 +29,11 @@ public:
|
||||
HeadlessView(std::shared_ptr<HeadlessDisplay> display, uint16_t width = 256, uint16_t height = 256, float pixelRatio = 1);
|
||||
~HeadlessView();
|
||||
|
||||
void resize(uint16_t width, uint16_t height, float pixelRatio);
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate() override;
|
||||
void discard() override;
|
||||
void resize(uint16_t width, uint16_t height, float pixelRatio) override;
|
||||
void invalidate(std::function<void()> render) override;
|
||||
std::unique_ptr<StillImage> readStillImage() override;
|
||||
|
||||
private:
|
||||
@@ -56,12 +55,7 @@ private:
|
||||
float pixelRatio = 0;
|
||||
};
|
||||
|
||||
// These are the values that represent the state of the current framebuffer.
|
||||
Dimensions current;
|
||||
|
||||
// These are the values that will be used after the next discard() event.
|
||||
std::mutex prospectiveMutex;
|
||||
Dimensions prospective;
|
||||
Dimensions dimensions;
|
||||
|
||||
#if MBGL_USE_CGL
|
||||
CGLContextObj glContext = nullptr;
|
||||
|
||||
@@ -16,12 +16,9 @@ public:
|
||||
~DefaultFileSource() override;
|
||||
|
||||
// FileSource API
|
||||
Request *request(const Resource &resource, uv_loop_t *loop, const Environment &env,
|
||||
Callback callback) override;
|
||||
void cancel(Request *request) override;
|
||||
void request(const Resource &resource, const Environment &env, Callback callback) override;
|
||||
|
||||
void abort(const Environment &env) override;
|
||||
Request* request(const Resource&, uv_loop_t*, Callback) override;
|
||||
void cancel(Request*) override;
|
||||
void request(const Resource&, Callback) override;
|
||||
|
||||
public:
|
||||
class Impl;
|
||||
|
||||
@@ -15,7 +15,6 @@ typedef struct uv_loop_s uv_loop_t;
|
||||
namespace mbgl {
|
||||
|
||||
class Request;
|
||||
class Environment;
|
||||
|
||||
class FileSource : private util::noncopyable {
|
||||
protected:
|
||||
@@ -28,19 +27,12 @@ public:
|
||||
|
||||
// These can be called from any thread. The callback will be invoked in the loop.
|
||||
// You can only cancel a request from the same thread it was created in.
|
||||
virtual Request *request(const Resource &resource, uv_loop_t *loop, const Environment &env,
|
||||
Callback callback) = 0;
|
||||
virtual void cancel(Request *request) = 0;
|
||||
virtual Request* request(const Resource&, uv_loop_t*, Callback) = 0;
|
||||
virtual void cancel(Request*) = 0;
|
||||
|
||||
// These can be called from any thread. The callback will be invoked in an arbitrary other thread.
|
||||
// You cannot cancel these requests.
|
||||
virtual void request(const Resource &resource, const Environment &env, Callback callback) = 0;
|
||||
|
||||
// This can be called from any thread. All requests with the environment pointer env should be
|
||||
// notified as errored. Note that this is /different/ from canceling requests; a canceled
|
||||
// request's callback is never called, while an aborted request's callback is called with
|
||||
// a error message.
|
||||
virtual void abort(const Environment &env) = 0;
|
||||
virtual void request(const Resource&, Callback) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -17,14 +17,13 @@ typedef struct uv_loop_s uv_loop_t;
|
||||
namespace mbgl {
|
||||
|
||||
class Response;
|
||||
class Environment;
|
||||
|
||||
class Request : private util::noncopyable {
|
||||
MBGL_STORE_THREAD(tid)
|
||||
|
||||
public:
|
||||
using Callback = std::function<void(const Response &)>;
|
||||
Request(const Resource &resource, uv_loop_t *loop, const Environment &env, Callback callback);
|
||||
Request(const Resource &resource, uv_loop_t *loop, Callback callback);
|
||||
|
||||
public:
|
||||
// May be called from any thread.
|
||||
@@ -48,11 +47,6 @@ private:
|
||||
|
||||
public:
|
||||
const Resource resource;
|
||||
|
||||
// The environment ref is used to associate requests with a particular environment. This allows
|
||||
// us to only terminate requests associated with that environment, e.g. when the map the env
|
||||
// belongs to is discarded.
|
||||
const Environment &env;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
#ifndef MBGL_UTIL_ASYNC_QUEUE
|
||||
#define MBGL_UTIL_ASYNC_QUEUE
|
||||
|
||||
#include "std.hpp"
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
#define UV_ASYNC_PARAMS(handle) uv_async_t *handle, int
|
||||
#else
|
||||
#define UV_ASYNC_PARAMS(handle) uv_async_t *handle
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
namespace util {
|
||||
|
||||
template <typename T>
|
||||
class AsyncQueue {
|
||||
public:
|
||||
AsyncQueue(uv_loop_t *loop, std::function<void(T &)> fn) :
|
||||
callback(fn) {
|
||||
async.data = this;
|
||||
uv_async_init(loop, &async, [](UV_ASYNC_PARAMS(handle)) {
|
||||
auto q = reinterpret_cast<AsyncQueue *>(handle->data);
|
||||
q->process();
|
||||
});
|
||||
}
|
||||
|
||||
void send(T &&data) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
queue.push(util::make_unique<T>(std::move(data)));
|
||||
}
|
||||
uv_async_send(&async);
|
||||
}
|
||||
|
||||
void send(std::unique_ptr<T> data) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
queue.push(std::move(data));
|
||||
}
|
||||
uv_async_send(&async);
|
||||
}
|
||||
|
||||
void stop() {
|
||||
uv_close((uv_handle_t *)&async, [](uv_handle_t *handle) {
|
||||
delete reinterpret_cast<AsyncQueue *>(handle->data);
|
||||
});
|
||||
}
|
||||
|
||||
void ref() {
|
||||
uv_ref((uv_handle_t *)&async);
|
||||
}
|
||||
|
||||
void unref() {
|
||||
uv_unref((uv_handle_t *)&async);
|
||||
}
|
||||
|
||||
private:
|
||||
~AsyncQueue() {
|
||||
}
|
||||
|
||||
void process() {
|
||||
std::unique_ptr<T> item;
|
||||
while (true) {
|
||||
mutex.lock();
|
||||
if (queue.empty()) {
|
||||
mutex.unlock();
|
||||
break;
|
||||
}
|
||||
item = std::move(queue.front());
|
||||
queue.pop();
|
||||
mutex.unlock();
|
||||
callback(*item);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex;
|
||||
uv_async_t async;
|
||||
std::queue<std::unique_ptr<T>> queue;
|
||||
std::function<void(T &)> callback;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -74,6 +74,11 @@ inline vec2<T> normal(const S1& a, const S2& b) {
|
||||
return { dx / c, dy / c };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T perp(const T& a) {
|
||||
return T(-a.y, a.x);
|
||||
}
|
||||
|
||||
template <typename T, typename S1, typename S2>
|
||||
inline T dist(const S1& a, const S2& b) {
|
||||
T dx = b.x - a.x;
|
||||
@@ -93,11 +98,22 @@ inline T mag(const S& a) {
|
||||
return std::sqrt(a.x * a.x + a.y * a.y);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline S unit(const S& a) {
|
||||
return a * (1 / mag(a));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T clamp(T value, T min, T max) {
|
||||
return value < min ? min : (value > max ? max : value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T wrap(T value, T min, T max) {
|
||||
T d = max - min;
|
||||
return value == max ? value : std::fmod((std::fmod((value - min), d) + d), d) + min;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T smoothstep(T edge0, T edge1, T x) {
|
||||
T t = clamp((x - edge0) / (edge1 - edge0), T(0), T(1));
|
||||
|
||||
@@ -61,7 +61,13 @@ struct vec2 {
|
||||
template <typename O>
|
||||
inline typename std::enable_if<!std::is_arithmetic<O>::value, vec2>::type
|
||||
operator-(const O &o) const {
|
||||
return {x - o.x, y - o.y};
|
||||
return vec2<T>(x - o.x, y - o.y);
|
||||
}
|
||||
|
||||
template <typename O>
|
||||
inline typename std::enable_if<!std::is_arithmetic<O>::value, vec2>::type
|
||||
operator+(const O &o) const {
|
||||
return vec2<T>(x + o.x, y + o.y);
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |m|
|
||||
|
||||
m.name = 'MapboxGL'
|
||||
m.version = '0.2.14'
|
||||
m.version = '0.2.18'
|
||||
|
||||
m.summary = 'Open source vector map solution for iOS with full styling capabilities.'
|
||||
m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.'
|
||||
|
||||
@@ -67,7 +67,6 @@ mbgl::Settings_NSUserDefaults *settings = nullptr;
|
||||
|
||||
self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds accessToken:accessToken];
|
||||
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.mapView.viewControllerForLayoutGuides = self;
|
||||
self.mapView.showsUserLocation = YES;
|
||||
self.mapView.delegate = self;
|
||||
[self.view addSubview:self.mapView];
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>MBGL</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.0.2</string>
|
||||
<string>0.0.3</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
'product_extension': 'app',
|
||||
'mac_bundle': 1,
|
||||
'mac_bundle_resources': [
|
||||
'<!@(find ./img -type f)',
|
||||
'<!@(find ../ios/app/img -type f)',
|
||||
'./features.geojson',
|
||||
'./Settings.bundle/'
|
||||
],
|
||||
|
||||
'dependencies': [
|
||||
'../../mbgl.gyp:bundle_styles',
|
||||
'../../mbgl.gyp:core',
|
||||
'../../mbgl.gyp:platform-<(platform_lib)',
|
||||
'../../mbgl.gyp:http-<(http_lib)',
|
||||
'../../mbgl.gyp:asset-<(asset_lib)',
|
||||
'../../mbgl.gyp:cache-<(cache_lib)',
|
||||
'../mbgl.gyp:bundle_styles',
|
||||
'../mbgl.gyp:core',
|
||||
'../mbgl.gyp:platform-<(platform_lib)',
|
||||
'../mbgl.gyp:http-<(http_lib)',
|
||||
'../mbgl.gyp:asset-<(asset_lib)',
|
||||
'../mbgl.gyp:cache-<(cache_lib)',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
@@ -38,7 +38,7 @@
|
||||
'SDKROOT': 'iphoneos',
|
||||
'SUPPORTED_PLATFORMS': 'iphonesimulator iphoneos',
|
||||
'IPHONEOS_DEPLOYMENT_TARGET': '7.0',
|
||||
'INFOPLIST_FILE': 'app-info.plist',
|
||||
'INFOPLIST_FILE': '../ios/app/app-info.plist',
|
||||
'TARGETED_DEVICE_FAMILY': '1,2',
|
||||
'COMBINE_HIDPI_IMAGES': 'NO', # don't merge @2x.png images into .tiff files
|
||||
'CLANG_ENABLE_OBJC_ARC': 'YES',
|
||||
@@ -90,7 +90,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
map.setStyleURL(style);
|
||||
|
||||
int ret = view->run();
|
||||
view->run();
|
||||
|
||||
// Save settings
|
||||
mbgl::LatLng latLng = map.getLatLng();
|
||||
@@ -101,5 +101,5 @@ int main(int argc, char *argv[]) {
|
||||
settings.debug = map.getDebug();
|
||||
settings.save();
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ int main() {
|
||||
// Load style
|
||||
map.setStyleURL("asset://styles/bright-v7.json");
|
||||
|
||||
int ret = view.run();
|
||||
view.run();
|
||||
|
||||
[reachability stopNotifier];
|
||||
|
||||
@@ -146,5 +146,5 @@ int main() {
|
||||
settings.debug = map.getDebug();
|
||||
settings.save();
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '<@(cflags_cc)' ],
|
||||
'OTHER_LDFLAGS': [ '<@(ldflags)' ],
|
||||
'SDKROOT': 'macosx',
|
||||
'INFOPLIST_FILE': 'Info.plist',
|
||||
'INFOPLIST_FILE': '../macosx/Info.plist',
|
||||
'CLANG_ENABLE_OBJC_ARC': 'YES'
|
||||
},
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <mbgl/storage/http_request.hpp>
|
||||
#include <mbgl/storage/http_context.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/uv.hpp>
|
||||
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/time.hpp>
|
||||
#include <mbgl/util/parsedate.h>
|
||||
|
||||
@@ -45,32 +45,33 @@ enum class ResponseStatus : uint8_t {
|
||||
|
||||
class HTTPNSURLContext;
|
||||
|
||||
class HTTPRequestImpl {
|
||||
class HTTPRequest : public RequestBase {
|
||||
public:
|
||||
HTTPRequestImpl(HTTPRequest *request, uv_loop_t *loop, std::shared_ptr<const Response> response);
|
||||
~HTTPRequestImpl();
|
||||
HTTPRequest(HTTPNSURLContext*,
|
||||
const Resource&,
|
||||
Callback,
|
||||
uv_loop_t*,
|
||||
std::shared_ptr<const Response>);
|
||||
~HTTPRequest();
|
||||
|
||||
void cancel();
|
||||
void cancelTimer();
|
||||
void cancel() override;
|
||||
void retry() override;
|
||||
|
||||
private:
|
||||
void start();
|
||||
void handleResult(NSData *data, NSURLResponse *res, NSError *error);
|
||||
void handleResponse();
|
||||
|
||||
void retry(uint64_t timeout);
|
||||
void retryImmediately();
|
||||
static void restart(uv_timer_t *timer, int);
|
||||
|
||||
private:
|
||||
HTTPNSURLContext *context = nullptr;
|
||||
HTTPRequest *request = nullptr;
|
||||
bool cancelled = false;
|
||||
NSURLSessionDataTask *task = nullptr;
|
||||
std::unique_ptr<Response> response;
|
||||
const std::shared_ptr<const Response> existingResponse;
|
||||
ResponseStatus status = ResponseStatus::PermanentError;
|
||||
uv_async_t *async = nullptr;
|
||||
uv::async async;
|
||||
uv::timer timer;
|
||||
int attempts = 0;
|
||||
uv_timer_t *timer = nullptr;
|
||||
enum : bool { PreemptImmediately, ExponentialBackoff } strategy = PreemptImmediately;
|
||||
|
||||
static const int maxAttempts = 4;
|
||||
@@ -78,18 +79,20 @@ private:
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
class HTTPNSURLContext : public HTTPContext<HTTPNSURLContext> {
|
||||
class HTTPNSURLContext : public HTTPContext {
|
||||
public:
|
||||
HTTPNSURLContext(uv_loop_t *loop);
|
||||
~HTTPNSURLContext();
|
||||
|
||||
RequestBase* createRequest(const Resource&,
|
||||
RequestBase::Callback,
|
||||
uv_loop_t*,
|
||||
std::shared_ptr<const Response>) override;
|
||||
|
||||
NSURLSession *session = nil;
|
||||
NSString *userAgent = nil;
|
||||
};
|
||||
|
||||
template<> pthread_key_t ThreadContext<HTTPNSURLContext>::key{};
|
||||
template<> pthread_once_t ThreadContext<HTTPNSURLContext>::once = PTHREAD_ONCE_INIT;
|
||||
|
||||
HTTPNSURLContext::HTTPNSURLContext(uv_loop_t *loop_) : HTTPContext(loop_) {
|
||||
@autoreleasepool {
|
||||
NSURLSessionConfiguration *sessionConfig =
|
||||
@@ -115,34 +118,42 @@ HTTPNSURLContext::~HTTPNSURLContext() {
|
||||
userAgent = nullptr;
|
||||
}
|
||||
|
||||
RequestBase* HTTPNSURLContext::createRequest(const Resource& resource,
|
||||
RequestBase::Callback callback,
|
||||
uv_loop_t* loop,
|
||||
std::shared_ptr<const Response> response) {
|
||||
return new HTTPRequest(this, resource, callback, loop, response);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
HTTPRequestImpl::HTTPRequestImpl(HTTPRequest *request_, uv_loop_t *loop,
|
||||
std::shared_ptr<const Response> existingResponse_)
|
||||
: context(HTTPNSURLContext::Get(loop)),
|
||||
request(request_),
|
||||
HTTPRequest::HTTPRequest(HTTPNSURLContext* context_, const Resource& resource_, Callback callback_, uv_loop_t *loop, std::shared_ptr<const Response> existingResponse_)
|
||||
: RequestBase(resource_, callback_),
|
||||
context(context_),
|
||||
existingResponse(existingResponse_),
|
||||
async(new uv_async_t) {
|
||||
assert(request);
|
||||
context->addRequest(request);
|
||||
|
||||
async->data = this;
|
||||
uv_async_init(loop, async, [](uv_async_t *as, int) {
|
||||
auto impl = reinterpret_cast<HTTPRequestImpl *>(as->data);
|
||||
impl->handleResponse();
|
||||
});
|
||||
|
||||
async(loop, [this] { handleResponse(); }),
|
||||
timer(loop) {
|
||||
context->addRequest(this);
|
||||
start();
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::start() {
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
assert(!task);
|
||||
|
||||
// Stop the backoff timer to avoid re-triggering this request.
|
||||
timer.stop();
|
||||
|
||||
context->removeRequest(this);
|
||||
}
|
||||
|
||||
void HTTPRequest::start() {
|
||||
assert(!task);
|
||||
|
||||
attempts++;
|
||||
|
||||
@autoreleasepool {
|
||||
|
||||
NSMutableString *url = [[NSMutableString alloc] initWithString:@(request->resource.url.c_str())];
|
||||
NSMutableString *url = [[NSMutableString alloc] initWithString:@(resource.url.c_str())];
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"mapbox_metrics_disabled"] == nil) {
|
||||
if ([url rangeOfString:@"?"].location == NSNotFound) {
|
||||
[url appendString:@"?"];
|
||||
@@ -174,13 +185,13 @@ void HTTPRequestImpl::start() {
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::handleResponse() {
|
||||
void HTTPRequest::handleResponse() {
|
||||
if (task) {
|
||||
[task release];
|
||||
task = nullptr;
|
||||
}
|
||||
|
||||
if (request) {
|
||||
if (!cancelled) {
|
||||
if (status == ResponseStatus::TemporaryError && attempts < maxAttempts) {
|
||||
strategy = ExponentialBackoff;
|
||||
return retry((1 << (attempts - 1)) * 1000);
|
||||
@@ -193,26 +204,21 @@ void HTTPRequestImpl::handleResponse() {
|
||||
|
||||
// Actually return the response.
|
||||
if (status == ResponseStatus::NotModified) {
|
||||
request->notify(std::move(response), FileCache::Hint::Refresh);
|
||||
notify(std::move(response), FileCache::Hint::Refresh);
|
||||
} else {
|
||||
request->notify(std::move(response), FileCache::Hint::Full);
|
||||
notify(std::move(response), FileCache::Hint::Full);
|
||||
}
|
||||
|
||||
context->removeRequest(request);
|
||||
request->ptr = nullptr;
|
||||
delete request;
|
||||
request = nullptr;
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::cancel() {
|
||||
context->removeRequest(request);
|
||||
request = nullptr;
|
||||
void HTTPRequest::cancel() {
|
||||
context->removeRequest(this);
|
||||
cancelled = true;
|
||||
|
||||
// Stop the backoff timer to avoid re-triggering this request.
|
||||
cancelTimer();
|
||||
timer.stop();
|
||||
|
||||
if (task) {
|
||||
[task cancel];
|
||||
@@ -223,29 +229,6 @@ void HTTPRequestImpl::cancel() {
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::cancelTimer() {
|
||||
if (timer) {
|
||||
uv_timer_stop(timer);
|
||||
uv::close(timer);
|
||||
timer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HTTPRequestImpl::~HTTPRequestImpl() {
|
||||
assert(!task);
|
||||
assert(async);
|
||||
|
||||
// Stop the backoff timer to avoid re-triggering this request.
|
||||
cancelTimer();
|
||||
|
||||
uv::close(async);
|
||||
|
||||
if (request) {
|
||||
context->removeRequest(request);
|
||||
request->ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t parseCacheControl(const char *value) {
|
||||
if (value) {
|
||||
unsigned long long seconds = 0;
|
||||
@@ -261,7 +244,7 @@ int64_t parseCacheControl(const char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::handleResult(NSData *data, NSURLResponse *res, NSError *error) {
|
||||
void HTTPRequest::handleResult(NSData *data, NSURLResponse *res, NSError *error) {
|
||||
if (error) {
|
||||
if ([error code] == NSURLErrorCancelled) {
|
||||
status = ResponseStatus::Canceled;
|
||||
@@ -361,73 +344,28 @@ void HTTPRequestImpl::handleResult(NSData *data, NSURLResponse *res, NSError *er
|
||||
response->message = "response class is not NSHTTPURLResponse";
|
||||
}
|
||||
|
||||
uv_async_send(async);
|
||||
async.send();
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::retry(uint64_t timeout) {
|
||||
void HTTPRequest::retry(uint64_t timeout) {
|
||||
response.reset();
|
||||
|
||||
assert(!timer);
|
||||
timer = new uv_timer_t;
|
||||
timer->data = this;
|
||||
uv_timer_init(async->loop, timer);
|
||||
uv_timer_start(timer, restart, timeout, 0);
|
||||
timer.stop();
|
||||
timer.start(timeout, 0, [this] { start(); });
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::retryImmediately() {
|
||||
void HTTPRequest::retry() {
|
||||
// All batons get notified when the network status changed, but some of them
|
||||
// might not actually wait for the network to become available again.
|
||||
if (timer && strategy == PreemptImmediately) {
|
||||
if (strategy == PreemptImmediately) {
|
||||
// Triggers the timer upon the next event loop iteration.
|
||||
uv_timer_stop(timer);
|
||||
uv_timer_start(timer, restart, 0, 0);
|
||||
timer.stop();
|
||||
timer.start(0, 0, [this] { start(); });
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::restart(uv_timer_t *timer, int) {
|
||||
// Restart the request.
|
||||
auto impl = reinterpret_cast<HTTPRequestImpl *>(timer->data);
|
||||
|
||||
// Get rid of the timer.
|
||||
impl->timer = nullptr;
|
||||
uv::close(timer);
|
||||
|
||||
impl->start();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
HTTPRequest::HTTPRequest(DefaultFileSource::Impl *source, const Resource &resource)
|
||||
: SharedRequestBase(source, resource) {
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<HTTPRequestImpl *>(ptr)->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
assert(!ptr);
|
||||
ptr = new HTTPRequestImpl(this, loop, response);
|
||||
}
|
||||
|
||||
void HTTPRequest::retryImmediately() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<HTTPRequestImpl *>(ptr)->retryImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::cancel() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
delete this;
|
||||
std::unique_ptr<HTTPContext> HTTPContext::createContext(uv_loop_t* loop) {
|
||||
return util::make_unique<HTTPNSURLContext>(loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <mbgl/storage/asset_request.hpp>
|
||||
#include <mbgl/storage/asset_context.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
@@ -6,27 +7,19 @@
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace algo = boost::algorithm;
|
||||
#include <limits>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class AssetRequestImpl {
|
||||
class AssetRequest : public RequestBase {
|
||||
MBGL_STORE_THREAD(tid)
|
||||
|
||||
public:
|
||||
AssetRequestImpl(AssetRequest *request, uv_loop_t *loop);
|
||||
~AssetRequestImpl();
|
||||
AssetRequest(const Resource&, Callback, uv_loop_t*, const std::string& assetRoot);
|
||||
~AssetRequest();
|
||||
|
||||
void cancel() override;
|
||||
|
||||
static void fileOpened(uv_fs_t *req);
|
||||
static void fileStated(uv_fs_t *req);
|
||||
@@ -35,8 +28,7 @@ public:
|
||||
static void notifyError(uv_fs_t *req);
|
||||
static void cleanup(uv_fs_t *req);
|
||||
|
||||
|
||||
AssetRequest *request = nullptr;
|
||||
std::string assetRoot;
|
||||
bool canceled = false;
|
||||
uv_fs_t req;
|
||||
uv_file fd = -1;
|
||||
@@ -44,33 +36,40 @@ public:
|
||||
std::unique_ptr<Response> response;
|
||||
};
|
||||
|
||||
AssetRequestImpl::~AssetRequestImpl() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (request) {
|
||||
request->ptr = nullptr;
|
||||
class AssetFSContext : public AssetContext {
|
||||
RequestBase* createRequest(const Resource& resource,
|
||||
RequestBase::Callback callback,
|
||||
uv_loop_t* loop,
|
||||
const std::string& assetRoot) override {
|
||||
return new AssetRequest(resource, callback, loop, assetRoot);
|
||||
}
|
||||
};
|
||||
|
||||
AssetRequest::~AssetRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
}
|
||||
|
||||
AssetRequestImpl::AssetRequestImpl(AssetRequest *request_, uv_loop_t *loop) : request(request_) {
|
||||
AssetRequest::AssetRequest(const Resource& resource_, Callback callback_, uv_loop_t* loop, const std::string& assetRoot_)
|
||||
: RequestBase(resource_, callback_),
|
||||
assetRoot(assetRoot_) {
|
||||
req.data = this;
|
||||
|
||||
const auto &url = request->resource.url;
|
||||
const auto &url = resource.url;
|
||||
std::string path;
|
||||
if (url.size() <= 8 || url[8] == '/') {
|
||||
// This is an empty or absolute path.
|
||||
path = url.substr(8);
|
||||
} else {
|
||||
// This is a relative path. Prefix with the application root.
|
||||
path = request->source->assetRoot + "/" + url.substr(8);
|
||||
path = assetRoot + "/" + url.substr(8);
|
||||
}
|
||||
|
||||
uv_fs_open(loop, &req, path.c_str(), O_RDONLY, S_IRUSR, fileOpened);
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileOpened(uv_fs_t *req) {
|
||||
void AssetRequest::fileOpened(uv_fs_t *req) {
|
||||
assert(req->data);
|
||||
auto self = reinterpret_cast<AssetRequestImpl *>(req->data);
|
||||
auto self = reinterpret_cast<AssetRequest *>(req->data);
|
||||
MBGL_VERIFY_THREAD(self->tid);
|
||||
|
||||
if (req->result < 0) {
|
||||
@@ -93,9 +92,9 @@ void AssetRequestImpl::fileOpened(uv_fs_t *req) {
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileStated(uv_fs_t *req) {
|
||||
void AssetRequest::fileStated(uv_fs_t *req) {
|
||||
assert(req->data);
|
||||
auto self = reinterpret_cast<AssetRequestImpl *>(req->data);
|
||||
auto self = reinterpret_cast<AssetRequest *>(req->data);
|
||||
MBGL_VERIFY_THREAD(self->tid);
|
||||
|
||||
if (req->result != 0 || self->canceled) {
|
||||
@@ -121,9 +120,7 @@ void AssetRequestImpl::fileStated(uv_fs_t *req) {
|
||||
#else
|
||||
response->message = uv_strerror(UV_EFBIG);
|
||||
#endif
|
||||
assert(self->request);
|
||||
self->request->notify(std::move(response), FileCache::Hint::No);
|
||||
delete self->request;
|
||||
self->notify(std::move(response), FileCache::Hint::No);
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
uv_fs_close(req->loop, req, self->fd, fileClosed);
|
||||
@@ -148,9 +145,9 @@ void AssetRequestImpl::fileStated(uv_fs_t *req) {
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileRead(uv_fs_t *req) {
|
||||
void AssetRequest::fileRead(uv_fs_t *req) {
|
||||
assert(req->data);
|
||||
auto self = reinterpret_cast<AssetRequestImpl *>(req->data);
|
||||
auto self = reinterpret_cast<AssetRequest *>(req->data);
|
||||
MBGL_VERIFY_THREAD(self->tid);
|
||||
|
||||
if (req->result < 0 || self->canceled) {
|
||||
@@ -160,18 +157,16 @@ void AssetRequestImpl::fileRead(uv_fs_t *req) {
|
||||
} else {
|
||||
// File was successfully read.
|
||||
self->response->status = Response::Successful;
|
||||
assert(self->request);
|
||||
self->request->notify(std::move(self->response), FileCache::Hint::No);
|
||||
delete self->request;
|
||||
self->notify(std::move(self->response), FileCache::Hint::No);
|
||||
}
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
uv_fs_close(req->loop, req, self->fd, fileClosed);
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileClosed(uv_fs_t *req) {
|
||||
void AssetRequest::fileClosed(uv_fs_t *req) {
|
||||
assert(req->data);
|
||||
auto self = reinterpret_cast<AssetRequestImpl *>(req->data);
|
||||
auto self = reinterpret_cast<AssetRequest *>(req->data);
|
||||
MBGL_VERIFY_THREAD(self->tid);
|
||||
(void(self)); // Silence unused variable error in Release mode
|
||||
|
||||
@@ -182,70 +177,37 @@ void AssetRequestImpl::fileClosed(uv_fs_t *req) {
|
||||
cleanup(req);
|
||||
}
|
||||
|
||||
void AssetRequestImpl::notifyError(uv_fs_t *req) {
|
||||
void AssetRequest::notifyError(uv_fs_t *req) {
|
||||
assert(req->data);
|
||||
auto self = reinterpret_cast<AssetRequestImpl *>(req->data);
|
||||
auto self = reinterpret_cast<AssetRequest *>(req->data);
|
||||
MBGL_VERIFY_THREAD(self->tid);
|
||||
|
||||
if (req->result < 0 && !self->canceled && req->result != UV_ECANCELED) {
|
||||
auto response = util::make_unique<Response>();
|
||||
response->status = Response::Error;
|
||||
response->message = uv::getFileRequestError(req);
|
||||
assert(self->request);
|
||||
self->request->notify(std::move(response), FileCache::Hint::No);
|
||||
delete self->request;
|
||||
self->notify(std::move(response), FileCache::Hint::No);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::cleanup(uv_fs_t *req) {
|
||||
void AssetRequest::cleanup(uv_fs_t *req) {
|
||||
assert(req->data);
|
||||
auto self = reinterpret_cast<AssetRequestImpl *>(req->data);
|
||||
auto self = reinterpret_cast<AssetRequest *>(req->data);
|
||||
MBGL_VERIFY_THREAD(self->tid);
|
||||
uv_fs_req_cleanup(req);
|
||||
delete self;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
AssetRequest::AssetRequest(DefaultFileSource::Impl *source_, const Resource &resource_)
|
||||
: SharedRequestBase(source_, resource_) {
|
||||
assert(algo::starts_with(resource.url, "asset://"));
|
||||
}
|
||||
|
||||
AssetRequest::~AssetRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<AssetRequestImpl *>(ptr)->request = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
// We're ignoring the existing response if any.
|
||||
(void(response));
|
||||
|
||||
assert(!ptr);
|
||||
ptr = new AssetRequestImpl(this, loop);
|
||||
// Note: the AssetRequestImpl deletes itself.
|
||||
}
|
||||
|
||||
void AssetRequest::cancel() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
canceled = true;
|
||||
// uv_cancel fails frequently when the request has already been started.
|
||||
// In that case, we have to let it complete and check the canceled bool
|
||||
// instead. The cancelation callback will delete the AssetRequest object.
|
||||
uv_cancel((uv_req_t *)&req);
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<AssetRequestImpl *>(ptr)->canceled = true;
|
||||
|
||||
// uv_cancel fails frequently when the request has already been started.
|
||||
// In that case, we have to let it complete and check the canceled bool
|
||||
// instead. The cancelation callback will delete the AssetRequest object.
|
||||
uv_cancel((uv_req_t *)&reinterpret_cast<AssetRequestImpl *>(ptr)->req);
|
||||
} else {
|
||||
// This request is canceled before we called start. We're safe to delete
|
||||
// ourselves now.
|
||||
delete this;
|
||||
}
|
||||
std::unique_ptr<AssetContext> AssetContext::createContext(uv_loop_t*) {
|
||||
return util::make_unique<AssetFSContext>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,45 +1,40 @@
|
||||
#include <mbgl/storage/asset_request.hpp>
|
||||
#include <mbgl/storage/thread_context.hpp>
|
||||
#include <mbgl/storage/asset_context.hpp>
|
||||
#include <mbgl/android/jni.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
#include <mbgl/util/uv.hpp>
|
||||
|
||||
#include <uv.h>
|
||||
#include "uv_zip.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <forward_list>
|
||||
|
||||
namespace algo = boost::algorithm;
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class AssetZipContext : public ThreadContext<AssetZipContext> {
|
||||
class AssetZipContext : public AssetContext {
|
||||
public:
|
||||
AssetZipContext(uv_loop_t *loop);
|
||||
~AssetZipContext();
|
||||
|
||||
RequestBase* createRequest(const Resource& resource,
|
||||
RequestBase::Callback callback,
|
||||
uv_loop_t* loop,
|
||||
const std::string& assetRoot) override;
|
||||
|
||||
uv_zip_t *getHandle(const std::string &path);
|
||||
void returnHandle(const std::string &path, uv_zip_t *zip);
|
||||
|
||||
private:
|
||||
// A list of resuable uv_zip handles to avoid creating and destroying them all the time.
|
||||
std::map<std::string, std::forward_list<uv_zip_t *>> handles;
|
||||
uv_loop_t *loop;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
template<> pthread_key_t ThreadContext<AssetZipContext>::key{};
|
||||
template<> pthread_once_t ThreadContext<AssetZipContext>::once = PTHREAD_ONCE_INIT;
|
||||
|
||||
AssetZipContext::AssetZipContext(uv_loop_t *loop_) : ThreadContext(loop_) {
|
||||
AssetZipContext::AssetZipContext(uv_loop_t *loop_) : loop(loop_) {
|
||||
}
|
||||
|
||||
uv_zip_t *AssetZipContext::getHandle(const std::string &path) {
|
||||
@@ -70,20 +65,18 @@ AssetZipContext::~AssetZipContext() {
|
||||
handles.clear();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
class AssetRequestImpl {
|
||||
class AssetRequest : public RequestBase {
|
||||
MBGL_STORE_THREAD(tid)
|
||||
|
||||
public:
|
||||
AssetRequestImpl(AssetRequest *request, uv_loop_t *loop);
|
||||
~AssetRequestImpl();
|
||||
AssetRequest(AssetZipContext&, const Resource&, Callback, const std::string& assetRoot);
|
||||
~AssetRequest();
|
||||
|
||||
void cancel();
|
||||
void cancel() override;
|
||||
|
||||
private:
|
||||
AssetZipContext &context;
|
||||
AssetRequest *request = nullptr;
|
||||
bool cancelled = false;
|
||||
const std::string root;
|
||||
const std::string path;
|
||||
std::unique_ptr<Response> response;
|
||||
@@ -101,21 +94,18 @@ private:
|
||||
void notifyError(const char *message);
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
AssetRequestImpl::~AssetRequestImpl() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (request) {
|
||||
request->ptr = nullptr;
|
||||
}
|
||||
RequestBase* AssetZipContext::createRequest(const Resource& resource,
|
||||
RequestBase::Callback callback,
|
||||
uv_loop_t*,
|
||||
const std::string& assetRoot) {
|
||||
return new AssetRequest(*this, resource, callback, assetRoot);
|
||||
}
|
||||
|
||||
AssetRequestImpl::AssetRequestImpl(AssetRequest *request_, uv_loop_t *loop)
|
||||
: context(*AssetZipContext::Get(loop)),
|
||||
request(request_),
|
||||
root(request->source->assetRoot),
|
||||
path(std::string { "assets/" } + request->resource.url.substr(8)) {
|
||||
AssetRequest::AssetRequest(AssetZipContext& context_, const Resource& resource_, Callback callback_, const std::string& assetRoot_)
|
||||
: RequestBase(resource_, callback_),
|
||||
context(context_),
|
||||
root(assetRoot_),
|
||||
path(std::string { "assets/" } + resource.url.substr(8)) {
|
||||
auto zip = context.getHandle(root);
|
||||
if (zip) {
|
||||
archiveOpened(zip);
|
||||
@@ -124,18 +114,19 @@ AssetRequestImpl::AssetRequestImpl(AssetRequest *request_, uv_loop_t *loop)
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::openZipArchive() {
|
||||
AssetRequest::~AssetRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
}
|
||||
|
||||
void AssetRequest::openZipArchive() {
|
||||
uv_fs_t *req = new uv_fs_t();
|
||||
req->data = this;
|
||||
|
||||
assert(request);
|
||||
assert(request->source);
|
||||
|
||||
// We're using uv_fs_open first to obtain a file descriptor. Then, uv_zip_fdopen will operate
|
||||
// on a read-only file.
|
||||
uv_fs_open(context.loop, req, root.c_str(), O_RDONLY, S_IRUSR, [](uv_fs_t *fsReq) {
|
||||
if (fsReq->result < 0) {
|
||||
auto impl = reinterpret_cast<AssetRequestImpl *>(fsReq->data);
|
||||
auto impl = reinterpret_cast<AssetRequest *>(fsReq->data);
|
||||
impl->notifyError(uv::getFileRequestError(fsReq));
|
||||
delete impl;
|
||||
} else {
|
||||
@@ -143,7 +134,7 @@ void AssetRequestImpl::openZipArchive() {
|
||||
uv_zip_init(zip);
|
||||
zip->data = fsReq->data;
|
||||
uv_zip_fdopen(fsReq->loop, zip, uv_file(fsReq->result), 0, [](uv_zip_t *openZip) {
|
||||
auto impl = reinterpret_cast<AssetRequestImpl *>(openZip->data);
|
||||
auto impl = reinterpret_cast<AssetRequest *>(openZip->data);
|
||||
if (openZip->result < 0) {
|
||||
impl->notifyError(openZip->message);
|
||||
delete openZip;
|
||||
@@ -163,20 +154,20 @@ void AssetRequestImpl::openZipArchive() {
|
||||
#define INVOKE_MEMBER(name) \
|
||||
[](uv_zip_t *zip_) { \
|
||||
assert(zip_->data); \
|
||||
reinterpret_cast<AssetRequestImpl *>(zip_->data)->name(zip_); \
|
||||
reinterpret_cast<AssetRequest *>(zip_->data)->name(zip_); \
|
||||
}
|
||||
|
||||
void AssetRequestImpl::archiveOpened(uv_zip_t *zip) {
|
||||
void AssetRequest::archiveOpened(uv_zip_t *zip) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
zip->data = this;
|
||||
uv_zip_stat(context.loop, zip, path.c_str(), 0, INVOKE_MEMBER(fileStated));
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileStated(uv_zip_t *zip) {
|
||||
void AssetRequest::fileStated(uv_zip_t *zip) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (!request || zip->result < 0) {
|
||||
if (cancelled || zip->result < 0) {
|
||||
// Stat failed, probably because the file doesn't exist.
|
||||
if (zip->result < 0) {
|
||||
notifyError(zip->message);
|
||||
@@ -206,14 +197,14 @@ void AssetRequestImpl::fileStated(uv_zip_t *zip) {
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileOpened(uv_zip_t *zip) {
|
||||
void AssetRequest::fileOpened(uv_zip_t *zip) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (zip->result < 0) {
|
||||
// Opening failed.
|
||||
notifyError(zip->message);
|
||||
cleanup(zip);
|
||||
} else if (!request) {
|
||||
} else if (cancelled) {
|
||||
// The request was canceled. Close the file again.
|
||||
uv_zip_fclose(context.loop, zip, zip->file, INVOKE_MEMBER(fileClosed));
|
||||
} else {
|
||||
@@ -221,23 +212,21 @@ void AssetRequestImpl::fileOpened(uv_zip_t *zip) {
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileRead(uv_zip_t *zip) {
|
||||
void AssetRequest::fileRead(uv_zip_t *zip) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (zip->result < 0) {
|
||||
// Reading failed. We still have an open file handle though.
|
||||
notifyError(zip->message);
|
||||
} else if (request) {
|
||||
} else if (!cancelled) {
|
||||
response->status = Response::Successful;
|
||||
request->notify(std::move(response), FileCache::Hint::No);
|
||||
delete request;
|
||||
assert(request == nullptr);
|
||||
notify(std::move(response), FileCache::Hint::No);
|
||||
}
|
||||
|
||||
uv_zip_fclose(context.loop, zip, zip->file, INVOKE_MEMBER(fileClosed));
|
||||
}
|
||||
|
||||
void AssetRequestImpl::fileClosed(uv_zip_t *zip) {
|
||||
void AssetRequest::fileClosed(uv_zip_t *zip) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (zip->result < 0) {
|
||||
@@ -247,66 +236,32 @@ void AssetRequestImpl::fileClosed(uv_zip_t *zip) {
|
||||
cleanup(zip);
|
||||
}
|
||||
|
||||
void AssetRequestImpl::cleanup(uv_zip_t *zip) {
|
||||
void AssetRequest::cleanup(uv_zip_t *zip) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
context.returnHandle(root, zip);
|
||||
delete this;
|
||||
}
|
||||
|
||||
void AssetRequestImpl::notifyError(const char *message) {
|
||||
void AssetRequest::notifyError(const char *message) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (request) {
|
||||
if (!cancelled) {
|
||||
response = util::make_unique<Response>();
|
||||
response->status = Response::Error;
|
||||
response->message = message;
|
||||
request->notify(std::move(response), FileCache::Hint::No);
|
||||
delete request;
|
||||
assert(request == nullptr);
|
||||
notify(std::move(response), FileCache::Hint::No);
|
||||
} else {
|
||||
// The request was already canceled and deleted.
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequestImpl::cancel() {
|
||||
request = nullptr;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
AssetRequest::AssetRequest(DefaultFileSource::Impl *source_, const Resource &resource_)
|
||||
: SharedRequestBase(source_, resource_) {
|
||||
assert(algo::starts_with(resource.url, "asset://"));
|
||||
}
|
||||
|
||||
AssetRequest::~AssetRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<AssetRequestImpl *>(ptr)->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
// We're ignoring the existing response if any.
|
||||
(void(response));
|
||||
|
||||
assert(!ptr);
|
||||
ptr = new AssetRequestImpl(this, loop);
|
||||
// Note: the AssetRequestImpl deletes itself.
|
||||
}
|
||||
|
||||
void AssetRequest::cancel() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<AssetRequestImpl *>(ptr)->cancel();
|
||||
}
|
||||
|
||||
delete this;
|
||||
std::unique_ptr<AssetContext> AssetContext::createContext(uv_loop_t* loop) {
|
||||
return util::make_unique<AssetZipContext>(loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
#include <mbgl/platform/gl.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_once_t loadGLExtensions = PTHREAD_ONCE_INIT;
|
||||
|
||||
GLFWView::GLFWView(bool fullscreen_) : fullscreen(fullscreen_) {
|
||||
#ifdef NVIDIA
|
||||
glDiscardFramebufferEXT = reinterpret_cast<PFNGLDISCARDFRAMEBUFFEREXTPROC>(glfwGetProcAddress("glDiscardFramebufferEXT"));
|
||||
#endif
|
||||
}
|
||||
|
||||
GLFWView::~GLFWView() {
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void glfwError(int error, const char *description) {
|
||||
mbgl::Log::Error(mbgl::Event::OpenGL, "GLFW error (%i): %s", error, description);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void GLFWView::initialize(mbgl::Map *map_) {
|
||||
View::initialize(map_);
|
||||
GLFWView::GLFWView(bool fullscreen_) : fullscreen(fullscreen_) {
|
||||
#ifdef NVIDIA
|
||||
glDiscardFramebufferEXT = reinterpret_cast<PFNGLDISCARDFRAMEBUFFEREXTPROC>(glfwGetProcAddress("glDiscardFramebufferEXT"));
|
||||
#endif
|
||||
|
||||
glfwSetErrorCallback(glfwError);
|
||||
|
||||
@@ -63,10 +57,6 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
int width, height;
|
||||
glfwGetWindowSize(window, &width, &height);
|
||||
onResize(window, width, height);
|
||||
|
||||
glfwSetCursorPosCallback(window, onMouseMove);
|
||||
glfwSetMouseButtonCallback(window, onMouseClick);
|
||||
glfwSetWindowSizeCallback(window, onResize);
|
||||
@@ -160,6 +150,19 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
}
|
||||
|
||||
GLFWView::~GLFWView() {
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void GLFWView::initialize(mbgl::Map *map_) {
|
||||
View::initialize(map_);
|
||||
|
||||
int width, height;
|
||||
glfwGetWindowSize(window, &width, &height);
|
||||
onResize(window, width, height);
|
||||
}
|
||||
|
||||
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
|
||||
@@ -221,7 +224,7 @@ void GLFWView::onResize(GLFWwindow *window, int width, int height ) {
|
||||
int fbWidth, fbHeight;
|
||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
|
||||
|
||||
view->resize(width, height, static_cast<float>(fbWidth) / static_cast<float>(width), fbWidth, fbHeight);
|
||||
view->map->resize(width, height, static_cast<float>(fbWidth) / static_cast<float>(width));
|
||||
}
|
||||
|
||||
void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modifiers) {
|
||||
@@ -264,21 +267,10 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) {
|
||||
view->lastY = y;
|
||||
}
|
||||
|
||||
int GLFWView::run() {
|
||||
map->start();
|
||||
|
||||
void GLFWView::run() {
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwWaitEvents();
|
||||
}
|
||||
|
||||
map->stop([]() {
|
||||
glfwWaitEvents();
|
||||
});
|
||||
|
||||
// Terminate here to save binary shaders
|
||||
map->terminate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GLFWView::activate() {
|
||||
@@ -293,9 +285,8 @@ void GLFWView::notify() {
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
void GLFWView::invalidate() {
|
||||
assert(map);
|
||||
map->render();
|
||||
void GLFWView::invalidate(std::function<void()> render) {
|
||||
render();
|
||||
glfwSwapBuffers(window);
|
||||
fps();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,9 @@ namespace mbgl {
|
||||
|
||||
HeadlessView::HeadlessView(uint16_t width, uint16_t height, float pixelRatio)
|
||||
: display(std::make_shared<HeadlessDisplay>()) {
|
||||
activate();
|
||||
resize(width, height, pixelRatio);
|
||||
deactivate();
|
||||
}
|
||||
|
||||
HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
|
||||
@@ -49,7 +51,9 @@ HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
|
||||
uint16_t height,
|
||||
float pixelRatio)
|
||||
: display(display_) {
|
||||
activate();
|
||||
resize(width, height, pixelRatio);
|
||||
deactivate();
|
||||
}
|
||||
|
||||
void HeadlessView::loadExtensions() {
|
||||
@@ -150,30 +154,17 @@ bool HeadlessView::isActive() {
|
||||
return std::this_thread::get_id() == thread;
|
||||
}
|
||||
|
||||
void HeadlessView::resize(const uint16_t width, const uint16_t height, const float pixelRatio) {
|
||||
std::lock_guard<std::mutex> lock(prospectiveMutex);
|
||||
prospective = { width, height, pixelRatio };
|
||||
}
|
||||
|
||||
HeadlessView::Dimensions::Dimensions(uint16_t width_, uint16_t height_, float pixelRatio_)
|
||||
: width(width_), height(height_), pixelRatio(pixelRatio_) {
|
||||
}
|
||||
|
||||
void HeadlessView::discard() {
|
||||
assert(isActive());
|
||||
|
||||
{ // Obtain the new values.
|
||||
std::lock_guard<std::mutex> lock(prospectiveMutex);
|
||||
if (current.pixelWidth() == prospective.pixelWidth() && current.pixelHeight() == prospective.pixelHeight()) {
|
||||
return;
|
||||
}
|
||||
current = prospective;
|
||||
}
|
||||
void HeadlessView::resize(const uint16_t width, const uint16_t height, const float pixelRatio) {
|
||||
dimensions = { width, height, pixelRatio };
|
||||
|
||||
clearBuffers();
|
||||
|
||||
const unsigned int w = current.width * current.pixelRatio;
|
||||
const unsigned int h = current.height * current.pixelRatio;
|
||||
const unsigned int w = dimensions.width * dimensions.pixelRatio;
|
||||
const unsigned int h = dimensions.height * dimensions.pixelRatio;
|
||||
|
||||
// Create depth/stencil buffer
|
||||
MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
|
||||
@@ -208,15 +199,13 @@ void HeadlessView::discard() {
|
||||
}
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
View::resize(current.width, current.height, current.pixelRatio, w, h);
|
||||
}
|
||||
|
||||
std::unique_ptr<StillImage> HeadlessView::readStillImage() {
|
||||
assert(isActive());
|
||||
|
||||
const unsigned int w = current.pixelWidth();
|
||||
const unsigned int h = current.pixelHeight();
|
||||
const unsigned int w = dimensions.pixelWidth();
|
||||
const unsigned int h = dimensions.pixelHeight();
|
||||
|
||||
auto image = util::make_unique<StillImage>();
|
||||
image->width = w;
|
||||
@@ -305,7 +294,6 @@ void HeadlessView::activate() {
|
||||
#endif
|
||||
|
||||
loadExtensions();
|
||||
discard();
|
||||
}
|
||||
|
||||
void HeadlessView::deactivate() {
|
||||
@@ -328,9 +316,8 @@ void HeadlessView::deactivate() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeadlessView::invalidate() {
|
||||
assert(map);
|
||||
map->render();
|
||||
void HeadlessView::invalidate(std::function<void()> render) {
|
||||
render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include <mbgl/storage/http_request.hpp>
|
||||
#include <mbgl/storage/http_context.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <mbgl/util/time.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
@@ -53,14 +54,20 @@ enum class ResponseStatus : int8_t {
|
||||
NotModified,
|
||||
};
|
||||
|
||||
class HTTPRequestImpl;
|
||||
class HTTPRequest;
|
||||
|
||||
class HTTPCURLContext : public HTTPContext<HTTPCURLContext> {
|
||||
class HTTPCURLContext : public HTTPContext {
|
||||
MBGL_STORE_THREAD(tid)
|
||||
|
||||
public:
|
||||
HTTPCURLContext(uv_loop_t *loop);
|
||||
~HTTPCURLContext();
|
||||
|
||||
RequestBase* createRequest(const Resource&,
|
||||
RequestBase::Callback,
|
||||
uv_loop_t*,
|
||||
std::shared_ptr<const Response>) override;
|
||||
|
||||
static int handleSocket(CURL *handle, curl_socket_t s, int action, void *userp, void *socketp);
|
||||
static void perform(uv_poll_t *req, int status, int events);
|
||||
static int startTimeout(CURLM *multi, long timeout_ms, void *userp);
|
||||
@@ -74,7 +81,8 @@ public:
|
||||
void returnHandle(CURL *handle);
|
||||
void checkMultiInfo();
|
||||
|
||||
public:
|
||||
uv_loop_t *loop = nullptr;
|
||||
|
||||
// Used as the CURL timer function to periodically check for socket updates.
|
||||
uv_timer_t *timeout = nullptr;
|
||||
|
||||
@@ -90,17 +98,21 @@ public:
|
||||
std::queue<CURL *> handles;
|
||||
};
|
||||
|
||||
|
||||
class HTTPRequestImpl {
|
||||
class HTTPRequest : public RequestBase {
|
||||
MBGL_STORE_THREAD(tid)
|
||||
|
||||
public:
|
||||
HTTPRequestImpl(HTTPRequest *request, uv_loop_t *loop, std::shared_ptr<const Response> response);
|
||||
~HTTPRequestImpl();
|
||||
HTTPRequest(HTTPCURLContext*,
|
||||
const Resource&,
|
||||
Callback,
|
||||
uv_loop_t*,
|
||||
std::shared_ptr<const Response>);
|
||||
~HTTPRequest();
|
||||
|
||||
void cancel() override;
|
||||
void retry() override;
|
||||
|
||||
void handleResult(CURLcode code);
|
||||
void abandon();
|
||||
void retryImmediately();
|
||||
|
||||
private:
|
||||
static size_t headerCallback(char *const buffer, const size_t size, const size_t nmemb, void *userp);
|
||||
@@ -115,9 +127,8 @@ private:
|
||||
void finish(ResponseStatus status);
|
||||
void start();
|
||||
|
||||
private:
|
||||
HTTPCURLContext *context = nullptr;
|
||||
HTTPRequest *request = nullptr;
|
||||
bool cancelled = false;
|
||||
|
||||
// Will store the current response.
|
||||
std::unique_ptr<Response> response;
|
||||
@@ -175,10 +186,9 @@ private:
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
template<> pthread_key_t ThreadContext<HTTPCURLContext>::key{};
|
||||
template<> pthread_once_t ThreadContext<HTTPCURLContext>::once = PTHREAD_ONCE_INIT;
|
||||
|
||||
HTTPCURLContext::HTTPCURLContext(uv_loop_t *loop_) : HTTPContext(loop_) {
|
||||
HTTPCURLContext::HTTPCURLContext(uv_loop_t *loop_)
|
||||
: HTTPContext(loop_),
|
||||
loop(loop_) {
|
||||
if (curl_global_init(CURL_GLOBAL_ALL)) {
|
||||
throw std::runtime_error("Could not init cURL");
|
||||
}
|
||||
@@ -207,6 +217,13 @@ HTTPCURLContext::~HTTPCURLContext() {
|
||||
uv::close(timeout);
|
||||
}
|
||||
|
||||
RequestBase* HTTPCURLContext::createRequest(const Resource& resource,
|
||||
RequestBase::Callback callback,
|
||||
uv_loop_t* loop_,
|
||||
std::shared_ptr<const Response> response) {
|
||||
return new HTTPRequest(this, resource, callback, loop_, response);
|
||||
}
|
||||
|
||||
CURL *HTTPCURLContext::getHandle() {
|
||||
if (!handles.empty()) {
|
||||
auto handle = handles.front();
|
||||
@@ -230,7 +247,7 @@ void HTTPCURLContext::checkMultiInfo() {
|
||||
while ((message = curl_multi_info_read(multi, &pending))) {
|
||||
switch (message->msg) {
|
||||
case CURLMSG_DONE: {
|
||||
HTTPRequestImpl *baton = nullptr;
|
||||
HTTPRequest *baton = nullptr;
|
||||
curl_easy_getinfo(message->easy_handle, CURLINFO_PRIVATE, (char *)&baton);
|
||||
assert(baton);
|
||||
baton->handleResult(message->data.result);
|
||||
@@ -425,13 +442,12 @@ static CURLcode sslctx_function(CURL * /* curl */, void *sslctx, void * /* parm
|
||||
}
|
||||
#endif
|
||||
|
||||
HTTPRequestImpl::HTTPRequestImpl(HTTPRequest *request_, uv_loop_t *loop, std::shared_ptr<const Response> response_)
|
||||
: context(HTTPCURLContext::Get(loop)),
|
||||
request(request_),
|
||||
HTTPRequest::HTTPRequest(HTTPCURLContext* context_, const Resource& resource_, Callback callback_, uv_loop_t*, std::shared_ptr<const Response> response_)
|
||||
: RequestBase(resource_, callback_),
|
||||
context(context_),
|
||||
existingResponse(response_),
|
||||
handle(context->getHandle()) {
|
||||
assert(request);
|
||||
context->addRequest(request);
|
||||
context->addRequest(this);
|
||||
|
||||
// Zero out the error buffer.
|
||||
memset(error, 0, sizeof(error));
|
||||
@@ -462,7 +478,7 @@ HTTPRequestImpl::HTTPRequestImpl(HTTPRequest *request_, uv_loop_t *loop, std::sh
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_CAINFO, "ca-bundle.crt"));
|
||||
#endif
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1));
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_URL, request->resource.url.c_str()));
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_URL, resource.url.c_str()));
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writeCallback));
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_WRITEDATA, this));
|
||||
handleError(curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, headerCallback));
|
||||
@@ -474,28 +490,10 @@ HTTPRequestImpl::HTTPRequestImpl(HTTPRequest *request_, uv_loop_t *loop, std::sh
|
||||
start();
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::abandon() {
|
||||
if (request) {
|
||||
context->removeRequest(request);
|
||||
request = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::start() {
|
||||
// Count up the attempts.
|
||||
attempts++;
|
||||
|
||||
// Start requesting the information.
|
||||
handleError(curl_multi_add_handle(context->multi, handle));
|
||||
}
|
||||
|
||||
HTTPRequestImpl::~HTTPRequestImpl() {
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (request) {
|
||||
context->removeRequest(request);
|
||||
request->ptr = nullptr;
|
||||
}
|
||||
context->removeRequest(this);
|
||||
|
||||
handleError(curl_multi_remove_handle(context->multi, handle));
|
||||
context->returnHandle(handle);
|
||||
@@ -514,11 +512,23 @@ HTTPRequestImpl::~HTTPRequestImpl() {
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::cancel() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
void HTTPRequest::start() {
|
||||
// Count up the attempts.
|
||||
attempts++;
|
||||
|
||||
// Start requesting the information.
|
||||
handleError(curl_multi_add_handle(context->multi, handle));
|
||||
}
|
||||
|
||||
// This function is called when we have new data for a request. We just append it to the string
|
||||
// containing the previous data.
|
||||
size_t HTTPRequestImpl::writeCallback(void *const contents, const size_t size, const size_t nmemb, void *userp) {
|
||||
size_t HTTPRequest::writeCallback(void *const contents, const size_t size, const size_t nmemb, void *userp) {
|
||||
assert(userp);
|
||||
auto impl = reinterpret_cast<HTTPRequestImpl *>(userp);
|
||||
auto impl = reinterpret_cast<HTTPRequest *>(userp);
|
||||
MBGL_VERIFY_THREAD(impl->tid);
|
||||
|
||||
if (!impl->response) {
|
||||
@@ -560,9 +570,9 @@ int64_t parseCacheControl(const char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t HTTPRequestImpl::headerCallback(char *const buffer, const size_t size, const size_t nmemb, void *userp) {
|
||||
size_t HTTPRequest::headerCallback(char *const buffer, const size_t size, const size_t nmemb, void *userp) {
|
||||
assert(userp);
|
||||
auto baton = reinterpret_cast<HTTPRequestImpl *>(userp);
|
||||
auto baton = reinterpret_cast<HTTPRequest *>(userp);
|
||||
MBGL_VERIFY_THREAD(baton->tid);
|
||||
|
||||
if (!baton->response) {
|
||||
@@ -589,8 +599,7 @@ size_t HTTPRequestImpl::headerCallback(char *const buffer, const size_t size, co
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
void HTTPRequestImpl::retry(uint64_t timeout) {
|
||||
void HTTPRequest::retry(uint64_t timeout) {
|
||||
handleError(curl_multi_remove_handle(context->multi, handle));
|
||||
|
||||
response.reset();
|
||||
@@ -602,7 +611,7 @@ void HTTPRequestImpl::retry(uint64_t timeout) {
|
||||
uv_timer_start(timer, restart, timeout, 0);
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::retryImmediately() {
|
||||
void HTTPRequest::retry() {
|
||||
// All batons get notified when the network status changed, but some of them
|
||||
// might not actually wait for the network to become available again.
|
||||
if (timer && strategy == PreemptImmediately) {
|
||||
@@ -613,12 +622,12 @@ void HTTPRequestImpl::retryImmediately() {
|
||||
}
|
||||
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
void HTTPRequestImpl::restart(uv_timer_t *timer, int) {
|
||||
void HTTPRequest::restart(uv_timer_t *timer, int) {
|
||||
#else
|
||||
void HTTPRequestImpl::restart(uv_timer_t *timer) {
|
||||
void HTTPRequest::restart(uv_timer_t *timer) {
|
||||
#endif
|
||||
// Restart the request.
|
||||
auto baton = reinterpret_cast<HTTPRequestImpl *>(timer->data);
|
||||
auto baton = reinterpret_cast<HTTPRequest *>(timer->data);
|
||||
|
||||
// Get rid of the timer.
|
||||
baton->timer = nullptr;
|
||||
@@ -627,7 +636,7 @@ void HTTPRequestImpl::restart(uv_timer_t *timer) {
|
||||
baton->start();
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::finish(ResponseStatus status) {
|
||||
void HTTPRequest::finish(ResponseStatus status) {
|
||||
if (status == ResponseStatus::TemporaryError && attempts < maxAttempts) {
|
||||
strategy = ExponentialBackoff;
|
||||
return retry((1 << (attempts - 1)) * 1000);
|
||||
@@ -640,19 +649,18 @@ void HTTPRequestImpl::finish(ResponseStatus status) {
|
||||
|
||||
// Actually return the response.
|
||||
if (status == ResponseStatus::NotModified) {
|
||||
request->notify(std::move(response), FileCache::Hint::Refresh);
|
||||
notify(std::move(response), FileCache::Hint::Refresh);
|
||||
} else {
|
||||
request->notify(std::move(response), FileCache::Hint::Full);
|
||||
notify(std::move(response), FileCache::Hint::Full);
|
||||
}
|
||||
|
||||
delete request;
|
||||
delete this;
|
||||
}
|
||||
|
||||
void HTTPRequestImpl::handleResult(CURLcode code) {
|
||||
void HTTPRequest::handleResult(CURLcode code) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (!request) {
|
||||
if (cancelled) {
|
||||
// In this case, it doesn't make sense to even process the response even further since
|
||||
// the request was canceled anyway.
|
||||
delete this;
|
||||
@@ -720,44 +728,8 @@ void HTTPRequestImpl::handleResult(CURLcode code) {
|
||||
throw std::runtime_error("Response hasn't been handled");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
HTTPRequest::HTTPRequest(DefaultFileSource::Impl *source_, const Resource &resource_)
|
||||
: SharedRequestBase(source_, resource_) {
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<HTTPRequestImpl *>(ptr)->abandon();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
assert(!ptr);
|
||||
ptr = new HTTPRequestImpl(this, loop, response);
|
||||
}
|
||||
|
||||
void HTTPRequest::retryImmediately() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
reinterpret_cast<HTTPRequestImpl *>(ptr)->retryImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::cancel() {
|
||||
MBGL_VERIFY_THREAD(tid);
|
||||
|
||||
if (ptr) {
|
||||
delete reinterpret_cast<HTTPRequestImpl *>(ptr);
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
delete this;
|
||||
std::unique_ptr<HTTPContext> HTTPContext::createContext(uv_loop_t* loop) {
|
||||
return util::make_unique<HTTPCURLContext>(loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ SQLiteCache::SQLiteCache(const std::string& path_)
|
||||
|
||||
SQLiteCache::~SQLiteCache() = default;
|
||||
|
||||
SQLiteCache::Impl::Impl(const std::string& path_)
|
||||
SQLiteCache::Impl::Impl(uv_loop_t*, const std::string& path_)
|
||||
: path(path_) {
|
||||
}
|
||||
|
||||
@@ -183,9 +183,9 @@ void SQLiteCache::put(const Resource &resource, std::shared_ptr<const Response>
|
||||
// storing a new response or updating the currently stored response, potentially setting a new
|
||||
// expiry date.
|
||||
if (hint == Hint::Full) {
|
||||
thread->invoke(&Impl::put, resource, std::move(response));
|
||||
thread->invoke(&Impl::put, resource, response);
|
||||
} else if (hint == Hint::Refresh) {
|
||||
thread->invoke(&Impl::refresh, resource, int64_t(response->expires));
|
||||
thread->invoke(&Impl::refresh, resource, response->expires);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <mbgl/storage/sqlite_cache.hpp>
|
||||
|
||||
typedef struct uv_loop_s uv_loop_t;
|
||||
|
||||
namespace mapbox {
|
||||
namespace sqlite {
|
||||
class Database;
|
||||
@@ -14,7 +16,7 @@ namespace mbgl {
|
||||
|
||||
class SQLiteCache::Impl {
|
||||
public:
|
||||
Impl(const std::string &path = ":memory:");
|
||||
Impl(uv_loop_t*, const std::string &path = ":memory:");
|
||||
~Impl();
|
||||
|
||||
std::unique_ptr<Response> get(const Resource&);
|
||||
|
||||
10
platform/ios/MGLFileCache.h
Normal file
10
platform/ios/MGLFileCache.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <mbgl/storage/sqlite_cache.hpp>
|
||||
|
||||
@interface MGLFileCache : NSObject
|
||||
|
||||
+ (mbgl::SQLiteCache *)obtainSharedCacheWithObject:(NSObject *)object;
|
||||
+ (void)releaseSharedCacheForObject:(NSObject *)object;
|
||||
|
||||
@end
|
||||
83
platform/ios/MGLFileCache.mm
Normal file
83
platform/ios/MGLFileCache.mm
Normal file
@@ -0,0 +1,83 @@
|
||||
#import "MGLFileCache.h"
|
||||
|
||||
@interface MGLFileCache ()
|
||||
|
||||
@property (nonatomic) MGLFileCache *sharedInstance;
|
||||
@property (nonatomic) mbgl::SQLiteCache *sharedCache;
|
||||
@property (nonatomic) NSHashTable *retainers;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLFileCache
|
||||
|
||||
const std::string &defaultCacheDatabasePath() {
|
||||
static const std::string path = []() -> std::string {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
if ([paths count] == 0) {
|
||||
// Disable the cache if we don't have a location to write.
|
||||
return "";
|
||||
}
|
||||
|
||||
NSString *libraryDirectory = [paths objectAtIndex:0];
|
||||
return [[libraryDirectory stringByAppendingPathComponent:@"cache.db"] UTF8String];
|
||||
}();
|
||||
return path;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_retainers = [NSHashTable weakObjectsHashTable];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static dispatch_once_t onceToken;
|
||||
static MGLFileCache *_sharedInstance;
|
||||
dispatch_once(&onceToken, ^{
|
||||
_sharedInstance = [[self alloc] init];
|
||||
});
|
||||
return _sharedInstance;
|
||||
}
|
||||
|
||||
- (void)teardown {
|
||||
if (self.sharedCache) {
|
||||
delete self.sharedCache;
|
||||
self.sharedCache = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self.retainers removeAllObjects];
|
||||
[self teardown];
|
||||
}
|
||||
|
||||
+ (mbgl::SQLiteCache *)obtainSharedCacheWithObject:(NSObject *)object {
|
||||
return [[MGLFileCache sharedInstance] obtainSharedCacheWithObject:object];
|
||||
}
|
||||
|
||||
- (mbgl::SQLiteCache *)obtainSharedCacheWithObject:(NSObject *)object {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
if (!self.sharedCache) {
|
||||
self.sharedCache = new mbgl::SQLiteCache(defaultCacheDatabasePath());
|
||||
}
|
||||
[self.retainers addObject:object];
|
||||
return self.sharedCache;
|
||||
}
|
||||
|
||||
+ (void)releaseSharedCacheForObject:(NSObject *)object {
|
||||
return [[MGLFileCache sharedInstance] releaseSharedCacheForObject:object];
|
||||
}
|
||||
|
||||
- (void)releaseSharedCacheForObject:(NSObject *)object {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
if ([self.retainers containsObject:object]) {
|
||||
[self.retainers removeObject:object];
|
||||
}
|
||||
if ([self.retainers count] == 0) {
|
||||
[self teardown];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@
|
||||
|
||||
#import "MGLMetricsLocationManager.h"
|
||||
#import "NSProcessInfo+MGLAdditions.h"
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
#import "NSException+MGLAdditions.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
@@ -17,6 +19,7 @@ NSString *const MGLEventTypeMapLoad = @"map.load";
|
||||
NSString *const MGLEventTypeMapTap = @"map.click";
|
||||
NSString *const MGLEventTypeMapDragEnd = @"map.dragend";
|
||||
NSString *const MGLEventTypeLocation = @"location";
|
||||
NSString *const MGLEventTypeVisit = @"visit";
|
||||
|
||||
NSString *const MGLEventKeyLatitude = @"lat";
|
||||
NSString *const MGLEventKeyLongitude = @"lng";
|
||||
@@ -29,6 +32,8 @@ NSString *const MGLEventKeyVerticalAccuracy = @"verticalAccuracy";
|
||||
NSString *const MGLEventKeyPushEnabled = @"enabled.push";
|
||||
NSString *const MGLEventKeyEmailEnabled = @"enabled.email";
|
||||
NSString *const MGLEventKeyGestureID = @"gesture";
|
||||
NSString *const MGLEventKeyArrivalDate = @"arrivalDate";
|
||||
NSString *const MGLEventKeyDepartureDate = @"departureDate";
|
||||
|
||||
NSString *const MGLEventGestureSingleTap = @"SingleTap";
|
||||
NSString *const MGLEventGestureDoubleTap = @"DoubleTap";
|
||||
@@ -50,7 +55,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
// from within a single thread use underscore syntax.
|
||||
//
|
||||
// All captures of `self` from within asynchronous
|
||||
// dispatches will use a `weakSelf` to avoid cyclical
|
||||
// dispatches will use a `strongSelf` to avoid cyclical
|
||||
// strong references.
|
||||
//
|
||||
|
||||
@@ -62,6 +67,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
@property (atomic) NSString *token;
|
||||
@property (atomic) NSString *appName;
|
||||
@property (atomic) NSString *appVersion;
|
||||
@property (atomic) NSString *appBuildNumber;
|
||||
@property (atomic) NSString *instanceID;
|
||||
@property (atomic) NSString *advertiserId;
|
||||
@property (atomic) NSString *vendorId;
|
||||
@@ -73,11 +79,14 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
@property (atomic) NSUInteger flushAt;
|
||||
@property (atomic) NSDateFormatter *rfc3339DateFormatter;
|
||||
@property (atomic) CGFloat scale;
|
||||
@property (atomic) NSURLSession *session;
|
||||
@property (atomic) NSData *digicertCert;
|
||||
@property (atomic) NSData *geoTrustCert;
|
||||
|
||||
|
||||
// The isPaused state tracker is only ever accessed from the main thread.
|
||||
// The paused state tracker is only ever accessed from the main thread.
|
||||
//
|
||||
@property (nonatomic) BOOL isPaused;
|
||||
@property (nonatomic, getter=isPaused) BOOL paused;
|
||||
|
||||
// The timer is only ever accessed from the main thread.
|
||||
//
|
||||
@@ -103,19 +112,19 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
// Must be called from the main thread. Only called internally.
|
||||
//
|
||||
- (instancetype) init {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
MGLAssertIsMainThread();
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
// Put Settings bundle into memory
|
||||
NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
|
||||
if(!settingsBundle) {
|
||||
NSString *appSettingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
|
||||
if(!appSettingsBundle) {
|
||||
NSLog(@"Could not find Settings.bundle");
|
||||
} else {
|
||||
// Dynamic Settings.bundle loading based on:
|
||||
// http://stackoverflow.com/questions/510216/can-you-make-the-settings-in-settings-bundle-default-even-if-you-dont-open-the
|
||||
NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
|
||||
NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[appSettingsBundle stringByAppendingPathComponent:@"Root.plist"]];
|
||||
NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
|
||||
NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
|
||||
for(NSDictionary *prefSpecification in preferences) {
|
||||
@@ -132,11 +141,32 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
_serialQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@.%@.events.serial", _appBundleId, uniqueID] UTF8String], DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
// Configure Events Infrastructure
|
||||
// ===============================
|
||||
|
||||
_paused = YES;
|
||||
[self resumeMetricsCollection];
|
||||
NSBundle *resourceBundle = [NSBundle bundleWithPath:[NSBundle mgl_resourceBundlePath]];
|
||||
|
||||
// Load Local Copy of Server's Public Key
|
||||
NSString *cerPath = nil;
|
||||
cerPath = [resourceBundle pathForResource:@"api_mapbox_com-geotrust" ofType:@"der"];
|
||||
if (cerPath != nil) {
|
||||
_geoTrustCert = [NSData dataWithContentsOfFile:cerPath];
|
||||
}
|
||||
|
||||
cerPath = nil;
|
||||
cerPath = [resourceBundle pathForResource:@"api_mapbox_com-digicert" ofType:@"der"];
|
||||
if (cerPath != nil) {
|
||||
_digicertCert = [NSData dataWithContentsOfFile:cerPath];
|
||||
}
|
||||
|
||||
// Events Control
|
||||
_eventQueue = [[NSMutableArray alloc] init];
|
||||
_flushAt = 20;
|
||||
_flushAfter = 60;
|
||||
_token = nil;
|
||||
_instanceID = [[NSUUID UUID] UUIDString];
|
||||
|
||||
// Dynamic detection of ASIdentifierManager from Mixpanel
|
||||
// https://github.com/mixpanel/mixpanel-iphone/blob/master/LICENSE
|
||||
_advertiserId = @"";
|
||||
@@ -177,7 +207,8 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
[NSTimeZone resetSystemTimeZone];
|
||||
[_rfc3339DateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
|
||||
|
||||
_isPaused = NO;
|
||||
// Enable Battery Monitoring
|
||||
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -192,8 +223,6 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
if ( ! NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) {
|
||||
void (^setupBlock)() = ^{
|
||||
_sharedManager = [[self alloc] init];
|
||||
// setup dedicated location manager on first use
|
||||
[MGLMetricsLocationManager sharedManager];
|
||||
};
|
||||
if ( ! [[NSThread currentThread] isMainThread]) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
@@ -208,47 +237,73 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
return _sharedManager;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self pauseMetricsCollection];
|
||||
}
|
||||
|
||||
// Must be called from the main thread.
|
||||
//
|
||||
+ (void) setToken:(NSString *)token {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
MGLAssertIsMainThread();
|
||||
[MGLMapboxEvents sharedManager].token = token;
|
||||
}
|
||||
|
||||
// Must be called from the main thread.
|
||||
//
|
||||
+ (void) setAppName:(NSString *)appName {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
MGLAssertIsMainThread();
|
||||
[MGLMapboxEvents sharedManager].appName = appName;
|
||||
}
|
||||
|
||||
// Must be called from the main thread.
|
||||
//
|
||||
+ (void) setAppVersion:(NSString *)appVersion {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
MGLAssertIsMainThread();
|
||||
[MGLMapboxEvents sharedManager].appVersion = appVersion;
|
||||
}
|
||||
|
||||
// Must be called from the main thread.
|
||||
//
|
||||
+ (void) pauseMetricsCollection {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
if ([MGLMapboxEvents sharedManager].isPaused) {
|
||||
return;
|
||||
}
|
||||
[MGLMapboxEvents sharedManager].isPaused = YES;
|
||||
[MGLMetricsLocationManager stopUpdatingLocation];
|
||||
+ (void) setAppBuildNumber:(NSString *)appBuildNumber {
|
||||
MGLAssertIsMainThread();
|
||||
[MGLMapboxEvents sharedManager].appBuildNumber = appBuildNumber;
|
||||
}
|
||||
|
||||
+ (void)pauseMetricsCollection {
|
||||
[[MGLMapboxEvents sharedManager] pauseMetricsCollection];
|
||||
}
|
||||
|
||||
// Must be called from the main thread.
|
||||
//
|
||||
+ (void) resumeMetricsCollection {
|
||||
assert([[NSThread currentThread] isMainThread]);
|
||||
if (![MGLMapboxEvents sharedManager].isPaused) {
|
||||
- (void)pauseMetricsCollection {
|
||||
MGLAssertIsMainThread();
|
||||
if (self.paused) {
|
||||
return;
|
||||
}
|
||||
[MGLMapboxEvents sharedManager].isPaused = NO;
|
||||
[MGLMetricsLocationManager startUpdatingLocation];
|
||||
self.paused = YES;
|
||||
[_session invalidateAndCancel];
|
||||
_session = nil;
|
||||
MGLMetricsLocationManager *sharedLocationManager = [MGLMetricsLocationManager sharedManager];
|
||||
[sharedLocationManager stopUpdatingLocation];
|
||||
[sharedLocationManager stopMonitoringVisits];
|
||||
}
|
||||
|
||||
+ (void)resumeMetricsCollection {
|
||||
[[MGLMapboxEvents sharedManager] resumeMetricsCollection];
|
||||
}
|
||||
|
||||
// Must be called from the main thread.
|
||||
//
|
||||
- (void)resumeMetricsCollection {
|
||||
MGLAssertIsMainThread();
|
||||
if (!self.isPaused) {
|
||||
return;
|
||||
}
|
||||
self.paused = NO;
|
||||
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
|
||||
MGLMetricsLocationManager *sharedLocationManager = [MGLMetricsLocationManager sharedManager];
|
||||
[sharedLocationManager startUpdatingLocation];
|
||||
[sharedLocationManager startMonitoringVisits];
|
||||
}
|
||||
|
||||
// Can be called from any thread. Can be called rapidly from
|
||||
@@ -267,6 +322,9 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
__weak MGLMapboxEvents *weakSelf = self;
|
||||
|
||||
dispatch_async(_serialQueue, ^{
|
||||
MGLMapboxEvents *strongSelf = weakSelf;
|
||||
if ( ! strongSelf) return;
|
||||
|
||||
// Opt Out Checking When Built
|
||||
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) {
|
||||
[_eventQueue removeAllObjects];
|
||||
@@ -280,7 +338,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
}
|
||||
|
||||
// Metrics Collection Has Been Paused
|
||||
if (_isPaused) {
|
||||
if (_paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -290,35 +348,35 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
// mapbox-events stock attributes
|
||||
[evt setObject:event forKey:@"event"];
|
||||
[evt setObject:@(1) forKey:@"version"];
|
||||
[evt setObject:[weakSelf.rfc3339DateFormatter stringFromDate:[NSDate date]] forKey:@"created"];
|
||||
[evt setObject:weakSelf.instanceID forKey:@"instance"];
|
||||
[evt setObject:weakSelf.advertiserId forKey:@"advertiserId"];
|
||||
[evt setObject:weakSelf.vendorId forKey:@"vendorId"];
|
||||
[evt setObject:weakSelf.appBundleId forKeyedSubscript:@"appBundleId"];
|
||||
[evt setObject:[strongSelf.rfc3339DateFormatter stringFromDate:[NSDate date]] forKey:@"created"];
|
||||
[evt setObject:strongSelf.instanceID forKey:@"instance"];
|
||||
[evt setObject:strongSelf.advertiserId forKey:@"advertiserId"];
|
||||
[evt setObject:strongSelf.vendorId forKey:@"vendorId"];
|
||||
[evt setObject:strongSelf.appBundleId forKeyedSubscript:@"appBundleId"];
|
||||
|
||||
// mapbox-events-ios stock attributes
|
||||
[evt setValue:weakSelf.model forKey:@"model"];
|
||||
[evt setValue:weakSelf.iOSVersion forKey:@"operatingSystem"];
|
||||
[evt setValue:[weakSelf getDeviceOrientation] forKey:@"orientation"];
|
||||
[evt setValue:@(100 * [UIDevice currentDevice].batteryLevel) forKey:@"batteryLevel"];
|
||||
[evt setValue:@(weakSelf.scale) forKey:@"resolution"];
|
||||
[evt setValue:weakSelf.carrier forKey:@"carrier"];
|
||||
[evt setValue:strongSelf.model forKey:@"model"];
|
||||
[evt setValue:strongSelf.iOSVersion forKey:@"operatingSystem"];
|
||||
[evt setValue:[strongSelf getDeviceOrientation] forKey:@"orientation"];
|
||||
[evt setValue:@((int)(100 * [UIDevice currentDevice].batteryLevel)) forKey:@"batteryLevel"];
|
||||
[evt setValue:@(strongSelf.scale) forKey:@"resolution"];
|
||||
[evt setValue:strongSelf.carrier forKey:@"carrier"];
|
||||
|
||||
NSString *cell = [weakSelf getCurrentCellularNetworkConnectionType];
|
||||
NSString *cell = [strongSelf getCurrentCellularNetworkConnectionType];
|
||||
if (cell) {
|
||||
[evt setValue:cell forKey:@"cellularNetworkType"];
|
||||
} else {
|
||||
[evt setObject:[NSNull null] forKey:@"cellularNetworkType"];
|
||||
}
|
||||
|
||||
NSString *wifi = [weakSelf getWifiNetworkName];
|
||||
NSString *wifi = [strongSelf getWifiNetworkName];
|
||||
if (wifi) {
|
||||
[evt setValue:wifi forKey:@"wifi"];
|
||||
} else {
|
||||
[evt setObject:[NSNull null] forKey:@"wifi"];
|
||||
}
|
||||
|
||||
[evt setValue:@([weakSelf getContentSizeScale]) forKey:@"accessibilityFontScale"];
|
||||
[evt setValue:@([strongSelf getContentSizeScale]) forKey:@"accessibilityFontScale"];
|
||||
|
||||
// Make Immutable Version
|
||||
NSDictionary *finalEvent = [NSDictionary dictionaryWithDictionary:evt];
|
||||
@@ -327,12 +385,12 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
[_eventQueue addObject:finalEvent];
|
||||
|
||||
// Has Flush Limit Been Reached?
|
||||
if (_eventQueue.count >= weakSelf.flushAt) {
|
||||
[weakSelf flush];
|
||||
if (_eventQueue.count >= strongSelf.flushAt) {
|
||||
[strongSelf flush];
|
||||
}
|
||||
|
||||
// Reset Timer (Initial Starting of Timer after first event is pushed)
|
||||
[weakSelf startTimer];
|
||||
[strongSelf startTimer];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -350,10 +408,13 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
__weak MGLMapboxEvents *weakSelf = self;
|
||||
|
||||
dispatch_async(_serialQueue, ^{
|
||||
MGLMapboxEvents *strongSelf = weakSelf;
|
||||
if ( ! strongSelf) return;
|
||||
|
||||
__block NSArray *events;
|
||||
|
||||
NSUInteger upper = weakSelf.flushAt;
|
||||
if (weakSelf.flushAt > [_eventQueue count]) {
|
||||
NSUInteger upper = strongSelf.flushAt;
|
||||
if (strongSelf.flushAt > [_eventQueue count]) {
|
||||
if ([_eventQueue count] == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -368,7 +429,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
[_eventQueue removeObjectsInRange:theRange];
|
||||
|
||||
// Send Array of Events to Server
|
||||
[weakSelf postEvents:events];
|
||||
[strongSelf postEvents:events];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -379,10 +440,13 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
__weak MGLMapboxEvents *weakSelf = self;
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
MGLMapboxEvents *strongSelf = weakSelf;
|
||||
if (!strongSelf) return;
|
||||
|
||||
// Setup URL Request
|
||||
NSString *url = [NSString stringWithFormat:@"%@/events/v1?access_token=%@", MGLMapboxEventsAPIBase, weakSelf.token];
|
||||
NSString *url = [NSString stringWithFormat:@"%@/events/v1?access_token=%@", MGLMapboxEventsAPIBase, strongSelf.token];
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
|
||||
[request setValue:[weakSelf getUserAgent] forHTTPHeaderField:@"User-Agent"];
|
||||
[request setValue:[strongSelf getUserAgent] forHTTPHeaderField:@"User-Agent"];
|
||||
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
|
||||
[request setHTTPMethod:@"POST"];
|
||||
|
||||
@@ -392,9 +456,8 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
[request setHTTPBody:jsonData];
|
||||
|
||||
// Send non blocking HTTP Request to server
|
||||
[NSURLConnection sendAsynchronousRequest:request
|
||||
queue:nil
|
||||
completionHandler:nil];
|
||||
NSURLSessionDataTask *task = [_session dataTaskWithRequest:request completionHandler: nil];
|
||||
[task resume];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -429,8 +492,8 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
// Can be called from any thread.
|
||||
//
|
||||
- (NSString *) getUserAgent {
|
||||
if (self.appName != nil && self.appVersion != nil && ([self.userAgent rangeOfString:self.appName].location == NSNotFound)) {
|
||||
self.userAgent = [NSString stringWithFormat:@"%@/%@ %@", self.appName, self.appVersion, self.userAgent];
|
||||
if (self.appName != nil && self.appVersion != nil && self.appBuildNumber != nil && ([self.userAgent rangeOfString:self.appName].location == NSNotFound)) {
|
||||
self.userAgent = [NSString stringWithFormat:@"%@/%@/%@ %@", self.appName, self.appVersion, self.appBuildNumber, self.userAgent];
|
||||
}
|
||||
return self.userAgent;
|
||||
}
|
||||
@@ -635,4 +698,66 @@ NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark NSURLSessionDelegate
|
||||
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^) (NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
|
||||
|
||||
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
|
||||
|
||||
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
|
||||
NSString *domain = [[challenge protectionSpace] host];
|
||||
SecTrustResultType trustResult;
|
||||
|
||||
// Validate the certificate chain with the device's trust store anyway
|
||||
// This *might* give use revocation checking
|
||||
SecTrustEvaluate(serverTrust, &trustResult);
|
||||
if (trustResult == kSecTrustResultUnspecified)
|
||||
{
|
||||
// Look for a pinned certificate in the server's certificate chain
|
||||
long numKeys = SecTrustGetCertificateCount(serverTrust);
|
||||
|
||||
BOOL found = false;
|
||||
// Try GeoTrust Cert First
|
||||
for (int lc = 0; lc < numKeys; lc++) {
|
||||
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, lc);
|
||||
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
|
||||
|
||||
// Compare Remote Key With Local Version
|
||||
if ([remoteCertificateData isEqualToData:_geoTrustCert]) {
|
||||
// Found the certificate; continue connecting
|
||||
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// Fallback to Digicert Cert
|
||||
for (int lc = 0; lc < numKeys; lc++) {
|
||||
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, lc);
|
||||
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
|
||||
|
||||
// Compare Remote Key With Local Version
|
||||
if ([remoteCertificateData isEqualToData:_digicertCert]) {
|
||||
// Found the certificate; continue connecting
|
||||
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// The certificate wasn't found in GeoTrust nor Digicert. Cancel the connection.
|
||||
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Certificate chain validation failed; cancel the connection
|
||||
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
@interface MGLMetricsLocationManager() <CLLocationManagerDelegate>
|
||||
|
||||
@property (nonatomic) CLLocationManager *locationManager;
|
||||
@property (atomic) NSDateFormatter *rfc3339DateFormatter;
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,8 +15,18 @@
|
||||
- (instancetype) init {
|
||||
if (self = [super init]) {
|
||||
_locationManager = [[CLLocationManager alloc] init];
|
||||
_locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
|
||||
_locationManager.distanceFilter = 10;
|
||||
[_locationManager setDelegate:self];
|
||||
|
||||
_rfc3339DateFormatter = [[NSDateFormatter alloc] init];
|
||||
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
|
||||
|
||||
[_rfc3339DateFormatter setLocale:enUSPOSIXLocale];
|
||||
[_rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
|
||||
// Clear Any System TimeZone Cache
|
||||
[NSTimeZone resetSystemTimeZone];
|
||||
[_rfc3339DateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -29,12 +40,26 @@
|
||||
return sharedManager;
|
||||
}
|
||||
|
||||
+ (void) startUpdatingLocation {
|
||||
[[MGLMetricsLocationManager sharedManager].locationManager startUpdatingLocation];
|
||||
- (void)startUpdatingLocation {
|
||||
[self.locationManager startUpdatingLocation];
|
||||
}
|
||||
|
||||
+ (void) stopUpdatingLocation {
|
||||
[[MGLMetricsLocationManager sharedManager].locationManager stopUpdatingLocation];
|
||||
- (void)stopUpdatingLocation {
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
}
|
||||
|
||||
- (void)startMonitoringVisits {
|
||||
// -[CLLocationManager startMonitoringVisits] is only available in iOS 8+.
|
||||
if ([self.locationManager respondsToSelector:@selector(startMonitoringVisits)]) {
|
||||
[self.locationManager startMonitoringVisits];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopMonitoringVisits {
|
||||
// -[CLLocationManager stopMonitoringVisits] is only available in iOS 8+.
|
||||
if ([self.locationManager respondsToSelector:@selector(stopMonitoringVisits)]) {
|
||||
[self.locationManager stopMonitoringVisits];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark CLLocationManagerDelegate
|
||||
@@ -53,6 +78,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit {
|
||||
[MGLMapboxEvents pushEvent:MGLEventTypeVisit withAttributes:@{
|
||||
MGLEventKeyLatitude: @(visit.coordinate.latitude),
|
||||
MGLEventKeyLongitude: @(visit.coordinate.longitude),
|
||||
MGLEventKeyHorizontalAccuracy: @(visit.horizontalAccuracy),
|
||||
MGLEventKeyArrivalDate: [[NSDate distantPast] isEqualToDate:visit.arrivalDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.arrivalDate],
|
||||
MGLEventKeyDepartureDate: [[NSDate distantFuture] isEqualToDate:visit.departureDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.departureDate]
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
|
||||
NSString *newStatus = nil;
|
||||
switch (status) {
|
||||
@@ -64,18 +99,21 @@
|
||||
break;
|
||||
case kCLAuthorizationStatusDenied:
|
||||
newStatus = @"User Explcitly Denied";
|
||||
[MGLMetricsLocationManager stopUpdatingLocation];
|
||||
[self stopUpdatingLocation];
|
||||
[self stopMonitoringVisits];
|
||||
break;
|
||||
case kCLAuthorizationStatusAuthorized:
|
||||
newStatus = @"User Has Authorized / Authorized Always";
|
||||
[MGLMetricsLocationManager startUpdatingLocation];
|
||||
[self startUpdatingLocation];
|
||||
[self startMonitoringVisits];
|
||||
break;
|
||||
// case kCLAuthorizationStatusAuthorizedAlways:
|
||||
// newStatus = @"Not Determined";
|
||||
// break;
|
||||
// case kCLAuthorizationStatusAuthorizedAlways:
|
||||
// newStatus = @"Not Determined";
|
||||
// break;
|
||||
case kCLAuthorizationStatusAuthorizedWhenInUse:
|
||||
newStatus = @"User Has Authorized When In Use Only";
|
||||
[MGLMetricsLocationManager startUpdatingLocation];
|
||||
[self startUpdatingLocation];
|
||||
[self startMonitoringVisits];
|
||||
break;
|
||||
default:
|
||||
newStatus = @"Unknown";
|
||||
|
||||
@@ -30,6 +30,7 @@ const CGFloat MGLTrackingDotRingWidth = 24.0;
|
||||
self.annotation.mapView = mapView;
|
||||
_mapView = mapView;
|
||||
[self setupLayers];
|
||||
self.accessibilityLabel = @"User location";
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
7
platform/ios/NSBundle+MGLAdditions.h
Normal file
7
platform/ios/NSBundle+MGLAdditions.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSBundle (MGLAdditions)
|
||||
|
||||
+ (NSString *)mgl_resourceBundlePath;
|
||||
|
||||
@end
|
||||
16
platform/ios/NSBundle+MGLAdditions.m
Normal file
16
platform/ios/NSBundle+MGLAdditions.m
Normal file
@@ -0,0 +1,16 @@
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
|
||||
#import "MGLMapView.h"
|
||||
|
||||
@implementation NSBundle (MGLAdditions)
|
||||
|
||||
+ (NSString *)mgl_resourceBundlePath
|
||||
{
|
||||
NSString *resourceBundlePath = [[NSBundle bundleForClass:[MGLMapView class]] pathForResource:@"MapboxGL" ofType:@"bundle"];
|
||||
|
||||
if ( ! resourceBundlePath) resourceBundlePath = [[NSBundle mainBundle] bundlePath];
|
||||
|
||||
return resourceBundlePath;
|
||||
}
|
||||
|
||||
@end
|
||||
3
platform/ios/NSException+MGLAdditions.h
Normal file
3
platform/ios/NSException+MGLAdditions.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define MGLAssertIsMainThread() NSAssert([[NSThread currentThread] isMainThread], @"-[%@ %@] must be accessed on the main thread, not %@", [self class], NSStringFromSelector(_cmd), [NSThread currentThread])
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.0 KiB |
BIN
platform/ios/resources/api_mapbox_com-digicert.der
Normal file
BIN
platform/ios/resources/api_mapbox_com-digicert.der
Normal file
Binary file not shown.
BIN
platform/ios/resources/api_mapbox_com-geotrust.der
Normal file
BIN
platform/ios/resources/api_mapbox_com-geotrust.der
Normal file
Binary file not shown.
15
scripts/android/install.sh
Executable file
15
scripts/android/install.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
mapbox_time "checkout_mason" \
|
||||
git submodule update --init .mason
|
||||
|
||||
export MASON_PLATFORM=android
|
||||
export MASON_ANDROID_ABI=${ANDROID_ABI}
|
||||
|
||||
mapbox_time "android_toolchain" \
|
||||
./scripts/android/toolchain.sh
|
||||
61
scripts/android/run.sh
Executable file
61
scripts/android/run.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
BUILDTYPE=${BUILDTYPE:-Release}
|
||||
TESTMUNK=${TESTMUNK:-no}
|
||||
export HOST=android
|
||||
export MASON_PLATFORM=android
|
||||
export MASON_ANDROID_ABI=${ANDROID_ABI:-arm-v7}
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
# Add Mason to PATH
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
################################################################################
|
||||
# Build
|
||||
################################################################################
|
||||
|
||||
mapbox_time "checkout_styles" \
|
||||
git submodule update --init styles
|
||||
|
||||
mkdir -p ./android/java/MapboxGLAndroidSDKTestApp/src/main/res/raw
|
||||
echo "${MAPBOX_ACCESS_TOKEN}" > ./android/java/MapboxGLAndroidSDKTestApp/src/main/res/raw/token.txt
|
||||
|
||||
mapbox_time "compile_library" \
|
||||
make android-lib -j${JOBS} BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "build_apk" \
|
||||
make android -j${JOBS} BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
################################################################################
|
||||
# Deploy
|
||||
################################################################################
|
||||
|
||||
if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then
|
||||
# Install and add awscli to PATH for uploading the results
|
||||
mapbox_time "install_awscli" \
|
||||
pip install --user awscli
|
||||
export PATH="`python -m site --user-base`/bin:${PATH}"
|
||||
|
||||
mapbox_time_start "deploy_results"
|
||||
echo "Deploying results..."
|
||||
|
||||
S3_PREFIX=s3://mapbox/mapbox-gl-native/android/build/${TRAVIS_JOB_NUMBER}
|
||||
APK_OUTPUTS=./android/java/MapboxGLAndroidSDKTestApp/build/outputs/apk
|
||||
|
||||
# Upload either the debug or the release build
|
||||
if [ ${BUILDTYPE} == "Debug" ] ; then
|
||||
aws s3 cp \
|
||||
${APK_OUTPUTS}/MapboxGLAndroidSDKTestApp-debug.apk \
|
||||
${S3_PREFIX}/MapboxGLAndroidSDKTestApp-debug.apk
|
||||
elif [ ${BUILDTYPE} == "Release" ] ; then
|
||||
aws s3 cp \
|
||||
${APK_OUTPUTS}/MapboxGLAndroidSDKTestApp-release-unsigned.apk \
|
||||
${S3_PREFIX}/MapboxGLAndroidSDKTestApp-release-unsigned.apk
|
||||
fi
|
||||
|
||||
mapbox_time_finish
|
||||
fi
|
||||
26
scripts/android/toolchain.sh
Executable file
26
scripts/android/toolchain.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
export MASON_PLATFORM=android
|
||||
export MASON_ANDROID_ABI=${MASON_ANDROID_ABI:-arm-v7}
|
||||
export PATH="`pwd`/.mason:${PATH}"
|
||||
export MASON_DIR="`pwd`/.mason"
|
||||
|
||||
export PATH=`mason env PATH`
|
||||
|
||||
echo MASON_PLATFORM=\"${MASON_PLATFORM}\"
|
||||
echo MASON_ANDROID_ABI=\"${MASON_ANDROID_ABI}\"
|
||||
echo CXX=\"`which $(mason env CXX)`\"
|
||||
echo CC=\"`which $(mason env CC)`\"
|
||||
echo LD=\"`which $(mason env LD)`\"
|
||||
echo LINK=\"`which $(mason env CXX)`\"
|
||||
echo AR=\"`which $(mason env AR)`\"
|
||||
echo RANLIB=\"`which $(mason env RANLIB)`\"
|
||||
echo STRIP=\"`which $(mason env STRIP)`\"
|
||||
echo LDFLAGS=\"`mason env LDFLAGS` \${LDFLAGS:-}\"
|
||||
echo CFLAGS=\"`mason env CFLAGS` \${CFLAGS:-}\"
|
||||
echo CXXFLAGS=\"`mason env CXXFLAGS` \${CXXFLAGS:-}\"
|
||||
echo CPPFLAGS=\"`mason env CPPFLAGS` \${CPPFLAGS:-}\"
|
||||
echo JNIDIR=\"`mason env JNIDIR`\"
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
./scripts/local_mason.sh
|
||||
|
||||
export MASON_PLATFORM=android
|
||||
|
||||
export PATH=`.mason/mason env PATH`
|
||||
|
||||
echo MASON_PLATFORM=\"android\"
|
||||
echo MASON_ANDROID_ABI=\"${MASON_ANDROID_ABI}\"
|
||||
|
||||
echo CXX=\"`which $(.mason/mason env CXX)`\"
|
||||
echo CC=\"`which $(.mason/mason env CC)`\"
|
||||
echo LD=\"`which $(.mason/mason env LD)`\"
|
||||
echo LINK=\"`which $(.mason/mason env CXX)`\"
|
||||
echo AR=\"`which $(.mason/mason env AR)`\"
|
||||
echo RANLIB=\"`which $(.mason/mason env RANLIB)`\"
|
||||
echo STRIP=\"`which $(.mason/mason env STRIP)`\"
|
||||
echo LDFLAGS=\"`.mason/mason env LDFLAGS` ${LDFLAGS}\"
|
||||
echo CFLAGS=\"`.mason/mason env CFLAGS` ${CFLAGS}\"
|
||||
echo CPPFLAGS=\"`.mason/mason env CPPFLAGS` ${CPPFLAGS}\"
|
||||
echo JNIDIR=\"`.mason/mason env JNIDIR`\"
|
||||
@@ -13,9 +13,9 @@ else:
|
||||
if sys.argv[2] == sys.argv[3]:
|
||||
tag = [0, 0, 0]
|
||||
else:
|
||||
ver = re.sub("[^0-9.]", "", sys.argv[2])
|
||||
ver = re.sub("[^0-9.]", "", sys.argv[2])
|
||||
tag = map(int, ver.split('.'))
|
||||
rev = sys.argv[3][0:8]
|
||||
rev = sys.argv[3][0:8]
|
||||
|
||||
|
||||
def mkdir_p(path):
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then
|
||||
export DISPLAY=:99.0
|
||||
|
||||
if [[ ${MASON_PLATFORM} != "android" ]]; then
|
||||
sh -e /etc/init.d/xvfb start
|
||||
fi
|
||||
|
||||
# use g++ that supports c++11
|
||||
if [[ ${CXX} == "g++" ]]; then
|
||||
export CXX="g++-4.8"
|
||||
export CC="gcc-4.8"
|
||||
fi
|
||||
|
||||
# If building in debug then turn on sanitizers.
|
||||
# They should both work with latest g++/clang++
|
||||
# but it's not worth a standalone matrix so here
|
||||
# we just test address->gcc and thread->clang for
|
||||
# some limited coverage
|
||||
# if [[ ${BUILDTYPE} == "Debug" ]]; then
|
||||
# if [[ ${CXX} == "g++" ]]; then
|
||||
# export CXXFLAGS="-fsanitize=address -g ${CXXFLAGS}"
|
||||
# export CFLAGS="-fsanitize=address -g ${CFLAGS}"
|
||||
# export LDFLAGS="-fsanitize=address ${LDFLAGS}"
|
||||
# elif [[ ${CXX} == "clang++" ]]; then
|
||||
# export CXXFLAGS="-fsanitize=thread -g -fPIC ${CXXFLAGS}"
|
||||
# export CFLAGS="-fsanitize=thread -g ${CFLAGS}"
|
||||
# export LDFLAGS="-fsanitize=thread -pie ${LDFLAGS}"
|
||||
# fi
|
||||
# fi
|
||||
fi
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
mason install node 0.10.35
|
||||
export PATH="`mason prefix node 0.10.35`/bin":"$PATH"
|
||||
@@ -16,10 +16,10 @@ security unlock-keychain -p travis ios-build.keychain
|
||||
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
|
||||
|
||||
# Add certificates to keychain and allow codesign to access them
|
||||
security import ./scripts/ios_travis/apple.crt -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
|
||||
security import ./scripts/ios_travis/ios-dist.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
|
||||
security import ./scripts/ios_travis/ios-dist.p12 -k ~/Library/Keychains/ios-build.keychain -P $IOS_KEY_PASSWORD -T /usr/bin/codesign
|
||||
security import ./scripts/ios/apple.crt -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
|
||||
security import ./scripts/ios/ios-dist.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
|
||||
security import ./scripts/ios/ios-dist.p12 -k ~/Library/Keychains/ios-build.keychain -P $IOS_KEY_PASSWORD -T /usr/bin/codesign
|
||||
|
||||
# Put the provisioning profile in place
|
||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||
cp "./scripts/ios_travis/$IOS_PROFILE_NAME.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
cp "./scripts/ios/$IOS_PROFILE_NAME.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
13
scripts/ios/after_failure.sh
Executable file
13
scripts/ios/after_failure.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
set -u
|
||||
|
||||
ls $KIF_SCREENSHOTS/
|
||||
|
||||
REPO_NAME=$(basename $TRAVIS_REPO_SLUG)
|
||||
|
||||
aws s3 cp $KIF_SCREENSHOTS/ s3://mapbox/$REPO_NAME/ios/tests/$TRAVIS_JOB_NUMBER/ --acl public-read --recursive > /dev/null
|
||||
|
||||
echo http://mapbox.s3.amazonaws.com/$REPO_NAME/ios/tests/$TRAVIS_JOB_NUMBER/index.html
|
||||
15
scripts/ios/install.sh
Executable file
15
scripts/ios/install.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
mapbox_time "checkout_mason" \
|
||||
git submodule update --init .mason
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
mapbox_time "install_xcpretty" \
|
||||
gem install xcpretty --no-rdoc --no-ri --no-document --quiet
|
||||
|
||||
mkdir -p ${KIF_SCREENSHOTS}
|
||||
@@ -4,11 +4,19 @@ set -e
|
||||
set -o pipefail
|
||||
set -u
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
NAME=MapboxGL
|
||||
OUTPUT=build/ios/pkg
|
||||
IOS_SDK_VERSION=`xcrun --sdk iphoneos --show-sdk-version`
|
||||
LIBUV_VERSION=0.10.28
|
||||
|
||||
if [[ ${#} -eq 0 ]]; then
|
||||
BUILD_FOR_DEVICE=true
|
||||
else
|
||||
BUILD_FOR_DEVICE=false
|
||||
fi
|
||||
|
||||
function step { >&2 echo -e "\033[1m\033[36m* $@\033[0m"; }
|
||||
function finish { >&2 echo -en "\033[0m"; }
|
||||
trap finish EXIT
|
||||
@@ -31,33 +39,43 @@ step "Creating build files..."
|
||||
export MASON_PLATFORM=ios
|
||||
export BUILDTYPE=${BUILDTYPE:-Release}
|
||||
export HOST=ios
|
||||
make Xcode/mbgl
|
||||
|
||||
step "Building iOS targets..."
|
||||
xcodebuild -sdk iphoneos${IOS_SDK_VERSION} \
|
||||
ARCHS="arm64 armv7 armv7s" \
|
||||
-project ./build/ios/mbgl.xcodeproj \
|
||||
-configuration ${BUILDTYPE} \
|
||||
-target everything \
|
||||
-jobs `sysctl -n hw.ncpu` | xcpretty -c
|
||||
make Xcode/ios
|
||||
|
||||
if [[ "${BUILD_FOR_DEVICE}" == true ]]; then
|
||||
step "Building iOS device targets..."
|
||||
xcodebuild -sdk iphoneos${IOS_SDK_VERSION} \
|
||||
ARCHS="arm64 armv7 armv7s" \
|
||||
ONLY_ACTIVE_ARCH=NO \
|
||||
-project ./build/ios/mbgl.xcodeproj \
|
||||
-configuration ${BUILDTYPE} \
|
||||
-target everything \
|
||||
-jobs ${JOBS} | xcpretty -c
|
||||
fi
|
||||
|
||||
step "Building iOS Simulator targets..."
|
||||
xcodebuild -sdk iphonesimulator${IOS_SDK_VERSION} \
|
||||
ARCHS="x86_64 i386" \
|
||||
ONLY_ACTIVE_ARCH=NO \
|
||||
-project ./build/ios/mbgl.xcodeproj \
|
||||
-configuration ${BUILDTYPE} \
|
||||
-target everything \
|
||||
-jobs `sysctl -n hw.ncpu` | xcpretty -c
|
||||
-jobs ${JOBS} | xcpretty -c
|
||||
|
||||
|
||||
step "Building static library..."
|
||||
LIBS=(core.a platform-ios.a asset-fs.a cache-sqlite.a http-nsurl.a)
|
||||
libtool -static -no_warning_for_no_symbols \
|
||||
-o ${OUTPUT}/static/lib${NAME}.a \
|
||||
${LIBS[@]/#/build/${BUILDTYPE}-iphoneos/libmbgl-} \
|
||||
${LIBS[@]/#/build/${BUILDTYPE}-iphonesimulator/libmbgl-} \
|
||||
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libuv.a`
|
||||
if [[ "${BUILD_FOR_DEVICE}" == true ]]; then
|
||||
libtool -static -no_warning_for_no_symbols \
|
||||
-o ${OUTPUT}/static/lib${NAME}.a \
|
||||
${LIBS[@]/#/build/${BUILDTYPE}-iphoneos/libmbgl-} \
|
||||
${LIBS[@]/#/build/${BUILDTYPE}-iphonesimulator/libmbgl-} \
|
||||
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libuv.a`
|
||||
else
|
||||
libtool -static -no_warning_for_no_symbols \
|
||||
-o ${OUTPUT}/static/lib${NAME}.a \
|
||||
${LIBS[@]/#/build/${BUILDTYPE}-iphonesimulator/libmbgl-} \
|
||||
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libuv.a`
|
||||
fi
|
||||
echo "Created ${OUTPUT}/static/lib${NAME}.a"
|
||||
|
||||
|
||||
35
scripts/ios/run.sh
Executable file
35
scripts/ios/run.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
set -u
|
||||
|
||||
BUILDTYPE=${BUILDTYPE:-Release}
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
# Add Mason to PATH
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
PUBLISH_TAG=($(git show -s --format=%B | sed -n 's/.*\[publish \([a-z]\{1,\}\)-v\([0-9.]\{1,\}\)\].*/\1 \2/p'))
|
||||
PUBLISH_PLATFORM=${PUBLISH_TAG[0],-}
|
||||
PUBLISH_VERSION=${PUBLISH_TAG[1],-}
|
||||
|
||||
|
||||
################################################################################
|
||||
# Build
|
||||
################################################################################
|
||||
|
||||
if [[ ${PUBLISH_PLATFORM} = 'ios' ]]; then
|
||||
# build & package iOS
|
||||
mapbox_time "package_ios" \
|
||||
make ipackage
|
||||
|
||||
# publish iOS build
|
||||
mapbox_time "deploy_ios" \
|
||||
./scripts/ios/publish.sh "${PUBLISH_VERSION}"
|
||||
else
|
||||
# build & test iOS
|
||||
mapbox_time "run_ios_tests" \
|
||||
make itest
|
||||
fi
|
||||
16
scripts/ios/test.sh
Executable file
16
scripts/ios/test.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
set -u
|
||||
|
||||
xcodebuild \
|
||||
-project ./test/ios/ios-tests.xcodeproj \
|
||||
-scheme 'Mapbox GL Tests' \
|
||||
-sdk iphonesimulator \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 5s,OS=7.1' \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 5s,OS=latest' \
|
||||
-destination 'platform=iOS Simulator,name=iPad 2,OS=7.1' \
|
||||
-destination 'platform=iOS Simulator,name=iPad 2,OS=latest' \
|
||||
test \
|
||||
| xcpretty
|
||||
13
scripts/linux/install.sh
Executable file
13
scripts/linux/install.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
mapbox_time "checkout_mason" \
|
||||
git submodule update --init .mason
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
mapbox_time "install_mesa" \
|
||||
mason install mesa 10.4.3
|
||||
75
scripts/linux/run.sh
Executable file
75
scripts/linux/run.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
BUILDTYPE=${BUILDTYPE:-Release}
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
# Add Mason to PATH
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
# Set the core file limit to unlimited so a core file is generated upon crash
|
||||
ulimit -c unlimited -S
|
||||
|
||||
################################################################################
|
||||
# X Server setup
|
||||
################################################################################
|
||||
|
||||
# Start the mock X server
|
||||
if [ -f /etc/init.d/xvfb ] ; then
|
||||
mapbox_time "start_xvfb" \
|
||||
sh -e /etc/init.d/xvfb start
|
||||
sleep 2 # sometimes, xvfb takes some time to start up
|
||||
fi
|
||||
|
||||
# Make sure we're connecting to xvfb
|
||||
export DISPLAY=:99.0
|
||||
|
||||
# Make sure we're loading the 10.4.3 libs we installed manually
|
||||
export LD_LIBRARY_PATH="`mason prefix mesa 10.4.3`/lib:${LD_LIBRARY_PATH:-}"
|
||||
|
||||
mapbox_time "glxinfo" \
|
||||
glxinfo
|
||||
|
||||
################################################################################
|
||||
# Build
|
||||
################################################################################
|
||||
|
||||
mapbox_time "checkout_styles" \
|
||||
git submodule update --init styles
|
||||
|
||||
mapbox_time "compile_program" \
|
||||
make linux -j${JOBS} BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "compile_tests" \
|
||||
make test -j${JOBS} BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
################################################################################
|
||||
# Test
|
||||
################################################################################
|
||||
|
||||
mapbox_time "checkout_test_suite" \
|
||||
git submodule update --init test/suite
|
||||
|
||||
mapbox_time "run_tests" \
|
||||
make test-* BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "compare_results" \
|
||||
./scripts/compare_images.sh
|
||||
|
||||
################################################################################
|
||||
# Deploy
|
||||
################################################################################
|
||||
|
||||
if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then
|
||||
# Install and add awscli to PATH for uploading the results
|
||||
mapbox_time "install_awscli" \
|
||||
pip install --user awscli
|
||||
export PATH="`python -m site --user-base`/bin:${PATH}"
|
||||
|
||||
mapbox_time_start "deploy_results"
|
||||
(cd ./test/suite/ && ./bin/deploy_results.sh)
|
||||
mapbox_time_finish
|
||||
fi
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
git submodule update --init .mason
|
||||
PATH=`pwd`/.mason:$PATH
|
||||
export MASON_DIR=`pwd`/.mason
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
cd bin
|
||||
$1 install --clang=1
|
||||
cd ../
|
||||
13
scripts/osx/install.sh
Executable file
13
scripts/osx/install.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
mapbox_time "checkout_mason" \
|
||||
git submodule update --init .mason
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
mapbox_time "install_xcpretty" \
|
||||
gem install xcpretty --no-rdoc --no-ri --no-document --quiet
|
||||
27
scripts/osx/run.sh
Executable file
27
scripts/osx/run.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
BUILDTYPE=${BUILDTYPE:-Release}
|
||||
|
||||
source ./scripts/travis_helper.sh
|
||||
|
||||
# Add Mason to PATH
|
||||
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
|
||||
|
||||
# Set the core file limit to unlimited so a core file is generated upon crash
|
||||
ulimit -c unlimited -S
|
||||
|
||||
################################################################################
|
||||
# Build
|
||||
################################################################################
|
||||
|
||||
mapbox_time "checkout_styles" \
|
||||
git submodule update --init styles
|
||||
|
||||
mapbox_time "compile_program" \
|
||||
make xosx -j${JOBS} BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "compile_tests" \
|
||||
make xtest -j${JOBS} BUILDTYPE=${BUILDTYPE}
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then
|
||||
#
|
||||
# install Linux dependencies
|
||||
#
|
||||
if [[ `lsb_release -r` =~ "12.04" ]]; then
|
||||
sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
fi
|
||||
sudo add-apt-repository --yes ppa:boost-latest/ppa
|
||||
|
||||
mapbox_time "apt_update" \
|
||||
sudo apt-get update -y
|
||||
|
||||
mapbox_time "install_gcc" \
|
||||
sudo apt-get -y install gcc-4.8 g++-4.8
|
||||
|
||||
mapbox_time "install_build_tools" \
|
||||
sudo apt-get -y install git build-essential zlib1g-dev automake gdb \
|
||||
libtool xutils-dev make cmake pkg-config python-pip \
|
||||
libboost1.55-dev libcurl4-openssl-dev \
|
||||
libpng-dev libsqlite3-dev
|
||||
|
||||
if [[ ${MASON_PLATFORM} != "android" ]]; then
|
||||
mapbox_time "install_opengl" \
|
||||
sudo apt-get -y install mesa-utils libxi-dev x11proto-randr-dev \
|
||||
x11proto-xext-dev libxrandr-dev \
|
||||
x11proto-xf86vidmode-dev libxxf86vm-dev \
|
||||
libxcursor-dev libxinerama-dev \
|
||||
llvm-3.4 # required for mesa
|
||||
|
||||
mapbox_time "install_mesa" \
|
||||
mason install mesa 10.4.3
|
||||
fi
|
||||
|
||||
mapbox_time "install_awscli" \
|
||||
sudo pip install awscli
|
||||
elif [[ ${TRAVIS_OS_NAME} == "osx" ]]; then
|
||||
#
|
||||
# install OS X dependencies
|
||||
#
|
||||
mapbox_time "install_build_tools" \
|
||||
brew install git
|
||||
|
||||
mapbox_time "install_awscli" \
|
||||
sudo pip install awscli
|
||||
|
||||
mapbox_time "install_xcpretty" \
|
||||
gem install xcpretty --no-rdoc --no-ri --no-document --quiet
|
||||
fi
|
||||
@@ -1,13 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
case `uname -s` in
|
||||
'Darwin') JOBS=$((`sysctl -n hw.ncpu` + 2)) ;;
|
||||
'Linux') JOBS=$((`nproc` + 2)) ;;
|
||||
*) JOBS=2 ;;
|
||||
esac
|
||||
|
||||
ANSI_CLEAR="\e[0m"
|
||||
|
||||
function mapbox_time_start {
|
||||
local name=$1
|
||||
mapbox_timer_name=$name
|
||||
|
||||
travis_fold start $name
|
||||
mapbox_fold start $name
|
||||
|
||||
mapbox_timer_id=$(printf %08x $(( RANDOM * RANDOM )))
|
||||
eval "mapbox_start_time_$mapbox_timer_id=$(travis_nanoseconds)"
|
||||
eval "mapbox_start_time_$mapbox_timer_id=$(mapbox_nanoseconds)"
|
||||
echo -en "travis_time:start:$mapbox_timer_id\n"
|
||||
}
|
||||
|
||||
@@ -16,11 +24,11 @@ function mapbox_time_finish {
|
||||
local timer_id=${2:-$mapbox_timer_id}
|
||||
local timer_start="mapbox_start_time_$timer_id"
|
||||
eval local start_time=\${$timer_start}
|
||||
local end_time=$(travis_nanoseconds)
|
||||
local end_time=$(mapbox_nanoseconds)
|
||||
local duration=$(($end_time-$start_time))
|
||||
echo -en "travis_time:end:$timer_id:start=$start_time,finish=$end_time,duration=$duration\n"
|
||||
|
||||
travis_fold end $name
|
||||
mapbox_fold end $name
|
||||
}
|
||||
|
||||
function mapbox_time {
|
||||
@@ -32,13 +40,13 @@ function mapbox_time {
|
||||
mapbox_time_finish $name $timer_id
|
||||
}
|
||||
|
||||
if [[ "${TRAVIS_COMMIT:-false}" == false ]]; then
|
||||
function travis_fold {
|
||||
function mapbox_fold {
|
||||
local action=$1
|
||||
local name=$2
|
||||
echo -en "travis_fold:${action}:${name}\r${ANSI_CLEAR}"
|
||||
}
|
||||
function travis_nanoseconds {
|
||||
|
||||
function mapbox_nanoseconds {
|
||||
local cmd="date"
|
||||
local format="+%s%N"
|
||||
local os=$(uname)
|
||||
@@ -51,11 +59,11 @@ function travis_nanoseconds {
|
||||
|
||||
$cmd -u $format
|
||||
}
|
||||
fi
|
||||
|
||||
export JOBS
|
||||
export ANSI_CLEAR
|
||||
export -f travis_fold
|
||||
export -f travis_nanoseconds
|
||||
export -f mapbox_fold
|
||||
export -f mapbox_nanoseconds
|
||||
export -f mapbox_time
|
||||
export -f mapbox_time_start
|
||||
export -f mapbox_time_finish
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
COMMIT_MESSAGE=$(git show -s --format=%B $1 | tr -d '\n')
|
||||
PUBLISH_TAG=$(echo "$COMMIT_MESSAGE" | grep -oE '\[publish [a-z0-9\.\-]+\]' | grep -oE '[a-z0-9\.\-]+' | tail -n1)
|
||||
PUBLISH_PLATFORM=$(echo "$PUBLISH_TAG" | awk -F '-v' '{ print $1 }')
|
||||
PUBLISH_VERSION=$(echo "$PUBLISH_TAG" | awk -F '-v' '{ print $2 }')
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
mapbox_time "checkout_styles" \
|
||||
git submodule update --init styles
|
||||
|
||||
if [[ $MASON_PLATFORM == "android" ]]; then
|
||||
./android/scripts/run-build.sh
|
||||
|
||||
elif [[ ${TRAVIS_OS_NAME} == "linux" ]]; then
|
||||
#
|
||||
# build & test Linux
|
||||
#
|
||||
mapbox_time "compile_program" \
|
||||
make linux -j$JOBS BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "compile_tests" \
|
||||
make test -j$JOBS BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "checkout_test_suite" \
|
||||
git submodule update --init test/suite
|
||||
|
||||
mapbox_time "run_tests" \
|
||||
make test-* BUILDTYPE=${BUILDTYPE}
|
||||
|
||||
mapbox_time "compare_results" \
|
||||
./scripts/compare_images.sh
|
||||
|
||||
if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then
|
||||
mapbox_time_start "deploy_results"
|
||||
(cd ./test/suite/ && ./bin/deploy_results.sh)
|
||||
mapbox_time_finish
|
||||
fi
|
||||
|
||||
elif [[ ${TRAVIS_OS_NAME} == "osx" && ${MASON_PLATFORM} == "osx" ]]; then
|
||||
#
|
||||
# build OS X
|
||||
#
|
||||
mapbox_time "build_osx" \
|
||||
make xosx -j$JOBS
|
||||
|
||||
elif [[ ${TRAVIS_OS_NAME} == "osx" && ${MASON_PLATFORM} == "ios" ]]; then
|
||||
#
|
||||
# build & package iOS
|
||||
#
|
||||
mapbox_time "package_ios"
|
||||
make ipackage
|
||||
#
|
||||
# conditionally deploy iOS build
|
||||
#
|
||||
if [[ -n "$PUBLISH_TAG" ]]; then
|
||||
mapbox_time "deploy_ios"
|
||||
./scripts/publish_ios.sh "$PUBLISH_VERSION"
|
||||
fi
|
||||
fi
|
||||
3
scripts/xcpretty.sh
Executable file
3
scripts/xcpretty.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
FN=$(which xcpretty) ; [ ! -z ${FN} ] && echo "| ${FN}"
|
||||
@@ -14,8 +14,3 @@ void LineElementsBuffer::add(element_type a, element_type b) {
|
||||
elements[0] = a;
|
||||
elements[1] = b;
|
||||
}
|
||||
|
||||
void PointElementsBuffer::add(element_type a) {
|
||||
uint16_t *data = static_cast<element_type *>(addElement());
|
||||
data[0] = a;
|
||||
}
|
||||
|
||||
@@ -44,16 +44,6 @@ public:
|
||||
void add(element_type a, element_type b);
|
||||
};
|
||||
|
||||
class PointElementsBuffer : public Buffer<
|
||||
2, // bytes per point (1 unsigned short)
|
||||
GL_ELEMENT_ARRAY_BUFFER
|
||||
> {
|
||||
public:
|
||||
typedef uint16_t element_type;
|
||||
|
||||
void add(element_type a);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user