From 57f0d6535cf4ce99aab1383ebef10341762f5104 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Fri, 31 Jul 2015 15:59:57 -0400 Subject: [PATCH 01/14] Document iOS region change delegate methods With #1026 the region delegate methods work reliably and as expected. This commit adds `mapView:regionWillChangeAnimated:`, `mapViewRegionIsChanging:`, and `mapView:regionDidChangeAnimated:` to the official documentation. --- include/mbgl/ios/MGLMapView.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h index 4b21d5bad..b8ea4ee7f 100644 --- a/include/mbgl/ios/MGLMapView.h +++ b/include/mbgl/ios/MGLMapView.h @@ -414,13 +414,22 @@ IB_DESIGNABLE // Responding to Map Position Changes -// TODO +/** Tells the delegate that the region displayed by the map view is about to change. + * + * This method is called whenever the currently displayed map region will start changing. + * @param animated Whether the change will cause an animated effect on the map. */ - (void)mapView:(MGLMapView *)mapView regionWillChangeAnimated:(BOOL)animated; -// TODO +/** Tells the delegate that the region displayed by the map view is changing. + * + * This method is called whenever the currently displayed map region changes. During movement, this method may be called many times to report updates to the map position. Therefore, your implementation of this method should be as lightweight as possible to avoid affecting performance. + * @param mapView The map view whose visible region is changing. */ - (void)mapViewRegionIsChanging:(MGLMapView *)mapView; -// TODO +/** Tells the delegate that the region displayed by the map view just changed. + * + * This method is called whenever the currently displayed map region has finished changing. + * @param animated Whether the change caused an animated effect on the map. */ - (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated; #pragma mark - Loading the Map Data From aa202f7e086fc298039eb3454150ad095cd2f64d Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Fri, 31 Jul 2015 16:18:43 -0400 Subject: [PATCH 02/14] Add more mapView! --- include/mbgl/ios/MGLMapView.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h index b8ea4ee7f..212a43983 100644 --- a/include/mbgl/ios/MGLMapView.h +++ b/include/mbgl/ios/MGLMapView.h @@ -417,6 +417,7 @@ IB_DESIGNABLE /** Tells the delegate that the region displayed by the map view is about to change. * * This method is called whenever the currently displayed map region will start changing. + * @param mapView The map view whose visible region will change. * @param animated Whether the change will cause an animated effect on the map. */ - (void)mapView:(MGLMapView *)mapView regionWillChangeAnimated:(BOOL)animated; @@ -429,6 +430,7 @@ IB_DESIGNABLE /** Tells the delegate that the region displayed by the map view just changed. * * This method is called whenever the currently displayed map region has finished changing. + * @param mapView The map view whose visible region changed. * @param animated Whether the change caused an animated effect on the map. */ - (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated; From cb54626bc286cf5a85b661cb0d4fd81cd3a23216 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 3 Aug 2015 17:05:46 -0500 Subject: [PATCH 03/14] #1982 - Updating to 2.5 --- android/java/build.gradle | 2 +- .../java/gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 51018 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/java/build.gradle b/android/java/build.gradle index 909007098..b1f4c8d08 100644 --- a/android/java/build.gradle +++ b/android/java/build.gradle @@ -1,4 +1,4 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. task wrapper(type: Wrapper) { - gradleVersion = '2.2.1' + gradleVersion = '2.5' } diff --git a/android/java/gradle/wrapper/gradle-wrapper.jar b/android/java/gradle/wrapper/gradle-wrapper.jar index 8c0fb64a8698b08ecc4158d828ca593c4928e9dd..c97a8bdb9088d370da7e88784a7a093b971aa23a 100644 GIT binary patch delta 43603 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 delta 42576 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 Date: Mon, 3 Aug 2015 17:10:10 -0500 Subject: [PATCH 04/14] #1982 - Updating wrapper .jar and .properties --- .../java/gradle/wrapper/gradle-wrapper.jar | Bin 51018 -> 52271 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/android/java/gradle/wrapper/gradle-wrapper.jar b/android/java/gradle/wrapper/gradle-wrapper.jar index c97a8bdb9088d370da7e88784a7a093b971aa23a..30d399d8d2bf522ff5de94bf434a7cc43a9a74b5 100644 GIT binary patch delta 20977 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 PLk7ag1cA^t9sc(}j}eS1 delta 19544 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 Date: Tue, 4 Aug 2015 12:45:10 +1000 Subject: [PATCH 05/14] First pass at tidying up Android annotation code --- android/cpp/jni.cpp | 774 +++++++++--------- .../mapboxgl/annotations/Annotation.java | 9 +- .../com/mapbox/mapboxgl/views/MapView.java | 18 +- .../mapbox/mapboxgl/views/NativeMapView.java | 91 +- include/mbgl/android/jni.hpp | 23 + 5 files changed, 467 insertions(+), 448 deletions(-) diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp index 85022dbc0..eee6bd8f6 100644 --- a/android/cpp/jni.cpp +++ b/android/cpp/jni.cpp @@ -42,6 +42,12 @@ jmethodID latLngConstructorId = nullptr; jfieldID latLngLatitudeId = nullptr; jfieldID latLngLongitudeId = nullptr; +jclass latLngZoomClass = nullptr; +jmethodID latLngZoomConstructorId = nullptr; +jfieldID latLngZoomLatitudeId = nullptr; +jfieldID latLngZoomLongitudeId = nullptr; +jfieldID latLngZoomZoomId = nullptr; + jclass markerClass = nullptr; jmethodID markerConstructorId = nullptr; jfieldID markerPositionId = nullptr; @@ -65,13 +71,6 @@ jfieldID polygonStrokeWidthId = nullptr; jfieldID polygonPointsId = nullptr; jfieldID polygonHolesId = nullptr; - -jclass latLngZoomClass = nullptr; -jmethodID latLngZoomConstructorId = nullptr; -jfieldID latLngZoomLatitudeId = nullptr; -jfieldID latLngZoomLongitudeId = nullptr; -jfieldID latLngZoomZoomId = nullptr; - jclass runtimeExceptionClass = nullptr; jclass nullPointerExceptionClass = nullptr; @@ -156,21 +155,21 @@ std::vector std_vector_string_from_jobject(JNIEnv *env, jobject jli return vector; } - jobjectArray array = + jobjectArray jarray = reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); - if (env->ExceptionCheck() || (array == nullptr)) { + if (env->ExceptionCheck() || (jarray == nullptr)) { env->ExceptionDescribe(); return vector; } - jsize len = env->GetArrayLength(array); + jsize len = env->GetArrayLength(jarray); if (len < 0) { env->ExceptionDescribe(); return vector; } for (jsize i = 0; i < len; i++) { - jstring jstr = reinterpret_cast(env->GetObjectArrayElement(array, i)); + jstring jstr = reinterpret_cast(env->GetObjectArrayElement(jarray, i)); if (jstr == nullptr) { env->ExceptionDescribe(); return vector; @@ -179,61 +178,12 @@ std::vector std_vector_string_from_jobject(JNIEnv *env, jobject jli vector.push_back(std_string_from_jstring(env, jstr)); } + env->DeleteLocalRef(jarray); + jarray = nullptr; + return vector; } -mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobject jlist) { - mbgl::AnnotationSegment segment; - - if (jlist == nullptr) { - if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) { - env->ExceptionDescribe(); - return segment; - } - return segment; - } - - jobjectArray array = - reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); - if (env->ExceptionCheck() || (array == nullptr)) { - env->ExceptionDescribe(); - return segment; - } - - jsize len = env->GetArrayLength(array); - if (len < 0) { - env->ExceptionDescribe(); - return segment; - } - - segment.reserve(len); - - for (jsize i = 0; i < len; i++) { - jobject latLng = reinterpret_cast(env->GetObjectArrayElement(array, i)); - if (latLng == nullptr) { - env->ExceptionDescribe(); - return segment; - } - - jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return segment; - } - - jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return segment; - } - - segment.push_back(mbgl::LatLng(latitude, longitude)); - env->DeleteLocalRef(latLng); - } - env->DeleteLocalRef(array); - return segment; -} - jobject std_vector_string_to_jobject(JNIEnv *env, std::vector vector) { jobject jlist = env->NewObject(arrayListClass, arrayListConstructorId); if (jlist == nullptr) { @@ -273,6 +223,91 @@ jlongArray std_vector_uint_to_jobject(JNIEnv *env, std::vector vector) return jarray; } +mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobject jlist) { + mbgl::AnnotationSegment segment; + + if (jlist == nullptr) { + if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) { + env->ExceptionDescribe(); + return segment; + } + return segment; + } + + jobjectArray jarray = + reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); + if (env->ExceptionCheck() || (jarray == nullptr)) { + env->ExceptionDescribe(); + return segment; + } + + jsize len = env->GetArrayLength(jarray); + if (len < 0) { + env->ExceptionDescribe(); + return segment; + } + + segment.reserve(len); + + for (jsize i = 0; i < len; i++) { + jobject latLng = reinterpret_cast(env->GetObjectArrayElement(jarray, i)); + if (latLng == nullptr) { + env->ExceptionDescribe(); + return segment; + } + + jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return segment; + } + + jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return segment; + } + + segment.push_back(mbgl::LatLng(latitude, longitude)); + env->DeleteLocalRef(latLng); + } + + env->DeleteLocalRef(jarray); + jarray = nullptr; + + return segment; +} + +std::pair annotation_std_pair_from_polygon_jobject(JNIEnv *env, jobject polygon) { + jfloat alpha = env->GetFloatField(polygon, polygonAlphaId); + //jboolean visible = env->GetBooleanField(polygon, polygonVisibleId); + jint fillColor = env->GetIntField(polygon, polygonFillColorId); + jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId); + + int rF = (fillColor >> 16) & 0xFF; + int gF = (fillColor >> 8) & 0xFF; + int bF = (fillColor) & 0xFF; + int aF = (fillColor >> 24) & 0xFF; + + int rS = (strokeColor >> 16) & 0xFF; + int gS = (strokeColor >> 8) & 0xFF; + int bS = (strokeColor) & 0xFF; + int aS = (strokeColor >> 24) & 0xFF; + + mbgl::StyleProperties shapeProperties; + mbgl::FillProperties fillProperties; + fillProperties.opacity = alpha; + fillProperties.stroke_color = {{ static_cast(rS) / 255.0f, static_cast(gS) / 255.0f, static_cast(bS) / 255.0f, static_cast(aS) / 255.0f }}; + fillProperties.fill_color = {{ static_cast(rF) / 255.0f, static_cast(gF) / 255.0f, static_cast(bF) / 255.0f, static_cast(aF) / 255.0f }}; + shapeProperties.set(fillProperties); + + jobject points = env->GetObjectField(polygon, polygonPointsId); + mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); + env->DeleteLocalRef(points); + + return std::make_pair(segment, shapeProperties); +} + } } @@ -530,271 +565,6 @@ void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, j nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration)); } -void JNICALL nativeSetSprite(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, - jstring symbol, jint width, jint height, jfloat scale, jbyteArray jpixels) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetSprite"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - - const std::string symbolName = std_string_from_jstring(env, symbol); - - jbyte* pixelData = env->GetByteArrayElements(jpixels, nullptr); - std::string pixels((char*)pixelData, width * height * 4); - env->ReleaseByteArrayElements(jpixels, pixelData, JNI_ABORT); - - auto spriteImage = std::make_shared( - uint16_t(width), - uint16_t(height), - float(scale), - std::move(pixels)); - - nativeMapView->getMap().setSprite(symbolName, spriteImage); -} - -jlong JNICALL nativeAddMarker(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject marker) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - - jobject position = env->GetObjectField(marker, markerPositionId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - jstring jsprite = (jstring)env->GetObjectField(marker, markerSpriteId); - std::string sprite = std_string_from_jstring(env, jsprite); - - jdouble latitude = env->GetDoubleField(position, latLngLatitudeId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - jdouble longitude = env->GetDoubleField(position, latLngLongitudeId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long. - return (jlong) nativeMapView->getMap().addPointAnnotation(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), sprite)); -} - -jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polyline) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolyline"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - - // ***** Java fields ***** // - // float alpha; - // boolean visible; - // int color - // float width - // List points - - jfloat alpha = env->GetFloatField(polyline, polylineAlphaId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - jboolean visible = env->GetBooleanField(polyline, polylineVisibleId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - visible = JNI_TRUE; - - jint color = env->GetIntField(polyline, polylineColorId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - int r = (color>>16)&0xFF; - int g = (color>>8)&0xFF; - int b = (color)&0xFF; - int a = (color>>24)&0xFF; - - jfloat width = env->GetFloatField(polyline, polylineWidthId); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - mbgl::StyleProperties shapeProperties; - mbgl::LineProperties lineProperties; - lineProperties.opacity = alpha; - lineProperties.color = {{ (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f }}; - lineProperties.width = width; - shapeProperties.set(lineProperties); - - jobject points = env->GetObjectField(polyline, polylinePointsId); - mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); - - std::vector shapes; - shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties); - - std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); - uint32_t id = shapeAnnotationIDs.at(0); - return (jlong) id; -} - - -std::pair readPolygon(JNIEnv *env, jobject polygon) { - // ***** Java fields ***** // - // float alpha; - // boolean visible; - // int fillColor - // int strokeColor - // float strokeWidth - // List points - // List> holes - - jfloat alpha = env->GetFloatField(polygon, polygonAlphaId); - jboolean visible = env->GetBooleanField(polygon, polygonVisibleId); - visible = JNI_TRUE; - jint fillColor = env->GetIntField(polygon, polygonFillColorId); - jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId); - - int rF = (fillColor>>16)&0xFF; - int gF = (fillColor>>8)&0xFF; - int bF = (fillColor)&0xFF; - int aF = (fillColor>>24)&0xFF; - - int rS = (strokeColor>>16)&0xFF; - int gS = (strokeColor>>8)&0xFF; - int bS = (strokeColor)&0xFF; - int aS = (strokeColor>>24)&0xFF; - - // jfloat strokeWidth = env->GetFloatField(polygon, polygonStrokeWidthId); - // if (env->ExceptionCheck()) { - // env->ExceptionDescribe(); - // return -1; - // } - - mbgl::StyleProperties shapeProperties; - mbgl::FillProperties fillProperties; - fillProperties.opacity = alpha; - fillProperties.stroke_color = {{ (float)rS / 255.0f, (float)gS / 255.0f, (float)bS / 255.0f, (float)aS / 255.0f }}; - fillProperties.fill_color = {{ (float)rF / 255.0f, (float)gF / 255.0f, (float)bF / 255.0f, (float)aF / 255.0f }}; - shapeProperties.set(fillProperties); - - jobject points = env->GetObjectField(polygon, polygonPointsId); - mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); - env->DeleteLocalRef(points); - - return std::make_pair(segment, shapeProperties); -} - -jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polygon) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygon"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - - std::vector shapes; - std::pair segment = readPolygon(env, polygon); - - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return -1; - } - - shapes.emplace_back(mbgl::AnnotationSegments {{ segment.first }}, segment.second); - - std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); - uint32_t id = shapeAnnotationIDs.at(0); - return (jlong) id; -} - -jlongArray JNICALL nativeAddPolygons(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject jlist) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygons"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - - std::vector shapes; - - if (jlist == nullptr) { - if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) { - env->ExceptionDescribe(); - return nullptr; - } - return nullptr; - } - - jobjectArray array = - reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); - if (env->ExceptionCheck() || (array == nullptr)) { - env->ExceptionDescribe(); - return nullptr; - } - - jsize len = env->GetArrayLength(array); - if (len < 0) { - env->ExceptionDescribe(); - return nullptr; - } - - shapes.reserve(len); - - for (jsize i = 0; i < len; i++) { - jobject polygon = reinterpret_cast(env->GetObjectArrayElement(array, i)); - - std::pair segment = readPolygon(env, polygon); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - return nullptr; - } - - shapes.emplace_back(mbgl::AnnotationSegments {{ segment.first }}, segment.second); - - env->DeleteLocalRef(polygon); - } - - std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); - return std_vector_uint_to_jobject(env, shapeAnnotationIDs); -} - -void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong annotationId) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - nativeMapView->getMap().removeAnnotation((uint32_t)annotationId); -} - -void JNICALL nativeRemoveAnnotations(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlongArray array) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotations"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - - std::vector ids; - - if (env->ExceptionCheck() || (array == nullptr)) { - env->ExceptionDescribe(); - return; - } - - jsize len = env->GetArrayLength(array); - if (len < 0) { - env->ExceptionDescribe(); - return; - } - - ids.reserve(len); - jlong* jids = env->GetLongArrayElements(array, nullptr); - - for (jsize i = 0; i < len; i++) { - if(jids[i] == -1L) - continue; - ids.push_back((uint32_t) jids[i]); - } - - env->ReleaseLongArrayElements(array, jids, JNI_ABORT); - - nativeMapView->getMap().removeAnnotations(ids); -} - jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng"); assert(nativeMapViewPtr != 0); @@ -956,6 +726,219 @@ void JNICALL nativeResetNorth(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) nativeMapView->getMap().resetNorth(); } +jlong JNICALL nativeAddMarker(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject marker) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + jobject position = env->GetObjectField(marker, markerPositionId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + jstring jsprite = reinterpret_cast(env->GetObjectField(marker, markerSpriteId)); + std::string sprite = std_string_from_jstring(env, jsprite); + + jdouble latitude = env->GetDoubleField(position, latLngLatitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + jdouble longitude = env->GetDoubleField(position, latLngLongitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long. + return nativeMapView->getMap().addPointAnnotation(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), sprite)); +} + +jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polyline) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolyline"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + jfloat alpha = env->GetFloatField(polyline, polylineAlphaId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + /*jboolean visible = env->GetBooleanField(polyline, polylineVisibleId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + }*/ + + jint color = env->GetIntField(polyline, polylineColorId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = (color) & 0xFF; + int a = (color >> 24) & 0xFF; + + jfloat width = env->GetFloatField(polyline, polylineWidthId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + mbgl::StyleProperties shapeProperties; + mbgl::LineProperties lineProperties; + lineProperties.opacity = alpha; + lineProperties.color = {{ static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f, static_cast(a) / 255.0f }}; + lineProperties.width = width; + shapeProperties.set(lineProperties); + + jobject points = env->GetObjectField(polyline, polylinePointsId); + mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); + + std::vector shapes; + shapes.emplace_back(mbgl::AnnotationSegments { segment }, shapeProperties); + + std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); + uint32_t id = shapeAnnotationIDs.at(0); + + return id; +} + +jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polygon) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygon"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + std::vector shapes; + std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); + + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second); + + std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); + uint32_t id = shapeAnnotationIDs.at(0); + return id; +} + +jlongArray JNICALL nativeAddPolygons(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject jlist) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygons"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + std::vector shapes; + + if (jlist == nullptr) { + if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) { + env->ExceptionDescribe(); + return nullptr; + } + return nullptr; + } + + jobjectArray jarray = + reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); + if (env->ExceptionCheck() || (jarray == nullptr)) { + env->ExceptionDescribe(); + return nullptr; + } + + jsize len = env->GetArrayLength(jarray); + if (len < 0) { + env->ExceptionDescribe(); + return nullptr; + } + + shapes.reserve(len); + + for (jsize i = 0; i < len; i++) { + jobject polygon = reinterpret_cast(env->GetObjectArrayElement(jarray, i)); + + std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second); + + env->DeleteLocalRef(polygon); + } + + env->DeleteLocalRef(jarray); + + std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); + return std_vector_uint_to_jobject(env, shapeAnnotationIDs); +} + +void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong annotationId) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + nativeMapView->getMap().removeAnnotation(static_cast(annotationId)); +} + +void JNICALL nativeRemoveAnnotations(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlongArray jarray) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotations"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + std::vector ids; + + if (env->ExceptionCheck() || (jarray == nullptr)) { + env->ExceptionDescribe(); + return; + } + + jsize len = env->GetArrayLength(jarray); + if (len < 0) { + env->ExceptionDescribe(); + return; + } + + ids.reserve(len); + jlong* jids = env->GetLongArrayElements(jarray, nullptr); + + for (jsize i = 0; i < len; i++) { + if(jids[i] == -1L) + continue; + ids.push_back(static_cast(jids[i])); + } + + env->ReleaseLongArrayElements(jarray, jids, JNI_ABORT); + + nativeMapView->getMap().removeAnnotations(ids); +} + +void JNICALL nativeSetSprite(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, + jstring symbol, jint width, jint height, jfloat scale, jbyteArray jpixels) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetSprite"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + const std::string symbolName = std_string_from_jstring(env, symbol); + + jbyte* pixelData = env->GetByteArrayElements(jpixels, nullptr); + std::string pixels(reinterpret_cast(pixelData), width * height * 4); + env->ReleaseByteArrayElements(jpixels, pixelData, JNI_ABORT); + + auto spriteImage = std::make_shared( + uint16_t(width), + uint16_t(height), + float(scale), + std::move(pixels)); + + nativeMapView->getMap().setSprite(symbolName, spriteImage); +} + void JNICALL nativeOnLowMemory(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnLowMemory"); assert(nativeMapViewPtr != 0); @@ -1179,6 +1162,36 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } + latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom"); + if (latLngZoomClass == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + latLngZoomConstructorId = env->GetMethodID(latLngZoomClass, "", "(DDD)V"); + if (latLngZoomConstructorId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + latLngZoomLatitudeId = env->GetFieldID(latLngZoomClass, "latitude", "D"); + if (latLngZoomLatitudeId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + latLngZoomLongitudeId = env->GetFieldID(latLngZoomClass, "longitude", "D"); + if (latLngZoomLongitudeId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + latLngZoomZoomId = env->GetFieldID(latLngZoomClass, "zoom", "D"); + if (latLngZoomZoomId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + markerClass = env->FindClass("com/mapbox/mapboxgl/annotations/Marker"); if (markerClass == nullptr) { env->ExceptionDescribe(); @@ -1299,36 +1312,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } - latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom"); - if (latLngZoomClass == nullptr) { - env->ExceptionDescribe(); - return JNI_ERR; - } - - latLngZoomConstructorId = env->GetMethodID(latLngZoomClass, "", "(DDD)V"); - if (latLngZoomConstructorId == nullptr) { - env->ExceptionDescribe(); - return JNI_ERR; - } - - latLngZoomLatitudeId = env->GetFieldID(latLngZoomClass, "latitude", "D"); - if (latLngZoomLatitudeId == nullptr) { - env->ExceptionDescribe(); - return JNI_ERR; - } - - latLngZoomLongitudeId = env->GetFieldID(latLngZoomClass, "longitude", "D"); - if (latLngZoomLongitudeId == nullptr) { - env->ExceptionDescribe(); - return JNI_ERR; - } - - latLngZoomZoomId = env->GetFieldID(latLngZoomClass, "zoom", "D"); - if (latLngZoomZoomId == nullptr) { - env->ExceptionDescribe(); - return JNI_ERR; - } - jclass nativeMapViewClass = env->FindClass("com/mapbox/mapboxgl/views/NativeMapView"); if (nativeMapViewClass == nullptr) { env->ExceptionDescribe(); @@ -1492,17 +1475,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { {"nativeMoveBy", "(JDDJ)V", reinterpret_cast(&nativeMoveBy)}, {"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V", reinterpret_cast(&nativeSetLatLng)}, - {"nativeSetSprite", "(JLjava/lang/String;IIF[B)V", reinterpret_cast(&nativeSetSprite)}, - {"nativeAddMarker", "(JLcom/mapbox/mapboxgl/annotations/Marker;)J", - reinterpret_cast(&nativeAddMarker)}, - {"nativeAddPolyline", "(JLcom/mapbox/mapboxgl/annotations/Polyline;)J", - reinterpret_cast(&nativeAddPolyline)}, - {"nativeAddPolygon", "(JLcom/mapbox/mapboxgl/annotations/Polygon;)J", - reinterpret_cast(&nativeAddPolygon)}, - {"nativeAddPolygons", "(JLjava/util/List;)[J", - reinterpret_cast(&nativeAddPolygons)}, - {"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast(&nativeRemoveAnnotation)}, - {"nativeRemoveAnnotations", "(J[J)V", reinterpret_cast(&nativeRemoveAnnotations)}, {"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeGetLatLng)}, {"nativeResetPosition", "(J)V", reinterpret_cast(&nativeResetPosition)}, @@ -1529,6 +1501,17 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { &nativeSetBearing))}, {"nativeGetBearing", "(J)D", reinterpret_cast(&nativeGetBearing)}, {"nativeResetNorth", "(J)V", reinterpret_cast(&nativeResetNorth)}, + {"nativeAddMarker", "(JLcom/mapbox/mapboxgl/annotations/Marker;)J", + reinterpret_cast(&nativeAddMarker)}, + {"nativeAddPolyline", "(JLcom/mapbox/mapboxgl/annotations/Polyline;)J", + reinterpret_cast(&nativeAddPolyline)}, + {"nativeAddPolygon", "(JLcom/mapbox/mapboxgl/annotations/Polygon;)J", + reinterpret_cast(&nativeAddPolygon)}, + {"nativeAddPolygons", "(JLjava/util/List;)[J", + reinterpret_cast(&nativeAddPolygons)}, + {"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast(&nativeRemoveAnnotation)}, + {"nativeRemoveAnnotations", "(J[J)V", reinterpret_cast(&nativeRemoveAnnotations)}, + {"nativeSetSprite", "(JLjava/lang/String;IIF[B)V", reinterpret_cast(&nativeSetSprite)}, {"nativeOnLowMemory", "(J)V", reinterpret_cast(&nativeOnLowMemory)}, {"nativeSetDebug", "(JZ)V", reinterpret_cast(&nativeSetDebug)}, {"nativeToggleDebug", "(J)V", reinterpret_cast(&nativeToggleDebug)}, @@ -1558,28 +1541,37 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } + latLngZoomClass = reinterpret_cast(env->NewGlobalRef(latLngZoomClass)); + if (latLngZoomClass == nullptr) { + env->ExceptionDescribe(); + env->DeleteGlobalRef(latLngClass); + return JNI_ERR; + } + markerClass = reinterpret_cast(env->NewGlobalRef(markerClass)); if (markerClass == nullptr) { env->ExceptionDescribe(); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); return JNI_ERR; } polylineClass = reinterpret_cast(env->NewGlobalRef(polylineClass)); if (polylineClass == nullptr) { env->ExceptionDescribe(); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(markerClass); return JNI_ERR; } polygonClass = reinterpret_cast(env->NewGlobalRef(polygonClass)); if (polygonClass == nullptr) { - env->ExceptionDescribe(); - return JNI_ERR; - } - - latLngZoomClass = reinterpret_cast(env->NewGlobalRef(latLngZoomClass)); - if (latLngZoomClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(markerClass); + env->DeleteGlobalRef(polylineClass); return JNI_ERR; } @@ -1588,6 +1580,9 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(markerClass); + env->DeleteGlobalRef(polylineClass); + env->DeleteGlobalRef(polygonClass); return JNI_ERR; } @@ -1597,6 +1592,9 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(markerClass); + env->DeleteGlobalRef(polylineClass); + env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); return JNI_ERR; } @@ -1606,6 +1604,9 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(markerClass); + env->DeleteGlobalRef(polylineClass); + env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); return JNI_ERR; @@ -1616,18 +1617,23 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(markerClass); + env->DeleteGlobalRef(polylineClass); + env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); env->DeleteGlobalRef(arrayListClass); return JNI_ERR; } - pointFClass = reinterpret_cast(env->NewGlobalRef(pointFClass)); if (pointFClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(polylineClass); + env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); env->DeleteGlobalRef(arrayListClass); @@ -1635,7 +1641,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } - char release[PROP_VALUE_MAX] = ""; __system_property_get("ro.build.version.release", release); androidRelease = std::string(release); @@ -1659,6 +1664,13 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { latLngLongitudeId = nullptr; latLngLatitudeId = nullptr; + env->DeleteGlobalRef(latLngZoomClass); + latLngZoomClass = nullptr; + latLngZoomConstructorId = nullptr; + latLngZoomLongitudeId = nullptr; + latLngZoomLatitudeId = nullptr; + latLngZoomZoomId = nullptr; + env->DeleteGlobalRef(markerClass); markerClass = nullptr; markerConstructorId = nullptr; @@ -1685,14 +1697,6 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { polygonPointsId = nullptr; polygonHolesId = nullptr; - - env->DeleteGlobalRef(latLngZoomClass); - latLngZoomClass = nullptr; - latLngZoomConstructorId = nullptr; - latLngZoomLongitudeId = nullptr; - latLngZoomLatitudeId = nullptr; - latLngZoomZoomId = nullptr; - onInvalidateId = nullptr; onMapChangedId = nullptr; onFpsChangedId = nullptr; diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java index 6feb733f0..4f172c6e2 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java @@ -10,20 +10,19 @@ public abstract class Annotation { * * Internal C++ id is stored as unsigned int. */ - protected Long id; // null unless added to a MapView + protected long id = -1; // -1 unless added to a MapView private MapView mapView; - float alpha = 1; + float alpha = 1.0f; boolean visible = true; - public Annotation() {} public float getAlpha() { return alpha; } - public Long getId() { + public long getId() { return id; } @@ -40,7 +39,7 @@ public abstract class Annotation { this.alpha = alpha; } - public void setId(Long id) { + public void setId(long id) { this.id = id; } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index bc4b823c0..473f33a1a 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -241,7 +241,7 @@ public class MapView extends SurfaceView { public Marker addMarker(MarkerOptions markerOptions) { Marker marker = markerOptions.getMarker(); - Long id = mNativeMapView.addMarker(marker); + long id = mNativeMapView.addMarker(marker); marker.setId(id); // the annotation needs to know its id marker.setMapView(this); // the annotation needs to know which map view it is in annotations.add(marker); @@ -250,7 +250,7 @@ public class MapView extends SurfaceView { public Polyline addPolyline(PolylineOptions polylineOptions) { Polyline polyline = polylineOptions.getPolyline(); - Long id = mNativeMapView.addPolyline(polyline); + long id = mNativeMapView.addPolyline(polyline); polyline.setId(id); polyline.setMapView(this); annotations.add(polyline); @@ -259,7 +259,7 @@ public class MapView extends SurfaceView { public Polygon addPolygon(PolygonOptions polygonOptions) { Polygon polygon = polygonOptions.getPolygon(); - Long id = mNativeMapView.addPolygon(polygon); + long id = mNativeMapView.addPolygon(polygon); polygon.setId(id); polygon.setMapView(this); annotations.add(polygon); @@ -274,7 +274,7 @@ public class MapView extends SurfaceView { long[] ids = mNativeMapView.addPolygons(polygons); - for(int i=0; i polygon) { - // NH TODO Throw exception if returns -1 - return nativeAddPolygons(mNativeMapViewPtr, polygon); - } - - public void removeAnnotation(long id) { - nativeRemoveAnnotation(mNativeMapViewPtr, id); - } - - public void removeAnnotations(long[] ids) { - nativeRemoveAnnotations(mNativeMapViewPtr, ids); - } - public LatLng getLatLng() { return nativeGetLatLng(mNativeMapViewPtr); } @@ -356,6 +325,34 @@ class NativeMapView { nativeResetNorth(mNativeMapViewPtr); } + public long addMarker(Marker marker) { + return nativeAddMarker(mNativeMapViewPtr, marker); + } + + public long addPolyline(Polyline polyline) { + return nativeAddPolyline(mNativeMapViewPtr, polyline); + } + + public long addPolygon(Polygon polygon) { + return nativeAddPolygon(mNativeMapViewPtr, polygon); + } + + public long[] addPolygons(List polygon) { + return nativeAddPolygons(mNativeMapViewPtr, polygon); + } + + public void removeAnnotation(long id) { + nativeRemoveAnnotation(mNativeMapViewPtr, id); + } + + public void removeAnnotations(long[] ids) { + nativeRemoveAnnotations(mNativeMapViewPtr, ids); + } + + public void setSprite(String symbol, int width, int height, float scale, byte[] pixels) { + nativeSetSprite(mNativeMapViewPtr, symbol, width, height, scale, pixels); + } + public void onLowMemory() { nativeOnLowMemory(mNativeMapViewPtr); } @@ -392,7 +389,7 @@ class NativeMapView { nativeSetReachability(mNativeMapViewPtr, status); } - //public void getWorldBoundsMeters(); + //public void (); //public void getWorldBoundsLatLng(); @@ -507,21 +504,6 @@ class NativeMapView { private native void nativeSetLatLng(long nativeMapViewPtr, LatLng latLng, long duration); - private native void nativeSetSprite(long nativeMapViewPtr, String symbol, - int width, int height, float scale, byte[] pixels); - - private native long nativeAddMarker(long nativeMapViewPtr, Marker marker); - - private native long nativeAddPolyline(long nativeMapViewPtr, Polyline polyline); - - private native long nativeAddPolygon(long mNativeMapViewPtr, Polygon polygon); - - private native long[] nativeAddPolygons(long mNativeMapViewPtr, List polygon); - - private native void nativeRemoveAnnotation(long nativeMapViewPtr, long id); - - private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id); - private native LatLng nativeGetLatLng(long nativeMapViewPtr); private native void nativeResetPosition(long nativeMapViewPtr); @@ -563,6 +545,21 @@ class NativeMapView { private native void nativeResetNorth(long nativeMapViewPtr); + private native long nativeAddMarker(long nativeMapViewPtr, Marker marker); + + private native long nativeAddPolyline(long nativeMapViewPtr, Polyline polyline); + + private native long nativeAddPolygon(long mNativeMapViewPtr, Polygon polygon); + + private native long[] nativeAddPolygons(long mNativeMapViewPtr, List polygon); + + private native void nativeRemoveAnnotation(long nativeMapViewPtr, long id); + + private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id); + + private native void nativeSetSprite(long nativeMapViewPtr, String symbol, + int width, int height, float scale, byte[] pixels); + private native void nativeOnLowMemory(long nativeMapViewPtr); private native void nativeSetDebug(long nativeMapViewPtr, boolean debug); diff --git a/include/mbgl/android/jni.hpp b/include/mbgl/android/jni.hpp index 48e2740b0..f27c8c844 100644 --- a/include/mbgl/android/jni.hpp +++ b/include/mbgl/android/jni.hpp @@ -31,6 +31,29 @@ extern jfieldID latLngZoomLatitudeId; extern jfieldID latLngZoomLongitudeId; extern jfieldID latLngZoomZoomId; +extern jclass markerClass; +extern jmethodID markerConstructorId; +extern jfieldID markerPositionId; +extern jfieldID markerSpriteId; + +extern jclass polylineClass; +extern jmethodID polylineConstructorId; +extern jfieldID polylineAlphaId; +extern jfieldID polylineVisibleId; +extern jfieldID polylineColorId; +extern jfieldID polylineWidthId; +extern jfieldID polylinePointsId; + +extern jclass polygonClass; +extern jmethodID polygonConstructorId; +extern jfieldID polygonAlphaId; +extern jfieldID polygonVisibleId; +extern jfieldID polygonFillColorId; +extern jfieldID polygonStrokeColorId; +extern jfieldID polygonStrokeWidthId; +extern jfieldID polygonPointsId; +extern jfieldID polygonHolesId; + extern jclass runtimeExceptionClass; extern jclass nullPointerExceptionClass; From 78ec33320ff5837f23e85e336716692f63fd0254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Mon, 3 Aug 2015 15:01:35 +0200 Subject: [PATCH 06/14] don't use certain STL functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 
some functions defined in , as well as std::to_string aren't available on GNU's STL for some platforms, e.g. Android --- include/mbgl/util/projection.hpp | 8 ++++---- linux/main.cpp | 2 ++ linux/mapboxgl-app.gypi | 1 + macosx/mapboxgl-app.gypi | 1 + platform/default/asset_request_fs.cpp | 3 ++- platform/default/glfw_view.cpp | 3 ++- platform/default/http_request_curl.cpp | 6 ++++-- platform/default/sqlite3.cpp | 1 + src/csscolorparser/csscolorparser.cpp | 2 +- src/mbgl/geometry/collision_box_buffer.cpp | 4 ++-- src/mbgl/geometry/debug_font_buffer.cpp | 4 ++-- src/mbgl/geometry/icon_buffer.cpp | 6 +++--- src/mbgl/geometry/line_buffer.cpp | 4 ++-- src/mbgl/geometry/text_buffer.cpp | 6 +++--- src/mbgl/map/annotation.cpp | 12 +++++++----- src/mbgl/map/map.cpp | 6 +++--- src/mbgl/map/map_context.cpp | 3 ++- src/mbgl/map/source.cpp | 4 ++-- src/mbgl/map/transform.cpp | 4 ++-- src/mbgl/map/transform_state.cpp | 4 ++-- src/mbgl/platform/gl.cpp | 3 ++- src/mbgl/platform/log.cpp | 1 + src/mbgl/renderer/fill_bucket.cpp | 2 +- src/mbgl/renderer/frame_history.cpp | 4 ++-- src/mbgl/renderer/painter_line.cpp | 2 +- src/mbgl/renderer/symbol_bucket.cpp | 2 +- src/mbgl/text/collision_tile.cpp | 2 +- src/mbgl/text/font_stack.cpp | 4 ++-- src/mbgl/text/get_anchors.cpp | 2 +- src/mbgl/util/compression.cpp | 1 + src/mbgl/util/geojsonvt | 2 +- src/mbgl/util/io.cpp | 1 + src/mbgl/util/tile_cover.cpp | 8 ++++---- src/mbgl/util/time.cpp | 2 ++ 34 files changed, 69 insertions(+), 51 deletions(-) diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp index f301d9300..956390085 100644 --- a/include/mbgl/util/projection.hpp +++ b/include/mbgl/util/projection.hpp @@ -33,16 +33,16 @@ public: static inline double getMetersPerPixelAtLatitude(const double lat, const double zoom) { const double mapPixelWidthAtZoom = std::pow(2.0, zoom) * util::tileSize; - const double constrainedLatitude = std::fmin(std::fmax(lat, -util::LATITUDE_MAX), util::LATITUDE_MAX); + const double constrainedLatitude = ::fmin(::fmax(lat, -util::LATITUDE_MAX), util::LATITUDE_MAX); return std::cos(constrainedLatitude * util::DEG2RAD) * util::M2PI * util::EARTH_RADIUS_M / mapPixelWidthAtZoom; } static inline const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) { - const double constrainedLatitude = std::fmin(std::fmax(latLng.latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); + const double constrainedLatitude = ::fmin(::fmax(latLng.latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); const double m = 1 - 1e-15; - const double f = std::fmin(std::fmax(std::sin(util::DEG2RAD * constrainedLatitude), -m), m); + const double f = ::fmin(::fmax(std::sin(util::DEG2RAD * constrainedLatitude), -m), m); const double easting = util::EARTH_RADIUS_M * latLng.longitude * util::DEG2RAD; const double northing = 0.5 * util::EARTH_RADIUS_M * std::log((1 + f) / (1 - f)); @@ -54,7 +54,7 @@ public: double latitude = (2 * std::atan(std::exp(projectedMeters.northing / util::EARTH_RADIUS_M)) - (M_PI / 2)) * util::RAD2DEG; double longitude = projectedMeters.easting * util::RAD2DEG / util::EARTH_RADIUS_M; - latitude = std::fmin(std::fmax(latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); + latitude = ::fmin(::fmax(latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); return LatLng(latitude, longitude); } diff --git a/linux/main.cpp b/linux/main.cpp index 9145b180f..9acbbb659 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include namespace { diff --git a/linux/mapboxgl-app.gypi b/linux/mapboxgl-app.gypi index 35ca322e2..3d43da384 100644 --- a/linux/mapboxgl-app.gypi +++ b/linux/mapboxgl-app.gypi @@ -29,6 +29,7 @@ 'variables' : { 'cflags_cc': [ + '<@(boost_cflags)', '<@(glfw3_cflags)', ], 'ldflags': [ diff --git a/macosx/mapboxgl-app.gypi b/macosx/mapboxgl-app.gypi index c56bca659..3b7d904a7 100644 --- a/macosx/mapboxgl-app.gypi +++ b/macosx/mapboxgl-app.gypi @@ -34,6 +34,7 @@ 'variables' : { 'cflags_cc': [ + '<@(boost_cflags)', '<@(glfw3_cflags)', ], 'ldflags': [ diff --git a/platform/default/asset_request_fs.cpp b/platform/default/asset_request_fs.cpp index 4511cf882..733e240fb 100644 --- a/platform/default/asset_request_fs.cpp +++ b/platform/default/asset_request_fs.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -131,7 +132,7 @@ void AssetRequest::fileStated(uv_fs_t *req) { #else self->response->modified = stat->st_mtime; #endif - self->response->etag = std::to_string(stat->st_ino); + self->response->etag = util::toString(stat->st_ino); const auto size = (unsigned int)(stat->st_size); self->response->data.resize(size); self->buffer = uv_buf_init(const_cast(self->response->data.data()), size); diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index 49ae8c4f6..fb08b9234 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -188,7 +189,7 @@ void GLFWView::addRandomCustomPointAnnotations(int count) { for (int i = 0; i < count; i++) { static int spriteID = 1; - const auto name = std::string{ "marker-" } + std::to_string(spriteID++); + const auto name = std::string{ "marker-" } + mbgl::util::toString(spriteID++); map->setSprite(name, makeSpriteImage(22, 22, 1)); spriteIDs.push_back(name); points.emplace_back(makeRandomPoint(), name); diff --git a/platform/default/http_request_curl.cpp b/platform/default/http_request_curl.cpp index 6b2c38e77..22cb1df6f 100644 --- a/platform/default/http_request_curl.cpp +++ b/platform/default/http_request_curl.cpp @@ -7,6 +7,7 @@ #include #include +#include #include @@ -20,6 +21,7 @@ #include #include #include +#include void handleError(CURLMcode code) { if (code != CURLM_OK) { @@ -700,12 +702,12 @@ void HTTPCURLRequest::handleResult(CURLcode code) { } else if (responseCode >= 500 && responseCode < 600) { // Server errors may be temporary, so back off exponentially. response->status = Response::Error; - response->message = "HTTP status code " + std::to_string(responseCode); + response->message = "HTTP status code " + util::toString(responseCode); return finish(ResponseStatus::TemporaryError); } else { // We don't know how to handle any other errors, so declare them as permanently failing. response->status = Response::Error; - response->message = "HTTP status code " + std::to_string(responseCode); + response->message = "HTTP status code " + util::toString(responseCode); return finish(ResponseStatus::PermanentError); } } diff --git a/platform/default/sqlite3.cpp b/platform/default/sqlite3.cpp index b2ae4e65b..ca525cd20 100644 --- a/platform/default/sqlite3.cpp +++ b/platform/default/sqlite3.cpp @@ -3,6 +3,7 @@ #include #include +#include // Check sqlite3 library version. const static bool sqliteVersionCheck = []() { diff --git a/src/csscolorparser/csscolorparser.cpp b/src/csscolorparser/csscolorparser.cpp index 7ba989fde..8281eb420 100644 --- a/src/csscolorparser/csscolorparser.cpp +++ b/src/csscolorparser/csscolorparser.cpp @@ -116,7 +116,7 @@ const size_t namedColorCount = sizeof (namedColors) / sizeof (NamedColor); template uint8_t clamp_css_byte(T i) { // Clamp to integer 0 .. 255. - i = std::round(i); // Seems to be what Chrome does (vs truncation). + i = ::round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 255 ? 255 : i; } diff --git a/src/mbgl/geometry/collision_box_buffer.cpp b/src/mbgl/geometry/collision_box_buffer.cpp index 050a999db..da9031c89 100644 --- a/src/mbgl/geometry/collision_box_buffer.cpp +++ b/src/mbgl/geometry/collision_box_buffer.cpp @@ -13,8 +13,8 @@ size_t CollisionBoxVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, f int16_t *shorts = static_cast(data); shorts[0] /* pos */ = x; shorts[1] /* pos */ = y; - shorts[2] /* offset */ = std::round(ox); // use 1/64 pixels for placement - shorts[3] /* offset */ = std::round(oy); + shorts[2] /* offset */ = ::round(ox); // use 1/64 pixels for placement + shorts[3] /* offset */ = ::round(oy); uint8_t *ubytes = static_cast(data); // a_data1 diff --git a/src/mbgl/geometry/debug_font_buffer.cpp b/src/mbgl/geometry/debug_font_buffer.cpp index 1ec71463e..e4af70766 100644 --- a/src/mbgl/geometry/debug_font_buffer.cpp +++ b/src/mbgl/geometry/debug_font_buffer.cpp @@ -23,8 +23,8 @@ void DebugFontBuffer::addText(const char *text, double left, double baseline, do if (glyph.data[j] == -1 && glyph.data[j + 1] == -1) { prev = false; } else { - int16_t x = std::round(left + glyph.data[j] * scale); - int16_t y = std::round(baseline - glyph.data[j + 1] * scale); + int16_t x = ::round(left + glyph.data[j] * scale); + int16_t y = ::round(baseline - glyph.data[j + 1] * scale); if (prev) { coords = static_cast(addElement()); coords[0] = prev_x; diff --git a/src/mbgl/geometry/icon_buffer.cpp b/src/mbgl/geometry/icon_buffer.cpp index 2ca15b6c5..831ffc72a 100644 --- a/src/mbgl/geometry/icon_buffer.cpp +++ b/src/mbgl/geometry/icon_buffer.cpp @@ -13,8 +13,8 @@ size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t t int16_t *shorts = static_cast(data); shorts[0] /* pos */ = x; shorts[1] /* pos */ = y; - shorts[2] /* offset */ = std::round(ox * 64); // use 1/64 pixels for placement - shorts[3] /* offset */ = std::round(oy * 64); + shorts[2] /* offset */ = ::round(ox * 64); // use 1/64 pixels for placement + shorts[3] /* offset */ = ::round(oy * 64); uint8_t *ubytes = static_cast(data); // a_data1 @@ -24,7 +24,7 @@ size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t t // a_data2 ubytes[12] /* minzoom */ = minzoom * 10; // 1/10 zoom levels: z16 == 160. - ubytes[13] /* maxzoom */ = std::fmin(maxzoom, 25) * 10; // 1/10 zoom levels: z16 == 160. + ubytes[13] /* maxzoom */ = ::fmin(maxzoom, 25) * 10; // 1/10 zoom levels: z16 == 160. return idx; } diff --git a/src/mbgl/geometry/line_buffer.cpp b/src/mbgl/geometry/line_buffer.cpp index 770483848..f475c63b2 100644 --- a/src/mbgl/geometry/line_buffer.cpp +++ b/src/mbgl/geometry/line_buffer.cpp @@ -14,8 +14,8 @@ size_t LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, i coords[1] = (y * 2) | ty; int8_t *extrude = static_cast(data); - extrude[4] = std::round(extrudeScale * ex); - extrude[5] = std::round(extrudeScale * ey); + extrude[4] = ::round(extrudeScale * ex); + extrude[5] = ::round(extrudeScale * ey); extrude[6] = static_cast(linesofar / 128); extrude[7] = static_cast(linesofar % 128); diff --git a/src/mbgl/geometry/text_buffer.cpp b/src/mbgl/geometry/text_buffer.cpp index e3f7117eb..8f312c9fa 100644 --- a/src/mbgl/geometry/text_buffer.cpp +++ b/src/mbgl/geometry/text_buffer.cpp @@ -13,8 +13,8 @@ size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t int16_t *shorts = static_cast(data); shorts[0] /* pos */ = x; shorts[1] /* pos */ = y; - shorts[2] /* offset */ = std::round(ox * 64); // use 1/64 pixels for placement - shorts[3] /* offset */ = std::round(oy * 64); + shorts[2] /* offset */ = ::round(ox * 64); // use 1/64 pixels for placement + shorts[3] /* offset */ = ::round(oy * 64); uint8_t *ubytes = static_cast(data); // a_data1 @@ -24,7 +24,7 @@ size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t // a_data2 ubytes[12] /* minzoom */ = minzoom * 10; // 1/10 zoom levels: z16 == 160. - ubytes[13] /* maxzoom */ = std::fmin(maxzoom, 25) * 10; // 1/10 zoom levels: z16 == 160. + ubytes[13] /* maxzoom */ = ::fmin(maxzoom, 25) * 10; // 1/10 zoom levels: z16 == 160. return idx; } diff --git a/src/mbgl/map/annotation.cpp b/src/mbgl/map/annotation.cpp index 9915bcb1f..874459797 100644 --- a/src/mbgl/map/annotation.cpp +++ b/src/mbgl/map/annotation.cpp @@ -6,6 +6,8 @@ #include #include #include +#include + #include #include @@ -66,7 +68,7 @@ uint32_t AnnotationManager::nextID() { vec2 AnnotationManager::projectPoint(const LatLng& point) { // Clamp to the latitude limits of Mercator. - const double constrainedLatitude = std::fmin(std::fmax(point.latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); + const double constrainedLatitude = ::fmin(::fmax(point.latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); // Project a coordinate into unit space in a square map. const double sine = std::sin(constrainedLatitude * M_PI / 180.0); @@ -109,7 +111,7 @@ AnnotationManager::addTileFeature(const uint32_t annotationID, std::vector points; for (size_t i = 0; i < segments[0].size(); ++i) { // first segment for now (no holes) - const double constraintedLatitude = std::fmin(std::fmax(segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); + const double constraintedLatitude = ::fmin(::fmax(segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); points.push_back(LonLat(segments[0][i].longitude, constraintedLatitude)); } @@ -219,7 +221,7 @@ AnnotationManager::addTileFeature(const uint32_t annotationID, if (type == AnnotationType::Point) { layerID = PointLayerID; } else { - layerID = ShapeLayerID + "." + std::to_string(annotationID); + layerID = ShapeLayerID + "." + util::toString(annotationID); } if (tile_pos.second || tile_pos.first->second.second->getMutableLayer(layerID) == nullptr) { layer = std::make_shared(); @@ -382,7 +384,7 @@ std::unordered_set AnnotationManager::removeAnnotations(co // remove shape layer from tiles if relevant for (auto tile_it = tiles.begin(); tile_it != tiles.end(); ++tile_it) { if (tile_it->second.first.count(annotationID)) { - tile_it->second.second->removeLayer(ShapeLayerID + "." + std::to_string(annotationID)); + tile_it->second.second->removeLayer(ShapeLayerID + "." + util::toString(annotationID)); affectedTiles.insert(tile_it->first); } } @@ -507,7 +509,7 @@ const LiveTile* AnnotationManager::getTile(const TileID& id) { // create shape tile layers from GeoJSONVT queries for (auto& tiler_it : shapeTilers) { const auto annotationID = tiler_it.first; - const std::string layerID = ShapeLayerID + "." + std::to_string(annotationID); + const std::string layerID = ShapeLayerID + "." + util::toString(annotationID); // check for existing render layer auto renderLayer = renderTile->getMutableLayer(layerID); diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 5b96b8319..f357c05e8 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -202,9 +202,9 @@ void Map::fitBounds(AnnotationSegment segment, EdgeInsets padding, const Duratio // Calculate the zoom level. double scaleX = (getWidth() - padding.left - padding.right) / size.x; double scaleY = (getHeight() - padding.top - padding.bottom) / size.y; - double minScale = std::fmin(scaleX, scaleY); - double zoom = std::log2(getScale() * minScale); - zoom = std::fmax(std::fmin(zoom, getMaxZoom()), getMinZoom()); + double minScale = ::fmin(scaleX, scaleY); + double zoom = ::log2(getScale() * minScale); + zoom = ::fmax(::fmin(zoom, getMaxZoom()), getMinZoom()); // Calculate the center point of a virtual bounds that is extended in all directions by padding. vec2<> paddedNEPixel = { diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 55652272d..56bca24af 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -170,7 +171,7 @@ void MapContext::updateAnnotationTiles(const std::unordered_setgetOrderedShapeAnnotations()) { - const std::string shapeLayerID = shapeID + "." + std::to_string(shapeAnnotationID); + const std::string shapeLayerID = shapeID + "." + util::toString(shapeAnnotationID); const auto layer_it = std::find_if(style->layers.begin(), style->layers.end(), [&shapeLayerID](util::ptr layer) { diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 94931602e..7368d1b44 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -312,7 +312,7 @@ double Source::getZoom(const TransformState& state) const { int32_t Source::coveringZoomLevel(const TransformState& state) const { double zoom = getZoom(state); if (info.type == SourceType::Raster || info.type == SourceType::Video) { - zoom = std::round(zoom); + zoom = ::round(zoom); } else { zoom = std::floor(zoom); } @@ -407,7 +407,7 @@ bool Source::update(MapData& data, double zoom = getZoom(transformState); if (info.type == SourceType::Raster || info.type == SourceType::Video) { - zoom = std::round(zoom); + zoom = ::round(zoom); } else { zoom = std::floor(zoom); } diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index b39614888..08cca3db2 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -101,7 +101,7 @@ void Transform::setLatLng(const LatLng latLng, const Duration& duration) { } const double m = 1 - 1e-15; - const double f = std::fmin(std::fmax(std::sin(util::DEG2RAD * latLng.latitude), -m), m); + const double f = ::fmin(::fmax(std::sin(util::DEG2RAD * latLng.latitude), -m), m); double xn = -latLng.longitude * state.Bc; double yn = 0.5 * state.Cc * std::log((1 + f) / (1 - f)); @@ -121,7 +121,7 @@ void Transform::setLatLngZoom(const LatLng latLng, const double zoom, const Dura state.Cc = s / util::M2PI; const double m = 1 - 1e-15; - const double f = std::fmin(std::fmax(std::sin(util::DEG2RAD * latLng.latitude), -m), m); + const double f = ::fmin(::fmax(std::sin(util::DEG2RAD * latLng.latitude), -m), m); double xn = -latLng.longitude * state.Bc; double yn = 0.5 * state.Cc * std::log((1 + f) / (1 - f)); diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index bb3e86d33..9a5e53092 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -140,11 +140,11 @@ double TransformState::getMinZoom() const { double test_y = y; constrain(test_scale, test_y); - return std::log2(std::fmin(min_scale, test_scale)); + return ::log2(::fmin(min_scale, test_scale)); } double TransformState::getMaxZoom() const { - return std::log2(max_scale); + return ::log2(max_scale); } diff --git a/src/mbgl/platform/gl.cpp b/src/mbgl/platform/gl.cpp index 76be580b9..d387f3fbf 100644 --- a/src/mbgl/platform/gl.cpp +++ b/src/mbgl/platform/gl.cpp @@ -1,4 +1,5 @@ #include +#include #include @@ -51,7 +52,7 @@ void checkError(const char *cmd, const char *file, int line) { default: error = "(unknown)"; break; } - throw ::mbgl::gl::Error(err, std::string(cmd) + ": Error GL_" + error + " - " + file + ":" + std::to_string(line)); + throw ::mbgl::gl::Error(err, std::string(cmd) + ": Error GL_" + error + " - " + file + ":" + util::toString(line)); } } diff --git a/src/mbgl/platform/log.cpp b/src/mbgl/platform/log.cpp index eec33444b..6daed4088 100644 --- a/src/mbgl/platform/log.cpp +++ b/src/mbgl/platform/log.cpp @@ -2,6 +2,7 @@ #include +#include #include #include diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp index fd4df4314..151e4c4a4 100644 --- a/src/mbgl/renderer/fill_bucket.cpp +++ b/src/mbgl/renderer/fill_bucket.cpp @@ -141,7 +141,7 @@ void FillBucket::tessellate() { for (size_t i = 0; i < vertex_count; ++i) { if (vertex_indices[i] == TESS_UNDEF) { - vertexBuffer.add(std::round(vertices[i * 2]), std::round(vertices[i * 2 + 1])); + vertexBuffer.add(::round(vertices[i * 2]), ::round(vertices[i * 2 + 1])); vertex_indices[i] = (TESSindex)total_vertex_count; total_vertex_count++; } diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp index c95e82631..cdc60f4eb 100644 --- a/src/mbgl/renderer/frame_history.cpp +++ b/src/mbgl/renderer/frame_history.cpp @@ -63,8 +63,8 @@ FadeProperties FrameHistory::getFadeProperties(const Duration& duration) { float startingZ = history.front().z; const FrameSnapshot lastFrame = history.back(); float endingZ = lastFrame.z; - float lowZ = std::fmin(startingZ, endingZ); - float highZ = std::fmax(startingZ, endingZ); + float lowZ = ::fmin(startingZ, endingZ); + float highZ = ::fmax(startingZ, endingZ); // Calculate the speed of zooming, and how far it would zoom in terms of zoom levels in one // duration diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index 0860bbc03..f406c0d8f 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -70,7 +70,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const LinePatternPos posB = lineAtlas->getDashPosition(properties.dash_array.to, layout.cap == CapType::Round); lineAtlas->bind(); - float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0 * id.overscaling; + float patternratio = std::pow(2.0, std::floor(::log2(state.getScale())) - id.z) / 8.0 * id.overscaling; float scaleXA = patternratio / posA.width / properties.dash_line_width / properties.dash_array.fromScale; float scaleYA = -posA.height / 2.0; float scaleXB = patternratio / posB.width / properties.dash_line_width / properties.dash_array.toScale; diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index c4347febb..1ee90293d 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -448,7 +448,7 @@ template void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine) { const float zoom = collision.zoom; - const float placementZoom = std::fmax(std::log(scale) / std::log(2) + zoom, 0); + const float placementZoom = ::fmax(std::log(scale) / std::log(2) + zoom, 0); for (const auto& symbol : symbols) { const auto &tl = symbol.tl; diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp index 3c2d22a5b..1c7806a4e 100644 --- a/src/mbgl/text/collision_tile.cpp +++ b/src/mbgl/text/collision_tile.cpp @@ -44,7 +44,7 @@ float CollisionTile::placeFeature(const CollisionFeature &feature) { if (std::isnan(s1) || std::isnan(s2)) s1 = s2 = 1; if (std::isnan(s3) || std::isnan(s4)) s3 = s4 = 1; - float collisionFreeScale = std::fmin(std::fmax(s1, s2), std::fmax(s3, s4)); + float collisionFreeScale = ::fmin(::fmax(s1, s2), ::fmax(s3, s4)); if (collisionFreeScale > blocking.maxScale) { // After a box's maxScale the label has shrunk enough that the box is no longer needed to cover it, diff --git a/src/mbgl/text/font_stack.cpp b/src/mbgl/text/font_stack.cpp index d4d3a3947..6d06796e8 100644 --- a/src/mbgl/text/font_stack.cpp +++ b/src/mbgl/text/font_stack.cpp @@ -27,8 +27,8 @@ const Shaping FontStack::getShaping(const std::u32string &string, const float ma // the y offset *should* be part of the font metadata const int32_t yOffset = -17; - float x = std::round(translate.x * 24); // one em - const float y = std::round(translate.y * 24) + yOffset; // one em + float x = ::round(translate.x * 24); // one em + const float y = ::round(translate.y * 24) + yOffset; // one em // Loop through all characters of this label and shape. for (uint32_t chr : string) { diff --git a/src/mbgl/text/get_anchors.cpp b/src/mbgl/text/get_anchors.cpp index ef8a75c02..6492fd067 100644 --- a/src/mbgl/text/get_anchors.cpp +++ b/src/mbgl/text/get_anchors.cpp @@ -32,7 +32,7 @@ Anchors resample(const std::vector &line, const float offset, const y = util::interpolate(float(a.y), float(b.y), t); if (x >= 0 && x < 4096 && y >= 0 && y < 4096) { - Anchor anchor(std::round(x), std::round(y), angle, 0.5f, i); + Anchor anchor(::round(x), ::round(y), angle, 0.5f, i); if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) { anchors.push_back(anchor); diff --git a/src/mbgl/util/compression.cpp b/src/mbgl/util/compression.cpp index 3a1658b8f..139dba754 100644 --- a/src/mbgl/util/compression.cpp +++ b/src/mbgl/util/compression.cpp @@ -2,6 +2,7 @@ #include +#include #include #include diff --git a/src/mbgl/util/geojsonvt b/src/mbgl/util/geojsonvt index ed99a6290..995ffc72c 160000 --- a/src/mbgl/util/geojsonvt +++ b/src/mbgl/util/geojsonvt @@ -1 +1 @@ -Subproject commit ed99a6290fa42107a982e7f3675aae49d29026b1 +Subproject commit 995ffc72c556da4b4880a6036fbcf7159fc5ecce diff --git a/src/mbgl/util/io.cpp b/src/mbgl/util/io.cpp index bb4c3595c..0f7ce0e55 100644 --- a/src/mbgl/util/io.cpp +++ b/src/mbgl/util/io.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index f410b8e81..9e444fec1 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -27,8 +27,8 @@ typedef const std::function ScanLine; // scan-line conversion static void scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine scanLine) { - double y0 = std::fmax(ymin, std::floor(e1.y0)); - double y1 = std::fmin(ymax, std::ceil(e1.y1)); + double y0 = ::fmax(ymin, std::floor(e1.y0)); + double y1 = ::fmin(ymax, std::ceil(e1.y1)); // sort edges by x-coordinate if ((e0.x0 == e1.x0 && e0.y0 == e1.y0) ? @@ -43,8 +43,8 @@ static void scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine sca double d0 = e0.dx > 0; // use y + 1 to compute x0 double d1 = e1.dx < 0; // use y + 1 to compute x1 for (int32_t y = y0; y < y1; y++) { - double x0 = m0 * std::fmax(0, std::fmin(e0.dy, y + d0 - e0.y0)) + e0.x0; - double x1 = m1 * std::fmax(0, std::fmin(e1.dy, y + d1 - e1.y0)) + e1.x0; + double x0 = m0 * ::fmax(0, ::fmin(e0.dy, y + d0 - e0.y0)) + e0.x0; + double x1 = m1 * ::fmax(0, ::fmin(e1.dy, y + d1 - e1.y0)) + e1.x0; scanLine(std::floor(x1), std::ceil(x0), y); } } diff --git a/src/mbgl/util/time.cpp b/src/mbgl/util/time.cpp index 94936acff..4612ae29b 100644 --- a/src/mbgl/util/time.cpp +++ b/src/mbgl/util/time.cpp @@ -1,6 +1,8 @@ #include #include +#include + namespace mbgl { namespace util { From 66f0473bcf585724a0311416466b30694d7754d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Mon, 3 Aug 2015 15:59:03 +0200 Subject: [PATCH 07/14] add MBGL_USE_GLES2 define --- include/mbgl/platform/default/glfw_view.hpp | 2 +- include/mbgl/platform/gl.hpp | 2 +- include/mbgl/util/gl_helper.hpp | 21 ++++++++++++--------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/mbgl/platform/default/glfw_view.hpp b/include/mbgl/platform/default/glfw_view.hpp index f65565c03..1bc210b29 100644 --- a/include/mbgl/platform/default/glfw_view.hpp +++ b/include/mbgl/platform/default/glfw_view.hpp @@ -3,7 +3,7 @@ #include -#ifdef NVIDIA +#ifdef MBGL_USE_GLES2 #define GLFW_INCLUDE_ES2 #endif #include diff --git a/include/mbgl/platform/gl.hpp b/include/mbgl/platform/gl.hpp index 73f0801fa..6bcb85fee 100644 --- a/include/mbgl/platform/gl.hpp +++ b/include/mbgl/platform/gl.hpp @@ -19,7 +19,7 @@ #else #error Unsupported Apple platform #endif -#elif __ANDROID__ +#elif __ANDROID__ || MBGL_USE_GLES2 #define GL_GLEXT_PROTOTYPES #include #include diff --git a/include/mbgl/util/gl_helper.hpp b/include/mbgl/util/gl_helper.hpp index cf007e8a6..288fc2c68 100644 --- a/include/mbgl/util/gl_helper.hpp +++ b/include/mbgl/util/gl_helper.hpp @@ -25,21 +25,21 @@ inline void setBlend(const bool& enabled) { enabled ? MBGL_CHECK_ERROR(glEnable(GL_BLEND)) : MBGL_CHECK_ERROR(glDisable(GL_BLEND)); } -inline std::array getClearColor() { - std::array color; - MBGL_CHECK_ERROR(glGetDoublev(GL_COLOR_CLEAR_VALUE, color.data())); +inline std::array getClearColor() { + std::array color; + MBGL_CHECK_ERROR(glGetFloatv(GL_COLOR_CLEAR_VALUE, color.data())); return color; } -inline void setClearColor(const std::array& color) { +inline void setClearColor(const std::array& color) { MBGL_CHECK_ERROR(glClearColor(color[0], color[1], color[2], color[3])); } inline std::array getBlendFunc() { GLint func[2]; - glGetIntegerv(GL_BLEND_SRC, &func[0]); - glGetIntegerv(GL_BLEND_DST, &func[1]); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &func[0]); + glGetIntegerv(GL_BLEND_DST_ALPHA, &func[1]); return {{ static_cast(func[0]), static_cast(func[1]) }}; } @@ -47,7 +47,7 @@ inline void setBlendFunc(const std::array& func) { MBGL_CHECK_ERROR(glBlendFunc(func[0], func[1])); } - +#ifndef GL_ES_VERSION_2_0 inline std::array getPixelZoom() { std::array zoom; glGetDoublev(GL_ZOOM_X, &zoom[0]); @@ -69,17 +69,20 @@ inline std::array getRasterPos() { inline void setRasterPos(const std::array& pos) { MBGL_CHECK_ERROR(glRasterPos4d(pos[0], pos[1], pos[2], pos[3])); } - +#endif } // end anonymous namespace namespace mbgl { namespace gl { using PreserveBlend = Preserve; -using PreserveClearColor = Preserve, getClearColor, setClearColor>; +using PreserveClearColor = Preserve, getClearColor, setClearColor>; using PreserveBlendFunc = Preserve, getBlendFunc, setBlendFunc>; + +#ifndef GL_ES_VERSION_2_0 using PreservePixelZoom = Preserve, getPixelZoom, setPixelZoom>; using PreserveRasterPos = Preserve, getRasterPos, setRasterPos>; +#endif } } From ac0b634bac0c22fd913c870900a1bf89c099ab81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Mon, 3 Aug 2015 16:02:21 +0200 Subject: [PATCH 08/14] respect fullscreen flag in Linux app --- linux/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/main.cpp b/linux/main.cpp index 9acbbb659..c21d7446e 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -31,11 +31,11 @@ void quit_handler(int) { } int main(int argc, char *argv[]) { - int fullscreen_flag = 0; + bool fullscreen = false; std::string style; const struct option long_options[] = { - {"fullscreen", no_argument, &fullscreen_flag, 'f'}, + {"fullscreen", no_argument, 0, 'f'}, {"style", required_argument, 0, 's'}, {0, 0, 0, 0} }; @@ -50,7 +50,7 @@ int main(int argc, char *argv[]) { if (long_options[option_index].flag != 0) break; case 'f': - // handle fullscreen_flag + fullscreen = true; break; case 's': style = std::string("asset://") + std::string(optarg); @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) { sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, NULL); - view = std::make_unique(); + view = std::make_unique(fullscreen); mbgl::SQLiteCache cache("/tmp/mbgl-cache.db"); mbgl::DefaultFileSource fileSource(&cache); From daaa643bbf925e8f6f40649bba7b4c93911a1725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Jul 2015 10:00:25 +0200 Subject: [PATCH 09/14] support cURL versions older than 7.21.6 prior to cURL 7.21.6, CURLOPT_ACCEPT_ENCODING was called CURLOPT_ENCODING --- platform/default/http_request_curl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/default/http_request_curl.cpp b/platform/default/http_request_curl.cpp index 22cb1df6f..0f7f8c0ac 100644 --- a/platform/default/http_request_curl.cpp +++ b/platform/default/http_request_curl.cpp @@ -470,7 +470,11 @@ HTTPCURLRequest::HTTPCURLRequest(HTTPCURLContext* context_, const Resource& reso handleError(curl_easy_setopt(handle, CURLOPT_WRITEDATA, this)); handleError(curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, headerCallback)); handleError(curl_easy_setopt(handle, CURLOPT_HEADERDATA, this)); +#if LIBCURL_VERSION_NUM >= ((7) << 16 | (21) << 8 | 6) // Renamed in 7.21.6 handleError(curl_easy_setopt(handle, CURLOPT_ACCEPT_ENCODING, "gzip, deflate")); +#else + handleError(curl_easy_setopt(handle, CURLOPT_ENCODING, "gzip, deflate")); +#endif handleError(curl_easy_setopt(handle, CURLOPT_USERAGENT, "MapboxGL/1.0")); handleError(curl_easy_setopt(handle, CURLOPT_SHARE, context->share)); From 19e5d9af22cc76f4d3a1e911b1b6fabd352284eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Jul 2015 10:02:56 +0200 Subject: [PATCH 10/14] don't require PNG_ALPHA_PREMULTIPLIED to support older versions of libpng --- platform/default/png_reader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/default/png_reader.cpp b/platform/default/png_reader.cpp index 4f8596a7b..42b694609 100644 --- a/platform/default/png_reader.cpp +++ b/platform/default/png_reader.cpp @@ -157,7 +157,12 @@ void PngReader::read(unsigned x0, unsigned y0, unsigned w, unsigned h, char * double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); + +#ifdef PNG_ALPHA_PREMULTIPLIED png_set_alpha_mode(png_ptr, PNG_ALPHA_PREMULTIPLIED, PNG_GAMMA_LINEAR); +#else + // TODO: Manually premultiply the image data. +#endif if (x0 == 0 && y0 == 0 && w >= width_ && h >= height_) { From da4c62087d9b46eef8ffcfb4403c74be8da8b417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Jul 2015 11:21:42 +0200 Subject: [PATCH 11/14] include $CFLAGS into build --- gyp/common.gypi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gyp/common.gypi b/gyp/common.gypi index d7d21f761..b44f69868 100644 --- a/gyp/common.gypi +++ b/gyp/common.gypi @@ -20,6 +20,7 @@ '-Wno-variadic-macros', '-frtti', '-fexceptions', + '${CFLAGS}', ], 'GCC_WARN_PEDANTIC': 'YES', 'GCC_WARN_UNINITIALIZED_AUTOS': 'YES_AGGRESSIVE', @@ -37,6 +38,7 @@ '-Wno-c++1y-extensions', '-frtti', '-fexceptions', + '${CFLAGS}', ], }], ['OS=="linux"', { From b44fe1c7af889089a640097583add8cd90e9330a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Jul 2015 11:21:55 +0200 Subject: [PATCH 12/14] use OpenGL and Boost for the linux app --- linux/mapboxgl-app.gypi | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/mapboxgl-app.gypi b/linux/mapboxgl-app.gypi index 3d43da384..379bd4ad5 100644 --- a/linux/mapboxgl-app.gypi +++ b/linux/mapboxgl-app.gypi @@ -29,6 +29,7 @@ 'variables' : { 'cflags_cc': [ + '<@(opengl_cflags)', '<@(boost_cflags)', '<@(glfw3_cflags)', ], From e6053aa5475e03568f39e4967dc49ef4aba3c5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Mon, 3 Aug 2015 17:04:31 +0200 Subject: [PATCH 13/14] Make build system architecture agnostic to remove Android special case --- .gitignore | 2 + .mason | 2 +- Makefile | 278 +++++------------- .../{mapboxgl-app.gyp => mapboxgl-app.gypi} | 20 +- bin/render.gypi | 14 +- config/defaults.mk | 67 ----- configure | 217 ++++---------- gyp/android.gyp | 5 + gyp/asset-fs.gypi | 6 +- gyp/asset-zip.gypi | 16 +- gyp/cache-sqlite.gypi | 12 +- gyp/core.gypi | 8 +- gyp/http-curl.gypi | 18 +- gyp/http-nsurl.gypi | 6 +- gyp/linux.gyp | 7 +- gyp/platform-android.gypi | 18 +- gyp/platform-ios.gypi | 4 +- gyp/platform-linux.gypi | 18 +- gyp/platform-osx.gypi | 4 +- linux/mapboxgl-app.gypi | 6 +- macosx/mapboxgl-app.gypi | 6 +- scripts/android/configure.sh | 14 + scripts/android/defaults.mk | 11 + scripts/ios/configure.sh | 6 + scripts/ios/defaults.mk | 12 + scripts/ios/package.sh | 4 +- scripts/linux/configure.sh | 18 ++ scripts/linux/defaults.mk | 5 + scripts/main.mk | 127 ++++++++ scripts/osx/configure.sh | 13 + scripts/osx/defaults.mk | 5 + test/test.gypi | 12 +- 32 files changed, 448 insertions(+), 513 deletions(-) rename android/{mapboxgl-app.gyp => mapboxgl-app.gypi} (84%) delete mode 100644 config/defaults.mk create mode 100644 gyp/android.gyp create mode 100644 scripts/android/configure.sh create mode 100644 scripts/android/defaults.mk create mode 100644 scripts/ios/configure.sh create mode 100644 scripts/ios/defaults.mk create mode 100644 scripts/linux/configure.sh create mode 100644 scripts/linux/defaults.mk create mode 100644 scripts/main.mk create mode 100644 scripts/osx/configure.sh create mode 100644 scripts/osx/defaults.mk diff --git a/.gitignore b/.gitignore index b253752e5..3e46c0a0a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ /ios/build /ios/app/build /test/build +/gyp/build +/gyp/java /test/node_modules /test/fixtures/*/*_actual.* /test/fixtures/api/1.png diff --git a/.mason b/.mason index abdc13127..1d5789dfa 160000 --- a/.mason +++ b/.mason @@ -1 +1 @@ -Subproject commit abdc131273c3e50e42f245b1166c27de4c34c582 +Subproject commit 1d5789dfadeffa5df8e58770e3326840d1e6d9c9 diff --git a/Makefile b/Makefile index 34af9b85e..59bd1dfef 100644 --- a/Makefile +++ b/Makefile @@ -1,225 +1,101 @@ -BUILDTYPE ?= Release -PYTHON ?= python -PREFIX ?= /usr/local -ANDROID_ABI ?= arm-v7 +export BUILDTYPE ?= Release +export BUILD_TEST ?= 1 +export BUILD_RENDER ?= 1 +# Determine build platform ifeq ($(shell uname -s), Darwin) -HOST = osx -HEADLESS = cgl -JOBS ?= $(shell sysctl -n hw.ncpu) -endif - -ifeq ($(shell uname -s), Linux) -HOST = linux -JOBS ?= $(shell grep --count processor /proc/cpuinfo) -BUILD_ROOT = $(shell pwd) -endif - -JOBS ?= 1 - -all: mbgl - -include config/defaults.mk - -#### Dependencies ############################################################## - -# Wildcard targets get removed after build by default, but we want to preserve the config. -.PRECIOUS: config/%.gypi -config/%.gypi: CMD = ./configure config/$*.gypi -config/%.gypi: configure - @$(ENV_$*) ./scripts/flock.py build/Configure.lock ./configure config/$*.gypi - -styles/styles: - git submodule update --init styles - -ifeq ($(shell uname -s), Darwin) -SMCalloutView: - git submodule update --init platform/ios/vendor/SMCalloutView +export BUILD = osx +export JOBS ?= $(shell sysctl -n hw.ncpu) +export XCPRETTY := $(shell ./scripts/xcpretty.sh) +else ifeq ($(shell uname -s), Linux) +export BUILD = linux +export JOBS ?= $(shell grep --count processor /proc/cpuinfo) else -SMCalloutView: +$(error Cannot determine build platform) +endif +export BUILD_VERSION = $(shell uname -m) + +RUN = @$(MAKE) -f scripts/main.mk + +default: ; @printf "You must specify a valid target\n" + +#### OS X targets ############################################################## + +ifeq ($(BUILD),osx) +.PHONY: osx xosx run-osx run-xosx +osx: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Makefile/osxapp +xosx: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/osxapp +run-osx: osx ; @"build/osx-x86_64/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL" +run-xosx: xosx ; @"gyp/build/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL" + +.PHONY: Xcode/osx Xcode/ios +Xcode/ios: ; $(RUN) HOST=ios Xcode/__project__ +Xcode/osx: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/__project__ + +.PHONY: xproj iproj +xproj: Xcode/osx ; @open ./build/osx-x86_64/gyp/osx.xcodeproj +iproj: Xcode/ios ; @open ./build/ios-all/gyp/ios.xcodeproj + +.PHONY: ios ibench isim +ios ibench isim: export XCODEBUILD_ARGS += PROVISIONING_PROFILE="$$(PROVISIONING_PROFILE)" + +ios: export XCODEBUILD_ARGS += -sdk iphoneos ARCHS="arm64 armv7 armv7s" +ios: ; $(RUN) HOST=ios Xcode/iosapp + +isim: export XCODEBUILD_ARGS += -sdk iphonesimulator ARCHS="x86_64 i386" +isim: ; $(RUN) HOST=ios Xcode/iosapp + +ibench: export XCODEBUILD_ARGS += -sdk iphoneos ARCHS="arm64" +ibench: ; $(RUN) HOST=ios Xcode/ios-bench + +.PHONY: ipackage ipackage-strip ipackage-sim itest +ipackage: Xcode/ios ; @JOBS=$(JOBS) ./scripts/ios/package.sh +ipackage-strip: Xcode/ios ; @JOBS=$(JOBS) ./scripts/ios/package.sh strip +ipackage-sim: Xcode/ios ; @JOBS=$(JOBS) ./scripts/ios/package.sh sim +itest: ipackage-sim ; ./scripts/ios/test.sh endif -geojsonvt: - git submodule update --init src/mbgl/util/geojsonvt +#### All platforms targets ##################################################### -KIF: - git submodule update --init test/ios/KIF - - -#### Build files ############################################################### - -.PRECIOUS: Makefile/project -Makefile/project: config/$(HOST).gypi styles/styles SMCalloutView geojsonvt - 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 geojsonvt - deps/run_gyp gyp/$(HOST).gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f xcode - - -#### Library builds ############################################################ - -mbgl: Makefile/project - $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) everything - -standalone: Makefile/project - LINK=`pwd`/gyp/link.py $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) standalone - -install: Makefile/project - LINK=`pwd`/gyp/link.py $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) install - - -##### Test builds ############################################################## - -.PHONY: test -test: Makefile/project - $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) test - -test-%: test - ./scripts/run_tests.sh "build/$(HOST)/$(BUILDTYPE)/test" --gtest_filter=$* - -.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=$* - - -#### Mac OS X application builds ############################################### - -.PHONY: osx run-osx -osx: Makefile/project - $(MAKE) -C build/osx BUILDTYPE=$(BUILDTYPE) osxapp - -run-osx: osx - "build/osx/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL" - -run-valgrind-osx: osx - (valgrind --leak-check=full --suppressions=scripts/valgrind.sup build/osx/$(BUILDTYPE)/Mapbox\ GL.app/Contents/MacOS/Mapbox\ GL) - -.PHONY: xosx-proj xosx run-xosx -xosx-proj: Xcode/project - open ./build/osx/gyp/osx.xcodeproj - -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 - "gyp/build/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL" - -# Legacy name -xproj: xosx-proj - - - -#### iOS application builds #################################################### - -.PRECIOUS: Xcode/ios -Xcode/ios: gyp/ios.gyp config/ios.gypi styles/styles SMCalloutView geojsonvt - 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/gyp/ios.xcodeproj - -ios: XCPRETTY := $(shell ./scripts/xcpretty.sh) -ios: Xcode/ios - xcodebuild -sdk iphoneos ARCHS="arm64 armv7 armv7s" PROVISIONING_PROFILE="19324a54-7455-4f0b-8e1c-e6957c718ebc" -project ./build/ios/gyp/ios.xcodeproj -configuration Release -target iosapp -jobs $(JOBS) $(XCPRETTY) - -ibench: XCPRETTY := $(shell ./scripts/xcpretty.sh) -ibench: Xcode/ios - xcodebuild -sdk iphoneos ARCHS="arm64" PROVISIONING_PROFILE="19324a54-7455-4f0b-8e1c-e6957c718ebc" -project ./build/ios/gyp/ios.xcodeproj -configuration Release -target ios-bench -jobs $(JOBS) $(XCPRETTY) - -isim: XCPRETTY := $(shell ./scripts/xcpretty.sh) -isim: Xcode/ios - xcodebuild -sdk iphonesimulator ARCHS="x86_64 i386" -project ./build/ios/gyp/ios.xcodeproj -configuration Debug -target iosapp -jobs $(JOBS) $(XCPRETTY) - -ipackage: Xcode/ios - JOBS=$(JOBS) ./scripts/ios/package.sh - -ipackage-strip: Xcode/ios - JOBS=$(JOBS) ./scripts/ios/package.sh strip - -ipackage-sim: Xcode/ios - JOBS=$(JOBS) ./scripts/ios/package.sh sim - -itest: ipackage-sim KIF - ./scripts/ios/test.sh - -# Legacy name -iproj: ios-proj - - -#### Linux application builds ################################################## - -.PHONY: linux run-linux -linux: Makefile/project - $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) linuxapp - -run-linux: linux - (cd build/$(HOST)/$(BUILDTYPE) && ./mapbox-gl) - -run-valgrind-linux: linux - (cd build/$(HOST)/$(BUILDTYPE) && valgrind --leak-check=full --suppressions=$(BUILD_ROOT)/scripts/valgrind.sup ./mapbox-gl) - -.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 - "gyp/build/$(BUILDTYPE)/mapbox-gl" - - -#### Android libaries ######################################################### - -.PRECIOUS: Makefile/android-% -Makefile/android-%: CMD = deps/run_gyp android/mapboxgl-app.gyp $(CONFIG_android-$*) $(LIBS_android) --generator-output=./build/android-$* -f make-android -Makefile/android-%: config/android-%.gypi styles/styles geojsonvt - @echo $(CMD) - @$(ENV_android-$*) $(CMD) +.PHONY: linux xlinux run-linux run-xlinux +linux: ; $(RUN) Makefile/linuxapp +.PHONY: android android-lib # Builds a particular android architecture. -android-lib-%: Makefile/android-% - @$(ENV_android-$*) ./scripts/flock.py -v build/Android.lock $(MAKE) -C build/android-$* BUILDTYPE=$(BUILDTYPE) androidapp +android-lib-%: ; $(RUN) HOST=android HOST_VERSION=$* Makefile/androidapp + +# Builds the default Android library +android-lib: ; $(RUN) HOST=android Makefile/androidapp # Builds the selected/default Android library -android-lib: android-lib-$(ANDROID_ABI) - -# Builds the selected/default Android library -android: android-lib-$(ANDROID_ABI) +android: android-lib cd android/java && ./gradlew --parallel-threads=$(JOBS) assemble$(BUILDTYPE) # Builds all android architectures. -android-all: $(ANDROID_ABIS) +android-all: android-lib-arm-v5 android-lib-arm-v7 android-lib-arm-v8 +android-all: android-lib-x86 android-lib-x86-64 +android-all: android-lib-mips android-lib-mips-64 cd android/java && ./gradlew --parallel-threads=$(JOBS) assemble$(BUILDTYPE) -# Full build of GL Core for each architecture, build the Android Library, publish to Maven Central -android-deploy: $(ANDROID_ABIS) - cd android/java/MapboxGLAndroidSDK && chmod ugo+x deploy.sh && ./deploy.sh +.PHONY: test +test: ; $(RUN) Makefile/test +test-%: ; $(RUN) test-$* +ifeq ($(BUILD),osx) +xtest: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/test +endif -android-project: android-lib - - -##### Render builds ############################################################ - -render: Makefile/project - $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) mbgl-render - -.PHONY: xrender -xrender: XCPRETTY := $(shell ./scripts/xcpretty.sh) -xrender: Xcode/project - xcodebuild -project ./build/osx/gyp/osx.xcodeproj -configuration $(BUILDTYPE) -target mbgl-render -jobs $(JOBS) $(XCPRETTY) +.PHONY: render xrender +render: ; $(RUN) Makefile/mbgl-render +ifeq ($(BUILD),osx) +xrender: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/mbgl-render +endif ##### Maintenace operations #################################################### .PHONY: clear_xcode_cache clear_xcode_cache: -ifeq ($(PLATFORM), osx) +ifeq ($(BUILD), osx) @CUSTOM_DD=`defaults read com.apple.dt.Xcode IDECustomDerivedDataLocation 2>/dev/null`; \ if [ $$CUSTOM_DD ]; then \ echo clearing files in $$CUSTOM_DD older than one day; \ @@ -233,7 +109,7 @@ endif .PHONY: clear_sqlite_cache clear_sqlite_cache: -ifeq ($(PLATFORM), osx) +ifeq ($(BUILD), osx) rm -f ~/Library/Application\ Support/Mapbox\ GL/cache.db else rm -f /tmp/mbgl-cache.db diff --git a/android/mapboxgl-app.gyp b/android/mapboxgl-app.gypi similarity index 84% rename from android/mapboxgl-app.gyp rename to android/mapboxgl-app.gypi index d16d1dd4a..107bbcbd5 100644 --- a/android/mapboxgl-app.gyp +++ b/android/mapboxgl-app.gypi @@ -26,13 +26,13 @@ ], 'libraries': [ '<@(openssl_static_libs)', - '<@(curl_static_libs)', - '<@(png_static_libs)', + '<@(libcurl_static_libs)', + '<@(libpng_static_libs)', '<@(jpeg_static_libs)', - '<@(sqlite3_static_libs)', - '<@(uv_static_libs)', - '<@(nu_static_libs)', - '<@(zip_static_libs)', + '<@(sqlite_static_libs)', + '<@(libuv_static_libs)', + '<@(nunicode_static_libs)', + '<@(libzip_static_libs)', ], 'variables': { 'ldflags': [ @@ -42,13 +42,13 @@ '-lGLESv2', '-lstdc++', '-latomic', - '<@(png_ldflags)', + '<@(libpng_ldflags)', '<@(jpeg_ldflags)', - '<@(sqlite3_ldflags)', + '<@(sqlite_ldflags)', '<@(openssl_ldflags)', - '<@(curl_ldflags)', + '<@(libcurl_ldflags)', '<@(zlib_ldflags)', - '<@(zip_ldflags)', + '<@(libzip_ldflags)', ], }, 'conditions': [ diff --git a/bin/render.gypi b/bin/render.gypi index 2e1dbd8f7..45c9ebb0e 100644 --- a/bin/render.gypi +++ b/bin/render.gypi @@ -27,18 +27,18 @@ 'variables' : { 'cflags_cc': [ - '<@(glfw3_cflags)', - '<@(uv_cflags)', + '<@(glfw_cflags)', + '<@(libuv_cflags)', '<@(boost_cflags)', ], 'ldflags': [ - '<@(glfw3_ldflags)', - '<@(uv_ldflags)', + '<@(glfw_ldflags)', + '<@(libuv_ldflags)', ], 'libraries': [ - '<@(glfw3_static_libs)', - '<@(uv_static_libs)', - '<@(boost_program_options_static_libs)' + '<@(glfw_static_libs)', + '<@(libuv_static_libs)', + '<@(boost_libprogram_options_static_libs)' ], }, diff --git a/config/defaults.mk b/config/defaults.mk deleted file mode 100644 index 1449bf8e1..000000000 --- a/config/defaults.mk +++ /dev/null @@ -1,67 +0,0 @@ - -#### Configuration defaults #################################################### - -ENV_osx = MASON_PLATFORM=osx -CONFIG_osx = -Dhost=osx -Iconfig/osx.gypi -Dinstall_prefix=$(PREFIX) -LIBS_osx = -Dheadless_lib=$(word 1,$(HEADLESS) cgl) -LIBS_osx += -Dplatform_lib=$(word 1,$(PLATFORM) osx) -LIBS_osx += -Dasset_lib=$(word 1,$(ASSET) fs) -LIBS_osx += -Dhttp_lib=$(word 1,$(HTTP) nsurl) -LIBS_osx += -Dcache_lib=$(word 1,$(CACHE) sqlite) -LIBS_osx += --depth=. -Goutput_dir=. - - -ENV_ios = MASON_PLATFORM=ios -CONFIG_ios = -Dhost=ios -Iconfig/ios.gypi -Dinstall_prefix=$(PREFIX) -LIBS_ios = -Dheadless_lib=none -LIBS_ios += -Dplatform_lib=$(word 1,$(PLATFORM) ios) -LIBS_ios += -Dasset_lib=$(word 1,$(ASSET) fs) -LIBS_ios += -Dhttp_lib=$(word 1,$(HTTP) nsurl) -LIBS_ios += -Dcache_lib=$(word 1,$(CACHE) sqlite) -LIBS_ios += --depth=. -Goutput_dir=. - - -ENV_linux = MASON_PLATFORM=linux -CONFIG_linux = -Dhost=linux -Iconfig/linux.gypi -Dinstall_prefix=$(PREFIX) -LIBS_linux = -Dheadless_lib=$(word 1,$(HEADLESS) glx) -LIBS_linux += -Dplatform_lib=$(word 1,$(PLATFORM) linux) -LIBS_linux += -Dasset_lib=$(word 1,$(ASSET) fs) -LIBS_linux += -Dhttp_lib=$(word 1,$(HTTP) curl) -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/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/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/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/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/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/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/toolchain.sh) -CONFIG_android-mips-64 = -Dhost=android -Iconfig/android-mips-64.gypi - -LIBS_android = -Dheadless_lib=none -LIBS_android += -Dplatform_lib=$(word 1,$(PLATFORM) android) -LIBS_android += -Dasset_lib=$(word 1,$(ASSET) zip) -LIBS_android += -Dhttp_lib=$(word 1,$(HTTP) curl) -LIBS_android += -Dcache_lib=$(word 1,$(CACHE) sqlite) -LIBS_android += --depth=. -Goutput_dir=. diff --git a/configure b/configure index c1f7f6da1..6fbaa9f7f 100755 --- a/configure +++ b/configure @@ -1,76 +1,56 @@ #!/usr/bin/env bash -set -e -set -o pipefail +set -euo pipefail CONFIG_FILE=$1 -if [ `uname -s` = 'Darwin' ]; then - MASON_PLATFORM=${MASON_PLATFORM:-osx} -fi - -function finish { - >&2 echo -en "\033[0m"; -} -trap finish EXIT - -# Install mason -git submodule update --init .mason -export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason" - -case ${MASON_PLATFORM} in - 'ios') - SQLITE_VERSION=system - LIBUV_VERSION=0.10.28 - ZLIB_VERSION=system - BOOST_VERSION=system - ;; - 'android') - SQLITE_VERSION=3.8.8.1 - LIBPNG_VERSION=1.6.16 - LIBJPEG_VERSION=v9a - OPENSSL_VERSION=1.0.1l - LIBCURL_VERSION=7.40.0 - LIBUV_VERSION=1.4.0 - ZLIB_VERSION=system - BOOST_VERSION=1.57.0 - NUNICODE_VERSION=1.5.1 - LIBZIP_VERSION=0.11.2 - ;; - *) - GLFW_VERSION=3.1 - SQLITE_VERSION=3.8.8.1 - LIBPNG_VERSION=1.6.16 - LIBJPEG_VERSION=v9a - LIBCURL_VERSION=system - LIBUV_VERSION=0.10.28 - ZLIB_VERSION=system - BOOST_VERSION=1.57.0 - BOOST_PROGRAM_OPTIONS_VERSION=1.57.0 - NUNICODE_VERSION=1.5.1 - LIBZIP_VERSION=0.11.2 - ;; -esac - -if [ ${MASON_PLATFORM} == 'linux' ] ; then - MESA_VERSION=10.4.3 - mason install mesa ${MESA_VERSION} - export PKG_CONFIG_PATH=`mason prefix mesa ${MESA_VERSION}`/lib/pkgconfig -fi - -function abort { >&2 echo -e "\033[1m\033[31m$1\033[0m"; exit 1; } - if [ -z ${CONFIG_FILE} ]; then abort 'You need to specify an output path for the configuration file' fi -if [[ ${MASON_PLATFORM} = 'android' && -z ${MASON_ANDROID_ABI} ]]; then - abort 'You need to specify an ABI for android platforms' -fi +# Make sure we clear all colors +trap '>&2 echo -en "\033[0m"' TERM INT -echo -n "MASON_PLATFORM=${MASON_PLATFORM} " -if [ ${MASON_PLATFORM} = 'android' ]; then echo -n "MASON_ANDROID_ABI=${MASON_ANDROID_ABI} " ; fi -echo $0 $@ +function abort { >&2 echo -e "\033[1m\033[31m$1\033[0m"; exit 1; } +function info { >&2 echo -e "\033[1m\033[33m$1\033[0m"; } +function warn { >&2 echo -e "\033[1m\033[33m$1\033[0m"; } + +# Install mason +export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason" + +# You can override the function for a particular set of flags by defining a +# print_XXX_flags function in your dependencies.sh file +function print_flags { + local NAME=$1; shift + if [ "$(type -t print_${NAME}_flags)" = 'function' ]; then + print_${NAME}_flags + else + local VERSION=`echo "${NAME}_VERSION" | tr "[:lower:]" "[:upper:]"` + if [ ! -z ${!VERSION:-} ] ; then + mason install ${NAME} ${!VERSION} + for FLAGS in "$@" ; do + CONFIG+=" '${NAME}_${FLAGS}%': $(quote_flags $(mason ${FLAGS} ${NAME} ${!VERSION})),"$LN + done + else + warn "* Not using ${NAME}" + fi + fi +} + +function print_default_flags { + : +} + +function print_opengl_flags { + CONFIG+=" 'opengl_cflags%': [],"$LN + CONFIG+=" 'opengl_ldflags%': [],"$LN +} + +# Load dependencies +source scripts/${MASON_PLATFORM}/configure.sh +if [ -e scripts/${MASON_PLATFORM}/${MASON_PLATFORM_VERSION}/configure.sh ]; then + source scripts/${MASON_PLATFORM}/${MASON_PLATFORM_VERSION}/configure.sh +fi PYTHON=`which python || abort 'Cannot find python'` @@ -78,12 +58,6 @@ PYTHON=`which python || abort 'Cannot find python'` >&2 ${PYTHON} --version >&2 echo -en "\033[0m"; -PKG_CONFIG=`which pkg-config || abort 'Cannot find pkg-config'` - ->&2 echo -en "\033[1m\033[32m* Using pkg-config " ->&2 ${PKG_CONFIG} --version ->&2 echo -en "\033[0m"; - function quote_flags { ${PYTHON} -c "import sys, re; print filter(None, re.split('(? ${CONFIG_FILE} cat ${CONFIG_FILE} diff --git a/gyp/android.gyp b/gyp/android.gyp new file mode 100644 index 000000000..0a09edb6c --- /dev/null +++ b/gyp/android.gyp @@ -0,0 +1,5 @@ +{ + 'includes': [ + '../android/mapboxgl-app.gypi', + ], +} diff --git a/gyp/asset-fs.gypi b/gyp/asset-fs.gypi index f7fbea1c7..e84fabb62 100644 --- a/gyp/asset-fs.gypi +++ b/gyp/asset-fs.gypi @@ -17,14 +17,14 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', '<@(boost_cflags)', ], 'ldflags': [ - '<@(uv_ldflags)', + '<@(libuv_ldflags)', ], 'libraries': [ - '<@(uv_static_libs)', + '<@(libuv_static_libs)', ], 'defines': [ '-DMBGL_ASSET_FS' diff --git a/gyp/asset-zip.gypi b/gyp/asset-zip.gypi index 8a195649f..e8854734e 100644 --- a/gyp/asset-zip.gypi +++ b/gyp/asset-zip.gypi @@ -18,21 +18,21 @@ 'variables': { 'cflags': [ - '<@(uv_cflags)', - '<@(zip_cflags)', + '<@(libuv_cflags)', + '<@(libzip_cflags)', ], 'cflags_cc': [ - '<@(uv_cflags)', - '<@(zip_cflags)', + '<@(libuv_cflags)', + '<@(libzip_cflags)', '<@(boost_cflags)', ], 'ldflags': [ - '<@(uv_ldflags)', - '<@(zip_ldflags)', + '<@(libuv_ldflags)', + '<@(libzip_ldflags)', ], 'libraries': [ - '<@(uv_static_libs)', - '<@(zip_static_libs)', + '<@(libuv_static_libs)', + '<@(libzip_static_libs)', ], 'defines': [ '-DMBGL_ASSET_ZIP' diff --git a/gyp/cache-sqlite.gypi b/gyp/cache-sqlite.gypi index a9d21924c..704dc490e 100644 --- a/gyp/cache-sqlite.gypi +++ b/gyp/cache-sqlite.gypi @@ -19,17 +19,17 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', - '<@(sqlite3_cflags)', + '<@(libuv_cflags)', + '<@(sqlite_cflags)', ], 'ldflags': [ - '<@(uv_ldflags)', - '<@(sqlite3_ldflags)', + '<@(libuv_ldflags)', + '<@(sqlite_ldflags)', '<@(zlib_ldflags)', ], 'libraries': [ - '<@(uv_static_libs)', - '<@(sqlite3_static_libs)', + '<@(libuv_static_libs)', + '<@(sqlite_static_libs)', '<@(zlib_static_libs)', ], }, diff --git a/gyp/core.gypi b/gyp/core.gypi index 246419371..f9b361032 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -28,21 +28,21 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', '<@(opengl_cflags)', '<@(boost_cflags)', ], 'cflags': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', '<@(opengl_cflags)', '-fPIC' ], 'ldflags': [ - '<@(uv_ldflags)', + '<@(libuv_ldflags)', '<@(opengl_ldflags)', ], 'libraries': [ - '<@(uv_static_libs)', + '<@(libuv_static_libs)', ], }, diff --git a/gyp/http-curl.gypi b/gyp/http-curl.gypi index b7c583235..7ae5b1b75 100644 --- a/gyp/http-curl.gypi +++ b/gyp/http-curl.gypi @@ -17,17 +17,17 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', - '<@(curl_cflags)', + '<@(libuv_cflags)', + '<@(libcurl_cflags)', '<@(boost_cflags)', ], 'ldflags': [ - '<@(uv_ldflags)', - '<@(curl_ldflags)', + '<@(libuv_ldflags)', + '<@(libcurl_ldflags)', ], 'libraries': [ - '<@(uv_static_libs)', - '<@(curl_static_libs)', + '<@(libuv_static_libs)', + '<@(libcurl_static_libs)', ], 'defines': [ '-DMBGL_HTTP_CURL' @@ -38,9 +38,9 @@ ['host == "android"', { 'variables': { # Android uses libzip and openssl to set CURL's CA bundle. - 'cflags_cc': [ '<@(zip_cflags)', '<@(openssl_cflags)' ], - 'ldflags': [ '<@(zip_ldflags)', ], - 'libraries': [ '<@(zip_static_libs)', ], + 'cflags_cc': [ '<@(libzip_cflags)', '<@(openssl_cflags)' ], + 'ldflags': [ '<@(libzip_ldflags)', ], + 'libraries': [ '<@(libzip_static_libs)', ], }, }], ['OS == "mac"', { diff --git a/gyp/http-nsurl.gypi b/gyp/http-nsurl.gypi index a64c8508e..efd2c18a7 100644 --- a/gyp/http-nsurl.gypi +++ b/gyp/http-nsurl.gypi @@ -17,14 +17,14 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', ], 'ldflags': [ '-framework Foundation', # For NSURLRequest - '<@(uv_ldflags)', + '<@(libuv_ldflags)', ], 'libraries': [ - '<@(uv_static_libs)', + '<@(libuv_static_libs)', ], 'defines': [ '-DMBGL_HTTP_NSURL' diff --git a/gyp/linux.gyp b/gyp/linux.gyp index 0f7126934..6cc168ba8 100644 --- a/gyp/linux.gyp +++ b/gyp/linux.gyp @@ -1,7 +1,10 @@ { 'includes': [ '../linux/mapboxgl-app.gypi', - '../test/test.gypi', - '../bin/render.gypi', + ], + + 'conditions': [ + ['test', { 'includes': [ '../test/test.gypi' ] } ], + ['render', { 'includes': [ '../bin/render.gypi' ] } ], ], } diff --git a/gyp/platform-android.gypi b/gyp/platform-android.gypi index 7701393bb..41a5733ac 100644 --- a/gyp/platform-android.gypi +++ b/gyp/platform-android.gypi @@ -22,23 +22,23 @@ 'variables': { 'cflags_cc': [ - '<@(png_cflags)', + '<@(libpng_cflags)', '<@(jpeg_cflags)', - '<@(uv_cflags)', - '<@(nu_cflags)', + '<@(libuv_cflags)', + '<@(nunicode_cflags)', '<@(boost_cflags)', ], 'ldflags': [ - '<@(png_ldflags)', + '<@(libpng_ldflags)', '<@(jpeg_ldflags)', - '<@(uv_ldflags)', - '<@(nu_ldflags)', + '<@(libuv_ldflags)', + '<@(nunicode_ldflags)', ], 'libraries': [ - '<@(png_static_libs)', + '<@(libpng_static_libs)', '<@(jpeg_static_libs)', - '<@(uv_static_libs)', - '<@(nu_static_libs)', + '<@(libuv_static_libs)', + '<@(nunicode_static_libs)', ], }, diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index 7baba06e5..481e0b2bb 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -65,11 +65,11 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', '<@(boost_cflags)', ], 'libraries': [ - '<@(uv_static_libs)', + '<@(libuv_static_libs)', ], 'ldflags': [ '-framework CoreLocation', diff --git a/gyp/platform-linux.gypi b/gyp/platform-linux.gypi index 394433870..f614b831e 100644 --- a/gyp/platform-linux.gypi +++ b/gyp/platform-linux.gypi @@ -23,23 +23,23 @@ 'variables': { 'cflags_cc': [ - '<@(png_cflags)', + '<@(libpng_cflags)', '<@(jpeg_cflags)', - '<@(uv_cflags)', - '<@(nu_cflags)', + '<@(libuv_cflags)', + '<@(nunicode_cflags)', '<@(boost_cflags)', ], 'ldflags': [ - '<@(png_ldflags)', + '<@(libpng_ldflags)', '<@(jpeg_ldflags)', - '<@(uv_ldflags)', - '<@(nu_ldflags)', + '<@(libuv_ldflags)', + '<@(nunicode_ldflags)', ], 'libraries': [ - '<@(png_static_libs)', + '<@(libpng_static_libs)', '<@(jpeg_static_libs)', - '<@(uv_static_libs)', - '<@(nu_static_libs)', + '<@(libuv_static_libs)', + '<@(nunicode_static_libs)', ], }, diff --git a/gyp/platform-osx.gypi b/gyp/platform-osx.gypi index ae5194761..af30019ee 100644 --- a/gyp/platform-osx.gypi +++ b/gyp/platform-osx.gypi @@ -20,11 +20,11 @@ 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', '<@(boost_cflags)', ], 'libraries': [ - '<@(uv_static_libs)', + '<@(libuv_static_libs)', ], 'ldflags': [ '-framework Foundation', diff --git a/linux/mapboxgl-app.gypi b/linux/mapboxgl-app.gypi index 379bd4ad5..8457c2ce7 100644 --- a/linux/mapboxgl-app.gypi +++ b/linux/mapboxgl-app.gypi @@ -31,13 +31,13 @@ 'cflags_cc': [ '<@(opengl_cflags)', '<@(boost_cflags)', - '<@(glfw3_cflags)', + '<@(glfw_cflags)', ], 'ldflags': [ - '<@(glfw3_ldflags)', + '<@(glfw_ldflags)', ], 'libraries': [ - '<@(glfw3_static_libs)', + '<@(glfw_static_libs)', ], }, diff --git a/macosx/mapboxgl-app.gypi b/macosx/mapboxgl-app.gypi index 3b7d904a7..589ae29bd 100644 --- a/macosx/mapboxgl-app.gypi +++ b/macosx/mapboxgl-app.gypi @@ -35,14 +35,14 @@ 'variables' : { 'cflags_cc': [ '<@(boost_cflags)', - '<@(glfw3_cflags)', + '<@(glfw_cflags)', ], 'ldflags': [ '-framework SystemConfiguration', # For NSUserDefaults and Reachability - '<@(glfw3_ldflags)', + '<@(glfw_ldflags)', ], 'libraries': [ - '<@(glfw3_static_libs)', + '<@(glfw_static_libs)', ], }, diff --git a/scripts/android/configure.sh b/scripts/android/configure.sh new file mode 100644 index 000000000..667ea6891 --- /dev/null +++ b/scripts/android/configure.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +BOOST_VERSION=1.57.0 +LIBCURL_VERSION=7.40.0 +OPENSSL_VERSION=1.0.1l +LIBPNG_VERSION=1.6.16 +JPEG_VERSION=v9a +SQLITE_VERSION=3.8.8.1 +LIBUV_VERSION=1.4.0 +ZLIB_VERSION=system +NUNICODE_VERSION=1.5.1 +LIBZIP_VERSION=0.11.2 + +export MASON_ANDROID_ABI=${MASON_PLATFORM_VERSION} \ No newline at end of file diff --git a/scripts/android/defaults.mk b/scripts/android/defaults.mk new file mode 100644 index 000000000..436f9db71 --- /dev/null +++ b/scripts/android/defaults.mk @@ -0,0 +1,11 @@ +HEADLESS ?= none +PLATFORM ?= android +ASSET ?= zip +HTTP ?= curl +CACHE ?= sqlite + +GYP_FLAVOR_SUFFIX=-android + +HOST_VERSION ?= arm-v7 + +ENV = $(shell MASON_ANDROID_ABI=$(HOST_VERSION) ./scripts/android/toolchain.sh) diff --git a/scripts/ios/configure.sh b/scripts/ios/configure.sh new file mode 100644 index 000000000..0562e0e39 --- /dev/null +++ b/scripts/ios/configure.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +BOOST_VERSION=1.57.0 +SQLITE_VERSION=system +LIBUV_VERSION=0.10.28 +ZLIB_VERSION=system diff --git a/scripts/ios/defaults.mk b/scripts/ios/defaults.mk new file mode 100644 index 000000000..fafc33213 --- /dev/null +++ b/scripts/ios/defaults.mk @@ -0,0 +1,12 @@ +HEADLESS = none +PLATFORM ?= ios +ASSET ?= fs +HTTP ?= nsurl +CACHE ?= sqlite + +HOST_VERSION = all + +PROVISIONING_PROFILE ?= 19324a54-7455-4f0b-8e1c-e6957c718ebc + +export MASON_PLATFORM=$(HOST) +export MASON_PLATFORM_VERSION=$(HOST_VERSION) diff --git a/scripts/ios/package.sh b/scripts/ios/package.sh index b499f4a10..449cf5c25 100755 --- a/scripts/ios/package.sh +++ b/scripts/ios/package.sh @@ -50,7 +50,7 @@ if [[ "${BUILD_FOR_DEVICE}" == true ]]; then ARCHS="arm64 armv7 armv7s" \ ONLY_ACTIVE_ARCH=NO \ GCC_GENERATE_DEBUGGING_SYMBOLS=${GCC_GENERATE_DEBUGGING_SYMBOLS} \ - -project ./build/ios/mbgl.xcodeproj \ + -project ./build/ios-all/mbgl.xcodeproj \ -configuration ${BUILDTYPE} \ -target everything \ -jobs ${JOBS} | xcpretty -c @@ -61,7 +61,7 @@ xcodebuild -sdk iphonesimulator${IOS_SDK_VERSION} \ ARCHS="x86_64 i386" \ ONLY_ACTIVE_ARCH=NO \ GCC_GENERATE_DEBUGGING_SYMBOLS=${GCC_GENERATE_DEBUGGING_SYMBOLS} \ - -project ./build/ios/mbgl.xcodeproj \ + -project ./build/ios-all/mbgl.xcodeproj \ -configuration ${BUILDTYPE} \ -target everything \ -jobs ${JOBS} | xcpretty -c diff --git a/scripts/linux/configure.sh b/scripts/linux/configure.sh new file mode 100644 index 000000000..1099a6550 --- /dev/null +++ b/scripts/linux/configure.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +BOOST_VERSION=1.57.0 +BOOST_LIBPROGRAM_OPTIONS_VERSION=1.57.0 +LIBCURL_VERSION=system +GLFW_VERSION=3.1 +LIBPNG_VERSION=1.6.16 +JPEG_VERSION=v9a +SQLITE_VERSION=3.8.8.1 +LIBUV_VERSION=0.10.28 +ZLIB_VERSION=system +NUNICODE_VERSION=1.5.1 +LIBZIP_VERSION=0.11.2 + +function print_opengl_flags { + CONFIG+=" 'opengl_cflags%': $(quote_flags $(pkg-config gl x11 --cflags)),"$LN + CONFIG+=" 'opengl_ldflags%': $(quote_flags $(pkg-config gl x11 --libs)),"$LN +} diff --git a/scripts/linux/defaults.mk b/scripts/linux/defaults.mk new file mode 100644 index 000000000..126c8f99a --- /dev/null +++ b/scripts/linux/defaults.mk @@ -0,0 +1,5 @@ +HEADLESS ?= glx +PLATFORM ?= linux +ASSET ?= fs +HTTP ?= curl +CACHE ?= sqlite diff --git a/scripts/main.mk b/scripts/main.mk new file mode 100644 index 000000000..b641a6ffe --- /dev/null +++ b/scripts/main.mk @@ -0,0 +1,127 @@ +ifeq (,$(V)) + QUIET = @ +endif + +# Determine host platform +HOST ?= $(BUILD) + +# Defines host defaults +include scripts/$(HOST)/defaults.mk + +HOST_VERSION ?= $(BUILD_VERSION) + +# Optionally include version-specific host defaults +-include scripts/$(HOST)/$(HOST_VERSION)/defaults.mk + +export MASON_PLATFORM=$(HOST) +export MASON_PLATFORM_VERSION=$(HOST_VERSION) + +HOST_SLUG = $(HOST)-$(HOST_VERSION) +CONFIGURE_FILES = scripts/$(HOST)/configure.sh +ifneq (,$(wildcard scripts/$(HOST)/$(HOST_VERSION)/configure.sh)) + CONFIGURE_FILES += scripts/$(HOST)/$(HOST_VERSION)/configure.sh +endif + + +# Text formatting +TEXT_BOLD = \033[1m +COLOR_GREEN = \033[32m +COLOR_CYAN = \033[36m +COLOR_PINK = \033[35m +FORMAT_END = \033[0m + +default: ; + +#### Dependencies ############################################################## + +SUBMODULES += .mason/mason.sh +.mason/mason.sh: + ./scripts/flock.py .git/Submodule.lock git submodule update --init .mason + +SUBMODULES += styles/styles +styles/styles: + ./scripts/flock.py .git/Submodule.lock git submodule update --init styles + +SUBMODULES += src/mbgl/util/geojsonvt/geojsonvt.hpp +src/mbgl/util/geojsonvt/geojsonvt.hpp: + ./scripts/flock.py .git/Submodule.lock git submodule update --init src/mbgl/util/geojsonvt + +SUBMODULES += test/suite/package.json +test/suite/package.json: + ./scripts/flock.py .git/Submodule.lock git submodule update --init test/suite + +ifeq ($(HOST),ios) +SUBMODULES += platform/ios/vendor/SMCalloutView/SMCalloutView.h +platform/ios/vendor/SMCalloutView/SMCalloutView.h: + ./scripts/flock.py .git/Submodule.lock git submodule update --init platform/ios/vendor/SMCalloutView + +SUBMODULES += test/ios/KIF/KIF.xcodeproj +test/ios/KIF/KIF.xcodeproj: + ./scripts/flock.py .git/Submodule.lock git submodule update --init test/ios/KIF +endif + +# Wildcard targets get removed after build by default, but we want to preserve the config. +.PRECIOUS: config/%.gypi +config/%.gypi: $(SUBMODULES) configure $(CONFIGURE_FILES) + @printf "$(TEXT_BOLD)$(COLOR_GREEN)* Recreating project...$(FORMAT_END)\n" + $(QUIET)$(ENV) ./scripts/flock.py build/Configure.lock ./configure config/$*.gypi + + +#### Build files ############################################################### + +GYP_FLAGS += -Dhost=$(HOST) +GYP_FLAGS += -Iconfig/$(HOST_SLUG).gypi +GYP_FLAGS += -Dplatform_lib=$(PLATFORM) +GYP_FLAGS += -Dhttp_lib=$(HTTP) +GYP_FLAGS += -Dasset_lib=$(ASSET) +GYP_FLAGS += -Dcache_lib=$(CACHE) +GYP_FLAGS += -Dheadless_lib=$(HEADLESS) +GYP_FLAGS += -Dtest=$(BUILD_TEST) +GYP_FLAGS += -Drender=$(BUILD_RENDER) +GYP_FLAGS += --depth=. +GYP_FLAGS += -Goutput_dir=. +GYP_FLAGS += --generator-output=./build/$(HOST_SLUG) + +.PHONY: Makefile/__project__ +Makefile/__project__: print-env $(SUBMODULES) config/$(HOST_SLUG).gypi + @printf "$(TEXT_BOLD)$(COLOR_GREEN)* Recreating project...$(FORMAT_END)\n" + $(QUIET)$(ENV) deps/run_gyp gyp/$(HOST).gyp $(GYP_FLAGS) -f make$(GYP_FLAVOR_SUFFIX) + +.PHONY: Xcode/__project__ +Xcode/__project__: print-env $(SUBMODULES) config/$(HOST_SLUG).gypi + @printf "$(TEXT_BOLD)$(COLOR_GREEN)* Recreating project...$(FORMAT_END)\n" + $(QUIET)$(ENV) deps/run_gyp gyp/$(HOST).gyp $(GYP_FLAGS) -f xcode$(GYP_FLAVOR_SUFFIX) + +#### Build individual targets ################################################## + +Makefile/%: Makefile/__project__ + @printf "$(TEXT_BOLD)$(COLOR_GREEN)* Building target $*...$(FORMAT_END)\n" + $(QUIET)$(ENV) $(MAKE) -C build/$(HOST_SLUG) BUILDTYPE=$(BUILDTYPE) $* + +Xcode/%: Xcode/__project__ + @printf "$(TEXT_BOLD)$(COLOR_GREEN)* Building target $*...$(FORMAT_END)\n" + $(QUIET)$(ENV) xcodebuild \ + $(XCODEBUILD_ARGS) \ + -project ./build/$(HOST_SLUG)/gyp/$(HOST).xcodeproj \ + -configuration $(BUILDTYPE) \ + -target $* \ + -jobs $(JOBS) \ + $(XCPRETTY) + +#### Run tests ################################################################# + +test-%: Makefile/test + ./scripts/run_tests.sh "build/$(HOST_SLUG)/$(BUILDTYPE)/test" --gtest_filter=$* + +#### Helper targets ############################################################ + +.PHONY: print-env +print-env: $(SUBMODULES) + @printf "$(COLOR_PINK)build:$(FORMAT_END) $(BUILD)/$(BUILD_VERSION)\n" + @printf "$(COLOR_PINK)host:$(FORMAT_END) $(HOST)/$(HOST_VERSION)\n" + @printf "$(COLOR_PINK)libs:$(FORMAT_END) " + @printf "headless=$(COLOR_CYAN)%s$(FORMAT_END) " $(HEADLESS) + @printf "platform=$(COLOR_CYAN)%s$(FORMAT_END) " $(PLATFORM) + @printf "asset=$(COLOR_CYAN)%s$(FORMAT_END) " $(ASSET) + @printf "http=$(COLOR_CYAN)%s$(FORMAT_END) " $(HTTP) + @printf "cache=$(COLOR_CYAN)%s$(FORMAT_END)\n" $(CACHE) diff --git a/scripts/osx/configure.sh b/scripts/osx/configure.sh new file mode 100644 index 000000000..fc3c5f464 --- /dev/null +++ b/scripts/osx/configure.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +BOOST_VERSION=1.57.0 +BOOST_LIBPROGRAM_OPTIONS_VERSION=1.57.0 +LIBCURL_VERSION=system +GLFW_VERSION=3.1 +LIBPNG_VERSION=1.6.16 +JPEG_VERSION=v9a +SQLITE_VERSION=3.8.8.1 +LIBUV_VERSION=0.10.28 +ZLIB_VERSION=system +NUNICODE_VERSION=1.5.1 +LIBZIP_VERSION=0.11.2 diff --git a/scripts/osx/defaults.mk b/scripts/osx/defaults.mk new file mode 100644 index 000000000..f148f66d8 --- /dev/null +++ b/scripts/osx/defaults.mk @@ -0,0 +1,5 @@ +HEADLESS ?= cgl +PLATFORM ?= osx +ASSET ?= fs +HTTP ?= nsurl +CACHE ?= sqlite diff --git a/test/test.gypi b/test/test.gypi index 142445d98..4e669aee1 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -94,19 +94,19 @@ 'style/sprite.cpp', ], 'libraries': [ - '<@(uv_static_libs)', - '<@(sqlite3_static_libs)', + '<@(libuv_static_libs)', + '<@(sqlite_static_libs)', ], 'variables': { 'cflags_cc': [ - '<@(uv_cflags)', + '<@(libuv_cflags)', '<@(opengl_cflags)', '<@(boost_cflags)', - '<@(sqlite3_cflags)', + '<@(sqlite_cflags)', ], 'ldflags': [ - '<@(uv_ldflags)', - '<@(sqlite3_ldflags)', + '<@(libuv_ldflags)', + '<@(sqlite_ldflags)', ], }, 'conditions': [ From 3b4a0b228cd95f203e12c224db99e27fe1132cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 4 Aug 2015 18:09:02 +0200 Subject: [PATCH 14/14] output the build artifacts to the right directory this was introduced by using a file in /gyp as the root entry point for gyp builds, rather than a gyp file in /android. --- android/mapboxgl-app.gypi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/mapboxgl-app.gypi b/android/mapboxgl-app.gypi index 107bbcbd5..e32775ff7 100644 --- a/android/mapboxgl-app.gypi +++ b/android/mapboxgl-app.gypi @@ -77,7 +77,7 @@ '../common/ca-bundle.crt', '../styles/styles' ], - 'destination': '<(pwd)/java/MapboxGLAndroidSDK/src/main/assets' + 'destination': '<(pwd)/../android/java/MapboxGLAndroidSDK/src/main/assets' }, ], @@ -85,7 +85,7 @@ { 'action_name': 'Strip dynamic library', 'inputs': [ '<(PRODUCT_DIR)/lib.target/libmapbox-gl.so' ], - 'outputs': [ '<(pwd)/java/MapboxGLAndroidSDK/src/main/jniLibs/$(JNIDIR)/libmapbox-gl.so' ], + 'outputs': [ '<(pwd)/../android/java/MapboxGLAndroidSDK/src/main/jniLibs/$(JNIDIR)/libmapbox-gl.so' ], 'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ] }, ],