From 473dd52b33661e71f4a1a8d92bc52e89d11f4680 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Sun, 9 Aug 2026 11:42:52 +0000 Subject: [PATCH 1/9] feat(extensions): add PostGIS raster and GDAL support --- .../src/oliphaunt/extensions.rs | 5 + .../src/testdata/postgis-smoke.sql | 30 +++ src/extensions/catalog/extensions.source.json | 3 +- .../contrib/.release-semantic-inputs.json | 4 +- src/extensions/evidence/matrix.toml | 1 + .../pg_hashids/.release-semantic-inputs.json | 4 +- .../pg_ivm/.release-semantic-inputs.json | 4 +- .../.release-semantic-inputs.json | 4 +- .../pg_uuidv7/.release-semantic-inputs.json | 4 +- .../pgtap/.release-semantic-inputs.json | 4 +- .../postgis/.release-semantic-inputs.json | 12 +- .../postgis/dependencies/gdal/source.toml | 4 + src/extensions/external/postgis/deps.toml | 8 + src/extensions/external/postgis/recipe.toml | 48 +++- src/extensions/external/postgis/source.toml | 8 +- .../targets/native-static-registry.toml | 34 ++- .../external/postgis/targets/native.toml | 32 ++- .../external/postgis/targets/wasix.toml | 49 +++- .../external/postgis/tests/smoke.sql | 30 +++ .../external/postgis/tests/upstream.toml | 5 +- .../external/postgis/tools/build_wasix.sh | 84 ++++++- .../postgis/upstream-license-data.json | 34 ++- .../vector/.release-semantic-inputs.json | 4 +- .../generated/docs/extension-evidence.json | 3 +- src/extensions/generated/docs/extensions.json | 3 +- .../generated/extensions.build-plan.json | 22 +- .../generated/extensions.catalog.json | 7 +- .../generated/mobile/static-extensions.tsv | 2 +- .../generated/mobile/static-registry.json | 27 +++ src/extensions/generated/sdk/js.json | 61 ++++- src/extensions/generated/sdk/kotlin.json | 61 ++++- .../generated/sdk/react-native.json | 62 ++++- src/extensions/generated/sdk/rust.json | 61 ++++- src/extensions/generated/sdk/swift.json | 61 ++++- .../generated/wasix/extensions.json | 6 + .../native/.release-semantic-inputs.json | 10 +- .../native/bin/build-postgres18-linux.sh | 135 +++++++++-- .../native/bin/build-postgres18-macos.sh | 141 ++++++++++-- .../native/bin/build-postgres18-windows.ps1 | 214 +++++++++++++++++- .../native/bin/mobile-postgis-extensions.sh | 207 +++++++++++++++-- .../bin/postgis-reproducible-time.test.sh | 8 +- .../native/tools/test-symbol-scope.sh | 2 +- .../wasix/.release-semantic-inputs.json | 36 +-- .../wasix/assets/build/build_wasix_gdal.sh | 124 ++++++++++ .../build/wasix_shim/gdal_wasix_compat.h | 22 ++ .../wasix/assets/build/wasix_third_party.sh | 4 +- .../assets/generated/asset-inputs.sha256 | 2 +- .../wasix/assets/generated/wasix-dl.exports | 14 +- src/sdks/js/src/generated/extensions.ts | 62 ++++- .../android/extension-legal-catalog.json | 30 ++- .../oliphaunt/android/extensions.properties | 2 +- .../oliphaunt/src/generated/extensions.json | 61 ++++- .../src/generated/extensions.json | 62 ++++- .../react-native/src/generated/extensions.ts | 64 +++++- .../react-native/tools/stage-ios-app.test.mjs | 3 +- src/sdks/rust/src/generated/extensions.rs | 44 +++- .../rust/src/liboliphaunt/root/extensions.rs | 8 + src/sdks/rust/src/runtime_resources.rs | 4 + .../rust/tests/fixtures/postgis-smoke.sql | 30 +++ src/sdks/rust/tests/sdk_extensions.rs | 10 +- src/sdks/swift/.release-semantic-inputs.json | 4 +- tools/dev/bun.sh | 12 +- tools/dev/install-pinned-js-runtime.sh | 8 +- .../assertions/assert-source-inputs.mjs | 3 +- .../extension-upstream-licenses.test.mjs | 3 + .../github-content-write-pacer.test.mjs | 22 +- .../github-release-asset-upload-plan.test.mjs | 12 +- .../js-exact-candidate-consumer.test.mjs | 4 +- .../postgis-reproducible-time.test.mjs | 4 +- .../upload-github-release-assets.test.mjs | 8 +- tools/xtask/src/asset_checks.rs | 2 + tools/xtask/src/asset_pipeline.rs | 2 +- tools/xtask/src/extension_catalog.rs | 24 +- tools/xtask/src/fs_utils.rs | 21 ++ 74 files changed, 1996 insertions(+), 223 deletions(-) create mode 100644 src/extensions/external/postgis/dependencies/gdal/source.toml create mode 100755 src/runtimes/liboliphaunt/wasix/assets/build/build_wasix_gdal.sh create mode 100644 src/runtimes/liboliphaunt/wasix/assets/build/wasix_shim/gdal_wasix_compat.h diff --git a/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/extensions.rs b/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/extensions.rs index 0842288d..224e9362 100644 --- a/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/extensions.rs +++ b/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/extensions.rs @@ -423,6 +423,11 @@ mod candidate_tests { run_direct_and_restart_smoke_set(&[generated::CANDIDATE_UUID_OSSP]) } + #[test] + fn postgis_passes_direct_and_restart_smoke() -> Result<()> { + run_direct_and_restart_smoke_set(&[generated::POSTGIS]) + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[ignore = "promotion gate: run manually before marking packaged candidates stable"] async fn packaged_candidate_extensions_pass_server_smoke() -> Result<()> { diff --git a/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/testdata/postgis-smoke.sql b/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/testdata/postgis-smoke.sql index 4f05b7be..85c48d46 100644 --- a/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/testdata/postgis-smoke.sql +++ b/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/testdata/postgis-smoke.sql @@ -1,3 +1,7 @@ +CREATE EXTENSION IF NOT EXISTS postgis_raster; +-- oliphaunt-statement +SET postgis.gdal_enabled_drivers = 'ENABLE_ALL'; +-- oliphaunt-statement DROP TABLE IF EXISTS liboliphaunt_postgis_points; -- oliphaunt-statement CREATE TEMP TABLE liboliphaunt_postgis_points(id int PRIMARY KEY, geom geometry(Point, 4326)); @@ -15,6 +19,9 @@ DECLARE area float8; polygons int; nearby int; + gdal_drivers int; + raster_roundtrip raster; + raster_value float8; BEGIN SELECT ST_Distance(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('POINT(3 4)')) INTO distance; IF distance <> 5 THEN @@ -56,6 +63,29 @@ BEGIN IF nearby <> 2 THEN RAISE EXCEPTION 'postgis dwithin failed: %', nearby; END IF; + SELECT count(*) INTO gdal_drivers + FROM ST_GDALDrivers() + WHERE short_name = 'GTiff' AND can_read AND can_write; + IF gdal_drivers <> 1 THEN + RAISE EXCEPTION 'postgis raster GeoTIFF driver is unavailable'; + END IF; + SELECT ST_FromGDALRaster( + ST_AsGDALRaster( + ST_AddBand( + ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 4326), + '8BUI'::text, + 7::double precision, + 0::double precision + ), + 'GTiff' + ) + ) INTO raster_roundtrip; + SELECT ST_Value(raster_roundtrip, 1, 1, 1) INTO raster_value; + IF raster_value <> 7 OR ST_SRID(raster_roundtrip) <> 4326 THEN + RAISE EXCEPTION 'postgis raster GDAL round-trip failed: value %, srid %', + raster_value, + ST_SRID(raster_roundtrip); + END IF; END $$; -- oliphaunt-statement DROP TABLE IF EXISTS liboliphaunt_postgis_points; diff --git a/src/extensions/catalog/extensions.source.json b/src/extensions/catalog/extensions.source.json index 83cf220a..8030c23e 100644 --- a/src/extensions/catalog/extensions.source.json +++ b/src/extensions/catalog/extensions.source.json @@ -1197,7 +1197,7 @@ "postgres extension", "experimental" ], - "bundle-size": 8551161, + "bundle-size": 11490267, "control-file": "target/oliphaunt-sources/checkouts/postgis/extensions/postgis/postgis.control.in", "control": { "module-pathname": "@MODULEPATH@", @@ -1206,6 +1206,7 @@ }, "dependencies": [], "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", diff --git a/src/extensions/contrib/.release-semantic-inputs.json b/src/extensions/contrib/.release-semantic-inputs.json index 2cae8a54..c685889b 100644 --- a/src/extensions/contrib/.release-semantic-inputs.json +++ b/src/extensions/contrib/.release-semantic-inputs.json @@ -218,7 +218,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -377,5 +377,5 @@ ] } ], - "sha256": "419f620e12df219054374188e11b362780ba9e436f547348c20acd0bf7c29d24" + "sha256": "98252ebbafb0c1ef632a4d861f423c0cb6e9d09a91e6fbf37c979292dd1e8a10" } diff --git a/src/extensions/evidence/matrix.toml b/src/extensions/evidence/matrix.toml index 3d5c7155..b87ab604 100644 --- a/src/extensions/evidence/matrix.toml +++ b/src/extensions/evidence/matrix.toml @@ -16,6 +16,7 @@ source-digest-inputs = [ "src/extensions/external/pg_textsearch/source.toml", "src/extensions/external/pg_uuidv7/source.toml", "src/extensions/external/pgtap/source.toml", + "src/extensions/external/postgis/dependencies/gdal/source.toml", "src/extensions/external/postgis/dependencies/geos/source.toml", "src/extensions/external/postgis/dependencies/json-c/source.toml", "src/extensions/external/postgis/dependencies/libiconv/source.toml", diff --git a/src/extensions/external/pg_hashids/.release-semantic-inputs.json b/src/extensions/external/pg_hashids/.release-semantic-inputs.json index e10d6f04..26e7b4ef 100644 --- a/src/extensions/external/pg_hashids/.release-semantic-inputs.json +++ b/src/extensions/external/pg_hashids/.release-semantic-inputs.json @@ -184,7 +184,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -343,5 +343,5 @@ ] } ], - "sha256": "cd9da3b78ef5e8df01dacab7774205aef15270bf3d20dee1718b81bad78c13b1" + "sha256": "e91c587cc2556d9c456dae649a2c9113c8442a62aa85d6e1f1d5bbe0ae1745b4" } diff --git a/src/extensions/external/pg_ivm/.release-semantic-inputs.json b/src/extensions/external/pg_ivm/.release-semantic-inputs.json index 46bcd81a..11b92763 100644 --- a/src/extensions/external/pg_ivm/.release-semantic-inputs.json +++ b/src/extensions/external/pg_ivm/.release-semantic-inputs.json @@ -184,7 +184,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -343,5 +343,5 @@ ] } ], - "sha256": "93852eada395596f863f6ff4bf11709c09758e8720e2f92ec0ae315a80ea07ef" + "sha256": "cb69acade62d6aecf3748f74e1d4f223526177084418ba6305e2af840b828393" } diff --git a/src/extensions/external/pg_textsearch/.release-semantic-inputs.json b/src/extensions/external/pg_textsearch/.release-semantic-inputs.json index aeac4dcf..49507131 100644 --- a/src/extensions/external/pg_textsearch/.release-semantic-inputs.json +++ b/src/extensions/external/pg_textsearch/.release-semantic-inputs.json @@ -184,7 +184,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -343,5 +343,5 @@ ] } ], - "sha256": "93af1bc0cc1039d7285d1bfdefeca1b1a959c89bb0c523490711b59601b3c427" + "sha256": "409d6c6986de030409627e7d33954b86b2cba7826560780a89d57cb576c0f3f1" } diff --git a/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json b/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json index 36aa011e..c2263ab9 100644 --- a/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json +++ b/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json @@ -184,7 +184,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -343,5 +343,5 @@ ] } ], - "sha256": "582f1d4797443f6cda96d94f8f3a6c1bf66bcd4778d3f8518b937233aab11e2e" + "sha256": "cf1fe73ef32ba83d6eaf8d9858cba1fb8c7f6c5f3763e5cfb9c8cddf1a52039d" } diff --git a/src/extensions/external/pgtap/.release-semantic-inputs.json b/src/extensions/external/pgtap/.release-semantic-inputs.json index 8e6eb89a..14533301 100644 --- a/src/extensions/external/pgtap/.release-semantic-inputs.json +++ b/src/extensions/external/pgtap/.release-semantic-inputs.json @@ -184,7 +184,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -343,5 +343,5 @@ ] } ], - "sha256": "5bd705d032c08abd0cee58e21f15836ee67f512822017e61ce4bea347a8c6031" + "sha256": "59fa73e1b278db5b9536a3011b3d86c2b05c3e6f9eda0b72372e47eb05d7463a" } diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index fd32cd81..8e825818 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -91,19 +91,19 @@ }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-linux.sh", - "sha256": "d9ded61bf55c42197f84115940c0546f2801876b1562084b17cae80b41aeae68" + "sha256": "551e2603d37157908c0a7fea72a086188bf65081fb2054b7d5874d31f1af819f" }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-macos.sh", - "sha256": "b53b165f9942a080ecfe84af9f2bffd41c194af79657ab09fa1018c156af20ca" + "sha256": "f23ac3a4bb06cc9d55b36fd1ed9d12b23063aa2159680b38b52e4f5a5545b8ef" }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1", - "sha256": "3ecdda83cf6ed8df45852ead088dc5baa415b07e302824b0531a4ff839cbb8c6" + "sha256": "21c8c44a8aa03aac5f8dda9674c630829d03ec8cd0c7a66eecf8e1b57ffa2186" }, { "path": "src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh", - "sha256": "3542a4b4c4efe80fe664eb8f2421b992675f88e01e2f19a30856ff98cb711fb1" + "sha256": "486ef696c48505ba03ca0f979525cabaed699e9e7a53281f37a9416254a693c1" } ] }, @@ -231,7 +231,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -390,5 +390,5 @@ ] } ], - "sha256": "a8d8102915899d7308025b7c9fd5401f64e18c347d2d53aed9c083c7b001c2a4" + "sha256": "ad61e99402000cb46d6bb9042ed56beaa13ab91e859e4f6012334636f6b7de8d" } diff --git a/src/extensions/external/postgis/dependencies/gdal/source.toml b/src/extensions/external/postgis/dependencies/gdal/source.toml new file mode 100644 index 00000000..4746701a --- /dev/null +++ b/src/extensions/external/postgis/dependencies/gdal/source.toml @@ -0,0 +1,4 @@ +name = "gdal" +url = "https://github.com/OSGeo/gdal.git" +branch = "v3.13.2" +commit = "b40672525acf3f5c4f29d8541aa7dcff1e18eb92" diff --git a/src/extensions/external/postgis/deps.toml b/src/extensions/external/postgis/deps.toml index 52004b0e..18f54369 100644 --- a/src/extensions/external/postgis/deps.toml +++ b/src/extensions/external/postgis/deps.toml @@ -1,5 +1,13 @@ schema = "oliphaunt-extension-deps-v1" +[[dependencies]] +name = "gdal" +source = "gdal" +version = "3.13.2" +linkage = "static" +license = "MIT" +mobile-static-dependencies = ["gdal"] + [[dependencies]] name = "geos" source = "geos" diff --git a/src/extensions/external/postgis/recipe.toml b/src/extensions/external/postgis/recipe.toml index 5cf0e659..e0909a0a 100644 --- a/src/extensions/external/postgis/recipe.toml +++ b/src/extensions/external/postgis/recipe.toml @@ -21,17 +21,53 @@ needs_superuser = true trusted = false [artifacts] -control_files = ["share/postgresql/extension/postgis.control"] -sql_globs = ["share/postgresql/extension/postgis--*.sql"] +control_files = [ + "share/postgresql/extension/postgis.control", + "share/postgresql/extension/postgis_raster.control", +] +sql_globs = [ + "share/postgresql/extension/postgis--*.sql", + "share/postgresql/extension/postgis_raster--*.sql", +] extension_sql_file_prefixes = [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis", ] extension_sql_file_names = ["uninstall_postgis.sql"] native_modules = ["lib/postgresql/postgis-3.so"] -native_dependency_modules = ["lib/postgresql/liboliphaunt_postgis_deps.so"] +native_dependency_modules = [ + "lib/postgresql/postgis_raster-3.so", + "lib/postgresql/liboliphaunt_postgis_deps.so", +] data_files = [ + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/contrib/postgis-3.6/legacy.sql", "share/postgresql/contrib/postgis-3.6/legacy_gist.sql", "share/postgresql/contrib/postgis-3.6/legacy_minimal.sql", @@ -44,6 +80,7 @@ data_files = [ ] headers = [] licenses = [ + "share/licenses/gdal/LICENSE.TXT", "share/licenses/geos/COPYING", "share/licenses/geos/src/deps/ryu/LICENSE", "share/licenses/geos/src/deps/ryu/LICENSE-Apache2", @@ -62,6 +99,11 @@ licenses = [ "share/licenses/sqlite/LICENSE.md", ] +[[runtime_environment]] +name = "GDAL_DATA" +path = "share/postgresql/gdal" +required_file = "gdalvrt.xsd" + [[runtime_environment]] name = "PROJ_DATA" path = "share/postgresql/proj" diff --git a/src/extensions/external/postgis/source.toml b/src/extensions/external/postgis/source.toml index f5ea03af..38805d43 100644 --- a/src/extensions/external/postgis/source.toml +++ b/src/extensions/external/postgis/source.toml @@ -1,11 +1,11 @@ name = "postgis" url = "https://github.com/postgis/postgis.git" -branch = "3.6.3" -commit = "3d12666588a84b23a3147618eaa9b40b0fe5e796" -source_date_epoch = 1776193981 +branch = "3.6.4" +commit = "94d984bd083635c1d253db0f87cf80b32548e406" +source_date_epoch = 1780943336 [extension-control] sql-name = "postgis" source-path = "extensions/postgis/postgis.control.in" source-default-version = "@EXTVERSION@" -default-version = "3.6.3" +default-version = "3.6.4" diff --git a/src/extensions/external/postgis/targets/native-static-registry.toml b/src/extensions/external/postgis/targets/native-static-registry.toml index 35aefc09..7ebb1c90 100644 --- a/src/extensions/external/postgis/targets/native-static-registry.toml +++ b/src/extensions/external/postgis/targets/native-static-registry.toml @@ -9,11 +9,37 @@ platform_targets = [ "android-arm64-v8a", "android-x86_64", ] -dependencies = ["geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] -ios_dependencies = ["geos", "proj", "sqlite", "libxml2", "json-c"] -android_dependencies = ["geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] +dependencies = ["gdal", "geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] +ios_dependencies = ["gdal", "geos", "proj", "sqlite", "libxml2", "json-c"] +android_dependencies = ["gdal", "geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] module_files = ["postgis-3"] data_files = [ + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/contrib/postgis-3.6/legacy.sql", "share/postgresql/contrib/postgis-3.6/legacy_gist.sql", "share/postgresql/contrib/postgis-3.6/legacy_minimal.sql", @@ -25,14 +51,12 @@ data_files = [ "share/postgresql/proj/proj.db", ] configure_flags = [ - "--without-raster", "--without-topology", "--without-sfcgal", "--without-address-standardizer", "--without-protobuf", ] excluded_sql_extensions = [ - "postgis_raster", "postgis_topology", "postgis_sfcgal", "postgis_tiger_geocoder", diff --git a/src/extensions/external/postgis/targets/native.toml b/src/extensions/external/postgis/targets/native.toml index 7c6cbf89..a4d43913 100644 --- a/src/extensions/external/postgis/targets/native.toml +++ b/src/extensions/external/postgis/targets/native.toml @@ -2,12 +2,38 @@ schema = "oliphaunt-extension-target-v1" artifact_family = "native-dynamic" status = "supported" build_kind = "autotools" -dependencies = ["geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] +dependencies = ["gdal", "geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] module_files = [ "lib/postgresql/postgis-3.so", - "lib/postgresql/liboliphaunt_postgis_deps.so", + "lib/postgresql/postgis_raster-3.so", ] data_files = [ + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/contrib/postgis-3.6/legacy.sql", "share/postgresql/contrib/postgis-3.6/legacy_gist.sql", "share/postgresql/contrib/postgis-3.6/legacy_minimal.sql", @@ -19,14 +45,12 @@ data_files = [ "share/postgresql/proj/proj.db", ] configure_flags = [ - "--without-raster", "--without-topology", "--without-sfcgal", "--without-address-standardizer", "--without-protobuf", ] excluded_sql_extensions = [ - "postgis_raster", "postgis_topology", "postgis_sfcgal", "postgis_tiger_geocoder", diff --git a/src/extensions/external/postgis/targets/wasix.toml b/src/extensions/external/postgis/targets/wasix.toml index 818c728b..8a47a8a4 100644 --- a/src/extensions/external/postgis/targets/wasix.toml +++ b/src/extensions/external/postgis/targets/wasix.toml @@ -3,12 +3,39 @@ artifact_family = "wasix-side-module" status = "supported" build_kind = "autotools" build_script = "src/extensions/external/postgis/tools/build_wasix.sh" -dependencies = ["geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] +dependencies = ["gdal", "geos", "proj", "sqlite", "libxml2", "json-c", "libiconv"] module_files = [ "lib/postgresql/postgis-3.so", + "lib/postgresql/postgis_raster-3.so", "lib/postgresql/liboliphaunt_postgis_deps.so", ] data_files = [ + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/contrib/postgis-3.6/legacy.sql", "share/postgresql/contrib/postgis-3.6/legacy_gist.sql", "share/postgresql/contrib/postgis-3.6/legacy_minimal.sql", @@ -20,7 +47,6 @@ data_files = [ "share/postgresql/proj/proj.db", ] configure_flags = [ - "--without-raster", "--without-topology", "--without-sfcgal", "--without-address-standardizer", @@ -31,14 +57,17 @@ configure_flags = [ required_build_files = [ "postgis/postgis-3.so", "postgis/liboliphaunt_postgis_deps.so", + "raster/rt_pg/postgis_raster-3.so", "extensions/postgis/postgis.control", + "extensions/postgis_raster/postgis_raster.control", + "share/gdal/gdalvrt.xsd", "share/proj/proj.db", ] required_build_globs = [ "extensions/postgis/sql/postgis--*.sql", + "extensions/postgis_raster/sql/postgis_raster--*.sql", ] excluded_sql_extensions = [ - "postgis_raster", "postgis_topology", "postgis_sfcgal", "postgis_tiger_geocoder", @@ -52,6 +81,12 @@ runtime_path = "lib/postgresql/liboliphaunt_postgis_deps.so" build_path = "postgis/postgis/liboliphaunt_postgis_deps.so" aot_file = "postgis_deps-llvm-opta.bin.zst" +[[native_support_modules]] +name = "postgis_raster" +runtime_path = "lib/postgresql/postgis_raster-3.so" +build_path = "postgis/raster/rt_pg/postgis_raster-3.so" +aot_file = "postgis_raster-llvm-opta.bin.zst" + [staging] module_source_dir = "postgis/postgis" control_source = "postgis/extensions/postgis/postgis.control" @@ -60,3 +95,11 @@ sql_source_dir = "postgis/extensions/postgis/sql" [[staging.data_dirs]] source = "postgis/share/proj" destination = "share/proj" + +[[staging.data_dirs]] +source = "postgis/share/gdal" +destination = "share/postgresql/gdal" + +[[staging.data_dirs]] +source = "postgis/share/extension-raster" +destination = "share/postgresql/extension" diff --git a/src/extensions/external/postgis/tests/smoke.sql b/src/extensions/external/postgis/tests/smoke.sql index 4f05b7be..85c48d46 100644 --- a/src/extensions/external/postgis/tests/smoke.sql +++ b/src/extensions/external/postgis/tests/smoke.sql @@ -1,3 +1,7 @@ +CREATE EXTENSION IF NOT EXISTS postgis_raster; +-- oliphaunt-statement +SET postgis.gdal_enabled_drivers = 'ENABLE_ALL'; +-- oliphaunt-statement DROP TABLE IF EXISTS liboliphaunt_postgis_points; -- oliphaunt-statement CREATE TEMP TABLE liboliphaunt_postgis_points(id int PRIMARY KEY, geom geometry(Point, 4326)); @@ -15,6 +19,9 @@ DECLARE area float8; polygons int; nearby int; + gdal_drivers int; + raster_roundtrip raster; + raster_value float8; BEGIN SELECT ST_Distance(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('POINT(3 4)')) INTO distance; IF distance <> 5 THEN @@ -56,6 +63,29 @@ BEGIN IF nearby <> 2 THEN RAISE EXCEPTION 'postgis dwithin failed: %', nearby; END IF; + SELECT count(*) INTO gdal_drivers + FROM ST_GDALDrivers() + WHERE short_name = 'GTiff' AND can_read AND can_write; + IF gdal_drivers <> 1 THEN + RAISE EXCEPTION 'postgis raster GeoTIFF driver is unavailable'; + END IF; + SELECT ST_FromGDALRaster( + ST_AsGDALRaster( + ST_AddBand( + ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 4326), + '8BUI'::text, + 7::double precision, + 0::double precision + ), + 'GTiff' + ) + ) INTO raster_roundtrip; + SELECT ST_Value(raster_roundtrip, 1, 1, 1) INTO raster_value; + IF raster_value <> 7 OR ST_SRID(raster_roundtrip) <> 4326 THEN + RAISE EXCEPTION 'postgis raster GDAL round-trip failed: value %, srid %', + raster_value, + ST_SRID(raster_roundtrip); + END IF; END $$; -- oliphaunt-statement DROP TABLE IF EXISTS liboliphaunt_postgis_points; diff --git a/src/extensions/external/postgis/tests/upstream.toml b/src/extensions/external/postgis/tests/upstream.toml index 5fb15934..c80a687e 100644 --- a/src/extensions/external/postgis/tests/upstream.toml +++ b/src/extensions/external/postgis/tests/upstream.toml @@ -1,10 +1,9 @@ schema = "oliphaunt-extension-upstream-tests-v1" runner = "postgis-installcheck" status = "candidate" -reason = "The reduced WASIX/mobile PostGIS surface is smoke-gated today. Upstream PostGIS installcheck is required before broadening the public evidence tier beyond transitional catalog smoke." -included_suites = ["postgis"] +reason = "The portable and mobile PostGIS surface is smoke-gated today. Upstream PostGIS installcheck is required before broadening the public evidence tier beyond exact-candidate lifecycle qualification." +included_suites = ["postgis", "raster"] excluded_suites = [ - "raster", "topology", "sfcgal", "tiger_geocoder", diff --git a/src/extensions/external/postgis/tools/build_wasix.sh b/src/extensions/external/postgis/tools/build_wasix.sh index f54f1a3f..b253162b 100755 --- a/src/extensions/external/postgis/tools/build_wasix.sh +++ b/src/extensions/external/postgis/tools/build_wasix.sh @@ -86,7 +86,7 @@ $dependency_stamp_block profile=$(oliphaunt_wasix_wasix_profile_signature) wasixcc=$wasixcc_version configure=$(oliphaunt_wasix_extension_configure_signature "$REPO_ROOT" postgis) -link=postgis-plus-selected-support-side-module-v2" +link=postgis-raster-plus-selected-support-side-module-v3" if [ -f "$POSTGIS_BUILD_DIR/.oliphaunt-wasix-postgis-build" ] && oliphaunt_wasix_extension_build_outputs_exist "$REPO_ROOT" postgis "$POSTGIS_BUILD_DIR" --quiet && @@ -118,6 +118,31 @@ esac EOF chmod +x "$geos_config" + gdal_config="$POSTGIS_BUILD_DIR/oliphaunt-gdal-config" + cat >"$gdal_config" <&2 + exit 1 + ;; +esac +EOF + chmod +x "$gdal_config" + pkg_config="$POSTGIS_BUILD_DIR/oliphaunt-pkg-config" cat >"$pkg_config" <&2 oliphaunt_wasix_extension_build_outputs_exist "$REPO_ROOT" postgis "$POSTGIS_BUILD_DIR" diff --git a/src/extensions/external/postgis/upstream-license-data.json b/src/extensions/external/postgis/upstream-license-data.json index 54da3c16..e73f4d93 100644 --- a/src/extensions/external/postgis/upstream-license-data.json +++ b/src/extensions/external/postgis/upstream-license-data.json @@ -1,6 +1,14 @@ { "schema": "oliphaunt-extension-upstream-license-data-v1", "sources": [ + { + "id": "gdal", + "manifest": "src/extensions/external/postgis/dependencies/gdal/source.toml", + "kind": "git", + "url": "https://github.com/OSGeo/gdal.git", + "branch": "v3.13.2", + "commit": "b40672525acf3f5c4f29d8541aa7dcff1e18eb92" + }, { "id": "geos", "manifest": "src/extensions/external/postgis/dependencies/geos/source.toml", @@ -38,8 +46,8 @@ "manifest": "src/extensions/external/postgis/source.toml", "kind": "git", "url": "https://github.com/postgis/postgis.git", - "branch": "3.6.3", - "commit": "3d12666588a84b23a3147618eaa9b40b0fe5e796" + "branch": "3.6.4", + "commit": "94d984bd083635c1d253db0f87cf80b32548e406" }, { "id": "proj", @@ -61,6 +69,15 @@ "extension": { "sql_name": "postgis", "files": [ + { + "source": "gdal", + "path": "LICENSE.TXT", + "destination": "share/licenses/gdal/LICENSE.TXT", + "role": "license", + "spdx": "MIT", + "license_url": "https://github.com/OSGeo/gdal/blob/b40672525acf3f5c4f29d8541aa7dcff1e18eb92/LICENSE.TXT", + "sha256": "1dae3468e81d00da56e2936f74d33b8b3ad09d726437f19ce209a5dabea41f77" + }, { "source": "geos", "path": "COPYING", @@ -139,7 +156,7 @@ "destination": "share/licenses/postgis/COPYING", "role": "license", "spdx": "GPL-2.0-or-later", - "license_url": "https://github.com/postgis/postgis/blob/3d12666588a84b23a3147618eaa9b40b0fe5e796/COPYING", + "license_url": "https://github.com/postgis/postgis/blob/94d984bd083635c1d253db0f87cf80b32548e406/COPYING", "sha256": "8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643" }, { @@ -148,7 +165,7 @@ "destination": "share/licenses/postgis/LICENSE.TXT", "role": "notice", "spdx": "GPL-2.0-or-later", - "license_url": "https://github.com/postgis/postgis/blob/3d12666588a84b23a3147618eaa9b40b0fe5e796/LICENSE.TXT", + "license_url": "https://github.com/postgis/postgis/blob/94d984bd083635c1d253db0f87cf80b32548e406/LICENSE.TXT", "sha256": "81749eea887e78402c9b85896cd629b155bc29256927f818f01001f038146391" }, { @@ -157,7 +174,7 @@ "destination": "share/licenses/postgis/deps/flatgeobuf/flatbuffers/LICENSE", "role": "license", "spdx": "Apache-2.0", - "license_url": "https://github.com/postgis/postgis/blob/3d12666588a84b23a3147618eaa9b40b0fe5e796/deps/flatgeobuf/include/flatbuffers/LICENSE", + "license_url": "https://github.com/postgis/postgis/blob/94d984bd083635c1d253db0f87cf80b32548e406/deps/flatgeobuf/include/flatbuffers/LICENSE", "sha256": "e55b7f3aaf3a9db897cc6a63fd6a79ae8fbbcaa32ffbe382ae77ce1f0db33f99" }, { @@ -166,7 +183,7 @@ "destination": "share/licenses/postgis/deps/ryu/LICENSE", "role": "notice", "spdx": "Apache-2.0", - "license_url": "https://github.com/postgis/postgis/blob/3d12666588a84b23a3147618eaa9b40b0fe5e796/deps/ryu/LICENSE", + "license_url": "https://github.com/postgis/postgis/blob/94d984bd083635c1d253db0f87cf80b32548e406/deps/ryu/LICENSE", "sha256": "087edee322a9d2e527453ddc6731ccb4f015a36e55864b30715934f32a4879c1" }, { @@ -175,7 +192,7 @@ "destination": "share/licenses/postgis/deps/ryu/LICENSE-Apache2", "role": "license", "spdx": "Apache-2.0", - "license_url": "https://github.com/postgis/postgis/blob/3d12666588a84b23a3147618eaa9b40b0fe5e796/deps/ryu/LICENSE-Apache2", + "license_url": "https://github.com/postgis/postgis/blob/94d984bd083635c1d253db0f87cf80b32548e406/deps/ryu/LICENSE-Apache2", "sha256": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4" }, { @@ -184,7 +201,7 @@ "destination": "share/licenses/postgis/deps/ryu/LICENSE-Boost", "role": "notice", "spdx": "Apache-2.0", - "license_url": "https://github.com/postgis/postgis/blob/3d12666588a84b23a3147618eaa9b40b0fe5e796/deps/ryu/LICENSE-Boost", + "license_url": "https://github.com/postgis/postgis/blob/94d984bd083635c1d253db0f87cf80b32548e406/deps/ryu/LICENSE-Boost", "sha256": "c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566" }, { @@ -209,6 +226,7 @@ }, "blobs": { "087edee322a9d2e527453ddc6731ccb4f015a36e55864b30715934f32a4879c1": "QWxsIHRoZSBDIGNvZGUgaXMgY29weXJpZ2h0ZWQgYnkgVWxmIEFkYW1zIGFuZCBjb250cmlidXRvcnMsIGFuZCBtYXkgYmUgdXNlZCBmcmVlbHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBBcGFjaGUgMi4wIGxpY2Vuc2UuIEFsdGVybmF0aXZlbHksIGl0IG1heSBiZSB1c2VkIGZyZWVseSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIEJvb3N0IDEuMCBsaWNlbnNlLg==", + "1dae3468e81d00da56e2936f74d33b8b3ad09d726437f19ce209a5dabea41f77": "CkdEQUwvT0dSIExpY2Vuc2luZwo9PT09PT09PT09PT09PT09PT0KClRoaXMgZmlsZSBhdHRlbXB0cyB0byBpbmNsdWRlIGFsbCBsaWNlbnNlcyB0aGF0IGFwcGx5IHdpdGhpbiB0aGUgR0RBTC9PR1IKc291cmNlIHRyZWUsIGluIHBhcnRpY3VsYXIgYW55IHRoYXQgYXJlIHN1cHBvc2VkIHRvIGJlIGV4cG9zZWQgdG8gdGhlIGVuZCB1c2VyCmZvciBjcmVkaXQgcmVxdWlyZW1lbnRzIGZvciBpbnN0YW5jZS4gIFRoZSBjb250ZW50cyBvZiB0aGlzIGZpbGUgY2FuIGJlCmRpc3BsYXllZCBmcm9tIEdEQUwgY29tbWFuZGxpbmUgdXRpbGl0aWVzIHVzaW5nIHRoZSAtLWxpY2Vuc2UgY29tbWFuZGxpbmUKc3dpdGNoLgoKCkdEQUwvT0dSIEdlbmVyYWwKLS0tLS0tLS0tLS0tLS0tLQoKSW4gZ2VuZXJhbCBHREFML09HUiBpcyBsaWNlbnNlZCB1bmRlciBhbiBNSVQgc3R5bGUgbGljZW5zZSB3aXRoIHRoZQpmb2xsb3dpbmcgdGVybXM6CgpQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYQpjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAp0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCnRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLAphbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUKU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKClRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkCmluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLgoKVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MKT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMClRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCkxJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCkZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIKREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgoKCnBvcnQvY3BsX2Zsb2F0LmNwcAotLS0tLS0tLS0tLS0tLS0tLS0KCkNvcHlyaWdodCAoYykgMjAwMiwgSW5kdXN0cmlhbCBMaWdodCAmIE1hZ2ljLCBhIGRpdmlzaW9uIG9mIEx1Y2FzCkRpZ2l0YWwgTHRkLiBMTEMKCkFsbCByaWdodHMgcmVzZXJ2ZWQuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZQptZXQ6CiogICAgICAgUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgoqICAgICAgIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUKY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lcgppbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlCmRpc3RyaWJ1dGlvbi4KKiAgICAgICBOZWl0aGVyIHRoZSBuYW1lIG9mIEluZHVzdHJpYWwgTGlnaHQgJiBNYWdpYyBub3IgdGhlIG5hbWVzIG9mCml0cyBjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgoKVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUwoiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IKQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQKT1dORVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsClNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QKTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsCkRBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWQpUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUCihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRQpPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgoKCmZybXRzL2hkZjQvaGRmLWVvcy8qCi0tLS0tLS0tLS0tLS0tLS0tLS0tCgogQ29weXJpZ2h0IChDKSAxOTk2IEh1Z2hlcyBhbmQgQXBwbGllZCBSZXNlYXJjaCBDb3Jwb3JhdGlvbgoKIFBlcm1pc3Npb24gdG8gdXNlLCBtb2RpZnksIGFuZCBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgYW5kIGl0cyBkb2N1bWVudGF0aW9uCiBmb3IgYW55IHB1cnBvc2Ugd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlCiBjb3B5cmlnaHQgbm90aWNlIGFwcGVhciBpbiBhbGwgY29waWVzIGFuZCB0aGF0IGJvdGggdGhhdCBjb3B5cmlnaHQgbm90aWNlIGFuZAogdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBhcHBlYXIgaW4gc3VwcG9ydGluZyBkb2N1bWVudGF0aW9uLgoKCmZybXRzL3BjcmFzdGVyL2xpYmNzZgotLS0tLS0tLS0tLS0tLS0tLS0tLS0KCkNvcHlyaWdodCAoYykgMTk5Ny0yMDAzLCBVdHJlY2h0IFVuaXZlcnNpdHkKQWxsIHJpZ2h0cyByZXNlcnZlZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAptb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKYXJlIG1ldDoKCiogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCgoqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUKICBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZwogIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZAogIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KCiogTmVpdGhlciB0aGUgbmFtZSBvZiBVdHJlY2h0IFVuaXZlcnNpdHkgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzCiAgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlCiAgd2l0aG91dCBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uCgpUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTCiJBUyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UCkxJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUgpBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVApPV05FUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwKU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwKREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZClRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQKKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFCk9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCgpmcm10cy9ncmliL2RlZ3JpYi8qCi0tLS0tLS0tLS0tLS0tLS0tLS0KClRoZSBkZWdyaWIgYW5kIGcyY2xpYiBzb3VyY2UgY29kZSBhcmUgbW9kaWZpZWQgdmVyc2lvbnMgb2YgY29kZSBwcm9kdWNlZApieSBOT0FBIE5XUyBhbmQgYXJlIGluIHRoZSBwdWJsaWMgZG9tYWluIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZwpyZXN0cmljdGlvbnM6CgpodHRwOi8vd3d3LndlYXRoZXIuZ292L2ltL3NvZnRhLmh0bQoKRElTQ0xBSU1FUiBUaGUgVW5pdGVkIFN0YXRlcyBHb3Zlcm5tZW50IG1ha2VzIG5vIHdhcnJhbnR5LCBleHByZXNzZWQgb3IKaW1wbGllZCwgYXMgdG8gdGhlIHVzZWZ1bG5lc3Mgb2YgdGhlIHNvZnR3YXJlIGFuZCBkb2N1bWVudGF0aW9uIGZvciBhbnkKcHVycG9zZS4gVGhlIFUuUy4gR292ZXJubWVudCwgaXRzIGluc3RydW1lbnRhbGl0aWVzLCBvZmZpY2VycywgZW1wbG95ZWVzLAphbmQgYWdlbnRzIGFzc3VtZXMgbm8gcmVzcG9uc2liaWxpdHkgKDEpIGZvciB0aGUgdXNlIG9mIHRoZSBzb2Z0d2FyZSBhbmQKZG9jdW1lbnRhdGlvbiBsaXN0ZWQgYmVsb3csIG9yICgyKSB0byBwcm92aWRlIHRlY2huaWNhbCBzdXBwb3J0IHRvIHVzZXJzLgoKaHR0cDovL3d3dy53ZWF0aGVyLmdvdi9kaXNjbGFpbWVyLnBocAoKIFRoZSBpbmZvcm1hdGlvbiBvbiBnb3Zlcm5tZW50IHNlcnZlcnMgYXJlIGluIHRoZSBwdWJsaWMgZG9tYWluLCB1bmxlc3MKc3BlY2lmaWNhbGx5IGFubm90YXRlZCBvdGhlcndpc2UsIGFuZCBtYXkgYmUgdXNlZCBmcmVlbHkgYnkgdGhlIHB1YmxpYyBzbwpsb25nIGFzIHlvdSBkbyBub3QgMSkgY2xhaW0gaXQgaXMgeW91ciBvd24gKGUuZy4gYnkgY2xhaW1pbmcgY29weXJpZ2h0IGZvcgpOV1MgaW5mb3JtYXRpb24gLS0gc2VlIGJlbG93KSwgMikgdXNlIGl0IGluIGEgbWFubmVyIHRoYXQgaW1wbGllcyBhbgplbmRvcnNlbWVudCBvciBhZmZpbGlhdGlvbiB3aXRoIE5PQUEvTldTLCBvciAzKSBtb2RpZnkgaXQgaW4gY29udGVudCBhbmQKdGhlbiBwcmVzZW50IGl0IGFzIG9mZmljaWFsIGdvdmVybm1lbnQgbWF0ZXJpYWwuIFlvdSBhbHNvIGNhbm5vdCBwcmVzZW50CmluZm9ybWF0aW9uIG9mIHlvdXIgb3duIGluIGEgd2F5IHRoYXQgbWFrZXMgaXQgYXBwZWFyIHRvIGJlIG9mZmljaWFsCmdvdmVybm1lbnQgaW5mb3JtYXRpb24uLgoKIFRoZSB1c2VyIGFzc3VtZXMgdGhlIGVudGlyZSByaXNrIHJlbGF0ZWQgdG8gaXRzIHVzZSBvZiB0aGlzIGRhdGEuIE5XUyBpcwpwcm92aWRpbmcgdGhpcyBkYXRhICJhcyBpcywiIGFuZCBOV1MgZGlzY2xhaW1zIGFueSBhbmQgYWxsIHdhcnJhbnRpZXMsCndoZXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLCBpbmNsdWRpbmcgKHdpdGhvdXQgbGltaXRhdGlvbikgYW55IGltcGxpZWQKd2FycmFudGllcyBvZiBtZXJjaGFudGFiaWxpdHkgb3IgZml0bmVzcyBmb3IgYSBwYXJ0aWN1bGFyIHB1cnBvc2UuIEluIG5vCmV2ZW50IHdpbGwgTldTIGJlIGxpYWJsZSB0byB5b3Ugb3IgdG8gYW55IHRoaXJkIHBhcnR5IGZvciBhbnkgZGlyZWN0LAppbmRpcmVjdCwgaW5jaWRlbnRhbCwgY29uc2VxdWVudGlhbCwgc3BlY2lhbCBvciBleGVtcGxhcnkgZGFtYWdlcyBvciBsb3N0CnByb2ZpdCByZXN1bHRpbmcgZnJvbSBhbnkgdXNlIG9yIG1pc3VzZSBvZiB0aGlzIGRhdGEuCgogQXMgcmVxdWlyZWQgYnkgMTcgVS5TLkMuIDQwMywgdGhpcmQgcGFydGllcyBwcm9kdWNpbmcgY29weXJpZ2h0ZWQgd29ya3MKY29uc2lzdGluZyBwcmVkb21pbmFudGx5IG9mIHRoZSBtYXRlcmlhbCBhcHBlYXJpbmcgaW4gTldTIFdlYiBwYWdlcyBtdXN0CnByb3ZpZGUgbm90aWNlIHdpdGggc3VjaCB3b3JrKHMpIGlkZW50aWZ5aW5nIHRoZSBOV1MgbWF0ZXJpYWwgaW5jb3Jwb3JhdGVkCmFuZCBzdGF0aW5nIHRoYXQgc3VjaCBtYXRlcmlhbCBpcyBub3Qgc3ViamVjdCB0byBjb3B5cmlnaHQgcHJvdGVjdGlvbi4KCnBvcnQvY3BsX21pbml6aXAqCi0tLS0tLS0tLS0tLS0tLS0tCgpUaGlzIGlzIHZlcnNpb24gMjAwNS1GZWItMTAgb2YgdGhlIEluZm8tWklQIGNvcHlyaWdodCBhbmQgbGljZW5zZS4KVGhlIGRlZmluaXRpdmUgdmVyc2lvbiBvZiB0aGlzIGRvY3VtZW50IHNob3VsZCBiZSBhdmFpbGFibGUgYXQKZnRwOi8vZnRwLmluZm8temlwLm9yZy9wdWIvaW5mb3ppcC9saWNlbnNlLmh0bWwgaW5kZWZpbml0ZWx5LgoKCkNvcHlyaWdodCAoYykgMTk5MC0yMDA1IEluZm8tWklQLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4KCkZvciB0aGUgcHVycG9zZXMgb2YgdGhpcyBjb3B5cmlnaHQgYW5kIGxpY2Vuc2UsICJJbmZvLVpJUCIgaXMgZGVmaW5lZCBhcwp0aGUgZm9sbG93aW5nIHNldCBvZiBpbmRpdmlkdWFsczoKCiAgIE1hcmsgQWRsZXIsIEpvaG4gQnVzaCwgS2FybCBEYXZpcywgSGFyYWxkIERlbmtlciwgSmVhbi1NaWNoZWwgRHVib2lzLAogICBKZWFuLWxvdXAgR2FpbGx5LCBIdW50ZXIgR29hdGxleSwgRWQgR29yZG9uLCBJYW4gR29ybWFuLCBDaHJpcyBIZXJib3J0aCwKICAgRGlyayBIYWFzZSwgR3JlZyBIYXJ0d2lnLCBSb2JlcnQgSGVhdGgsIEpvbmF0aGFuIEh1ZHNvbiwgUGF1bCBLaWVuaXR6LAogICBEYXZpZCBLaXJzY2hiYXVtLCBKb2hubnkgTGVlLCBPbm5vIHZhbiBkZXIgTGluZGVuLCBJZ29yIE1hbmRyaWNoZW5rbywKICAgU3RldmUgUC4gTWlsbGVyLCBTZXJnaW8gTW9uZXNpLCBLZWl0aCBPd2VucywgR2VvcmdlIFBldHJvdiwgR3JlZyBSb2Vsb2ZzLAogICBLYWkgVXdlIFJvbW1lbCwgU3RldmUgU2FsaXNidXJ5LCBEYXZlIFNtaXRoLCBTdGV2ZW4gTS4gU2Nod2VkYSwKICAgQ2hyaXN0aWFuIFNwaWVsZXIsIENvc21pbiBUcnV0YSwgQW50b2luZSBWZXJoZWlqZW4sIFBhdWwgdm9uIEJlaHJlbiwKICAgUmljaCBXYWxlcywgTWlrZSBXaGl0ZQoKVGhpcyBzb2Z0d2FyZSBpcyBwcm92aWRlZCAiYXMgaXMsIiB3aXRob3V0IHdhcnJhbnR5IG9mIGFueSBraW5kLCBleHByZXNzCm9yIGltcGxpZWQuICBJbiBubyBldmVudCBzaGFsbCBJbmZvLVpJUCBvciBpdHMgY29udHJpYnV0b3JzIGJlIGhlbGQgbGlhYmxlCmZvciBhbnkgZGlyZWN0LCBpbmRpcmVjdCwgaW5jaWRlbnRhbCwgc3BlY2lhbCBvciBjb25zZXF1ZW50aWFsIGRhbWFnZXMKYXJpc2luZyBvdXQgb2YgdGhlIHVzZSBvZiBvciBpbmFiaWxpdHkgdG8gdXNlIHRoaXMgc29mdHdhcmUuCgpQZXJtaXNzaW9uIGlzIGdyYW50ZWQgdG8gYW55b25lIHRvIHVzZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZSwKaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdApmcmVlbHksIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6CgogICAgMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLAogICAgICAgZGVmaW5pdGlvbiwgZGlzY2xhaW1lciwgYW5kIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zLgoKICAgIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSAoY29tcGlsZWQgZXhlY3V0YWJsZXMpIG11c3QgcmVwcm9kdWNlCiAgICAgICB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgZGVmaW5pdGlvbiwgZGlzY2xhaW1lciwgYW5kIHRoaXMgbGlzdCBvZgogICAgICAgY29uZGl0aW9ucyBpbiBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUKICAgICAgIGRpc3RyaWJ1dGlvbi4gIFRoZSBzb2xlIGV4Y2VwdGlvbiB0byB0aGlzIGNvbmRpdGlvbiBpcyByZWRpc3RyaWJ1dGlvbgogICAgICAgb2YgYSBzdGFuZGFyZCBVblppcFNGWCBiaW5hcnkgKGluY2x1ZGluZyBTRlhXaXopIGFzIHBhcnQgb2YgYQogICAgICAgc2VsZi1leHRyYWN0aW5nIGFyY2hpdmU7IHRoYXQgaXMgcGVybWl0dGVkIHdpdGhvdXQgaW5jbHVzaW9uIG9mIHRoaXMKICAgICAgIGxpY2Vuc2UsIGFzIGxvbmcgYXMgdGhlIG5vcm1hbCBTRlggYmFubmVyIGhhcyBub3QgYmVlbiByZW1vdmVkIGZyb20KICAgICAgIHRoZSBiaW5hcnkgb3IgZGlzYWJsZWQuCgogICAgMy4gQWx0ZXJlZCB2ZXJzaW9ucy0taW5jbHVkaW5nLCBidXQgbm90IGxpbWl0ZWQgdG8sIHBvcnRzIHRvIG5ldyBvcGVyYXRpbmcKICAgICAgIHN5c3RlbXMsIGV4aXN0aW5nIHBvcnRzIHdpdGggbmV3IGdyYXBoaWNhbCBpbnRlcmZhY2VzLCBhbmQgZHluYW1pYywKICAgICAgIHNoYXJlZCwgb3Igc3RhdGljIGxpYnJhcnkgdmVyc2lvbnMtLW11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaAogICAgICAgYW5kIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkIGFzIGJlaW5nIHRoZSBvcmlnaW5hbCBzb3VyY2UuICBTdWNoCiAgICAgICBhbHRlcmVkIHZlcnNpb25zIGFsc28gbXVzdCBub3QgYmUgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgSW5mby1aSVAKICAgICAgIHJlbGVhc2VzLS1pbmNsdWRpbmcsIGJ1dCBub3QgbGltaXRlZCB0bywgbGFiZWxpbmcgb2YgdGhlIGFsdGVyZWQKICAgICAgIHZlcnNpb25zIHdpdGggdGhlIG5hbWVzICJJbmZvLVpJUCIgKG9yIGFueSB2YXJpYXRpb24gdGhlcmVvZiwgaW5jbHVkaW5nLAogICAgICAgYnV0IG5vdCBsaW1pdGVkIHRvLCBkaWZmZXJlbnQgY2FwaXRhbGl6YXRpb25zKSwgIlBvY2tldCBVblppcCwiICJXaVoiCiAgICAgICBvciAiTWFjWmlwIiB3aXRob3V0IHRoZSBleHBsaWNpdCBwZXJtaXNzaW9uIG9mIEluZm8tWklQLiAgU3VjaCBhbHRlcmVkCiAgICAgICB2ZXJzaW9ucyBhcmUgZnVydGhlciBwcm9oaWJpdGVkIGZyb20gbWlzcmVwcmVzZW50YXRpdmUgdXNlIG9mIHRoZQogICAgICAgWmlwLUJ1Z3Mgb3IgSW5mby1aSVAgZS1tYWlsIGFkZHJlc3NlcyBvciBvZiB0aGUgSW5mby1aSVAgVVJMKHMpLgoKICAgIDQuIEluZm8tWklQIHJldGFpbnMgdGhlIHJpZ2h0IHRvIHVzZSB0aGUgbmFtZXMgIkluZm8tWklQLCIgIlppcCwiICJVblppcCwiCiAgICAgICAiVW5aaXBTRlgsIiAiV2laLCIgIlBvY2tldCBVblppcCwiICJQb2NrZXQgWmlwLCIgYW5kICJNYWNaaXAiIGZvciBpdHMKICAgICAgIG93biBzb3VyY2UgYW5kIGJpbmFyeSByZWxlYXNlcy4KCgpvZ3Ivb2dyc2ZfZnJtdHMvZHhmL2ludHJvbnVyYnMuY3BwCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClRoaXMgY29kZSBpcyBkZXJpdmVkIGZyb20gdGhlIGNvZGUgYXNzb2NpYXRlZCB3aXRoIHRoZSBib29rICJBbiBJbnRyb2R1Y3Rpb24KdG8gTlVSQlMiIGJ5IERhdmlkIEYuIFJvZ2Vycy4gIE1vcmUgaW5mb3JtYXRpb24gb24gdGhlIGJvb2sgYW5kIHRoZSBjb2RlIGlzCmF2YWlsYWJsZSBhdDoKCiAgaHR0cDovL3d3dy5uYXItYXNzb2NpYXRlcy5jb20vbnVyYnMvCgoKQ29weXJpZ2h0IChjKSAyMDA5LCBEYXZpZCBGLiBSb2dlcnMKQWxsIHJpZ2h0cyByZXNlcnZlZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAptb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKCiAgICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwKICAgICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci4KICAgICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLAogICAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uCiAgICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgogICAgKiBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBEYXZpZCBGLiBSb2dlcnMgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzCiAgICAgIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZQogICAgICB3aXRob3V0IHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi4KClRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgIkFTIElTIgpBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFCklNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFCkFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUKTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUgpDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRgpTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MKSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4KQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkKQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUKUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCgphbGcvdGhpbnBsYXRlc3BsaW5lLmNwcAotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKSUVFRTc1NCBsb2coKSBjb2RlIGRlcml2ZWQgZnJvbToKQCgjKWVfbG9nLmMgMS4zIDk1LzAxLzE4CgpDb3B5cmlnaHQgKEMpIDE5OTMgYnkgU3VuIE1pY3Jvc3lzdGVtcywgSW5jLiBBbGwgcmlnaHRzIHJlc2VydmVkLgoKRGV2ZWxvcGVkIGF0IFN1blNvZnQsIGEgU3VuIE1pY3Jvc3lzdGVtcywgSW5jLiBidXNpbmVzcy4KUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kIGRpc3RyaWJ1dGUgdGhpcwpzb2Z0d2FyZSBpcyBmcmVlbHkgZ3JhbnRlZCwgcHJvdmlkZWQgdGhhdCB0aGlzIG5vdGljZQppcyBwcmVzZXJ2ZWQuCgoKYWxnL2xpYnFodWxsCi0tLS0tLS0tLS0tLQoKT25seSBhcHBsaWVzIHdoZW4gR0RBTCBpcyBjb21waWxlZCB3aXRoIGludGVybmFsIHFodWxsIHN1cHBvcnQKCgogICAgICAgICAgICAgICAgICAgIFFodWxsLCBDb3B5cmlnaHQgKGMpIDE5OTMtMjAxMgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEMuQi4gQmFyYmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEFybGluZ3RvbiwgTUEKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQKCiAgICAgICBUaGUgTmF0aW9uYWwgU2NpZW5jZSBhbmQgVGVjaG5vbG9neSBSZXNlYXJjaCBDZW50ZXIgZm9yCiAgICAgICAgQ29tcHV0YXRpb24gYW5kIFZpc3VhbGl6YXRpb24gb2YgR2VvbWV0cmljIFN0cnVjdHVyZXMKICAgICAgICAgICAgICAgICAgICAgICAgKFRoZSBHZW9tZXRyeSBDZW50ZXIpCiAgICAgICAgICAgICAgICAgICAgICAgVW5pdmVyc2l0eSBvZiBNaW5uZXNvdGEKCiAgICAgICAgICAgICAgICAgICAgICAgZW1haWw6IHFodWxsQHFodWxsLm9yZwoKVGhpcyBzb2Z0d2FyZSBpbmNsdWRlcyBRaHVsbCBmcm9tIEMuQi4gQmFyYmVyIGFuZCBUaGUgR2VvbWV0cnkgQ2VudGVyLgpRaHVsbCBpcyBjb3B5cmlnaHRlZCBhcyBub3RlZCBhYm92ZS4gIFFodWxsIGlzIGZyZWUgc29mdHdhcmUgYW5kIG1heQpiZSBvYnRhaW5lZCB2aWEgaHR0cCBmcm9tIHd3dy5xaHVsbC5vcmcuICBJdCBtYXkgYmUgZnJlZWx5IGNvcGllZCwgbW9kaWZpZWQsCmFuZCByZWRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKCjEuIEFsbCBjb3B5cmlnaHQgbm90aWNlcyBtdXN0IHJlbWFpbiBpbnRhY3QgaW4gYWxsIGZpbGVzLgoKMi4gQSBjb3B5IG9mIHRoaXMgdGV4dCBmaWxlIG11c3QgYmUgZGlzdHJpYnV0ZWQgYWxvbmcgd2l0aCBhbnkgY29waWVzCiAgIG9mIFFodWxsIHRoYXQgeW91IHJlZGlzdHJpYnV0ZTsgdGhpcyBpbmNsdWRlcyBjb3BpZXMgdGhhdCB5b3UgaGF2ZQogICBtb2RpZmllZCwgb3IgY29waWVzIG9mIHByb2dyYW1zIG9yIG90aGVyIHNvZnR3YXJlIHByb2R1Y3RzIHRoYXQKICAgaW5jbHVkZSBRaHVsbC4KCjMuIElmIHlvdSBtb2RpZnkgUWh1bGwsIHlvdSBtdXN0IGluY2x1ZGUgYSBub3RpY2UgZ2l2aW5nIHRoZQogICBuYW1lIG9mIHRoZSBwZXJzb24gcGVyZm9ybWluZyB0aGUgbW9kaWZpY2F0aW9uLCB0aGUgZGF0ZSBvZgogICBtb2RpZmljYXRpb24sIGFuZCB0aGUgcmVhc29uIGZvciBzdWNoIG1vZGlmaWNhdGlvbi4KCjQuIFdoZW4gZGlzdHJpYnV0aW5nIG1vZGlmaWVkIHZlcnNpb25zIG9mIFFodWxsLCBvciBvdGhlciBzb2Z0d2FyZQogICBwcm9kdWN0cyB0aGF0IGluY2x1ZGUgUWh1bGwsIHlvdSBtdXN0IHByb3ZpZGUgbm90aWNlIHRoYXQgdGhlIG9yaWdpbmFsCiAgIHNvdXJjZSBjb2RlIG1heSBiZSBvYnRhaW5lZCBhcyBub3RlZCBhYm92ZS4KCjUuIFRoZXJlIGlzIG5vIHdhcnJhbnR5IG9yIG90aGVyIGd1YXJhbnRlZSBvZiBmaXRuZXNzIGZvciBRaHVsbCwgaXQgaXMKICAgcHJvdmlkZWQgc29sZWx5ICJhcyBpcyIuICBCdWcgcmVwb3J0cyBvciBmaXhlcyBtYXkgYmUgc2VudCB0bwogICBxaHVsbF9idWdAcWh1bGwub3JnOyB0aGUgYXV0aG9ycyBtYXkgb3IgbWF5IG5vdCBhY3Qgb24gdGhlbSBhcwogICB0aGV5IGRlc2lyZS4KCmZybXRzL3BkZi9wZGZkYXRhc2V0LmNwcCAobWV0aG9kIFBERml1bVJlbmRlclBhZ2VCaXRtYXAoKSkKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKQ29weXJpZ2h0IDIwMTQgUERGaXVtIEF1dGhvcnMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZQptZXQ6CgogICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0Cm5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci4KICAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlCmNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIKaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZQpkaXN0cmlidXRpb24uCiAgICogTmVpdGhlciB0aGUgbmFtZSBvZiBHb29nbGUgSW5jLiBub3IgdGhlIG5hbWVzIG9mIGl0cwpjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbQp0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgoKVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUwoiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IKQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQKT1dORVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsClNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QKTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsCkRBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWQpUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUCihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRQpPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgoKZnJtdHMvbXJmLyogKGFwcGx5IHdoZW4gTVJGIGRyaXZlciBpbmNsdWRlZCBpbiBidWlsZCkKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpDb3B5cmlnaHQgKGMpIDIwMDItMjAxMiwgQ2FsaWZvcm5pYSBJbnN0aXR1dGUgb2YgVGVjaG5vbG9neS4KQWxsIHJpZ2h0cyByZXNlcnZlZC4gIEJhc2VkIG9uIEdvdmVybm1lbnQgU3BvbnNvcmVkIFJlc2VhcmNoIHVuZGVyIGNvbnRyYWN0cyBOQVM3LTE0MDcgYW5kL29yIE5BUzctMDMwMDEuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6CiAgMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgogIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwKICAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgogIDMuIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIENhbGlmb3JuaWEgSW5zdGl0dXRlIG9mIFRlY2hub2xvZ3kgKENhbHRlY2gpLCBpdHMgb3BlcmF0aW5nIGRpdmlzaW9uIHRoZSBKZXQgUHJvcHVsc2lvbiBMYWJvcmF0b3J5IChKUEwpLAogICAgIHRoZSBOYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24gKE5BU0EpLCBub3IgdGhlIG5hbWVzIG9mIGl0cyBjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8KICAgICBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dCBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uCgpUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTICJBUyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywKSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4KSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENBTElGT1JOSUEgSU5TVElUVVRFIE9GIFRFQ0hOT0xPR1kgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwKRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOwpMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsClNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsCkVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCgp+fn5+fn5+fgoKQ29weXJpZ2h0IDIwMTQtMjAxNSBFc3JpCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdApodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KCmNtYWtlL21vZHVsZXMvMy4qIChiYWNrcG9ydGVkIENNYWtlIGZpbmQgbW9kdWxlcykKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKQ01ha2UgLSBDcm9zcyBQbGF0Zm9ybSBNYWtlZmlsZSBHZW5lcmF0b3IKQ29weXJpZ2h0IDIwMDAtMjAyMiBLaXR3YXJlLCBJbmMuIGFuZCBDb250cmlidXRvcnMKQWxsIHJpZ2h0cyByZXNlcnZlZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAptb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKYXJlIG1ldDoKCiogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCgoqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0CiAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZQogIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCgoqIE5laXRoZXIgdGhlIG5hbWUgb2YgS2l0d2FyZSwgSW5jLiBub3IgdGhlIG5hbWVzIG9mIENvbnRyaWJ1dG9ycwogIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcwogIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgoKVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUwoiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IKQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQKSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLApTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UCkxJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLApEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkKVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVAooSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UKT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KCm9nci9vZ3JzZl9mcm10cy9mbGF0Z2VvYnVmCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpGbGF0R2VvYnVmCisrKysrKysrKysKCklTQyBMaWNlbnNlCgpDb3B5cmlnaHQgKGMpIDIwMTgsIEJqb3JuIEhhcnJ0ZWxsCgpQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkKcHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZQpjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIGFwcGVhciBpbiBhbGwgY29waWVzLgoKVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTCldJVEggUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YKTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IKQU5ZIFNQRUNJQUwsIERJUkVDVCwgSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUwpXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NIExPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4KQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SIE9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YKT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IgUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS4KCkZsYXRidXNoCisrKysrKysrCgpJU0MgTGljZW5zZQoKQ29weXJpZ2h0IChjKSAyMDE4LCBWbGFkaW1pciBBZ2Fmb25raW4KClBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlCndpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UKYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2UgYXBwZWFyIGluIGFsbCBjb3BpZXMuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSApSRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5ECkZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULApJTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST00gTE9TUwpPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1IgT1RIRVIKVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUiBQRVJGT1JNQU5DRSBPRgpUSElTIFNPRlRXQVJFLgoKb2dyL29ncnNmX2ZybXRzL2ZsYXRnZW9idWYvZmxhdGJ1ZmZlcnMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCkNvcHlyaWdodCAyMDIxIEdvb2dsZSBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgpMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgpZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKCiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKClVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuClNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCg==", "20e50fe7aae3e56378ebf0417d9de904f55a0e61e4df315333e632a4d3555d95": "ICAgICAgICAgICAgICAgICAgR05VIExFU1NFUiBHRU5FUkFMIFBVQkxJQyBMSUNFTlNFCiAgICAgICAgICAgICAgICAgICAgICAgVmVyc2lvbiAyLjEsIEZlYnJ1YXJ5IDE5OTkKCiBDb3B5cmlnaHQgKEMpIDE5OTEsIDE5OTkgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBJbmMuCiA8aHR0cHM6Ly9mc2Yub3JnLz4KIEV2ZXJ5b25lIGlzIHBlcm1pdHRlZCB0byBjb3B5IGFuZCBkaXN0cmlidXRlIHZlcmJhdGltIGNvcGllcwogb2YgdGhpcyBsaWNlbnNlIGRvY3VtZW50LCBidXQgY2hhbmdpbmcgaXQgaXMgbm90IGFsbG93ZWQuCgpbVGhpcyBpcyB0aGUgZmlyc3QgcmVsZWFzZWQgdmVyc2lvbiBvZiB0aGUgTGVzc2VyIEdQTC4gIEl0IGFsc28gY291bnRzCiBhcyB0aGUgc3VjY2Vzc29yIG9mIHRoZSBHTlUgTGlicmFyeSBQdWJsaWMgTGljZW5zZSwgdmVyc2lvbiAyLCBoZW5jZQogdGhlIHZlcnNpb24gbnVtYmVyIDIuMS5dCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJlYW1ibGUKCiAgVGhlIGxpY2Vuc2VzIGZvciBtb3N0IHNvZnR3YXJlIGFyZSBkZXNpZ25lZCB0byB0YWtlIGF3YXkgeW91cgpmcmVlZG9tIHRvIHNoYXJlIGFuZCBjaGFuZ2UgaXQuICBCeSBjb250cmFzdCwgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYwpMaWNlbnNlcyBhcmUgaW50ZW5kZWQgdG8gZ3VhcmFudGVlIHlvdXIgZnJlZWRvbSB0byBzaGFyZSBhbmQgY2hhbmdlCmZyZWUgc29mdHdhcmUtLXRvIG1ha2Ugc3VyZSB0aGUgc29mdHdhcmUgaXMgZnJlZSBmb3IgYWxsIGl0cyB1c2Vycy4KCiAgVGhpcyBsaWNlbnNlLCB0aGUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsIGFwcGxpZXMgdG8gc29tZQpzcGVjaWFsbHkgZGVzaWduYXRlZCBzb2Z0d2FyZSBwYWNrYWdlcy0tdHlwaWNhbGx5IGxpYnJhcmllcy0tb2YgdGhlCkZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiBhbmQgb3RoZXIgYXV0aG9ycyB3aG8gZGVjaWRlIHRvIHVzZSBpdC4gIFlvdQpjYW4gdXNlIGl0IHRvbywgYnV0IHdlIHN1Z2dlc3QgeW91IGZpcnN0IHRoaW5rIGNhcmVmdWxseSBhYm91dCB3aGV0aGVyCnRoaXMgbGljZW5zZSBvciB0aGUgb3JkaW5hcnkgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBpcyB0aGUgYmV0dGVyCnN0cmF0ZWd5IHRvIHVzZSBpbiBhbnkgcGFydGljdWxhciBjYXNlLCBiYXNlZCBvbiB0aGUgZXhwbGFuYXRpb25zIGJlbG93LgoKICBXaGVuIHdlIHNwZWFrIG9mIGZyZWUgc29mdHdhcmUsIHdlIGFyZSByZWZlcnJpbmcgdG8gZnJlZWRvbSBvZiB1c2UsCm5vdCBwcmljZS4gIE91ciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlcyBhcmUgZGVzaWduZWQgdG8gbWFrZSBzdXJlIHRoYXQKeW91IGhhdmUgdGhlIGZyZWVkb20gdG8gZGlzdHJpYnV0ZSBjb3BpZXMgb2YgZnJlZSBzb2Z0d2FyZSAoYW5kIGNoYXJnZQpmb3IgdGhpcyBzZXJ2aWNlIGlmIHlvdSB3aXNoKTsgdGhhdCB5b3UgcmVjZWl2ZSBzb3VyY2UgY29kZSBvciBjYW4gZ2V0Cml0IGlmIHlvdSB3YW50IGl0OyB0aGF0IHlvdSBjYW4gY2hhbmdlIHRoZSBzb2Z0d2FyZSBhbmQgdXNlIHBpZWNlcyBvZgppdCBpbiBuZXcgZnJlZSBwcm9ncmFtczsgYW5kIHRoYXQgeW91IGFyZSBpbmZvcm1lZCB0aGF0IHlvdSBjYW4gZG8KdGhlc2UgdGhpbmdzLgoKICBUbyBwcm90ZWN0IHlvdXIgcmlnaHRzLCB3ZSBuZWVkIHRvIG1ha2UgcmVzdHJpY3Rpb25zIHRoYXQgZm9yYmlkCmRpc3RyaWJ1dG9ycyB0byBkZW55IHlvdSB0aGVzZSByaWdodHMgb3IgdG8gYXNrIHlvdSB0byBzdXJyZW5kZXIgdGhlc2UKcmlnaHRzLiAgVGhlc2UgcmVzdHJpY3Rpb25zIHRyYW5zbGF0ZSB0byBjZXJ0YWluIHJlc3BvbnNpYmlsaXRpZXMgZm9yCnlvdSBpZiB5b3UgZGlzdHJpYnV0ZSBjb3BpZXMgb2YgdGhlIGxpYnJhcnkgb3IgaWYgeW91IG1vZGlmeSBpdC4KCiAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkaXN0cmlidXRlIGNvcGllcyBvZiB0aGUgbGlicmFyeSwgd2hldGhlciBncmF0aXMKb3IgZm9yIGEgZmVlLCB5b3UgbXVzdCBnaXZlIHRoZSByZWNpcGllbnRzIGFsbCB0aGUgcmlnaHRzIHRoYXQgd2UgZ2F2ZQp5b3UuICBZb3UgbXVzdCBtYWtlIHN1cmUgdGhhdCB0aGV5LCB0b28sIHJlY2VpdmUgb3IgY2FuIGdldCB0aGUgc291cmNlCmNvZGUuICBJZiB5b3UgbGluayBvdGhlciBjb2RlIHdpdGggdGhlIGxpYnJhcnksIHlvdSBtdXN0IHByb3ZpZGUKY29tcGxldGUgb2JqZWN0IGZpbGVzIHRvIHRoZSByZWNpcGllbnRzLCBzbyB0aGF0IHRoZXkgY2FuIHJlbGluayB0aGVtCndpdGggdGhlIGxpYnJhcnkgYWZ0ZXIgbWFraW5nIGNoYW5nZXMgdG8gdGhlIGxpYnJhcnkgYW5kIHJlY29tcGlsaW5nCml0LiAgQW5kIHlvdSBtdXN0IHNob3cgdGhlbSB0aGVzZSB0ZXJtcyBzbyB0aGV5IGtub3cgdGhlaXIgcmlnaHRzLgoKICBXZSBwcm90ZWN0IHlvdXIgcmlnaHRzIHdpdGggYSB0d28tc3RlcCBtZXRob2Q6ICgxKSB3ZSBjb3B5cmlnaHQgdGhlCmxpYnJhcnksIGFuZCAoMikgd2Ugb2ZmZXIgeW91IHRoaXMgbGljZW5zZSwgd2hpY2ggZ2l2ZXMgeW91IGxlZ2FsCnBlcm1pc3Npb24gdG8gY29weSwgZGlzdHJpYnV0ZSBhbmQvb3IgbW9kaWZ5IHRoZSBsaWJyYXJ5LgoKICBUbyBwcm90ZWN0IGVhY2ggZGlzdHJpYnV0b3IsIHdlIHdhbnQgdG8gbWFrZSBpdCB2ZXJ5IGNsZWFyIHRoYXQKdGhlcmUgaXMgbm8gd2FycmFudHkgZm9yIHRoZSBmcmVlIGxpYnJhcnkuICBBbHNvLCBpZiB0aGUgbGlicmFyeSBpcwptb2RpZmllZCBieSBzb21lb25lIGVsc2UgYW5kIHBhc3NlZCBvbiwgdGhlIHJlY2lwaWVudHMgc2hvdWxkIGtub3cKdGhhdCB3aGF0IHRoZXkgaGF2ZSBpcyBub3QgdGhlIG9yaWdpbmFsIHZlcnNpb24sIHNvIHRoYXQgdGhlIG9yaWdpbmFsCmF1dGhvcidzIHJlcHV0YXRpb24gd2lsbCBub3QgYmUgYWZmZWN0ZWQgYnkgcHJvYmxlbXMgdGhhdCBtaWdodCBiZQppbnRyb2R1Y2VkIGJ5IG90aGVycy4KDAogIEZpbmFsbHksIHNvZnR3YXJlIHBhdGVudHMgcG9zZSBhIGNvbnN0YW50IHRocmVhdCB0byB0aGUgZXhpc3RlbmNlIG9mCmFueSBmcmVlIHByb2dyYW0uICBXZSB3aXNoIHRvIG1ha2Ugc3VyZSB0aGF0IGEgY29tcGFueSBjYW5ub3QKZWZmZWN0aXZlbHkgcmVzdHJpY3QgdGhlIHVzZXJzIG9mIGEgZnJlZSBwcm9ncmFtIGJ5IG9idGFpbmluZyBhCnJlc3RyaWN0aXZlIGxpY2Vuc2UgZnJvbSBhIHBhdGVudCBob2xkZXIuICBUaGVyZWZvcmUsIHdlIGluc2lzdCB0aGF0CmFueSBwYXRlbnQgbGljZW5zZSBvYnRhaW5lZCBmb3IgYSB2ZXJzaW9uIG9mIHRoZSBsaWJyYXJ5IG11c3QgYmUKY29uc2lzdGVudCB3aXRoIHRoZSBmdWxsIGZyZWVkb20gb2YgdXNlIHNwZWNpZmllZCBpbiB0aGlzIGxpY2Vuc2UuCgogIE1vc3QgR05VIHNvZnR3YXJlLCBpbmNsdWRpbmcgc29tZSBsaWJyYXJpZXMsIGlzIGNvdmVyZWQgYnkgdGhlCm9yZGluYXJ5IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLiAgVGhpcyBsaWNlbnNlLCB0aGUgR05VIExlc3NlcgpHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLCBhcHBsaWVzIHRvIGNlcnRhaW4gZGVzaWduYXRlZCBsaWJyYXJpZXMsIGFuZAppcyBxdWl0ZSBkaWZmZXJlbnQgZnJvbSB0aGUgb3JkaW5hcnkgR2VuZXJhbCBQdWJsaWMgTGljZW5zZS4gIFdlIHVzZQp0aGlzIGxpY2Vuc2UgZm9yIGNlcnRhaW4gbGlicmFyaWVzIGluIG9yZGVyIHRvIHBlcm1pdCBsaW5raW5nIHRob3NlCmxpYnJhcmllcyBpbnRvIG5vbi1mcmVlIHByb2dyYW1zLgoKICBXaGVuIGEgcHJvZ3JhbSBpcyBsaW5rZWQgd2l0aCBhIGxpYnJhcnksIHdoZXRoZXIgc3RhdGljYWxseSBvciB1c2luZwphIHNoYXJlZCBsaWJyYXJ5LCB0aGUgY29tYmluYXRpb24gb2YgdGhlIHR3byBpcyBsZWdhbGx5IHNwZWFraW5nIGEKY29tYmluZWQgd29yaywgYSBkZXJpdmF0aXZlIG9mIHRoZSBvcmlnaW5hbCBsaWJyYXJ5LiAgVGhlIG9yZGluYXJ5CkdlbmVyYWwgUHVibGljIExpY2Vuc2UgdGhlcmVmb3JlIHBlcm1pdHMgc3VjaCBsaW5raW5nIG9ubHkgaWYgdGhlCmVudGlyZSBjb21iaW5hdGlvbiBmaXRzIGl0cyBjcml0ZXJpYSBvZiBmcmVlZG9tLiAgVGhlIExlc3NlciBHZW5lcmFsClB1YmxpYyBMaWNlbnNlIHBlcm1pdHMgbW9yZSBsYXggY3JpdGVyaWEgZm9yIGxpbmtpbmcgb3RoZXIgY29kZSB3aXRoCnRoZSBsaWJyYXJ5LgoKICBXZSBjYWxsIHRoaXMgbGljZW5zZSB0aGUgIkxlc3NlciIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBiZWNhdXNlIGl0CmRvZXMgTGVzcyB0byBwcm90ZWN0IHRoZSB1c2VyJ3MgZnJlZWRvbSB0aGFuIHRoZSBvcmRpbmFyeSBHZW5lcmFsClB1YmxpYyBMaWNlbnNlLiAgSXQgYWxzbyBwcm92aWRlcyBvdGhlciBmcmVlIHNvZnR3YXJlIGRldmVsb3BlcnMgTGVzcwpvZiBhbiBhZHZhbnRhZ2Ugb3ZlciBjb21wZXRpbmcgbm9uLWZyZWUgcHJvZ3JhbXMuICBUaGVzZSBkaXNhZHZhbnRhZ2VzCmFyZSB0aGUgcmVhc29uIHdlIHVzZSB0aGUgb3JkaW5hcnkgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbWFueQpsaWJyYXJpZXMuICBIb3dldmVyLCB0aGUgTGVzc2VyIGxpY2Vuc2UgcHJvdmlkZXMgYWR2YW50YWdlcyBpbiBjZXJ0YWluCnNwZWNpYWwgY2lyY3Vtc3RhbmNlcy4KCiAgRm9yIGV4YW1wbGUsIG9uIHJhcmUgb2NjYXNpb25zLCB0aGVyZSBtYXkgYmUgYSBzcGVjaWFsIG5lZWQgdG8KZW5jb3VyYWdlIHRoZSB3aWRlc3QgcG9zc2libGUgdXNlIG9mIGEgY2VydGFpbiBsaWJyYXJ5LCBzbyB0aGF0IGl0IGJlY29tZXMKYSBkZS1mYWN0byBzdGFuZGFyZC4gIFRvIGFjaGlldmUgdGhpcywgbm9uLWZyZWUgcHJvZ3JhbXMgbXVzdCBiZQphbGxvd2VkIHRvIHVzZSB0aGUgbGlicmFyeS4gIEEgbW9yZSBmcmVxdWVudCBjYXNlIGlzIHRoYXQgYSBmcmVlCmxpYnJhcnkgZG9lcyB0aGUgc2FtZSBqb2IgYXMgd2lkZWx5IHVzZWQgbm9uLWZyZWUgbGlicmFyaWVzLiAgSW4gdGhpcwpjYXNlLCB0aGVyZSBpcyBsaXR0bGUgdG8gZ2FpbiBieSBsaW1pdGluZyB0aGUgZnJlZSBsaWJyYXJ5IHRvIGZyZWUKc29mdHdhcmUgb25seSwgc28gd2UgdXNlIHRoZSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZS4KCiAgSW4gb3RoZXIgY2FzZXMsIHBlcm1pc3Npb24gdG8gdXNlIGEgcGFydGljdWxhciBsaWJyYXJ5IGluIG5vbi1mcmVlCnByb2dyYW1zIGVuYWJsZXMgYSBncmVhdGVyIG51bWJlciBvZiBwZW9wbGUgdG8gdXNlIGEgbGFyZ2UgYm9keSBvZgpmcmVlIHNvZnR3YXJlLiAgRm9yIGV4YW1wbGUsIHBlcm1pc3Npb24gdG8gdXNlIHRoZSBHTlUgQyBMaWJyYXJ5IGluCm5vbi1mcmVlIHByb2dyYW1zIGVuYWJsZXMgbWFueSBtb3JlIHBlb3BsZSB0byB1c2UgdGhlIHdob2xlIEdOVQpvcGVyYXRpbmcgc3lzdGVtLCBhcyB3ZWxsIGFzIGl0cyB2YXJpYW50LCB0aGUgR05VL0xpbnV4IG9wZXJhdGluZwpzeXN0ZW0uCgogIEFsdGhvdWdoIHRoZSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBpcyBMZXNzIHByb3RlY3RpdmUgb2YgdGhlCnVzZXJzJyBmcmVlZG9tLCBpdCBkb2VzIGVuc3VyZSB0aGF0IHRoZSB1c2VyIG9mIGEgcHJvZ3JhbSB0aGF0IGlzCmxpbmtlZCB3aXRoIHRoZSBMaWJyYXJ5IGhhcyB0aGUgZnJlZWRvbSBhbmQgdGhlIHdoZXJld2l0aGFsIHRvIHJ1bgp0aGF0IHByb2dyYW0gdXNpbmcgYSBtb2RpZmllZCB2ZXJzaW9uIG9mIHRoZSBMaWJyYXJ5LgoKICBUaGUgcHJlY2lzZSB0ZXJtcyBhbmQgY29uZGl0aW9ucyBmb3IgY29weWluZywgZGlzdHJpYnV0aW9uIGFuZAptb2RpZmljYXRpb24gZm9sbG93LiAgUGF5IGNsb3NlIGF0dGVudGlvbiB0byB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGEKIndvcmsgYmFzZWQgb24gdGhlIGxpYnJhcnkiIGFuZCBhICJ3b3JrIHRoYXQgdXNlcyB0aGUgbGlicmFyeSIuICBUaGUKZm9ybWVyIGNvbnRhaW5zIGNvZGUgZGVyaXZlZCBmcm9tIHRoZSBsaWJyYXJ5LCB3aGVyZWFzIHRoZSBsYXR0ZXIgbXVzdApiZSBjb21iaW5lZCB3aXRoIHRoZSBsaWJyYXJ5IGluIG9yZGVyIHRvIHJ1bi4KDAogICAgICAgICAgICAgICAgICBHTlUgTEVTU0VSIEdFTkVSQUwgUFVCTElDIExJQ0VOU0UKICAgVEVSTVMgQU5EIENPTkRJVElPTlMgRk9SIENPUFlJTkcsIERJU1RSSUJVVElPTiBBTkQgTU9ESUZJQ0FUSU9OCgogIDAuIFRoaXMgTGljZW5zZSBBZ3JlZW1lbnQgYXBwbGllcyB0byBhbnkgc29mdHdhcmUgbGlicmFyeSBvciBvdGhlcgpwcm9ncmFtIHdoaWNoIGNvbnRhaW5zIGEgbm90aWNlIHBsYWNlZCBieSB0aGUgY29weXJpZ2h0IGhvbGRlciBvcgpvdGhlciBhdXRob3JpemVkIHBhcnR5IHNheWluZyBpdCBtYXkgYmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mCnRoaXMgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgKGFsc28gY2FsbGVkICJ0aGlzIExpY2Vuc2UiKS4KRWFjaCBsaWNlbnNlZSBpcyBhZGRyZXNzZWQgYXMgInlvdSIuCgogIEEgImxpYnJhcnkiIG1lYW5zIGEgY29sbGVjdGlvbiBvZiBzb2Z0d2FyZSBmdW5jdGlvbnMgYW5kL29yIGRhdGEKcHJlcGFyZWQgc28gYXMgdG8gYmUgY29udmVuaWVudGx5IGxpbmtlZCB3aXRoIGFwcGxpY2F0aW9uIHByb2dyYW1zCih3aGljaCB1c2Ugc29tZSBvZiB0aG9zZSBmdW5jdGlvbnMgYW5kIGRhdGEpIHRvIGZvcm0gZXhlY3V0YWJsZXMuCgogIFRoZSAiTGlicmFyeSIsIGJlbG93LCByZWZlcnMgdG8gYW55IHN1Y2ggc29mdHdhcmUgbGlicmFyeSBvciB3b3JrCndoaWNoIGhhcyBiZWVuIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZXNlIHRlcm1zLiAgQSAid29yayBiYXNlZCBvbiB0aGUKTGlicmFyeSIgbWVhbnMgZWl0aGVyIHRoZSBMaWJyYXJ5IG9yIGFueSBkZXJpdmF0aXZlIHdvcmsgdW5kZXIKY29weXJpZ2h0IGxhdzogdGhhdCBpcyB0byBzYXksIGEgd29yayBjb250YWluaW5nIHRoZSBMaWJyYXJ5IG9yIGEKcG9ydGlvbiBvZiBpdCwgZWl0aGVyIHZlcmJhdGltIG9yIHdpdGggbW9kaWZpY2F0aW9ucyBhbmQvb3IgdHJhbnNsYXRlZApzdHJhaWdodGZvcndhcmRseSBpbnRvIGFub3RoZXIgbGFuZ3VhZ2UuICAoSGVyZWluYWZ0ZXIsIHRyYW5zbGF0aW9uIGlzCmluY2x1ZGVkIHdpdGhvdXQgbGltaXRhdGlvbiBpbiB0aGUgdGVybSAibW9kaWZpY2F0aW9uIi4pCgogICJTb3VyY2UgY29kZSIgZm9yIGEgd29yayBtZWFucyB0aGUgcHJlZmVycmVkIGZvcm0gb2YgdGhlIHdvcmsgZm9yCm1ha2luZyBtb2RpZmljYXRpb25zIHRvIGl0LiAgRm9yIGEgbGlicmFyeSwgY29tcGxldGUgc291cmNlIGNvZGUgbWVhbnMKYWxsIHRoZSBzb3VyY2UgY29kZSBmb3IgYWxsIG1vZHVsZXMgaXQgY29udGFpbnMsIHBsdXMgYW55IGFzc29jaWF0ZWQKaW50ZXJmYWNlIGRlZmluaXRpb24gZmlsZXMsIHBsdXMgdGhlIHNjcmlwdHMgdXNlZCB0byBjb250cm9sIGNvbXBpbGF0aW9uCmFuZCBpbnN0YWxsYXRpb24gb2YgdGhlIGxpYnJhcnkuCgogIEFjdGl2aXRpZXMgb3RoZXIgdGhhbiBjb3B5aW5nLCBkaXN0cmlidXRpb24gYW5kIG1vZGlmaWNhdGlvbiBhcmUgbm90CmNvdmVyZWQgYnkgdGhpcyBMaWNlbnNlOyB0aGV5IGFyZSBvdXRzaWRlIGl0cyBzY29wZS4gIFRoZSBhY3Qgb2YKcnVubmluZyBhIHByb2dyYW0gdXNpbmcgdGhlIExpYnJhcnkgaXMgbm90IHJlc3RyaWN0ZWQsIGFuZCBvdXRwdXQgZnJvbQpzdWNoIGEgcHJvZ3JhbSBpcyBjb3ZlcmVkIG9ubHkgaWYgaXRzIGNvbnRlbnRzIGNvbnN0aXR1dGUgYSB3b3JrIGJhc2VkCm9uIHRoZSBMaWJyYXJ5IChpbmRlcGVuZGVudCBvZiB0aGUgdXNlIG9mIHRoZSBMaWJyYXJ5IGluIGEgdG9vbCBmb3IKd3JpdGluZyBpdCkuICBXaGV0aGVyIHRoYXQgaXMgdHJ1ZSBkZXBlbmRzIG9uIHdoYXQgdGhlIExpYnJhcnkgZG9lcwphbmQgd2hhdCB0aGUgcHJvZ3JhbSB0aGF0IHVzZXMgdGhlIExpYnJhcnkgZG9lcy4KCiAgMS4gWW91IG1heSBjb3B5IGFuZCBkaXN0cmlidXRlIHZlcmJhdGltIGNvcGllcyBvZiB0aGUgTGlicmFyeSdzCmNvbXBsZXRlIHNvdXJjZSBjb2RlIGFzIHlvdSByZWNlaXZlIGl0LCBpbiBhbnkgbWVkaXVtLCBwcm92aWRlZCB0aGF0CnlvdSBjb25zcGljdW91c2x5IGFuZCBhcHByb3ByaWF0ZWx5IHB1Ymxpc2ggb24gZWFjaCBjb3B5IGFuCmFwcHJvcHJpYXRlIGNvcHlyaWdodCBub3RpY2UgYW5kIGRpc2NsYWltZXIgb2Ygd2FycmFudHk7IGtlZXAgaW50YWN0CmFsbCB0aGUgbm90aWNlcyB0aGF0IHJlZmVyIHRvIHRoaXMgTGljZW5zZSBhbmQgdG8gdGhlIGFic2VuY2Ugb2YgYW55CndhcnJhbnR5OyBhbmQgZGlzdHJpYnV0ZSBhIGNvcHkgb2YgdGhpcyBMaWNlbnNlIGFsb25nIHdpdGggdGhlCkxpYnJhcnkuCgogIFlvdSBtYXkgY2hhcmdlIGEgZmVlIGZvciB0aGUgcGh5c2ljYWwgYWN0IG9mIHRyYW5zZmVycmluZyBhIGNvcHksCmFuZCB5b3UgbWF5IGF0IHlvdXIgb3B0aW9uIG9mZmVyIHdhcnJhbnR5IHByb3RlY3Rpb24gaW4gZXhjaGFuZ2UgZm9yIGEKZmVlLgoMCiAgMi4gWW91IG1heSBtb2RpZnkgeW91ciBjb3B5IG9yIGNvcGllcyBvZiB0aGUgTGlicmFyeSBvciBhbnkgcG9ydGlvbgpvZiBpdCwgdGh1cyBmb3JtaW5nIGEgd29yayBiYXNlZCBvbiB0aGUgTGlicmFyeSwgYW5kIGNvcHkgYW5kCmRpc3RyaWJ1dGUgc3VjaCBtb2RpZmljYXRpb25zIG9yIHdvcmsgdW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb24gMQphYm92ZSwgcHJvdmlkZWQgdGhhdCB5b3UgYWxzbyBtZWV0IGFsbCBvZiB0aGVzZSBjb25kaXRpb25zOgoKICAgIGEpIFRoZSBtb2RpZmllZCB3b3JrIG11c3QgaXRzZWxmIGJlIGEgc29mdHdhcmUgbGlicmFyeS4KCiAgICBiKSBZb3UgbXVzdCBjYXVzZSB0aGUgZmlsZXMgbW9kaWZpZWQgdG8gY2FycnkgcHJvbWluZW50IG5vdGljZXMKICAgIHN0YXRpbmcgdGhhdCB5b3UgY2hhbmdlZCB0aGUgZmlsZXMgYW5kIHRoZSBkYXRlIG9mIGFueSBjaGFuZ2UuCgogICAgYykgWW91IG11c3QgY2F1c2UgdGhlIHdob2xlIG9mIHRoZSB3b3JrIHRvIGJlIGxpY2Vuc2VkIGF0IG5vCiAgICBjaGFyZ2UgdG8gYWxsIHRoaXJkIHBhcnRpZXMgdW5kZXIgdGhlIHRlcm1zIG9mIHRoaXMgTGljZW5zZS4KCiAgICBkKSBJZiBhIGZhY2lsaXR5IGluIHRoZSBtb2RpZmllZCBMaWJyYXJ5IHJlZmVycyB0byBhIGZ1bmN0aW9uIG9yIGEKICAgIHRhYmxlIG9mIGRhdGEgdG8gYmUgc3VwcGxpZWQgYnkgYW4gYXBwbGljYXRpb24gcHJvZ3JhbSB0aGF0IHVzZXMKICAgIHRoZSBmYWNpbGl0eSwgb3RoZXIgdGhhbiBhcyBhbiBhcmd1bWVudCBwYXNzZWQgd2hlbiB0aGUgZmFjaWxpdHkKICAgIGlzIGludm9rZWQsIHRoZW4geW91IG11c3QgbWFrZSBhIGdvb2QgZmFpdGggZWZmb3J0IHRvIGVuc3VyZSB0aGF0LAogICAgaW4gdGhlIGV2ZW50IGFuIGFwcGxpY2F0aW9uIGRvZXMgbm90IHN1cHBseSBzdWNoIGZ1bmN0aW9uIG9yCiAgICB0YWJsZSwgdGhlIGZhY2lsaXR5IHN0aWxsIG9wZXJhdGVzLCBhbmQgcGVyZm9ybXMgd2hhdGV2ZXIgcGFydCBvZgogICAgaXRzIHB1cnBvc2UgcmVtYWlucyBtZWFuaW5nZnVsLgoKICAgIChGb3IgZXhhbXBsZSwgYSBmdW5jdGlvbiBpbiBhIGxpYnJhcnkgdG8gY29tcHV0ZSBzcXVhcmUgcm9vdHMgaGFzCiAgICBhIHB1cnBvc2UgdGhhdCBpcyBlbnRpcmVseSB3ZWxsLWRlZmluZWQgaW5kZXBlbmRlbnQgb2YgdGhlCiAgICBhcHBsaWNhdGlvbi4gIFRoZXJlZm9yZSwgU3Vic2VjdGlvbiAyZCByZXF1aXJlcyB0aGF0IGFueQogICAgYXBwbGljYXRpb24tc3VwcGxpZWQgZnVuY3Rpb24gb3IgdGFibGUgdXNlZCBieSB0aGlzIGZ1bmN0aW9uIG11c3QKICAgIGJlIG9wdGlvbmFsOiBpZiB0aGUgYXBwbGljYXRpb24gZG9lcyBub3Qgc3VwcGx5IGl0LCB0aGUgc3F1YXJlCiAgICByb290IGZ1bmN0aW9uIG11c3Qgc3RpbGwgY29tcHV0ZSBzcXVhcmUgcm9vdHMuKQoKVGhlc2UgcmVxdWlyZW1lbnRzIGFwcGx5IHRvIHRoZSBtb2RpZmllZCB3b3JrIGFzIGEgd2hvbGUuICBJZgppZGVudGlmaWFibGUgc2VjdGlvbnMgb2YgdGhhdCB3b3JrIGFyZSBub3QgZGVyaXZlZCBmcm9tIHRoZSBMaWJyYXJ5LAphbmQgY2FuIGJlIHJlYXNvbmFibHkgY29uc2lkZXJlZCBpbmRlcGVuZGVudCBhbmQgc2VwYXJhdGUgd29ya3MgaW4KdGhlbXNlbHZlcywgdGhlbiB0aGlzIExpY2Vuc2UsIGFuZCBpdHMgdGVybXMsIGRvIG5vdCBhcHBseSB0byB0aG9zZQpzZWN0aW9ucyB3aGVuIHlvdSBkaXN0cmlidXRlIHRoZW0gYXMgc2VwYXJhdGUgd29ya3MuICBCdXQgd2hlbiB5b3UKZGlzdHJpYnV0ZSB0aGUgc2FtZSBzZWN0aW9ucyBhcyBwYXJ0IG9mIGEgd2hvbGUgd2hpY2ggaXMgYSB3b3JrIGJhc2VkCm9uIHRoZSBMaWJyYXJ5LCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSB3aG9sZSBtdXN0IGJlIG9uIHRoZSB0ZXJtcyBvZgp0aGlzIExpY2Vuc2UsIHdob3NlIHBlcm1pc3Npb25zIGZvciBvdGhlciBsaWNlbnNlZXMgZXh0ZW5kIHRvIHRoZQplbnRpcmUgd2hvbGUsIGFuZCB0aHVzIHRvIGVhY2ggYW5kIGV2ZXJ5IHBhcnQgcmVnYXJkbGVzcyBvZiB3aG8gd3JvdGUKaXQuCgpUaHVzLCBpdCBpcyBub3QgdGhlIGludGVudCBvZiB0aGlzIHNlY3Rpb24gdG8gY2xhaW0gcmlnaHRzIG9yIGNvbnRlc3QKeW91ciByaWdodHMgdG8gd29yayB3cml0dGVuIGVudGlyZWx5IGJ5IHlvdTsgcmF0aGVyLCB0aGUgaW50ZW50IGlzIHRvCmV4ZXJjaXNlIHRoZSByaWdodCB0byBjb250cm9sIHRoZSBkaXN0cmlidXRpb24gb2YgZGVyaXZhdGl2ZSBvcgpjb2xsZWN0aXZlIHdvcmtzIGJhc2VkIG9uIHRoZSBMaWJyYXJ5LgoKSW4gYWRkaXRpb24sIG1lcmUgYWdncmVnYXRpb24gb2YgYW5vdGhlciB3b3JrIG5vdCBiYXNlZCBvbiB0aGUgTGlicmFyeQp3aXRoIHRoZSBMaWJyYXJ5IChvciB3aXRoIGEgd29yayBiYXNlZCBvbiB0aGUgTGlicmFyeSkgb24gYSB2b2x1bWUgb2YKYSBzdG9yYWdlIG9yIGRpc3RyaWJ1dGlvbiBtZWRpdW0gZG9lcyBub3QgYnJpbmcgdGhlIG90aGVyIHdvcmsgdW5kZXIKdGhlIHNjb3BlIG9mIHRoaXMgTGljZW5zZS4KCiAgMy4gWW91IG1heSBvcHQgdG8gYXBwbHkgdGhlIHRlcm1zIG9mIHRoZSBvcmRpbmFyeSBHTlUgR2VuZXJhbCBQdWJsaWMKTGljZW5zZSBpbnN0ZWFkIG9mIHRoaXMgTGljZW5zZSB0byBhIGdpdmVuIGNvcHkgb2YgdGhlIExpYnJhcnkuICBUbyBkbwp0aGlzLCB5b3UgbXVzdCBhbHRlciBhbGwgdGhlIG5vdGljZXMgdGhhdCByZWZlciB0byB0aGlzIExpY2Vuc2UsIHNvCnRoYXQgdGhleSByZWZlciB0byB0aGUgb3JkaW5hcnkgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsIHZlcnNpb24gMiwKaW5zdGVhZCBvZiB0byB0aGlzIExpY2Vuc2UuICAoSWYgYSBuZXdlciB2ZXJzaW9uIHRoYW4gdmVyc2lvbiAyIG9mIHRoZQpvcmRpbmFyeSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBoYXMgYXBwZWFyZWQsIHRoZW4geW91IGNhbiBzcGVjaWZ5CnRoYXQgdmVyc2lvbiBpbnN0ZWFkIGlmIHlvdSB3aXNoLikgIERvIG5vdCBtYWtlIGFueSBvdGhlciBjaGFuZ2UgaW4KdGhlc2Ugbm90aWNlcy4KDAogIE9uY2UgdGhpcyBjaGFuZ2UgaXMgbWFkZSBpbiBhIGdpdmVuIGNvcHksIGl0IGlzIGlycmV2ZXJzaWJsZSBmb3IKdGhhdCBjb3B5LCBzbyB0aGUgb3JkaW5hcnkgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXBwbGllcyB0byBhbGwKc3Vic2VxdWVudCBjb3BpZXMgYW5kIGRlcml2YXRpdmUgd29ya3MgbWFkZSBmcm9tIHRoYXQgY29weS4KCiAgVGhpcyBvcHRpb24gaXMgdXNlZnVsIHdoZW4geW91IHdpc2ggdG8gY29weSBwYXJ0IG9mIHRoZSBjb2RlIG9mCnRoZSBMaWJyYXJ5IGludG8gYSBwcm9ncmFtIHRoYXQgaXMgbm90IGEgbGlicmFyeS4KCiAgNC4gWW91IG1heSBjb3B5IGFuZCBkaXN0cmlidXRlIHRoZSBMaWJyYXJ5IChvciBhIHBvcnRpb24gb3IKZGVyaXZhdGl2ZSBvZiBpdCwgdW5kZXIgU2VjdGlvbiAyKSBpbiBvYmplY3QgY29kZSBvciBleGVjdXRhYmxlIGZvcm0KdW5kZXIgdGhlIHRlcm1zIG9mIFNlY3Rpb25zIDEgYW5kIDIgYWJvdmUgcHJvdmlkZWQgdGhhdCB5b3UgYWNjb21wYW55Cml0IHdpdGggdGhlIGNvbXBsZXRlIGNvcnJlc3BvbmRpbmcgbWFjaGluZS1yZWFkYWJsZSBzb3VyY2UgY29kZSwgd2hpY2gKbXVzdCBiZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgU2VjdGlvbnMgMSBhbmQgMiBhYm92ZSBvbiBhCm1lZGl1bSBjdXN0b21hcmlseSB1c2VkIGZvciBzb2Z0d2FyZSBpbnRlcmNoYW5nZS4KCiAgSWYgZGlzdHJpYnV0aW9uIG9mIG9iamVjdCBjb2RlIGlzIG1hZGUgYnkgb2ZmZXJpbmcgYWNjZXNzIHRvIGNvcHkKZnJvbSBhIGRlc2lnbmF0ZWQgcGxhY2UsIHRoZW4gb2ZmZXJpbmcgZXF1aXZhbGVudCBhY2Nlc3MgdG8gY29weSB0aGUKc291cmNlIGNvZGUgZnJvbSB0aGUgc2FtZSBwbGFjZSBzYXRpc2ZpZXMgdGhlIHJlcXVpcmVtZW50IHRvCmRpc3RyaWJ1dGUgdGhlIHNvdXJjZSBjb2RlLCBldmVuIHRob3VnaCB0aGlyZCBwYXJ0aWVzIGFyZSBub3QKY29tcGVsbGVkIHRvIGNvcHkgdGhlIHNvdXJjZSBhbG9uZyB3aXRoIHRoZSBvYmplY3QgY29kZS4KCiAgNS4gQSBwcm9ncmFtIHRoYXQgY29udGFpbnMgbm8gZGVyaXZhdGl2ZSBvZiBhbnkgcG9ydGlvbiBvZiB0aGUKTGlicmFyeSwgYnV0IGlzIGRlc2lnbmVkIHRvIHdvcmsgd2l0aCB0aGUgTGlicmFyeSBieSBiZWluZyBjb21waWxlZCBvcgpsaW5rZWQgd2l0aCBpdCwgaXMgY2FsbGVkIGEgIndvcmsgdGhhdCB1c2VzIHRoZSBMaWJyYXJ5Ii4gIFN1Y2ggYQp3b3JrLCBpbiBpc29sYXRpb24sIGlzIG5vdCBhIGRlcml2YXRpdmUgd29yayBvZiB0aGUgTGlicmFyeSwgYW5kCnRoZXJlZm9yZSBmYWxscyBvdXRzaWRlIHRoZSBzY29wZSBvZiB0aGlzIExpY2Vuc2UuCgogIEhvd2V2ZXIsIGxpbmtpbmcgYSAid29yayB0aGF0IHVzZXMgdGhlIExpYnJhcnkiIHdpdGggdGhlIExpYnJhcnkKY3JlYXRlcyBhbiBleGVjdXRhYmxlIHRoYXQgaXMgYSBkZXJpdmF0aXZlIG9mIHRoZSBMaWJyYXJ5IChiZWNhdXNlIGl0CmNvbnRhaW5zIHBvcnRpb25zIG9mIHRoZSBMaWJyYXJ5KSwgcmF0aGVyIHRoYW4gYSAid29yayB0aGF0IHVzZXMgdGhlCmxpYnJhcnkiLiAgVGhlIGV4ZWN1dGFibGUgaXMgdGhlcmVmb3JlIGNvdmVyZWQgYnkgdGhpcyBMaWNlbnNlLgpTZWN0aW9uIDYgc3RhdGVzIHRlcm1zIGZvciBkaXN0cmlidXRpb24gb2Ygc3VjaCBleGVjdXRhYmxlcy4KCiAgV2hlbiBhICJ3b3JrIHRoYXQgdXNlcyB0aGUgTGlicmFyeSIgdXNlcyBtYXRlcmlhbCBmcm9tIGEgaGVhZGVyIGZpbGUKdGhhdCBpcyBwYXJ0IG9mIHRoZSBMaWJyYXJ5LCB0aGUgb2JqZWN0IGNvZGUgZm9yIHRoZSB3b3JrIG1heSBiZSBhCmRlcml2YXRpdmUgd29yayBvZiB0aGUgTGlicmFyeSBldmVuIHRob3VnaCB0aGUgc291cmNlIGNvZGUgaXMgbm90LgpXaGV0aGVyIHRoaXMgaXMgdHJ1ZSBpcyBlc3BlY2lhbGx5IHNpZ25pZmljYW50IGlmIHRoZSB3b3JrIGNhbiBiZQpsaW5rZWQgd2l0aG91dCB0aGUgTGlicmFyeSwgb3IgaWYgdGhlIHdvcmsgaXMgaXRzZWxmIGEgbGlicmFyeS4gIFRoZQp0aHJlc2hvbGQgZm9yIHRoaXMgdG8gYmUgdHJ1ZSBpcyBub3QgcHJlY2lzZWx5IGRlZmluZWQgYnkgbGF3LgoKICBJZiBzdWNoIGFuIG9iamVjdCBmaWxlIHVzZXMgb25seSBudW1lcmljYWwgcGFyYW1ldGVycywgZGF0YQpzdHJ1Y3R1cmUgbGF5b3V0cyBhbmQgYWNjZXNzb3JzLCBhbmQgc21hbGwgbWFjcm9zIGFuZCBzbWFsbCBpbmxpbmUKZnVuY3Rpb25zICh0ZW4gbGluZXMgb3IgbGVzcyBpbiBsZW5ndGgpLCB0aGVuIHRoZSB1c2Ugb2YgdGhlIG9iamVjdApmaWxlIGlzIHVucmVzdHJpY3RlZCwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIGl0IGlzIGxlZ2FsbHkgYSBkZXJpdmF0aXZlCndvcmsuICAoRXhlY3V0YWJsZXMgY29udGFpbmluZyB0aGlzIG9iamVjdCBjb2RlIHBsdXMgcG9ydGlvbnMgb2YgdGhlCkxpYnJhcnkgd2lsbCBzdGlsbCBmYWxsIHVuZGVyIFNlY3Rpb24gNi4pCgogIE90aGVyd2lzZSwgaWYgdGhlIHdvcmsgaXMgYSBkZXJpdmF0aXZlIG9mIHRoZSBMaWJyYXJ5LCB5b3UgbWF5CmRpc3RyaWJ1dGUgdGhlIG9iamVjdCBjb2RlIGZvciB0aGUgd29yayB1bmRlciB0aGUgdGVybXMgb2YgU2VjdGlvbiA2LgpBbnkgZXhlY3V0YWJsZXMgY29udGFpbmluZyB0aGF0IHdvcmsgYWxzbyBmYWxsIHVuZGVyIFNlY3Rpb24gNiwKd2hldGhlciBvciBub3QgdGhleSBhcmUgbGlua2VkIGRpcmVjdGx5IHdpdGggdGhlIExpYnJhcnkgaXRzZWxmLgoMCiAgNi4gQXMgYW4gZXhjZXB0aW9uIHRvIHRoZSBTZWN0aW9ucyBhYm92ZSwgeW91IG1heSBhbHNvIGNvbWJpbmUgb3IKbGluayBhICJ3b3JrIHRoYXQgdXNlcyB0aGUgTGlicmFyeSIgd2l0aCB0aGUgTGlicmFyeSB0byBwcm9kdWNlIGEKd29yayBjb250YWluaW5nIHBvcnRpb25zIG9mIHRoZSBMaWJyYXJ5LCBhbmQgZGlzdHJpYnV0ZSB0aGF0IHdvcmsKdW5kZXIgdGVybXMgb2YgeW91ciBjaG9pY2UsIHByb3ZpZGVkIHRoYXQgdGhlIHRlcm1zIHBlcm1pdAptb2RpZmljYXRpb24gb2YgdGhlIHdvcmsgZm9yIHRoZSBjdXN0b21lcidzIG93biB1c2UgYW5kIHJldmVyc2UKZW5naW5lZXJpbmcgZm9yIGRlYnVnZ2luZyBzdWNoIG1vZGlmaWNhdGlvbnMuCgogIFlvdSBtdXN0IGdpdmUgcHJvbWluZW50IG5vdGljZSB3aXRoIGVhY2ggY29weSBvZiB0aGUgd29yayB0aGF0IHRoZQpMaWJyYXJ5IGlzIHVzZWQgaW4gaXQgYW5kIHRoYXQgdGhlIExpYnJhcnkgYW5kIGl0cyB1c2UgYXJlIGNvdmVyZWQgYnkKdGhpcyBMaWNlbnNlLiAgWW91IG11c3Qgc3VwcGx5IGEgY29weSBvZiB0aGlzIExpY2Vuc2UuICBJZiB0aGUgd29yawpkdXJpbmcgZXhlY3V0aW9uIGRpc3BsYXlzIGNvcHlyaWdodCBub3RpY2VzLCB5b3UgbXVzdCBpbmNsdWRlIHRoZQpjb3B5cmlnaHQgbm90aWNlIGZvciB0aGUgTGlicmFyeSBhbW9uZyB0aGVtLCBhcyB3ZWxsIGFzIGEgcmVmZXJlbmNlCmRpcmVjdGluZyB0aGUgdXNlciB0byB0aGUgY29weSBvZiB0aGlzIExpY2Vuc2UuICBBbHNvLCB5b3UgbXVzdCBkbyBvbmUKb2YgdGhlc2UgdGhpbmdzOgoKICAgIGEpIEFjY29tcGFueSB0aGUgd29yayB3aXRoIHRoZSBjb21wbGV0ZSBjb3JyZXNwb25kaW5nCiAgICBtYWNoaW5lLXJlYWRhYmxlIHNvdXJjZSBjb2RlIGZvciB0aGUgTGlicmFyeSBpbmNsdWRpbmcgd2hhdGV2ZXIKICAgIGNoYW5nZXMgd2VyZSB1c2VkIGluIHRoZSB3b3JrICh3aGljaCBtdXN0IGJlIGRpc3RyaWJ1dGVkIHVuZGVyCiAgICBTZWN0aW9ucyAxIGFuZCAyIGFib3ZlKTsgYW5kLCBpZiB0aGUgd29yayBpcyBhbiBleGVjdXRhYmxlIGxpbmtlZAogICAgd2l0aCB0aGUgTGlicmFyeSwgd2l0aCB0aGUgY29tcGxldGUgbWFjaGluZS1yZWFkYWJsZSAid29yayB0aGF0CiAgICB1c2VzIHRoZSBMaWJyYXJ5IiwgYXMgb2JqZWN0IGNvZGUgYW5kL29yIHNvdXJjZSBjb2RlLCBzbyB0aGF0IHRoZQogICAgdXNlciBjYW4gbW9kaWZ5IHRoZSBMaWJyYXJ5IGFuZCB0aGVuIHJlbGluayB0byBwcm9kdWNlIGEgbW9kaWZpZWQKICAgIGV4ZWN1dGFibGUgY29udGFpbmluZyB0aGUgbW9kaWZpZWQgTGlicmFyeS4gIChJdCBpcyB1bmRlcnN0b29kCiAgICB0aGF0IHRoZSB1c2VyIHdobyBjaGFuZ2VzIHRoZSBjb250ZW50cyBvZiBkZWZpbml0aW9ucyBmaWxlcyBpbiB0aGUKICAgIExpYnJhcnkgd2lsbCBub3QgbmVjZXNzYXJpbHkgYmUgYWJsZSB0byByZWNvbXBpbGUgdGhlIGFwcGxpY2F0aW9uCiAgICB0byB1c2UgdGhlIG1vZGlmaWVkIGRlZmluaXRpb25zLikKCiAgICBiKSBVc2UgYSBzdWl0YWJsZSBzaGFyZWQgbGlicmFyeSBtZWNoYW5pc20gZm9yIGxpbmtpbmcgd2l0aCB0aGUKICAgIExpYnJhcnkuICBBIHN1aXRhYmxlIG1lY2hhbmlzbSBpcyBvbmUgdGhhdCAoMSkgdXNlcyBhdCBydW4gdGltZSBhCiAgICBjb3B5IG9mIHRoZSBsaWJyYXJ5IGFscmVhZHkgcHJlc2VudCBvbiB0aGUgdXNlcidzIGNvbXB1dGVyIHN5c3RlbSwKICAgIHJhdGhlciB0aGFuIGNvcHlpbmcgbGlicmFyeSBmdW5jdGlvbnMgaW50byB0aGUgZXhlY3V0YWJsZSwgYW5kICgyKQogICAgd2lsbCBvcGVyYXRlIHByb3Blcmx5IHdpdGggYSBtb2RpZmllZCB2ZXJzaW9uIG9mIHRoZSBsaWJyYXJ5LCBpZgogICAgdGhlIHVzZXIgaW5zdGFsbHMgb25lLCBhcyBsb25nIGFzIHRoZSBtb2RpZmllZCB2ZXJzaW9uIGlzCiAgICBpbnRlcmZhY2UtY29tcGF0aWJsZSB3aXRoIHRoZSB2ZXJzaW9uIHRoYXQgdGhlIHdvcmsgd2FzIG1hZGUgd2l0aC4KCiAgICBjKSBBY2NvbXBhbnkgdGhlIHdvcmsgd2l0aCBhIHdyaXR0ZW4gb2ZmZXIsIHZhbGlkIGZvciBhdAogICAgbGVhc3QgdGhyZWUgeWVhcnMsIHRvIGdpdmUgdGhlIHNhbWUgdXNlciB0aGUgbWF0ZXJpYWxzCiAgICBzcGVjaWZpZWQgaW4gU3Vic2VjdGlvbiA2YSwgYWJvdmUsIGZvciBhIGNoYXJnZSBubyBtb3JlCiAgICB0aGFuIHRoZSBjb3N0IG9mIHBlcmZvcm1pbmcgdGhpcyBkaXN0cmlidXRpb24uCgogICAgZCkgSWYgZGlzdHJpYnV0aW9uIG9mIHRoZSB3b3JrIGlzIG1hZGUgYnkgb2ZmZXJpbmcgYWNjZXNzIHRvIGNvcHkKICAgIGZyb20gYSBkZXNpZ25hdGVkIHBsYWNlLCBvZmZlciBlcXVpdmFsZW50IGFjY2VzcyB0byBjb3B5IHRoZSBhYm92ZQogICAgc3BlY2lmaWVkIG1hdGVyaWFscyBmcm9tIHRoZSBzYW1lIHBsYWNlLgoKICAgIGUpIFZlcmlmeSB0aGF0IHRoZSB1c2VyIGhhcyBhbHJlYWR5IHJlY2VpdmVkIGEgY29weSBvZiB0aGVzZQogICAgbWF0ZXJpYWxzIG9yIHRoYXQgeW91IGhhdmUgYWxyZWFkeSBzZW50IHRoaXMgdXNlciBhIGNvcHkuCgogIEZvciBhbiBleGVjdXRhYmxlLCB0aGUgcmVxdWlyZWQgZm9ybSBvZiB0aGUgIndvcmsgdGhhdCB1c2VzIHRoZQpMaWJyYXJ5IiBtdXN0IGluY2x1ZGUgYW55IGRhdGEgYW5kIHV0aWxpdHkgcHJvZ3JhbXMgbmVlZGVkIGZvcgpyZXByb2R1Y2luZyB0aGUgZXhlY3V0YWJsZSBmcm9tIGl0LiAgSG93ZXZlciwgYXMgYSBzcGVjaWFsIGV4Y2VwdGlvbiwKdGhlIG1hdGVyaWFscyB0byBiZSBkaXN0cmlidXRlZCBuZWVkIG5vdCBpbmNsdWRlIGFueXRoaW5nIHRoYXQgaXMKbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKGluIGVpdGhlciBzb3VyY2Ugb3IgYmluYXJ5IGZvcm0pIHdpdGggdGhlIG1ham9yCmNvbXBvbmVudHMgKGNvbXBpbGVyLCBrZXJuZWwsIGFuZCBzbyBvbikgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0gb24Kd2hpY2ggdGhlIGV4ZWN1dGFibGUgcnVucywgdW5sZXNzIHRoYXQgY29tcG9uZW50IGl0c2VsZiBhY2NvbXBhbmllcwp0aGUgZXhlY3V0YWJsZS4KCiAgSXQgbWF5IGhhcHBlbiB0aGF0IHRoaXMgcmVxdWlyZW1lbnQgY29udHJhZGljdHMgdGhlIGxpY2Vuc2UKcmVzdHJpY3Rpb25zIG9mIG90aGVyIHByb3ByaWV0YXJ5IGxpYnJhcmllcyB0aGF0IGRvIG5vdCBub3JtYWxseQphY2NvbXBhbnkgdGhlIG9wZXJhdGluZyBzeXN0ZW0uICBTdWNoIGEgY29udHJhZGljdGlvbiBtZWFucyB5b3UgY2Fubm90CnVzZSBib3RoIHRoZW0gYW5kIHRoZSBMaWJyYXJ5IHRvZ2V0aGVyIGluIGFuIGV4ZWN1dGFibGUgdGhhdCB5b3UKZGlzdHJpYnV0ZS4KDAogIDcuIFlvdSBtYXkgcGxhY2UgbGlicmFyeSBmYWNpbGl0aWVzIHRoYXQgYXJlIGEgd29yayBiYXNlZCBvbiB0aGUKTGlicmFyeSBzaWRlLWJ5LXNpZGUgaW4gYSBzaW5nbGUgbGlicmFyeSB0b2dldGhlciB3aXRoIG90aGVyIGxpYnJhcnkKZmFjaWxpdGllcyBub3QgY292ZXJlZCBieSB0aGlzIExpY2Vuc2UsIGFuZCBkaXN0cmlidXRlIHN1Y2ggYSBjb21iaW5lZApsaWJyYXJ5LCBwcm92aWRlZCB0aGF0IHRoZSBzZXBhcmF0ZSBkaXN0cmlidXRpb24gb2YgdGhlIHdvcmsgYmFzZWQgb24KdGhlIExpYnJhcnkgYW5kIG9mIHRoZSBvdGhlciBsaWJyYXJ5IGZhY2lsaXRpZXMgaXMgb3RoZXJ3aXNlCnBlcm1pdHRlZCwgYW5kIHByb3ZpZGVkIHRoYXQgeW91IGRvIHRoZXNlIHR3byB0aGluZ3M6CgogICAgYSkgQWNjb21wYW55IHRoZSBjb21iaW5lZCBsaWJyYXJ5IHdpdGggYSBjb3B5IG9mIHRoZSBzYW1lIHdvcmsKICAgIGJhc2VkIG9uIHRoZSBMaWJyYXJ5LCB1bmNvbWJpbmVkIHdpdGggYW55IG90aGVyIGxpYnJhcnkKICAgIGZhY2lsaXRpZXMuICBUaGlzIG11c3QgYmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZQogICAgU2VjdGlvbnMgYWJvdmUuCgogICAgYikgR2l2ZSBwcm9taW5lbnQgbm90aWNlIHdpdGggdGhlIGNvbWJpbmVkIGxpYnJhcnkgb2YgdGhlIGZhY3QKICAgIHRoYXQgcGFydCBvZiBpdCBpcyBhIHdvcmsgYmFzZWQgb24gdGhlIExpYnJhcnksIGFuZCBleHBsYWluaW5nCiAgICB3aGVyZSB0byBmaW5kIHRoZSBhY2NvbXBhbnlpbmcgdW5jb21iaW5lZCBmb3JtIG9mIHRoZSBzYW1lIHdvcmsuCgogIDguIFlvdSBtYXkgbm90IGNvcHksIG1vZGlmeSwgc3VibGljZW5zZSwgbGluayB3aXRoLCBvciBkaXN0cmlidXRlCnRoZSBMaWJyYXJ5IGV4Y2VwdCBhcyBleHByZXNzbHkgcHJvdmlkZWQgdW5kZXIgdGhpcyBMaWNlbnNlLiAgQW55CmF0dGVtcHQgb3RoZXJ3aXNlIHRvIGNvcHksIG1vZGlmeSwgc3VibGljZW5zZSwgbGluayB3aXRoLCBvcgpkaXN0cmlidXRlIHRoZSBMaWJyYXJ5IGlzIHZvaWQsIGFuZCB3aWxsIGF1dG9tYXRpY2FsbHkgdGVybWluYXRlIHlvdXIKcmlnaHRzIHVuZGVyIHRoaXMgTGljZW5zZS4gIEhvd2V2ZXIsIHBhcnRpZXMgd2hvIGhhdmUgcmVjZWl2ZWQgY29waWVzLApvciByaWdodHMsIGZyb20geW91IHVuZGVyIHRoaXMgTGljZW5zZSB3aWxsIG5vdCBoYXZlIHRoZWlyIGxpY2Vuc2VzCnRlcm1pbmF0ZWQgc28gbG9uZyBhcyBzdWNoIHBhcnRpZXMgcmVtYWluIGluIGZ1bGwgY29tcGxpYW5jZS4KCiAgOS4gWW91IGFyZSBub3QgcmVxdWlyZWQgdG8gYWNjZXB0IHRoaXMgTGljZW5zZSwgc2luY2UgeW91IGhhdmUgbm90CnNpZ25lZCBpdC4gIEhvd2V2ZXIsIG5vdGhpbmcgZWxzZSBncmFudHMgeW91IHBlcm1pc3Npb24gdG8gbW9kaWZ5IG9yCmRpc3RyaWJ1dGUgdGhlIExpYnJhcnkgb3IgaXRzIGRlcml2YXRpdmUgd29ya3MuICBUaGVzZSBhY3Rpb25zIGFyZQpwcm9oaWJpdGVkIGJ5IGxhdyBpZiB5b3UgZG8gbm90IGFjY2VwdCB0aGlzIExpY2Vuc2UuICBUaGVyZWZvcmUsIGJ5Cm1vZGlmeWluZyBvciBkaXN0cmlidXRpbmcgdGhlIExpYnJhcnkgKG9yIGFueSB3b3JrIGJhc2VkIG9uIHRoZQpMaWJyYXJ5KSwgeW91IGluZGljYXRlIHlvdXIgYWNjZXB0YW5jZSBvZiB0aGlzIExpY2Vuc2UgdG8gZG8gc28sIGFuZAphbGwgaXRzIHRlcm1zIGFuZCBjb25kaXRpb25zIGZvciBjb3B5aW5nLCBkaXN0cmlidXRpbmcgb3IgbW9kaWZ5aW5nCnRoZSBMaWJyYXJ5IG9yIHdvcmtzIGJhc2VkIG9uIGl0LgoKICAxMC4gRWFjaCB0aW1lIHlvdSByZWRpc3RyaWJ1dGUgdGhlIExpYnJhcnkgKG9yIGFueSB3b3JrIGJhc2VkIG9uIHRoZQpMaWJyYXJ5KSwgdGhlIHJlY2lwaWVudCBhdXRvbWF0aWNhbGx5IHJlY2VpdmVzIGEgbGljZW5zZSBmcm9tIHRoZQpvcmlnaW5hbCBsaWNlbnNvciB0byBjb3B5LCBkaXN0cmlidXRlLCBsaW5rIHdpdGggb3IgbW9kaWZ5IHRoZSBMaWJyYXJ5CnN1YmplY3QgdG8gdGhlc2UgdGVybXMgYW5kIGNvbmRpdGlvbnMuICBZb3UgbWF5IG5vdCBpbXBvc2UgYW55IGZ1cnRoZXIKcmVzdHJpY3Rpb25zIG9uIHRoZSByZWNpcGllbnRzJyBleGVyY2lzZSBvZiB0aGUgcmlnaHRzIGdyYW50ZWQgaGVyZWluLgpZb3UgYXJlIG5vdCByZXNwb25zaWJsZSBmb3IgZW5mb3JjaW5nIGNvbXBsaWFuY2UgYnkgdGhpcmQgcGFydGllcyB3aXRoCnRoaXMgTGljZW5zZS4KDAogIDExLiBJZiwgYXMgYSBjb25zZXF1ZW5jZSBvZiBhIGNvdXJ0IGp1ZGdtZW50IG9yIGFsbGVnYXRpb24gb2YgcGF0ZW50CmluZnJpbmdlbWVudCBvciBmb3IgYW55IG90aGVyIHJlYXNvbiAobm90IGxpbWl0ZWQgdG8gcGF0ZW50IGlzc3VlcyksCmNvbmRpdGlvbnMgYXJlIGltcG9zZWQgb24geW91ICh3aGV0aGVyIGJ5IGNvdXJ0IG9yZGVyLCBhZ3JlZW1lbnQgb3IKb3RoZXJ3aXNlKSB0aGF0IGNvbnRyYWRpY3QgdGhlIGNvbmRpdGlvbnMgb2YgdGhpcyBMaWNlbnNlLCB0aGV5IGRvIG5vdApleGN1c2UgeW91IGZyb20gdGhlIGNvbmRpdGlvbnMgb2YgdGhpcyBMaWNlbnNlLiAgSWYgeW91IGNhbm5vdApkaXN0cmlidXRlIHNvIGFzIHRvIHNhdGlzZnkgc2ltdWx0YW5lb3VzbHkgeW91ciBvYmxpZ2F0aW9ucyB1bmRlciB0aGlzCkxpY2Vuc2UgYW5kIGFueSBvdGhlciBwZXJ0aW5lbnQgb2JsaWdhdGlvbnMsIHRoZW4gYXMgYSBjb25zZXF1ZW5jZSB5b3UKbWF5IG5vdCBkaXN0cmlidXRlIHRoZSBMaWJyYXJ5IGF0IGFsbC4gIEZvciBleGFtcGxlLCBpZiBhIHBhdGVudApsaWNlbnNlIHdvdWxkIG5vdCBwZXJtaXQgcm95YWx0eS1mcmVlIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBMaWJyYXJ5IGJ5CmFsbCB0aG9zZSB3aG8gcmVjZWl2ZSBjb3BpZXMgZGlyZWN0bHkgb3IgaW5kaXJlY3RseSB0aHJvdWdoIHlvdSwgdGhlbgp0aGUgb25seSB3YXkgeW91IGNvdWxkIHNhdGlzZnkgYm90aCBpdCBhbmQgdGhpcyBMaWNlbnNlIHdvdWxkIGJlIHRvCnJlZnJhaW4gZW50aXJlbHkgZnJvbSBkaXN0cmlidXRpb24gb2YgdGhlIExpYnJhcnkuCgpJZiBhbnkgcG9ydGlvbiBvZiB0aGlzIHNlY3Rpb24gaXMgaGVsZCBpbnZhbGlkIG9yIHVuZW5mb3JjZWFibGUgdW5kZXIgYW55CnBhcnRpY3VsYXIgY2lyY3Vtc3RhbmNlLCB0aGUgYmFsYW5jZSBvZiB0aGUgc2VjdGlvbiBpcyBpbnRlbmRlZCB0byBhcHBseSwKYW5kIHRoZSBzZWN0aW9uIGFzIGEgd2hvbGUgaXMgaW50ZW5kZWQgdG8gYXBwbHkgaW4gb3RoZXIgY2lyY3Vtc3RhbmNlcy4KCkl0IGlzIG5vdCB0aGUgcHVycG9zZSBvZiB0aGlzIHNlY3Rpb24gdG8gaW5kdWNlIHlvdSB0byBpbmZyaW5nZSBhbnkKcGF0ZW50cyBvciBvdGhlciBwcm9wZXJ0eSByaWdodCBjbGFpbXMgb3IgdG8gY29udGVzdCB2YWxpZGl0eSBvZiBhbnkKc3VjaCBjbGFpbXM7IHRoaXMgc2VjdGlvbiBoYXMgdGhlIHNvbGUgcHVycG9zZSBvZiBwcm90ZWN0aW5nIHRoZQppbnRlZ3JpdHkgb2YgdGhlIGZyZWUgc29mdHdhcmUgZGlzdHJpYnV0aW9uIHN5c3RlbSB3aGljaCBpcwppbXBsZW1lbnRlZCBieSBwdWJsaWMgbGljZW5zZSBwcmFjdGljZXMuICBNYW55IHBlb3BsZSBoYXZlIG1hZGUKZ2VuZXJvdXMgY29udHJpYnV0aW9ucyB0byB0aGUgd2lkZSByYW5nZSBvZiBzb2Z0d2FyZSBkaXN0cmlidXRlZAp0aHJvdWdoIHRoYXQgc3lzdGVtIGluIHJlbGlhbmNlIG9uIGNvbnNpc3RlbnQgYXBwbGljYXRpb24gb2YgdGhhdApzeXN0ZW07IGl0IGlzIHVwIHRvIHRoZSBhdXRob3IvZG9ub3IgdG8gZGVjaWRlIGlmIGhlIG9yIHNoZSBpcyB3aWxsaW5nCnRvIGRpc3RyaWJ1dGUgc29mdHdhcmUgdGhyb3VnaCBhbnkgb3RoZXIgc3lzdGVtIGFuZCBhIGxpY2Vuc2VlIGNhbm5vdAppbXBvc2UgdGhhdCBjaG9pY2UuCgpUaGlzIHNlY3Rpb24gaXMgaW50ZW5kZWQgdG8gbWFrZSB0aG9yb3VnaGx5IGNsZWFyIHdoYXQgaXMgYmVsaWV2ZWQgdG8KYmUgYSBjb25zZXF1ZW5jZSBvZiB0aGUgcmVzdCBvZiB0aGlzIExpY2Vuc2UuCgogIDEyLiBJZiB0aGUgZGlzdHJpYnV0aW9uIGFuZC9vciB1c2Ugb2YgdGhlIExpYnJhcnkgaXMgcmVzdHJpY3RlZCBpbgpjZXJ0YWluIGNvdW50cmllcyBlaXRoZXIgYnkgcGF0ZW50cyBvciBieSBjb3B5cmlnaHRlZCBpbnRlcmZhY2VzLCB0aGUKb3JpZ2luYWwgY29weXJpZ2h0IGhvbGRlciB3aG8gcGxhY2VzIHRoZSBMaWJyYXJ5IHVuZGVyIHRoaXMgTGljZW5zZSBtYXkgYWRkCmFuIGV4cGxpY2l0IGdlb2dyYXBoaWNhbCBkaXN0cmlidXRpb24gbGltaXRhdGlvbiBleGNsdWRpbmcgdGhvc2UgY291bnRyaWVzLApzbyB0aGF0IGRpc3RyaWJ1dGlvbiBpcyBwZXJtaXR0ZWQgb25seSBpbiBvciBhbW9uZyBjb3VudHJpZXMgbm90IHRodXMKZXhjbHVkZWQuICBJbiBzdWNoIGNhc2UsIHRoaXMgTGljZW5zZSBpbmNvcnBvcmF0ZXMgdGhlIGxpbWl0YXRpb24gYXMgaWYKd3JpdHRlbiBpbiB0aGUgYm9keSBvZiB0aGlzIExpY2Vuc2UuCgogIDEzLiBUaGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIG1heSBwdWJsaXNoIHJldmlzZWQgYW5kL29yIG5ldwp2ZXJzaW9ucyBvZiB0aGUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZnJvbSB0aW1lIHRvIHRpbWUuClN1Y2ggbmV3IHZlcnNpb25zIHdpbGwgYmUgc2ltaWxhciBpbiBzcGlyaXQgdG8gdGhlIHByZXNlbnQgdmVyc2lvbiwKYnV0IG1heSBkaWZmZXIgaW4gZGV0YWlsIHRvIGFkZHJlc3MgbmV3IHByb2JsZW1zIG9yIGNvbmNlcm5zLgoKRWFjaCB2ZXJzaW9uIGlzIGdpdmVuIGEgZGlzdGluZ3Vpc2hpbmcgdmVyc2lvbiBudW1iZXIuICBJZiB0aGUgTGlicmFyeQpzcGVjaWZpZXMgYSB2ZXJzaW9uIG51bWJlciBvZiB0aGlzIExpY2Vuc2Ugd2hpY2ggYXBwbGllcyB0byBpdCBhbmQKImFueSBsYXRlciB2ZXJzaW9uIiwgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiBmb2xsb3dpbmcgdGhlIHRlcm1zIGFuZApjb25kaXRpb25zIGVpdGhlciBvZiB0aGF0IHZlcnNpb24gb3Igb2YgYW55IGxhdGVyIHZlcnNpb24gcHVibGlzaGVkIGJ5CnRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uICBJZiB0aGUgTGlicmFyeSBkb2VzIG5vdCBzcGVjaWZ5IGEKbGljZW5zZSB2ZXJzaW9uIG51bWJlciwgeW91IG1heSBjaG9vc2UgYW55IHZlcnNpb24gZXZlciBwdWJsaXNoZWQgYnkKdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KDAogIDE0LiBJZiB5b3Ugd2lzaCB0byBpbmNvcnBvcmF0ZSBwYXJ0cyBvZiB0aGUgTGlicmFyeSBpbnRvIG90aGVyIGZyZWUKcHJvZ3JhbXMgd2hvc2UgZGlzdHJpYnV0aW9uIGNvbmRpdGlvbnMgYXJlIGluY29tcGF0aWJsZSB3aXRoIHRoZXNlLAp3cml0ZSB0byB0aGUgYXV0aG9yIHRvIGFzayBmb3IgcGVybWlzc2lvbi4gIEZvciBzb2Z0d2FyZSB3aGljaCBpcwpjb3B5cmlnaHRlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCB3cml0ZSB0byB0aGUgRnJlZQpTb2Z0d2FyZSBGb3VuZGF0aW9uOyB3ZSBzb21ldGltZXMgbWFrZSBleGNlcHRpb25zIGZvciB0aGlzLiAgT3VyCmRlY2lzaW9uIHdpbGwgYmUgZ3VpZGVkIGJ5IHRoZSB0d28gZ29hbHMgb2YgcHJlc2VydmluZyB0aGUgZnJlZSBzdGF0dXMKb2YgYWxsIGRlcml2YXRpdmVzIG9mIG91ciBmcmVlIHNvZnR3YXJlIGFuZCBvZiBwcm9tb3RpbmcgdGhlIHNoYXJpbmcKYW5kIHJldXNlIG9mIHNvZnR3YXJlIGdlbmVyYWxseS4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOTyBXQVJSQU5UWQoKICAxNS4gQkVDQVVTRSBUSEUgTElCUkFSWSBJUyBMSUNFTlNFRCBGUkVFIE9GIENIQVJHRSwgVEhFUkUgSVMgTk8KV0FSUkFOVFkgRk9SIFRIRSBMSUJSQVJZLCBUTyBUSEUgRVhURU5UIFBFUk1JVFRFRCBCWSBBUFBMSUNBQkxFIExBVy4KRVhDRVBUIFdIRU4gT1RIRVJXSVNFIFNUQVRFRCBJTiBXUklUSU5HIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQvT1IKT1RIRVIgUEFSVElFUyBQUk9WSURFIFRIRSBMSUJSQVJZICJBUyBJUyIgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkKS0lORCwgRUlUSEVSIEVYUFJFU1NFRCBPUiBJTVBMSUVELCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFCklNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUgpQVVJQT1NFLiAgVEhFIEVOVElSRSBSSVNLIEFTIFRPIFRIRSBRVUFMSVRZIEFORCBQRVJGT1JNQU5DRSBPRiBUSEUKTElCUkFSWSBJUyBXSVRIIFlPVS4gIFNIT1VMRCBUSEUgTElCUkFSWSBQUk9WRSBERUZFQ1RJVkUsIFlPVSBBU1NVTUUKVEhFIENPU1QgT0YgQUxMIE5FQ0VTU0FSWSBTRVJWSUNJTkcsIFJFUEFJUiBPUiBDT1JSRUNUSU9OLgoKICAxNi4gSU4gTk8gRVZFTlQgVU5MRVNTIFJFUVVJUkVEIEJZIEFQUExJQ0FCTEUgTEFXIE9SIEFHUkVFRCBUTyBJTgpXUklUSU5HIFdJTEwgQU5ZIENPUFlSSUdIVCBIT0xERVIsIE9SIEFOWSBPVEhFUiBQQVJUWSBXSE8gTUFZIE1PRElGWQpBTkQvT1IgUkVESVNUUklCVVRFIFRIRSBMSUJSQVJZIEFTIFBFUk1JVFRFRCBBQk9WRSwgQkUgTElBQkxFIFRPIFlPVQpGT1IgREFNQUdFUywgSU5DTFVESU5HIEFOWSBHRU5FUkFMLCBTUEVDSUFMLCBJTkNJREVOVEFMIE9SCkNPTlNFUVVFTlRJQUwgREFNQUdFUyBBUklTSU5HIE9VVCBPRiBUSEUgVVNFIE9SIElOQUJJTElUWSBUTyBVU0UgVEhFCkxJQlJBUlkgKElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gTE9TUyBPRiBEQVRBIE9SIERBVEEgQkVJTkcKUkVOREVSRUQgSU5BQ0NVUkFURSBPUiBMT1NTRVMgU1VTVEFJTkVEIEJZIFlPVSBPUiBUSElSRCBQQVJUSUVTIE9SIEEKRkFJTFVSRSBPRiBUSEUgTElCUkFSWSBUTyBPUEVSQVRFIFdJVEggQU5ZIE9USEVSIFNPRlRXQVJFKSwgRVZFTiBJRgpTVUNIIEhPTERFUiBPUiBPVEhFUiBQQVJUWSBIQVMgQkVFTiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNICkRBTUFHRVMuCgogICAgICAgICAgICAgICAgICAgICBFTkQgT0YgVEVSTVMgQU5EIENPTkRJVElPTlMKDAogICAgICAgICAgIEhvdyB0byBBcHBseSBUaGVzZSBUZXJtcyB0byBZb3VyIE5ldyBMaWJyYXJpZXMKCiAgSWYgeW91IGRldmVsb3AgYSBuZXcgbGlicmFyeSwgYW5kIHlvdSB3YW50IGl0IHRvIGJlIG9mIHRoZSBncmVhdGVzdApwb3NzaWJsZSB1c2UgdG8gdGhlIHB1YmxpYywgd2UgcmVjb21tZW5kIG1ha2luZyBpdCBmcmVlIHNvZnR3YXJlIHRoYXQKZXZlcnlvbmUgY2FuIHJlZGlzdHJpYnV0ZSBhbmQgY2hhbmdlLiAgWW91IGNhbiBkbyBzbyBieSBwZXJtaXR0aW5nCnJlZGlzdHJpYnV0aW9uIHVuZGVyIHRoZXNlIHRlcm1zIChvciwgYWx0ZXJuYXRpdmVseSwgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZQpvcmRpbmFyeSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlKS4KCiAgVG8gYXBwbHkgdGhlc2UgdGVybXMsIGF0dGFjaCB0aGUgZm9sbG93aW5nIG5vdGljZXMgdG8gdGhlIGxpYnJhcnkuICBJdCBpcwpzYWZlc3QgdG8gYXR0YWNoIHRoZW0gdG8gdGhlIHN0YXJ0IG9mIGVhY2ggc291cmNlIGZpbGUgdG8gbW9zdCBlZmZlY3RpdmVseQpjb252ZXkgdGhlIGV4Y2x1c2lvbiBvZiB3YXJyYW50eTsgYW5kIGVhY2ggZmlsZSBzaG91bGQgaGF2ZSBhdCBsZWFzdCB0aGUKImNvcHlyaWdodCIgbGluZSBhbmQgYSBwb2ludGVyIHRvIHdoZXJlIHRoZSBmdWxsIG5vdGljZSBpcyBmb3VuZC4KCiAgICA8b25lIGxpbmUgdG8gZ2l2ZSB0aGUgbGlicmFyeSdzIG5hbWUgYW5kIGEgYnJpZWYgaWRlYSBvZiB3aGF0IGl0IGRvZXMuPgogICAgQ29weXJpZ2h0IChDKSA8eWVhcj4gIDxuYW1lIG9mIGF1dGhvcj4KCiAgICBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAgICBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICAgIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgoKICAgIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICAgIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAgICBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgoKICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICAgIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uCgpBbHNvIGFkZCBpbmZvcm1hdGlvbiBvbiBob3cgdG8gY29udGFjdCB5b3UgYnkgZWxlY3Ryb25pYyBhbmQgcGFwZXIgbWFpbC4KCllvdSBzaG91bGQgYWxzbyBnZXQgeW91ciBlbXBsb3llciAoaWYgeW91IHdvcmsgYXMgYSBwcm9ncmFtbWVyKSBvciB5b3VyCnNjaG9vbCwgaWYgYW55LCB0byBzaWduIGEgImNvcHlyaWdodCBkaXNjbGFpbWVyIiBmb3IgdGhlIGxpYnJhcnksIGlmCm5lY2Vzc2FyeS4gIEhlcmUgaXMgYSBzYW1wbGU7IGFsdGVyIHRoZSBuYW1lczoKCiAgWW95b2R5bmUsIEluYy4sIGhlcmVieSBkaXNjbGFpbXMgYWxsIGNvcHlyaWdodCBpbnRlcmVzdCBpbiB0aGUKICBsaWJyYXJ5IGBGcm9iJyAoYSBsaWJyYXJ5IGZvciB0d2Vha2luZyBrbm9icykgd3JpdHRlbiBieSBKYW1lcyBSYW5kb20gSGFja2VyLgoKICA8c2lnbmF0dXJlIG9mIE1vZSBHaG91bD4sIDEgQXByaWwgMTk5MAogIE1vZSBHaG91bCwgUHJlc2lkZW50IG9mIFZpY2UKClRoYXQncyBhbGwgdGhlcmUgaXMgdG8gaXQhCg==", "5d4873884a890122a4b9b20ad56ac6f7da1d796a5bfcf04a427970ac96217626": "RXhjZXB0IHdoZXJlIG90aGVyd2lzZSBub3RlZCBpbiB0aGUgc291cmNlIGNvZGUgKGUuZy4gdGhlIGZpbGVzIGRpY3QuYyBhbmQKbGlzdC5jLCB3aGljaCBhcmUgY292ZXJlZCBieSBhIHNpbWlsYXIgbGljZW5jZSBidXQgd2l0aCBkaWZmZXJlbnQgQ29weXJpZ2h0Cm5vdGljZXMpIGFsbCB0aGUgZmlsZXMgYXJlOgoKIENvcHlyaWdodCAoQykgMTk5OC0yMDEyIERhbmllbCBWZWlsbGFyZC4gIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiBDb3B5cmlnaHQgKEMpIFRoZSBMaWJ4bWwyIENvbnRyaWJ1dG9ycy4KClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXItCm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CgpUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbgphbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4KClRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCklNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVQtCk5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuICBJTiBOTyBFVkVOVCBTSEFMTCBUSEUKQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgpMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLApPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOClRIRSBTT0ZUV0FSRS4K", "6a8f30793e877d32e3f88b972f0970a051a3b5a26cd057d3993cb51e21c43319": "CkFsbCBzb3VyY2UsIGRhdGEgZmlsZXMgYW5kIG90aGVyIGNvbnRlbnRzIG9mIHRoZSBQUk9KIHBhY2thZ2UgYXJlIAphdmFpbGFibGUgdW5kZXIgdGhlIGZvbGxvd2luZyB0ZXJtcy4gIE5vdGUgdGhhdCB0aGUgUFJPSiA0LjMgYW5kIGVhcmxpZXIKd2FzICJwdWJsaWMgZG9tYWluIiBhcyBpcyBjb21tb24gd2l0aCBVUyBnb3Zlcm5tZW50IHdvcmssIGJ1dCBhcHBhcmVudGx5CnRoaXMgaXMgbm90IGEgd2VsbCBkZWZpbmVkIGxlZ2FsIHRlcm0gaW4gbWFueSBjb3VudHJpZXMuIEZyYW5rIFdhcm1lcmRhbSBwbGFjZWQKZXZlcnl0aGluZyB1bmRlciB0aGUgZm9sbG93aW5nIE1JVCBzdHlsZSBsaWNlbnNlIGJlY2F1c2UgaGUgYmVsaWV2ZWQgaXQgaXMKZWZmZWN0aXZlbHkgdGhlIHNhbWUgYXMgcHVibGljIGRvbWFpbiwgYWxsb3dpbmcgYW55b25lIHRvIHVzZSB0aGUgY29kZSBhcwp0aGV5IHdpc2gsIGluY2x1ZGluZyBtYWtpbmcgcHJvcHJpZXRhcnkgZGVyaXZhdGl2ZXMuCgpJbml0aWFsIFBST0ogNC4zIHB1YmxpYyBkb21haW4gY29kZSB3YXMgcHV0IGFzIEZyYW5rIFdhcm1lcmRhbSBhcyBjb3B5cmlnaHQKaG9sZGVyLCBidXQgaGUgZGlkbid0IG1lYW4gdG8gaW1wbHkgaGUgZGlkIHRoZSB3b3JrLiBFc3NlbnRpYWxseSBhbGwgd29yayB3YXMKZG9uZSBieSBHZXJhbGQgRXZlbmRlbi4KCkNvcHlyaWdodCBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQgaW4gc291cmNlIGZpbGVzLgoKIC0tLS0tLS0tLS0tLS0tCgogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEKIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCiB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwKIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKCiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZAogaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MKIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwKIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORwogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUgogREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgo=", diff --git a/src/extensions/external/vector/.release-semantic-inputs.json b/src/extensions/external/vector/.release-semantic-inputs.json index baf87a34..b2dfcfb5 100644 --- a/src/extensions/external/vector/.release-semantic-inputs.json +++ b/src/extensions/external/vector/.release-semantic-inputs.json @@ -184,7 +184,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -343,5 +343,5 @@ ] } ], - "sha256": "f97b62f53ca3ddf959883c4f057a4a077b08a9f0529169768bc426468a8b5d27" + "sha256": "bbbc8601954d8ad75eefa03a0749eae7e6ba1aee98828b90153504bfe4d49276" } diff --git a/src/extensions/generated/docs/extension-evidence.json b/src/extensions/generated/docs/extension-evidence.json index 80431e38..39963852 100644 --- a/src/extensions/generated/docs/extension-evidence.json +++ b/src/extensions/generated/docs/extension-evidence.json @@ -1347,7 +1347,7 @@ "current-source-status": "requires-exact-candidate-ci", "kind": "exact-sha-ci" }, - "source-digest": "sha256:d30cde83f40642f68c2dd7f2b1fe1bf1a9ca05122a7a6232fca42d624a06fed2", + "source-digest": "sha256:c5c4209245d495e274c9241f5f3114cc2bf1ad6340c47f98f334894a1851f513", "source-digest-inputs": [ "src/postgres/versions/18/source.toml", "src/extensions/catalog/extensions.promoted.toml", @@ -1365,6 +1365,7 @@ "src/extensions/external/pg_textsearch/source.toml", "src/extensions/external/pg_uuidv7/source.toml", "src/extensions/external/pgtap/source.toml", + "src/extensions/external/postgis/dependencies/gdal/source.toml", "src/extensions/external/postgis/dependencies/geos/source.toml", "src/extensions/external/postgis/dependencies/json-c/source.toml", "src/extensions/external/postgis/dependencies/libiconv/source.toml", diff --git a/src/extensions/generated/docs/extensions.json b/src/extensions/generated/docs/extensions.json index 0f3e37d3..3c0a806d 100644 --- a/src/extensions/generated/docs/extensions.json +++ b/src/extensions/generated/docs/extensions.json @@ -1037,6 +1037,7 @@ "id": "postgis", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1077,7 +1078,7 @@ "native": "supported", "wasix": "supported" }, - "version": "3.6.3" + "version": "3.6.4" }, { "activation": "CREATE EXTENSION", diff --git a/src/extensions/generated/extensions.build-plan.json b/src/extensions/generated/extensions.build-plan.json index d69ddb6b..1a1949ad 100644 --- a/src/extensions/generated/extensions.build-plan.json +++ b/src/extensions/generated/extensions.build-plan.json @@ -1079,11 +1079,15 @@ "required-build-files": [ "postgis/postgis-3.so", "postgis/liboliphaunt_postgis_deps.so", + "raster/rt_pg/postgis_raster-3.so", "extensions/postgis/postgis.control", + "extensions/postgis_raster/postgis_raster.control", + "share/gdal/gdalvrt.xsd", "share/proj/proj.db" ], "required-build-globs": [ - "extensions/postgis/sql/postgis--*.sql" + "extensions/postgis/sql/postgis--*.sql", + "extensions/postgis_raster/sql/postgis_raster--*.sql" ], "source-dir": "target/oliphaunt-sources/checkouts/postgis", "module-file": "postgis-3.so", @@ -1092,6 +1096,7 @@ "stable": true, "dependencies": [], "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1105,12 +1110,17 @@ "runtime-path": "lib/postgresql/liboliphaunt_postgis_deps.so", "build-path": "postgis/postgis/liboliphaunt_postgis_deps.so", "aot-file": "postgis_deps-llvm-opta.bin.zst" + }, + { + "name": "postgis_raster", + "runtime-path": "lib/postgresql/postgis_raster-3.so", + "build-path": "postgis/raster/rt_pg/postgis_raster-3.so", + "aot-file": "postgis_raster-llvm-opta.bin.zst" } ], "excluded-sql-extensions": [ "address_standardizer", "address_standardizer_data_us", - "postgis_raster", "postgis_sfcgal", "postgis_tiger_geocoder", "postgis_topology" @@ -1123,6 +1133,14 @@ { "source": "postgis/share/proj", "destination": "share/proj" + }, + { + "source": "postgis/share/gdal", + "destination": "share/postgresql/gdal" + }, + { + "source": "postgis/share/extension-raster", + "destination": "share/postgresql/extension" } ] }, diff --git a/src/extensions/generated/extensions.catalog.json b/src/extensions/generated/extensions.catalog.json index 0da53898..6ac74d08 100644 --- a/src/extensions/generated/extensions.catalog.json +++ b/src/extensions/generated/extensions.catalog.json @@ -1724,16 +1724,17 @@ "postgres extension", "experimental" ], - "bundle-size": 8551161, + "bundle-size": 11490267, "control-file": "target/oliphaunt-sources/checkouts/postgis/extensions/postgis/postgis.control.in", "control": { - "default-version": "3.6.3", + "default-version": "3.6.4", "module-pathname": "@MODULEPATH@", "requires": [], "relocatable": "false" }, "dependencies": [], "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1770,7 +1771,7 @@ "promoted": true, "stable": true, "archive": "extensions/postgis.tar.zst", - "module-sha256": "2a0d7432348cfae67e7736687e4638d60f2df05ddcbc870ef44921940feb35d4" + "module-sha256": "791e5863374a7ac63a07dd2689b734d030ecf1bea2df8fa1a77d3eaca81436bd" }, "notes": [] }, diff --git a/src/extensions/generated/mobile/static-extensions.tsv b/src/extensions/generated/mobile/static-extensions.tsv index e2e9f500..7c7816a8 100644 --- a/src/extensions/generated/mobile/static-extensions.tsv +++ b/src/extensions/generated/mobile/static-extensions.tsv @@ -29,7 +29,7 @@ pg_uuidv7 pg_uuidv7 external target/oliphaunt-sources/checkouts/pg_uuidv7 pg_visibility pg_visibility contrib contrib/pg_visibility pg_walinspect pg_walinspect contrib contrib/pg_walinspect pgcrypto pgcrypto contrib contrib/pgcrypto openssl openssl openssl openssl openssl openssl openssl -postgis postgis-3 external target/oliphaunt-sources/checkouts/postgis geos,geos-c,json-c,libcharset,libiconv,libxml2,proj,sqlite geos,geos-c,json-c,libxml2,proj,sqlite geos,geos-c,json-c,libcharset,libiconv,libxml2,proj,sqlite geos,json-c,libiconv,libxml2,proj,sqlite geos,json-c,libxml2,proj,sqlite geos,json-c,libiconv,libxml2,proj,sqlite +postgis postgis-3 external target/oliphaunt-sources/checkouts/postgis gdal,geos,geos-c,json-c,libcharset,libiconv,libxml2,proj,sqlite gdal,geos,geos-c,json-c,libxml2,proj,sqlite gdal,geos,geos-c,json-c,libcharset,libiconv,libxml2,proj,sqlite gdal,geos,json-c,libiconv,libxml2,proj,sqlite gdal,geos,json-c,libxml2,proj,sqlite gdal,geos,json-c,libiconv,libxml2,proj,sqlite seg seg contrib contrib/seg tablefunc tablefunc contrib contrib/tablefunc tcn tcn contrib contrib/tcn diff --git a/src/extensions/generated/mobile/static-registry.json b/src/extensions/generated/mobile/static-registry.json index 405a0943..cd7b4ae1 100644 --- a/src/extensions/generated/mobile/static-registry.json +++ b/src/extensions/generated/mobile/static-registry.json @@ -257,10 +257,37 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "id": "postgis", "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", diff --git a/src/extensions/generated/sdk/js.json b/src/extensions/generated/sdk/js.json index 3c6a277b..632c3405 100644 --- a/src/extensions/generated/sdk/js.json +++ b/src/extensions/generated/sdk/js.json @@ -1,6 +1,6 @@ { "consumer": "js", - "extension-catalog-sha256": "cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7", + "extension-catalog-sha256": "2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1112,6 +1112,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1123,6 +1149,7 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", @@ -1130,6 +1157,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1144,6 +1172,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1159,6 +1192,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/extensions/generated/sdk/kotlin.json b/src/extensions/generated/sdk/kotlin.json index 43d02622..113c17b9 100644 --- a/src/extensions/generated/sdk/kotlin.json +++ b/src/extensions/generated/sdk/kotlin.json @@ -1,6 +1,6 @@ { "consumer": "kotlin", - "extension-catalog-sha256": "cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7", + "extension-catalog-sha256": "2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1112,6 +1112,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1123,6 +1149,7 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", @@ -1130,6 +1157,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1144,6 +1172,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1159,6 +1192,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/extensions/generated/sdk/react-native.json b/src/extensions/generated/sdk/react-native.json index a1818fd5..ba6b3437 100644 --- a/src/extensions/generated/sdk/react-native.json +++ b/src/extensions/generated/sdk/react-native.json @@ -1,6 +1,6 @@ { "consumer": "react-native", - "extension-catalog-sha256": "112d2060de12e08bf955c9f0f487b075f4ddb7273cb8130f60dc629733b4d4db", + "extension-catalog-sha256": "ec3c183ad919eff787020841ec9f02730a9956db663a8d4b40b61758359860dc", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1144,6 +1144,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1155,10 +1181,12 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", "ios-static-dependencies": [ + "gdal", "geos", "geos-c", "json-c", @@ -1170,6 +1198,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1184,6 +1213,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1199,6 +1233,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/extensions/generated/sdk/rust.json b/src/extensions/generated/sdk/rust.json index b3899171..eb375f0b 100644 --- a/src/extensions/generated/sdk/rust.json +++ b/src/extensions/generated/sdk/rust.json @@ -1,6 +1,6 @@ { "consumer": "rust", - "extension-catalog-sha256": "cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7", + "extension-catalog-sha256": "2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1112,6 +1112,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1123,6 +1149,7 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", @@ -1130,6 +1157,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1144,6 +1172,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1159,6 +1192,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/extensions/generated/sdk/swift.json b/src/extensions/generated/sdk/swift.json index fd63792e..6a234cc1 100644 --- a/src/extensions/generated/sdk/swift.json +++ b/src/extensions/generated/sdk/swift.json @@ -1,6 +1,6 @@ { "consumer": "swift", - "extension-catalog-sha256": "cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7", + "extension-catalog-sha256": "2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1112,6 +1112,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1123,6 +1149,7 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", @@ -1130,6 +1157,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1144,6 +1172,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1159,6 +1192,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/extensions/generated/wasix/extensions.json b/src/extensions/generated/wasix/extensions.json index 5da9f54d..ac66ccad 100644 --- a/src/extensions/generated/wasix/extensions.json +++ b/src/extensions/generated/wasix/extensions.json @@ -602,6 +602,12 @@ "build-path": "postgis/postgis/liboliphaunt_postgis_deps.so", "name": "postgis_deps", "runtime-path": "lib/postgresql/liboliphaunt_postgis_deps.so" + }, + { + "aot-file": "postgis_raster-llvm-opta.bin.zst", + "build-path": "postgis/raster/rt_pg/postgis_raster-3.so", + "name": "postgis_raster", + "runtime-path": "lib/postgresql/postgis_raster-3.so" } ], "sql-name": "postgis" diff --git a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json index 455ec844..248f4424 100644 --- a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json +++ b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json @@ -104,7 +104,7 @@ "inputs": [ { "path": "src/extensions/external/postgis/source.toml", - "sha256": "cd720f3bae015515639273795df9fb6be6ba2ad7c9d6714d1b1e330643c33040" + "sha256": "f9f6168aa0733aa64b59c61e1592c7bc2c337defb981569bce87a70f7f185934" }, { "path": "src/extensions/external/postgis/tools/reproducible-bin/date", @@ -319,7 +319,7 @@ }, { "path": "src/sdks/rust/src/generated/extensions.rs", - "sha256": "d68a58370ffd30d3c9082f7a90c25de29386fc22f4fa9e58540b76fefd5e5c2d" + "sha256": "508db44d433b395dab368a411be7219631f3f8e50664f98a5aae7941b52ceab1" }, { "path": "src/sdks/rust/src/lib.rs", @@ -339,7 +339,7 @@ }, { "path": "src/sdks/rust/src/liboliphaunt/root/extensions.rs", - "sha256": "7c00ef165b6261e051fdb3396a13d9338862d7f09ab093dff8b777013dda909b" + "sha256": "55363b84571d596e5dae07d1fa911896428403409145e2906e3951e787df6b5b" }, { "path": "src/sdks/rust/src/liboliphaunt/root/files.rs", @@ -371,7 +371,7 @@ }, { "path": "src/sdks/rust/src/runtime_resources.rs", - "sha256": "35a488818a700b0304758261348ef64590510f3a65ba6119d43dbecbab92b94e" + "sha256": "692238b38e26ea3e0e7f31201137fb598de7b3f128ca4e5f9bcfea0c045127b2" }, { "path": "src/sdks/rust/src/runtime_resources/extension_artifact.rs", @@ -457,5 +457,5 @@ ] } ], - "sha256": "abdff456e32ce1bb7af0733277f8f4578b6fa2e334046c7f63358aaa64d91d6c" + "sha256": "f6482c0e8ce42218eebd81c2324168004855b260a6ba4ae59f3616dab7bd4489" } diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-linux.sh b/src/runtimes/liboliphaunt/native/bin/build-postgres18-linux.sh index b962d45c..cb5d959b 100755 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-linux.sh +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-linux.sh @@ -150,6 +150,7 @@ required_extension_controls=( pg_ivm pgcrypto postgis + postgis_raster pg_surgery pg_textsearch pg_trgm @@ -192,6 +193,7 @@ required_extension_modules=( pg_ivm pgcrypto postgis-3 + postgis_raster-3 pg_surgery pg_textsearch pg_trgm @@ -256,6 +258,8 @@ filter_native_extension_selection() { postgis) selected_external+=(postgis) module_file="postgis-3.so" + selected_controls+=(postgis_raster) + selected_modules+=(postgis_raster-3) ;; *) external_id="$(awk -F '\t' -v sql="$sql" 'NR > 1 && $2 == sql { print $1; found = 1; exit } END { exit found ? 0 : 1 }' "$pgxs_plan" || true)" @@ -449,9 +453,17 @@ hash_extension_source_tree() { -name "meson_options.txt" \ \) -print | LC_ALL=C sort | - while IFS= read -r file; do - shasum -a 256 "$file" - done + ( + set -- + while IFS= read -r file; do + set -- "$@" "$file" + if [ "$#" -ge 256 ]; then + shasum -a 256 "$@" + set -- + fi + done + [ "$#" -eq 0 ] || shasum -a 256 "$@" + ) } exact_checkout_identity() { @@ -519,7 +531,7 @@ extension_build_fingerprint() { shasum -a 256 \ "$postgis_time_helper" \ "$repo_root/src/extensions/external/postgis/tools/reproducible-bin/date" - for dependency in geos proj sqlite json-c libxml2; do + for dependency in gdal geos proj sqlite json-c libxml2; do if [ -d "$repo_root/target/oliphaunt-sources/checkouts/$dependency" ]; then printf 'postgis-dependency:%s\n' "$dependency" local dependency_checkout="$repo_root/target/oliphaunt-sources/checkouts/$dependency" @@ -1157,6 +1169,7 @@ build_pgxs_extension() { native_postgis_dependency_root="${OLIPHAUNT_NATIVE_POSTGIS_DEPENDENCY_ROOT:-$work_root/postgis-native-dependencies}" native_postgis_dependency_build_roots=( + "$work_root/gdal-native-build" "$work_root/json-c-native-build" "$work_root/sqlite-native-build" "$work_root/geos-native-build" @@ -1164,6 +1177,9 @@ native_postgis_dependency_build_roots=( "$work_root/proj-native-build" ) native_postgis_dependency_required_outputs=( + "$native_postgis_dependency_root/gdal/bin/gdal-config" + "$native_postgis_dependency_root/gdal/include/gdal.h" + "$native_postgis_dependency_root/gdal/lib/libgdal.a" "$native_postgis_dependency_root/json-c/lib/libjson-c.a" "$native_postgis_dependency_root/sqlite/lib/libsqlite3.a" "$native_postgis_dependency_root/geos/lib/libgeos_c.a" @@ -1213,7 +1229,7 @@ native_postgis_dependency_fingerprint() { shasum -a 256 "$source_manifest" local dependency source_dir - for dependency in geos proj sqlite json-c libxml2; do + for dependency in gdal geos proj sqlite json-c libxml2; do source_dir="$repo_root/target/oliphaunt-sources/checkouts/$dependency" exact_checkout_identity "dependency.$dependency" "$source_dir" || return 1 hash_extension_source_tree "$source_dir" @@ -1352,6 +1368,61 @@ build_native_postgis_proj_dependency() { [ -f "$dependency_dir/share/proj/proj.db" ] || fail "PROJ build did not produce proj.db" } +build_native_postgis_gdal_dependency() { + local source_dir="$repo_root/target/oliphaunt-sources/checkouts/gdal" + local dependency_dir="$native_postgis_dependency_root/gdal" + local geos_dir="$native_postgis_dependency_root/geos" + local jsonc_dir="$native_postgis_dependency_root/json-c" + local libxml2_dir="$native_postgis_dependency_root/libxml2" + local proj_dir="$native_postgis_dependency_root/proj" + local sqlite_dir="$native_postgis_dependency_root/sqlite" + local build_root="$work_root/gdal-native-build" + local archive="$dependency_dir/lib/libgdal.a" + [ -f "$archive" ] && [ -f "$dependency_dir/include/gdal.h" ] && [ -x "$dependency_dir/bin/gdal-config" ] && return 0 + [ -f "$source_dir/CMakeLists.txt" ] || fail "missing GDAL checkout: $source_dir" + [ -f "$proj_dir/lib/libproj.a" ] || fail "GDAL dependency requires PROJ first" + rm -rf "$build_root" "$dependency_dir" + native_postgis_cmake_install "$source_dir" "$build_root" "$dependency_dir" \ + -DBASH_COMPLETIONS_DIR= \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_CSHARP_BINDINGS=OFF \ + -DBUILD_JAVA_BINDINGS=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF \ + -DBUILD_TESTING=OFF \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_ENABLE_DRIVER_GTIFF=ON \ + -DGDAL_ENABLE_DRIVER_VRT=ON \ + -DOGR_ENABLE_DRIVER_GEOJSON=ON \ + -DOGR_ENABLE_DRIVER_SHAPE=ON \ + -DGDAL_USE_EXTERNAL_LIBS=OFF \ + -DGDAL_USE_INTERNAL_LIBS=ON \ + -DGDAL_USE_OPENMP=OFF \ + -DGDAL_USE_CURL=OFF \ + -DGDAL_USE_OPENSSL=OFF \ + -DGDAL_USE_GEOS=ON \ + "-DGEOS_INCLUDE_DIR=$geos_dir/include" \ + "-DGEOS_LIBRARY=$geos_dir/lib/libgeos_c.a" \ + -DGDAL_USE_JSONC=ON \ + -DGDAL_USE_JSONC_INTERNAL=OFF \ + "-DJSONC_INCLUDE_DIR=$jsonc_dir/include/json-c" \ + "-DJSONC_LIBRARY=$jsonc_dir/lib/libjson-c.a" \ + -DGDAL_USE_LIBXML2=ON \ + "-DLIBXML2_INCLUDE_DIR=$libxml2_dir/include/libxml2" \ + "-DLIBXML2_LIBRARY=$libxml2_dir/lib/libxml2.a" \ + -DGDAL_USE_PROJ=ON \ + "-DPROJ_INCLUDE_DIR=$proj_dir/include" \ + "-DPROJ_LIBRARY=$proj_dir/lib/libproj.a" \ + -DGDAL_USE_SQLITE3=ON \ + "-DSQLite3_INCLUDE_DIR=$sqlite_dir/include" \ + "-DSQLite3_LIBRARY=$sqlite_dir/lib/libsqlite3.a" \ + -DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON + [ -f "$archive" ] || fail "GDAL build did not produce $archive" + [ -x "$dependency_dir/bin/gdal-config" ] || fail "GDAL build did not produce gdal-config" +} + build_native_postgis_dependencies() { native_postgis_require_tools local wanted @@ -1367,6 +1438,7 @@ build_native_postgis_dependencies() { build_native_postgis_geos_dependency build_native_postgis_libxml2_dependency build_native_postgis_proj_dependency + build_native_postgis_gdal_dependency oliphaunt_postgis_dependency_cache_commit \ "$native_postgis_dependency_root" \ "$wanted" \ @@ -1388,6 +1460,24 @@ EOF chmod +x "$path" } +native_postgis_gdal_config_script() { + local path="$1" + local real_config="$native_postgis_dependency_root/gdal/bin/gdal-config" + local real_libs + real_libs="$("$real_config" --libs)" + cat > "$path" < "$path" <> "$make_log" 2>&1 make -C doc CC="$native_cc" "${postgis_make_args[@]}" comments-install >> "$make_log" 2>&1 make -j"$jobs" -C postgis CC="$native_cc" "${postgis_make_args[@]}" install >> "$make_log" 2>&1 + make -j"$jobs" -C raster/rt_core CC="$native_cc" "${postgis_make_args[@]}" all >> "$make_log" 2>&1 + make -j"$jobs" -C raster/rt_pg CC="$native_cc" BE_DLLLIBS="$normal_module_be_dllibs" "${postgis_make_args[@]}" install >> "$make_log" 2>&1 make -j1 -C extensions CC="$native_cc" "${postgis_make_args[@]}" all >> "$make_log" 2>&1 make -j1 -C extensions CC="$native_cc" "${postgis_make_args[@]}" install >> "$make_log" 2>&1 make -C postgis clean >> "$make_log" 2>&1 || true make postgis_revision.h >> "$make_log" 2>&1 make -j"$jobs" -C postgis CC="$native_cc" CFLAGS="$native_cflags" BE_DLLLIBS="$embedded_module_be_dllibs" "${postgis_make_args[@]}" all >> "$make_log" 2>&1 + make -C raster/rt_pg clean >> "$make_log" 2>&1 || true + make -j"$jobs" -C raster/rt_pg CC="$native_cc" CFLAGS="$native_cflags" BE_DLLLIBS="$embedded_module_be_dllibs" "${postgis_make_args[@]}" all >> "$make_log" 2>&1 ) - copy_embedded_postgis_module "$postgis_build_dir/postgis" + copy_embedded_postgis_module "$postgis_build_dir/postgis" postgis-3 + copy_embedded_postgis_module "$postgis_build_dir/raster/rt_pg" postgis_raster-3 stage_postgis_data_files "$postgis_build_dir" } @@ -1684,7 +1786,8 @@ case "$script_mode" in configure_source install_runtime prune_base_runtime_optional_extensions - if artifact_ready && + if [ "${OLIPHAUNT_FORCE_EXTENSION_REBUILD:-0}" != "1" ] && + artifact_ready && (cd "$build_dir" && backend_objects_ready && plpgsql_objects_ready && jit_objects_ready) && [ -f "$stamp" ] && [ "$(cat "$stamp")" = "$(desired_hash)" ]; then diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-macos.sh b/src/runtimes/liboliphaunt/native/bin/build-postgres18-macos.sh index 2220d860..f420329d 100755 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-macos.sh +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-macos.sh @@ -134,6 +134,7 @@ required_extension_controls=( pg_ivm pgcrypto postgis + postgis_raster pg_surgery pg_textsearch pg_trgm @@ -176,6 +177,7 @@ required_extension_modules=( pg_ivm pgcrypto postgis-3 + postgis_raster-3 pg_surgery pg_textsearch pg_trgm @@ -240,6 +242,8 @@ filter_native_extension_selection() { postgis) selected_external+=(postgis) module_file="postgis-3.so" + selected_controls+=(postgis_raster) + selected_modules+=(postgis_raster-3) ;; *) external_id="$(awk -F '\t' -v sql="$sql" 'NR > 1 && $2 == sql { print $1; found = 1; exit } END { exit found ? 0 : 1 }' "$pgxs_plan" || true)" @@ -829,9 +833,17 @@ hash_extension_source_tree() { -name "meson_options.txt" \ \) -print | LC_ALL=C sort | - while IFS= read -r file; do - shasum -a 256 "$file" - done + ( + set -- + while IFS= read -r file; do + set -- "$@" "$file" + if [ "$#" -ge 256 ]; then + shasum -a 256 "$@" + set -- + fi + done + [ "$#" -eq 0 ] || shasum -a 256 "$@" + ) } native_postgis_dependency_fingerprint() { @@ -853,7 +865,7 @@ native_postgis_dependency_fingerprint() { shasum -a 256 "$source_manifest" local dependency source_dir - for dependency in geos proj sqlite json-c libxml2; do + for dependency in gdal geos proj sqlite json-c libxml2; do source_dir="$repo_root/target/oliphaunt-sources/checkouts/$dependency" exact_checkout_identity "postgis_dependency.$dependency" "$source_dir" || return 1 hash_extension_source_tree "$source_dir" @@ -924,7 +936,7 @@ extension_build_fingerprint() { shasum -a 256 \ "$postgis_time_helper" \ "$repo_root/src/extensions/external/postgis/tools/reproducible-bin/date" - for dependency in geos proj sqlite json-c libxml2; do + for dependency in gdal geos proj sqlite json-c libxml2; do if [ -d "$repo_root/target/oliphaunt-sources/checkouts/$dependency" ]; then printf 'postgis-dependency:%s\n' "$dependency" local dependency_checkout="$repo_root/target/oliphaunt-sources/checkouts/$dependency" @@ -1512,6 +1524,7 @@ audit_packaged_extension_modules() { native_postgis_dependency_root="${OLIPHAUNT_NATIVE_POSTGIS_DEPENDENCY_ROOT:-$work_root/postgis-native-dependencies}" native_postgis_dependency_build_roots=( + "$work_root/gdal-native-build" "$work_root/json-c-native-build" "$work_root/sqlite-native-build" "$work_root/geos-native-build" @@ -1519,6 +1532,9 @@ native_postgis_dependency_build_roots=( "$work_root/proj-native-build" ) native_postgis_dependency_required_outputs=( + "$native_postgis_dependency_root/gdal/bin/gdal-config" + "$native_postgis_dependency_root/gdal/include/gdal.h" + "$native_postgis_dependency_root/gdal/lib/libgdal.a" "$native_postgis_dependency_root/json-c/lib/libjson-c.a" "$native_postgis_dependency_root/sqlite/lib/libsqlite3.a" "$native_postgis_dependency_root/geos/lib/libgeos_c.a" @@ -1726,6 +1742,65 @@ build_native_postgis_proj_dependency() { native_postgis_dependency_archive proj "$archive" } +build_native_postgis_gdal_dependency() { + local source_dir="$repo_root/target/oliphaunt-sources/checkouts/gdal" + local dependency_dir="$native_postgis_dependency_root/gdal" + local geos_dir="$native_postgis_dependency_root/geos" + local jsonc_dir="$native_postgis_dependency_root/json-c" + local libxml2_dir="$native_postgis_dependency_root/libxml2" + local proj_dir="$native_postgis_dependency_root/proj" + local sqlite_dir="$native_postgis_dependency_root/sqlite" + local build_root="$work_root/gdal-native-build" + local archive="$dependency_dir/lib/libgdal.a" + if [ -f "$archive" ] && [ -f "$dependency_dir/include/gdal.h" ] && [ -x "$dependency_dir/bin/gdal-config" ]; then + native_postgis_dependency_archive gdal "$archive" + return 0 + fi + [ -f "$source_dir/CMakeLists.txt" ] || native_postgis_fail "missing GDAL checkout: $source_dir" + [ -f "$proj_dir/lib/libproj.a" ] || native_postgis_fail "GDAL dependency requires PROJ first" + rm -rf "$build_root" "$dependency_dir" + native_postgis_cmake_install "$source_dir" "$build_root" "$dependency_dir" \ + -DBASH_COMPLETIONS_DIR= \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_CSHARP_BINDINGS=OFF \ + -DBUILD_JAVA_BINDINGS=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF \ + -DBUILD_TESTING=OFF \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_ENABLE_DRIVER_GTIFF=ON \ + -DGDAL_ENABLE_DRIVER_VRT=ON \ + -DOGR_ENABLE_DRIVER_GEOJSON=ON \ + -DOGR_ENABLE_DRIVER_SHAPE=ON \ + -DGDAL_USE_EXTERNAL_LIBS=OFF \ + -DGDAL_USE_INTERNAL_LIBS=ON \ + -DGDAL_USE_OPENMP=OFF \ + -DGDAL_USE_CURL=OFF \ + -DGDAL_USE_OPENSSL=OFF \ + -DGDAL_USE_GEOS=ON \ + "-DGEOS_INCLUDE_DIR=$geos_dir/include" \ + "-DGEOS_LIBRARY=$geos_dir/lib/libgeos_c.a" \ + -DGDAL_USE_JSONC=ON \ + -DGDAL_USE_JSONC_INTERNAL=OFF \ + "-DJSONC_INCLUDE_DIR=$jsonc_dir/include/json-c" \ + "-DJSONC_LIBRARY=$jsonc_dir/lib/libjson-c.a" \ + -DGDAL_USE_LIBXML2=ON \ + "-DLIBXML2_INCLUDE_DIR=$libxml2_dir/include/libxml2" \ + "-DLIBXML2_LIBRARY=$libxml2_dir/lib/libxml2.a" \ + -DGDAL_USE_PROJ=ON \ + "-DPROJ_INCLUDE_DIR=$proj_dir/include" \ + "-DPROJ_LIBRARY=$proj_dir/lib/libproj.a" \ + -DGDAL_USE_SQLITE3=ON \ + "-DSQLite3_INCLUDE_DIR=$sqlite_dir/include" \ + "-DSQLite3_LIBRARY=$sqlite_dir/lib/libsqlite3.a" \ + -DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON + [ -f "$archive" ] || native_postgis_fail "GDAL build did not produce $archive" + [ -x "$dependency_dir/bin/gdal-config" ] || native_postgis_fail "GDAL build did not produce gdal-config" + native_postgis_dependency_archive gdal "$archive" +} + build_native_postgis_dependencies() { native_postgis_require_tools local wanted @@ -1741,6 +1816,7 @@ build_native_postgis_dependencies() { build_native_postgis_geos_dependency build_native_postgis_libxml2_dependency build_native_postgis_proj_dependency + build_native_postgis_gdal_dependency oliphaunt_postgis_dependency_cache_commit \ "$native_postgis_dependency_root" \ "$wanted" \ @@ -1770,6 +1846,24 @@ EOF chmod +x "$path" } +native_postgis_gdal_config_script() { + local path="$1" + local real_config="$native_postgis_dependency_root/gdal/bin/gdal-config" + local real_libs + real_libs="$("$real_config" --libs)" + cat > "$path" < "$path" <&2 + cp -p "$candidate" "$embedded_modules_dir/$stem.dylib" + if ! module_depends_on_liboliphaunt "$embedded_modules_dir/$stem.dylib"; then + echo "embedded PostGIS is not linked against liboliphaunt: $embedded_modules_dir/$stem.dylib" >&2 exit 1 fi return @@ -2133,6 +2230,11 @@ stage_postgis_data_files() { fi mkdir -p "$install_dir/share/postgresql/proj" cp -p "$proj_db" "$install_dir/share/postgresql/proj/proj.db" + local gdal_data="$native_postgis_dependency_root/gdal/share/gdal" + [ -f "$gdal_data/gdalvrt.xsd" ] || native_postgis_fail "PostGIS requires the pinned GDAL runtime data" + rm -rf "$install_dir/share/postgresql/gdal" + mkdir -p "$install_dir/share/postgresql/gdal" + cp -a "$gdal_data/." "$install_dir/share/postgresql/gdal/" } patch_postgis_generated_makefiles() { @@ -2195,7 +2297,6 @@ build_postgis_extension() { --with-pgconfig="$install_dir/bin/pg_config" \ "${postgis_configure_args[@]}" \ --without-protobuf \ - --without-raster \ --without-topology \ --without-sfcgal \ --without-address-standardizer \ @@ -2211,17 +2312,23 @@ build_postgis_extension() { make postgis_revision.h make -C doc CC="$postgis_cc" "${postgis_make_args[@]}" comments-install make -j"$jobs" -C postgis CC="$postgis_cc" BE_DLLLIBS="$normal_module_be_dllibs" "${postgis_make_args[@]}" install - # PostGIS extension SQL generation has shared raster helper outputs even - # when raster support is disabled, so keep this packaging phase serial. + make -j"$jobs" -C raster/rt_core CC="$postgis_cc" "${postgis_make_args[@]}" all + make -j"$jobs" -C raster/rt_pg CC="$postgis_cc" BE_DLLLIBS="$normal_module_be_dllibs" "${postgis_make_args[@]}" install + # PostGIS extension SQL generation shares raster helper outputs, so keep + # this packaging phase serial. make -j1 -C extensions CC="$postgis_cc" "${postgis_make_args[@]}" all make -j1 -C extensions CC="$postgis_cc" "${postgis_make_args[@]}" install make -C postgis clean || true make postgis_revision.h make -j"$jobs" -C postgis CC="$postgis_cc" CFLAGS="$native_cflags" BE_DLLLIBS="$embedded_module_be_dllibs" "${embedded_postgis_make_args[@]}" all + make -C raster/rt_pg clean || true + make -j"$jobs" -C raster/rt_pg CC="$postgis_cc" CFLAGS="$native_cflags" BE_DLLLIBS="$embedded_module_be_dllibs" "${embedded_postgis_make_args[@]}" all ) normalize_installed_module_suffix postgis-3 - copy_embedded_postgis_module "$postgis_build_dir/postgis" + normalize_installed_module_suffix postgis_raster-3 + copy_embedded_postgis_module "$postgis_build_dir/postgis" postgis-3 + copy_embedded_postgis_module "$postgis_build_dir/raster/rt_pg" postgis_raster-3 stage_postgis_data_files "$postgis_build_dir" } diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 index d3aca38c..69b6c2b0 100644 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 @@ -510,6 +510,7 @@ function Get-DesiredHash { (Join-Path $RepoRoot "src/extensions/external/pg_uuidv7/source.toml"), (Join-Path $RepoRoot "src/extensions/external/postgis/source.toml"), (Join-Path $RepoRoot "src/extensions/external/postgis/deps.toml"), + (Join-Path $RepoRoot "src/extensions/external/postgis/dependencies/gdal/source.toml"), (Join-Path $RepoRoot "src/extensions/external/postgis/dependencies/geos/source.toml"), (Join-Path $RepoRoot "src/extensions/external/postgis/dependencies/json-c/source.toml"), (Join-Path $RepoRoot "src/extensions/external/postgis/dependencies/libxml2/source.toml"), @@ -921,6 +922,74 @@ function Build-WindowsPostgisProjDependency { } } +function Build-WindowsPostgisGdalDependency { + if (-not (NativeExtension-Selected "postgis")) { + return + } + Build-WindowsPostgisProjDependency + $prefix = Join-Path $PostgisDependencyPrefix "gdal" + if ((Test-Path (Join-Path $prefix "include/gdal.h")) -and + (Find-FirstFileOrNull $prefix @("gdal.lib"))) { + return + } + $sourceDir = External-Checkout "gdal" + if (-not (Test-Path (Join-Path $sourceDir "CMakeLists.txt"))) { + Fail "missing GDAL checkout for PostGIS: $sourceDir" + } + $geosPrefix = Join-Path $PostgisDependencyPrefix "geos" + $jsonPrefix = Join-Path $PostgisDependencyPrefix "json-c" + $libxml2Prefix = Join-Path $PostgisDependencyPrefix "libxml2" + $projPrefix = Join-Path $PostgisDependencyPrefix "proj" + $sqlitePrefix = Join-Path $PostgisDependencyPrefix "sqlite" + $geosCLib = First-File $geosPrefix @("geos_c.lib") + $jsonLib = First-File $jsonPrefix @("json-c.lib", "json-c-static.lib") + $libxml2Lib = First-File $libxml2Prefix @("libxml2s.lib", "libxml2.lib", "xml2.lib") + $projLib = First-File $projPrefix @("proj.lib", "libproj.lib") + $sqliteLib = First-File $sqlitePrefix @("sqlite3.lib", "libsqlite3.lib") + Invoke-CmakeInstall "gdal" $sourceDir (Join-Path $WorkRoot "gdal-windows-build") $prefix @( + "-DBASH_COMPLETIONS_DIR=", + "-DBUILD_SHARED_LIBS=OFF", + "-DBUILD_APPS=OFF", + "-DBUILD_CSHARP_BINDINGS=OFF", + "-DBUILD_JAVA_BINDINGS=OFF", + "-DBUILD_PYTHON_BINDINGS=OFF", + "-DBUILD_TESTING=OFF", + "-DGDAL_BUILD_OPTIONAL_DRIVERS=OFF", + "-DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON", + "-DOGR_BUILD_OPTIONAL_DRIVERS=OFF", + "-DGDAL_ENABLE_DRIVER_GTIFF=ON", + "-DGDAL_ENABLE_DRIVER_VRT=ON", + "-DOGR_ENABLE_DRIVER_GEOJSON=ON", + "-DOGR_ENABLE_DRIVER_SHAPE=ON", + "-DGDAL_USE_EXTERNAL_LIBS=OFF", + "-DGDAL_USE_INTERNAL_LIBS=ON", + "-DGDAL_USE_OPENMP=OFF", + "-DGDAL_USE_CURL=OFF", + "-DGDAL_USE_OPENSSL=OFF", + "-DGDAL_USE_GEOS=ON", + "-DGEOS_INCLUDE_DIR=$(Join-Path $geosPrefix 'include')", + "-DGEOS_LIBRARY=$geosCLib", + "-DGDAL_USE_JSONC=ON", + "-DGDAL_USE_JSONC_INTERNAL=OFF", + "-DJSONC_INCLUDE_DIR=$(Join-Path $jsonPrefix 'include/json-c')", + "-DJSONC_LIBRARY=$jsonLib", + "-DGDAL_USE_LIBXML2=ON", + "-DLIBXML2_INCLUDE_DIR=$(Join-Path $libxml2Prefix 'include/libxml2')", + "-DLIBXML2_LIBRARY=$libxml2Lib", + "-DGDAL_USE_PROJ=ON", + "-DPROJ_INCLUDE_DIR=$(Join-Path $projPrefix 'include')", + "-DPROJ_LIBRARY=$projLib", + "-DGDAL_USE_SQLITE3=ON", + "-DSQLite3_INCLUDE_DIR=$(Join-Path $sqlitePrefix 'include')", + "-DSQLite3_LIBRARY=$sqliteLib", + "-DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON" + ) + [void](First-File $prefix @("gdal.lib")) + if (-not (Test-Path (Join-Path $prefix "include/gdal.h"))) { + Fail "GDAL Windows build did not produce headers under $prefix" + } +} + function Build-WindowsPostgisDependencies { if (-not (NativeExtension-Selected "postgis")) { return @@ -930,6 +999,7 @@ function Build-WindowsPostgisDependencies { Build-WindowsPostgisGeosDependency Build-WindowsPostgisLibxml2Dependency Build-WindowsPostgisProjDependency + Build-WindowsPostgisGdalDependency } function Read-PostgisVersionConfig([string]$PostgisSourceDir) { @@ -1020,6 +1090,7 @@ function Initialize-WindowsPostgisGeneratedSource([string]$PostgisDir, [string]$ $buildDate = Format-PostgisSourceDate $sourceDateEpoch $geosVersionNumber = "31401" $projVersionNumber = "90801" + $gdalVersionNumber = "31302" $libXmlVersion = "2.14.6" $postgisVersion = "$($version.Major).$($version.Minor) USE_GEOS=1 USE_PROJ=1 USE_STATS=1" $localeDir = (Meson-Path (Join-Path $InstallDir "share/locale")) @@ -1057,7 +1128,7 @@ function Initialize-WindowsPostgisGeneratedSource([string]$PostgisDir, [string]$ #define PGSQL_LOCALEDIR "$localeDir" #define POSTGIS_BUILD_DATE "$buildDate" /* #undef POSTGIS_SFCGAL_VERSION */ -/* #undef POSTGIS_GDAL_VERSION */ +#define POSTGIS_GDAL_VERSION $gdalVersionNumber #define POSTGIS_GEOS_VERSION $geosVersionNumber #define POSTGIS_LIBXML2_VERSION "$libXmlVersion" #define POSTGIS_LIB_VERSION "$($version.Version)" @@ -1093,11 +1164,23 @@ function Initialize-WindowsPostgisGeneratedSource([string]$PostgisDir, [string]$ } Expand-PostgisTemplate (Join-Path $PostgisDir "postgis/sqldefines.h.in") (Join-Path $PostgisDir "postgis/sqldefines.h") $templateValues Expand-PostgisTemplate (Join-Path $PostgisDir "liblwgeom/liblwgeom.h.in") (Join-Path $PostgisDir "liblwgeom/liblwgeom.h") $templateValues + Set-Content -Path (Join-Path $PostgisDir "raster/raster_config.h") -Encoding UTF8 -Value @" +/* raster_config.h. Generated by Oliphaunt's Windows native producer. */ +#ifndef POSTGIS_RASTER_CONFIG_H +#define POSTGIS_RASTER_CONFIG_H 1 +#define POSTGIS_GDAL_VERSION $gdalVersionNumber +#endif +"@ Expand-PostgisTemplate (Join-Path $PostgisDir "extensions/postgis/postgis.control.in") (Join-Path $PostgisDir "extensions/postgis/postgis.control") @{ EXTVERSION = $version.Version EXTENSION = "postgis" MODULEPATH = '$libdir/postgis-3' } + Expand-PostgisTemplate (Join-Path $PostgisDir "extensions/postgis_raster/postgis_raster.control.in") (Join-Path $PostgisDir "extensions/postgis_raster/postgis_raster.control") @{ + EXTVERSION = $version.Version + EXTENSION = "postgis_raster" + MODULEPATH = '$libdir/postgis_raster-3' + } $version } @@ -1344,13 +1427,17 @@ function New-PostgisRasterUnpackageSql([string]$PostgisDir, [string]$SqlDir, [st Set-Content -Path (Join-Path $SqlDir "raster_unpackage.sql") -Encoding UTF8 -Value ($prefix.ToString() + $body + $suffix.ToString()) } -function Convert-PostgisExtensionDropGuards([string]$InputPath, [string]$OutputPath) { +function Convert-PostgisExtensionDropGuards( + [string]$InputPath, + [string]$OutputPath, + [string]$ExtensionName = "postgis" +) { $text = (Get-Content -Raw -Path $InputPath).Replace("BEGIN;", "").Replace("COMMIT;", "") $lines = New-Object System.Collections.Generic.List[string] foreach ($line in ($text -split "`r?`n")) { if ($line -match "^(DROP .*)\;") { $drop = $Matches[1] - $lines.Add("SELECT @extschema@.postgis_extension_drop_if_exists('postgis', '$drop');") + $lines.Add("SELECT @extschema@.postgis_extension_drop_if_exists('$ExtensionName', '$drop');") } $lines.Add($line) } @@ -1447,6 +1534,42 @@ function Build-WindowsPostgisSql([string]$PostgisDir, [pscustomobject]$Version) $unpackagedVersionSql = Join-Path $extensionSqlDir "postgis--unpackaged--$($Version.Version).sql" Invoke-PerlFromInputFile $installSql @((Join-Path $PostgisDir "utils/create_unpackaged.pl"), "postgis") $unpackagedVersionSql Add-Content -Path $unpackagedVersionSql -Encoding UTF8 -Value (Get-Content -Raw -Path $anyUpgradeSql) + + $rasterExtensionDir = Join-Path $PostgisDir "extensions/postgis_raster" + $rasterExtensionSqlDir = Join-Path $rasterExtensionDir "sql" + New-Item -ItemType Directory -Force -Path $rasterExtensionSqlDir | Out-Null + $rasterModulePath = '$libdir/postgis_raster-3' + $rasterForExtension = Join-Path $rasterExtensionSqlDir "rtpostgis_for_extension.sql" + New-PostgisSqlFromTemplate (Join-Path $rasterDir "rtpostgis.sql.in") $rasterForExtension $rasterIncludeDirs $rasterModulePath $false $false + $rasterExtensionSql = Join-Path $rasterExtensionSqlDir "rtpostgis.sql" + $rasterExtensionText = (Get-Content -Raw -Path $rasterForExtension).Replace("BEGIN;", "").Replace("COMMIT;", "") + Set-Content -Path $rasterExtensionSql -Encoding UTF8 -Value $rasterExtensionText + + $rasterUpgradeInput = Join-Path $rasterExtensionSqlDir "rtpostgis_upgrade_for_extension.sql.in" + Invoke-PerlToFile @((Join-Path $PostgisDir "utils/create_upgrade.pl"), $rasterForExtension) $rasterUpgradeInput + $rasterUpgradeForExtension = Join-Path $rasterExtensionSqlDir "rtpostgis_upgrade_for_extension.sql" + Join-TextFiles $rasterUpgradeForExtension @( + (Join-Path $postgisSqlDir "common_before_upgrade.sql"), + (Join-Path $rasterDir "rtpostgis_upgrade_cleanup.sql"), + $rasterUpgradeInput, + (Join-Path $rasterDir "rtpostgis_drop.sql"), + (Join-Path $postgisSqlDir "common_after_upgrade.sql") + ) "BEGIN;" "COMMIT;" + $rasterUpgradeSql = Join-Path $rasterExtensionSqlDir "rtpostgis_upgrade.sql" + Convert-PostgisExtensionDropGuards $rasterUpgradeForExtension $rasterUpgradeSql "postgis_raster" + + $rasterInstallSql = Join-Path $rasterExtensionSqlDir "postgis_raster--$($Version.Version).sql" + Join-TextFiles $rasterInstallSql @($rasterExtensionSql) '\echo Use "CREATE EXTENSION postgis_raster" to load this file. \quit' + $rasterAnyUpgradeSql = Join-Path $rasterExtensionSqlDir "postgis_raster--ANY--$($Version.Version).sql" + Join-TextFiles $rasterAnyUpgradeSql @( + (Join-Path $PostgisDir "extensions/postgis_extension_helper.sql"), + $rasterUpgradeSql, + (Join-Path $PostgisDir "extensions/postgis_extension_helper_uninstall.sql") + ) '\echo Use "CREATE EXTENSION postgis_raster" to load this file. \quit' + Set-Content -Path (Join-Path $rasterExtensionSqlDir "postgis_raster--unpackaged.sql") -Encoding UTF8 -Value "-- Nothing to do here" + $rasterUnpackagedSql = Join-Path $rasterExtensionSqlDir "postgis_raster--unpackaged--$($Version.Version).sql" + Invoke-PerlFromInputFile $rasterInstallSql @((Join-Path $PostgisDir "utils/create_unpackaged.pl"), "postgis_raster") $rasterUnpackagedSql + Add-Content -Path $rasterUnpackagedSql -Encoding UTF8 -Value (Get-Content -Raw -Path $rasterAnyUpgradeSql) } function Patch-WindowsPostgisFlatgeobufSource([string]$SourceDir) { @@ -1564,7 +1687,7 @@ function Patch-WindowsPostgisSource([string]$PostgisDir) { $declarationPattern = "(?m)^\s*(?!(?:extern\s+)?PGDLLEXPORT\s+)(?:extern\s+)?Datum\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(PG_FUNCTION_ARGS\);\r?$" $patchedDeclarationCount = 0 - foreach ($subdir in @("postgis", "libpgcommon", "liblwgeom")) { + foreach ($subdir in @("postgis", "libpgcommon", "liblwgeom", "raster/rt_core", "raster/rt_pg")) { $root = Join-Path $PostgisDir $subdir foreach ($file in Get-ChildItem -Path $root -Recurse -File | Where-Object { $_.Extension -in @(".c", ".h") }) { $text = Get-Content -Raw -Path $file.FullName @@ -1650,6 +1773,15 @@ function Write-PostgisMesonModule([string]$PostgisDir, [pscustomobject]$Version, $geosLib = First-File (Join-Path $PostgisDependencyPrefix "geos") @("geos.lib") $libxml2Lib = First-File (Join-Path $PostgisDependencyPrefix "libxml2") @("libxml2s.lib", "libxml2.lib", "xml2.lib") $projLib = First-File (Join-Path $PostgisDependencyPrefix "proj") @("proj.lib", "libproj.lib") + $gdalLib = First-File (Join-Path $PostgisDependencyPrefix "gdal") @("gdal.lib") + $gdalDataSource = Join-Path $PostgisDependencyPrefix "gdal/share/gdal" + if (-not (Test-Path (Join-Path $gdalDataSource "gdalvrt.xsd"))) { + Fail "PostGIS requires the pinned GDAL runtime data under $gdalDataSource" + } + $gdalDataDir = Join-Path $PostgisDir "share/gdal" + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $gdalDataDir + New-Item -ItemType Directory -Force -Path $gdalDataDir | Out-Null + Copy-Item -Recurse -Force -Path (Join-Path $gdalDataSource "*") -Destination $gdalDataDir $sources = @( "postgis/postgis_module.c", @@ -1804,6 +1936,38 @@ function Write-PostgisMesonModule([string]$PostgisDir, [pscustomobject]$Version, "liblwgeom/lwspheroid.c", "deps/ryu/d2s.c" ) + $rasterSources = @( + "raster/rt_pg/rtpostgis.c", + "raster/rt_pg/rtpg_internal.c", + "raster/rt_pg/rtpg_legacy.c", + "raster/rt_pg/rtpg_spatial_relationship.c", + "raster/rt_pg/rtpg_mapalgebra.c", + "raster/rt_pg/rtpg_utility.c", + "raster/rt_pg/rtpg_inout.c", + "raster/rt_pg/rtpg_wkb.c", + "raster/rt_pg/rtpg_geometry.c", + "raster/rt_pg/rtpg_raster_properties.c", + "raster/rt_pg/rtpg_band_properties.c", + "raster/rt_pg/rtpg_pixel.c", + "raster/rt_pg/rtpg_create.c", + "raster/rt_pg/rtpg_gdal.c", + "raster/rt_pg/rtpg_statistics.c", + "raster/rt_core/rt_util.c", + "raster/rt_core/rt_spatial_relationship.c", + "raster/rt_core/rt_mapalgebra.c", + "raster/rt_core/rt_geometry.c", + "raster/rt_core/rt_statistics.c", + "raster/rt_core/rt_pixel.c", + "raster/rt_core/rt_warp.c", + "raster/rt_core/rt_gdal.c", + "raster/rt_core/rt_band.c", + "raster/rt_core/rt_raster.c", + "raster/rt_core/rt_serialize.c", + "raster/rt_core/rt_wkb.c", + "raster/rt_core/rt_context.c" + ) + @($sources | Where-Object { + $_.StartsWith("libpgcommon/") -or $_.StartsWith("liblwgeom/") -or $_.StartsWith("deps/ryu/") + } | Select-Object -Unique) $extensionSqlFiles = @( "extensions/postgis/postgis.control", "extensions/postgis/sql/postgis--$($Version.Version).sql", @@ -1811,7 +1975,12 @@ function Write-PostgisMesonModule([string]$PostgisDir, [pscustomobject]$Version, "extensions/postgis/sql/postgis--$($Version.Version)--ANY.sql", "extensions/postgis/sql/postgis--TEMPLATED--TO--ANY.sql", "extensions/postgis/sql/postgis--unpackaged.sql", - "extensions/postgis/sql/postgis--unpackaged--$($Version.Version).sql" + "extensions/postgis/sql/postgis--unpackaged--$($Version.Version).sql", + "extensions/postgis_raster/postgis_raster.control", + "extensions/postgis_raster/sql/postgis_raster--$($Version.Version).sql", + "extensions/postgis_raster/sql/postgis_raster--ANY--$($Version.Version).sql", + "extensions/postgis_raster/sql/postgis_raster--unpackaged.sql", + "extensions/postgis_raster/sql/postgis_raster--unpackaged--$($Version.Version).sql" ) $contribDataFiles = @( "postgis/legacy.sql", @@ -1836,6 +2005,10 @@ function Write-PostgisMesonModule([string]$PostgisDir, [pscustomobject]$Version, "/I$(Meson-Path (Join-Path $PostgisDir "deps/flatgeobuf"))", "/I$(Meson-Path (Join-Path $PostgisDir "deps/flatgeobuf/include"))", "/I$(Meson-Path (Join-Path $PostgisDir "deps/ryu"))", + "/I$(Meson-Path (Join-Path $PostgisDir "raster"))", + "/I$(Meson-Path (Join-Path $PostgisDir "raster/rt_core"))", + "/I$(Meson-Path (Join-Path $PostgisDir "raster/rt_pg"))", + "/I$(Meson-Path (Join-Path $PostgisDependencyPrefix "gdal/include"))", "/I$(Meson-Path (Join-Path $PostgisDependencyPrefix "geos/include"))", "/I$(Meson-Path (Join-Path $PostgisDependencyPrefix "proj/include"))", "/I$(Meson-Path (Join-Path $PostgisDependencyPrefix "json-c/include"))", @@ -1851,6 +2024,7 @@ function Write-PostgisMesonModule([string]$PostgisDir, [pscustomobject]$Version, ) + $includeArgs $linkArgs = @( (Meson-Path $FlatgeobufLib), + (Meson-Path $gdalLib), (Meson-Path $geosCLib), (Meson-Path $geosLib), (Meson-Path $projLib), @@ -1861,10 +2035,15 @@ function Write-PostgisMesonModule([string]$PostgisDir, [pscustomobject]$Version, "bcrypt.lib", "advapi32.lib", "shell32.lib", - "user32.lib" + "user32.lib", + "ole32.lib", + "oleaut32.lib", + "uuid.lib", + "msvcprt.lib" ) $sourceList = Meson-List $sources + $rasterSourceList = Meson-List $rasterSources $cArgList = Meson-List $cArgs " " $linkArgList = Meson-List $linkArgs " " $extensionDataList = Meson-List $extensionSqlFiles @@ -1887,6 +2066,23 @@ $linkArgList ) contrib_targets += postgis +postgis_raster = shared_module( + 'postgis_raster-3', + files( +$rasterSourceList, + ), + c_pch: pch_postgres_h, + kwargs: contrib_mod_args + { + 'c_args': [ +$cArgList + ], + 'link_args': [ +$linkArgList + ], + }, +) +contrib_targets += postgis_raster + install_data( $extensionDataList, kwargs: contrib_data_args, @@ -1897,6 +2093,12 @@ $contribDataList, install_dir: dir_data / 'contrib' / 'postgis-$($Version.MajorMinor)', ) +install_subdir( + 'share/gdal', + install_dir: dir_data / 'gdal', + strip_directory: true, +) + install_data( 'share/proj/proj.db', install_dir: dir_data / 'proj', diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh index a5a8f0f5..7db3ba5a 100644 --- a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh +++ b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh @@ -43,23 +43,26 @@ oliphaunt_postgis_output_fingerprint() { local alias_file="$4" local archive="$5" local control_file="$install_dir/share/postgresql/extension/postgis.control" + local raster_control_file="$install_dir/share/postgresql/extension/postgis_raster.control" local proj_database="$install_dir/share/postgresql/proj/proj.db" - local sql_source_root="$postgis_build/extensions/postgis/sql" + local sql_source_root local object sql_source installed_sql dependency local sql_count=0 local -a outputs - outputs=("$archive" "$objects_file" "$alias_file" "$control_file" "$proj_database") + outputs=("$archive" "$objects_file" "$alias_file" "$control_file" "$raster_control_file" "$proj_database") while IFS= read -r object; do [ -n "$object" ] || continue outputs+=("$object") done < "$objects_file" - while IFS= read -r sql_source; do - [ -n "$sql_source" ] || continue - installed_sql="$install_dir/share/postgresql/extension/$(basename "$sql_source")" - outputs+=("$installed_sql") - sql_count=$((sql_count + 1)) - done < <(find "$sql_source_root" -maxdepth 1 -type f -name '*.sql' -print 2>/dev/null | LC_ALL=C sort) + for sql_source_root in "$postgis_build/extensions/postgis/sql" "$postgis_build/extensions/postgis_raster/sql"; do + while IFS= read -r sql_source; do + [ -n "$sql_source" ] || continue + installed_sql="$install_dir/share/postgresql/extension/$(basename "$sql_source")" + outputs+=("$installed_sql") + sql_count=$((sql_count + 1)) + done < <(find "$sql_source_root" -maxdepth 1 -type f -name '*.sql' -print 2>/dev/null | LC_ALL=C sort) + done while IFS= read -r dependency; do [ -n "$dependency" ] || continue outputs+=("$dependency") @@ -294,6 +297,79 @@ build_postgis_proj_dependency() { oliphaunt_postgis_dependency_archive proj "$archive" } +build_postgis_gdal_dependency() { + oliphaunt_postgis_selected || return 0 + local source_dir="$repo_root/target/oliphaunt-sources/checkouts/gdal" + local dependency_dir="$mobile_static_dependency_root/gdal" + local geos_dir="$mobile_static_dependency_root/geos" + local jsonc_dir="$mobile_static_dependency_root/json-c" + local libxml2_dir="$mobile_static_dependency_root/libxml2" + local proj_dir="$mobile_static_dependency_root/proj" + local sqlite_dir="$mobile_static_dependency_root/sqlite" + local -a iconv_args=() + local build_root="$work_root/gdal-$oliphaunt_mobile_target-build" + local archive="$dependency_dir/lib/libgdal.a" + if [ -f "$archive" ] && [ -f "$dependency_dir/include/gdal.h" ] && [ -x "$dependency_dir/bin/gdal-config" ]; then + oliphaunt_postgis_dependency_archive gdal "$archive" + return 0 + fi + [ -f "$source_dir/CMakeLists.txt" ] || oliphaunt_postgis_fail "missing GDAL checkout: $source_dir" + [ -f "$proj_dir/lib/libproj.a" ] || oliphaunt_postgis_fail "GDAL dependency requires PROJ first" + case "$oliphaunt_mobile_target" in + android-arm64 | android-x86_64) + [ -f "$mobile_static_dependency_root/libiconv/lib/libiconv.a" ] || + oliphaunt_postgis_fail "GDAL dependency requires libiconv first on Android" + iconv_args=( + -DGDAL_USE_ICONV=ON + "-DIconv_INCLUDE_DIR=$mobile_static_dependency_root/libiconv/include" + "-DIconv_LIBRARY=$mobile_static_dependency_root/libiconv/lib/libiconv.a" + ) + ;; + esac + rm -rf "$build_root" "$dependency_dir" + oliphaunt_postgis_cmake_install "$source_dir" "$build_root" "$dependency_dir" \ + -DBASH_COMPLETIONS_DIR= \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_CSHARP_BINDINGS=OFF \ + -DBUILD_JAVA_BINDINGS=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF \ + -DBUILD_TESTING=OFF \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_ENABLE_DRIVER_GTIFF=ON \ + -DGDAL_ENABLE_DRIVER_VRT=ON \ + -DOGR_ENABLE_DRIVER_GEOJSON=ON \ + -DOGR_ENABLE_DRIVER_SHAPE=ON \ + -DGDAL_USE_EXTERNAL_LIBS=OFF \ + -DGDAL_USE_INTERNAL_LIBS=ON \ + -DGDAL_USE_OPENMP=OFF \ + -DGDAL_USE_CURL=OFF \ + -DGDAL_USE_OPENSSL=OFF \ + -DGDAL_USE_GEOS=ON \ + "-DGEOS_INCLUDE_DIR=$geos_dir/include" \ + "-DGEOS_LIBRARY=$geos_dir/lib/libgeos_c.a" \ + -DGDAL_USE_JSONC=ON \ + -DGDAL_USE_JSONC_INTERNAL=OFF \ + "-DJSONC_INCLUDE_DIR=$jsonc_dir/include/json-c" \ + "-DJSONC_LIBRARY=$jsonc_dir/lib/libjson-c.a" \ + -DGDAL_USE_LIBXML2=ON \ + "-DLIBXML2_INCLUDE_DIR=$libxml2_dir/include/libxml2" \ + "-DLIBXML2_LIBRARY=$libxml2_dir/lib/libxml2.a" \ + -DGDAL_USE_PROJ=ON \ + "-DPROJ_INCLUDE_DIR=$proj_dir/include" \ + "-DPROJ_LIBRARY=$proj_dir/lib/libproj.a" \ + -DGDAL_USE_SQLITE3=ON \ + "-DSQLite3_INCLUDE_DIR=$sqlite_dir/include" \ + "-DSQLite3_LIBRARY=$sqlite_dir/lib/libsqlite3.a" \ + -DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON \ + "${iconv_args[@]}" + [ -f "$archive" ] || oliphaunt_postgis_fail "GDAL build did not produce $archive" + [ -x "$dependency_dir/bin/gdal-config" ] || oliphaunt_postgis_fail "GDAL build did not produce gdal-config" + oliphaunt_postgis_dependency_archive gdal "$archive" +} + build_postgis_libiconv_dependency() { oliphaunt_postgis_selected || return 0 case "$oliphaunt_mobile_target" in @@ -345,6 +421,7 @@ build_postgis_mobile_static_dependencies() { build_postgis_libxml2_dependency build_postgis_proj_dependency build_postgis_libiconv_dependency + build_postgis_gdal_dependency } oliphaunt_postgis_host_alias() { @@ -358,10 +435,10 @@ oliphaunt_postgis_host_alias() { oliphaunt_postgis_extra_ldflags() { case "$oliphaunt_mobile_target" in ios-simulator | ios-device | macos-arm64) - printf '%s\n' "-isysroot $sdk_path -L$mobile_static_dependency_root/geos/lib -L$mobile_static_dependency_root/proj/lib -L$mobile_static_dependency_root/sqlite/lib -L$mobile_static_dependency_root/json-c/lib -L$mobile_static_dependency_root/libxml2/lib -lc++" + printf '%s\n' "-isysroot $sdk_path -L$mobile_static_dependency_root/gdal/lib -L$mobile_static_dependency_root/geos/lib -L$mobile_static_dependency_root/proj/lib -L$mobile_static_dependency_root/sqlite/lib -L$mobile_static_dependency_root/json-c/lib -L$mobile_static_dependency_root/libxml2/lib -lc++" ;; android-arm64 | android-x86_64) - printf '%s\n' "-L$mobile_static_dependency_root/geos/lib -L$mobile_static_dependency_root/proj/lib -L$mobile_static_dependency_root/sqlite/lib -L$mobile_static_dependency_root/json-c/lib -L$mobile_static_dependency_root/libxml2/lib -L$mobile_static_dependency_root/libiconv/lib -L$toolchain_dir/sysroot/usr/lib/$android_host -lc++_static -lc++abi" + printf '%s\n' "-L$mobile_static_dependency_root/gdal/lib -L$mobile_static_dependency_root/geos/lib -L$mobile_static_dependency_root/proj/lib -L$mobile_static_dependency_root/sqlite/lib -L$mobile_static_dependency_root/json-c/lib -L$mobile_static_dependency_root/libxml2/lib -L$mobile_static_dependency_root/libiconv/lib -L$toolchain_dir/sysroot/usr/lib/$android_host -lc++_static -lc++abi" ;; esac } @@ -373,6 +450,18 @@ oliphaunt_postgis_geos_config_libs() { esac } +oliphaunt_postgis_gdal_config_libs() { + local base="-L$mobile_static_dependency_root/gdal/lib -lgdal -L$mobile_static_dependency_root/geos/lib -lgeos_c -lgeos -L$mobile_static_dependency_root/proj/lib -lproj -L$mobile_static_dependency_root/sqlite/lib -lsqlite3 -L$mobile_static_dependency_root/json-c/lib -ljson-c -L$mobile_static_dependency_root/libxml2/lib -lxml2" + case "$oliphaunt_mobile_target" in + ios-simulator | ios-device | macos-arm64) + printf '%s\n' "$base -lc++" + ;; + android-arm64 | android-x86_64) + printf '%s\n' "$base -L$mobile_static_dependency_root/libiconv/lib -liconv -lcharset -lc++_static -lc++abi" + ;; + esac +} + oliphaunt_postgis_pkg_config_script() { local path="$1" local proj_cxx_libs @@ -481,6 +570,24 @@ EOF chmod +x "$path" } +oliphaunt_postgis_gdal_config_script() { + local path="$1" + local gdal_libs + gdal_libs="$(oliphaunt_postgis_gdal_config_libs)" + cat > "$path" <&2; exit 1 ;; +esac +EOF + chmod +x "$path" +} + oliphaunt_postgis_copy_archive_objects() { local archive="$1" local name="$2" @@ -518,13 +625,26 @@ oliphaunt_postgis_stage_object() { oliphaunt_postgis_stage_runtime_sql() { local postgis_build="$1" - mkdir -p "$install_dir/share/postgresql/extension" "$install_dir/share/postgresql/proj" + local gdal_data="$mobile_static_dependency_root/gdal/share/gdal" + [ -f "$gdal_data/gdalvrt.xsd" ] || oliphaunt_postgis_fail "PostGIS requires the pinned GDAL runtime data" + mkdir -p \ + "$install_dir/share/postgresql/extension" \ + "$install_dir/share/postgresql/proj" \ + "$install_dir/share/postgresql/gdal" cp -p "$postgis_build/extensions/postgis/postgis.control" \ "$install_dir/share/postgresql/extension/postgis.control" cp -p "$postgis_build/extensions/postgis/sql/"*.sql \ "$install_dir/share/postgresql/extension/" + cp -p "$postgis_build/extensions/postgis_raster/postgis_raster.control" \ + "$install_dir/share/postgresql/extension/postgis_raster.control" + cp -p "$postgis_build/extensions/postgis_raster/sql/"*.sql \ + "$install_dir/share/postgresql/extension/" + perl -0pi -e 's|\$libdir/postgis_raster-3(?:\.6)?|\$libdir/postgis-3|g' \ + "$install_dir/share/postgresql/extension/postgis_raster.control" \ + "$install_dir/share/postgresql/extension/postgis_raster--"*.sql cp -p "$mobile_static_dependency_root/proj/share/proj/proj.db" \ "$install_dir/share/postgresql/proj/proj.db" + cp -a "$gdal_data/." "$install_dir/share/postgresql/gdal/" } oliphaunt_postgis_patch_extension_makefile() { @@ -533,13 +653,15 @@ oliphaunt_postgis_patch_extension_makefile() { local makefile="$postgis_build/postgis/Makefile" [ -f "$makefile" ] || oliphaunt_postgis_fail "PostGIS extension Makefile is missing: $makefile" OLIPHAUNT_POSTGIS_PG_MAGIC_SYMBOL="${prefix}_Pg_magic_func" \ - OLIPHAUNT_POSTGIS_PG_INIT_SYMBOL="${prefix}__PG_init" \ + OLIPHAUNT_POSTGIS_PG_INIT_SYMBOL="${prefix}_core_PG_init" \ + OLIPHAUNT_POSTGIS_PG_FINI_SYMBOL="${prefix}_core_PG_fini" \ OLIPHAUNT_POSTGIS_DIFFERENCE_SYMBOL="${prefix}_difference" \ OLIPHAUNT_POSTGIS_PG_FINFO_DIFFERENCE_SYMBOL="${prefix}_pg_finfo_difference" \ perl -0pi -e ' my $defs = " -DPg_magic_func=$ENV{OLIPHAUNT_POSTGIS_PG_MAGIC_SYMBOL}" . " -D_PG_init=$ENV{OLIPHAUNT_POSTGIS_PG_INIT_SYMBOL}" . + " -D_PG_fini=$ENV{OLIPHAUNT_POSTGIS_PG_FINI_SYMBOL}" . " -Ddifference=$ENV{OLIPHAUNT_POSTGIS_DIFFERENCE_SYMBOL}" . " -Dpg_finfo_difference=$ENV{OLIPHAUNT_POSTGIS_PG_FINFO_DIFFERENCE_SYMBOL}"; my $updated = s|^(PG_CPPFLAGS \+= .*)$|$1$defs|m; @@ -547,6 +669,42 @@ oliphaunt_postgis_patch_extension_makefile() { ' "$makefile" } +oliphaunt_postgis_patch_raster_makefile() { + local postgis_build="$1" + local prefix="$2" + local makefile="$postgis_build/raster/rt_pg/Makefile" + [ -f "$makefile" ] || oliphaunt_postgis_fail "PostGIS raster Makefile is missing: $makefile" + OLIPHAUNT_POSTGIS_RASTER_MAGIC_SYMBOL="${prefix}_raster_Pg_magic_func" \ + OLIPHAUNT_POSTGIS_RASTER_INIT_SYMBOL="${prefix}_raster_PG_init" \ + OLIPHAUNT_POSTGIS_RASTER_FINI_SYMBOL="${prefix}_raster_PG_fini" \ + perl -0pi -e ' + my $defs = + " -DPg_magic_func=$ENV{OLIPHAUNT_POSTGIS_RASTER_MAGIC_SYMBOL}" . + " -D_PG_init=$ENV{OLIPHAUNT_POSTGIS_RASTER_INIT_SYMBOL}" . + " -D_PG_fini=$ENV{OLIPHAUNT_POSTGIS_RASTER_FINI_SYMBOL}"; + my $updated = s|^(PG_CPPFLAGS \+= .*)$|$1$defs|m; + die "could not patch PostGIS raster PG_CPPFLAGS\n" unless $updated; + ' "$makefile" +} + +oliphaunt_postgis_build_combined_init() { + local postgis_build="$1" + local prefix="$2" + local object_dir="$3" + local source="$object_dir/oliphaunt_postgis_combined_init.c" + local object="$object_dir/oliphaunt_postgis_combined_init.o" + cat > "$source" <> "$make_log" 2>&1 + printf '%s\n' "$object" +} + oliphaunt_postgis_write_static_symbol_aliases() { local path="$1" local prefix="$2" @@ -596,6 +754,7 @@ build_postgis_mobile_static_extension_objects() { if [ -f "$archive" ] && [ -s "$objects_file" ] && [ -s "$alias_file" ] && [ -f "$install_dir/share/postgresql/extension/postgis.control" ] && + [ -f "$install_dir/share/postgresql/extension/postgis_raster.control" ] && [ -s "$build_stamp" ] && [ "$(cat "$build_stamp")" = "$build_fingerprint" ] && [ -s "$output_stamp" ] && output_fingerprint="$(oliphaunt_postgis_output_fingerprint "$postgis_build" "$object_dir" "$objects_file" "$alias_file" "$archive")" && @@ -616,19 +775,21 @@ build_postgis_mobile_static_extension_objects() { chmod +x "$work_root/postgis-fake-postgres-bin/postgres" rsync -a --delete --exclude .git "$source_dir/" "$postgis_build/" - local pg_config geos_config pkg_config host_alias ldflags + local pg_config geos_config gdal_config pkg_config host_alias ldflags pg_config="$scripts_dir/pg_config" geos_config="$scripts_dir/geos-config" + gdal_config="$scripts_dir/gdal-config" pkg_config="$scripts_dir/pkg-config" host_alias="$(oliphaunt_postgis_host_alias)" ldflags="$(oliphaunt_postgis_extra_ldflags)" oliphaunt_postgis_pg_config_script "$pg_config" oliphaunt_postgis_geos_config_script "$geos_config" + oliphaunt_postgis_gdal_config_script "$gdal_config" oliphaunt_postgis_pkg_config_script "$pkg_config" local postgis_cflags postgis_cppflags postgis_cflags="$native_cflags" - postgis_cppflags="-I$build_dir/src/include -I$build_dir/src/include/port -I$build_dir/src/interfaces/libpq -I$mobile_static_dependency_root/libxml2/include/libxml2 -I$mobile_static_dependency_root/proj/include -I$mobile_static_dependency_root/json-c/include -I$mobile_static_dependency_root/json-c/include/json-c" + postgis_cppflags="-I$build_dir/src/include -I$build_dir/src/include/port -I$build_dir/src/interfaces/libpq -I$mobile_static_dependency_root/gdal/include -I$mobile_static_dependency_root/libxml2/include/libxml2 -I$mobile_static_dependency_root/proj/include -I$mobile_static_dependency_root/json-c/include -I$mobile_static_dependency_root/json-c/include/json-c" case "$oliphaunt_mobile_target" in android-arm64 | android-x86_64) postgis_cflags="$postgis_cflags -D_GNU_SOURCE" @@ -641,9 +802,9 @@ build_postgis_mobile_static_extension_objects() { --host="$host_alias" --with-pgconfig="$pg_config" --with-geosconfig="$geos_config" + --with-gdalconfig="$gdal_config" --with-xml2config="$mobile_static_dependency_root/libxml2/bin/xml2-config" --without-protobuf - --without-raster --without-topology --without-sfcgal --without-address-standardizer @@ -683,14 +844,16 @@ build_postgis_mobile_static_extension_objects() { build_alias="$(build-aux/config.guess)" ./configure --build="$build_alias" "${configure_args[@]}" >> "$make_log" 2>&1 oliphaunt_postgis_patch_extension_makefile "$postgis_build" "$prefix" + oliphaunt_postgis_patch_raster_makefile "$postgis_build" "$prefix" make -j"$jobs" -C liblwgeom liblwgeom.la >> "$make_log" 2>&1 make -j"$jobs" -C libpgcommon libpgcommon.a >> "$make_log" 2>&1 make -j"$jobs" -C deps/flatgeobuf all >> "$make_log" 2>&1 make -j"$jobs" -C postgis all >> "$make_log" 2>&1 || true - make -j1 raster-sql >> "$make_log" 2>&1 || true - make -j1 -C raster/rt_pg sql_objs >> "$make_log" 2>&1 + make -j"$jobs" -C raster/rt_core all >> "$make_log" 2>&1 + make -j"$jobs" -C raster/rt_pg all >> "$make_log" 2>&1 || true + [ -f raster/rt_pg/rtpostgis.o ] || oliphaunt_postgis_fail "PostGIS raster objects were not produced" make -j1 -C extensions postgis_extension_helper.sql >> "$make_log" 2>&1 - make -j1 -C extensions/postgis postgis.control all >> "$make_log" 2>&1 + make -j1 -C extensions all >> "$make_log" 2>&1 ) : > "$objects_file" @@ -700,6 +863,10 @@ build_postgis_mobile_static_extension_objects() { [ -n "$object" ] || continue oliphaunt_postgis_stage_object "$object" postgis "$object_dir" "$objects_file" done < <(find "$postgis_build/postgis" -maxdepth 1 -type f -name '*.o' -print | LC_ALL=C sort) + while IFS= read -r object; do + [ -n "$object" ] || continue + oliphaunt_postgis_stage_object "$object" raster "$object_dir" "$objects_file" + done < <(find "$postgis_build/raster/rt_pg" -maxdepth 1 -type f -name '*.o' -print | LC_ALL=C sort) for object in \ "$postgis_build/deps/flatgeobuf/flatgeobuf_c.o" \ "$postgis_build/deps/flatgeobuf/geometrywriter.o" \ @@ -711,6 +878,10 @@ build_postgis_mobile_static_extension_objects() { done oliphaunt_postgis_copy_archive_objects "$postgis_build/liblwgeom/.libs/liblwgeom.a" liblwgeom "$object_dir" "$objects_file" oliphaunt_postgis_copy_archive_objects "$postgis_build/libpgcommon/libpgcommon.a" libpgcommon "$object_dir" "$objects_file" + oliphaunt_postgis_copy_archive_objects "$postgis_build/raster/rt_core/librtcore.a" rtcore "$object_dir" "$objects_file" + object="$(oliphaunt_postgis_build_combined_init "$postgis_build" "$prefix" "$object_dir")" + printf '%s\n' "$object" >> "$objects_file" + mobile_static_objects+=("$object") [ -s "$objects_file" ] || oliphaunt_postgis_fail "PostGIS did not produce object inputs" oliphaunt_postgis_verify_prefixed_module_symbol "$stem" "$prefix" oliphaunt_postgis_verify_prefixed_legacy_symbols "$stem" "$prefix" diff --git a/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh b/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh index 1a76e69c..dbf91fc9 100755 --- a/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh +++ b/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh @@ -4,8 +4,8 @@ set -euo pipefail root="$(git rev-parse --show-toplevel)" helper="$root/src/extensions/external/postgis/tools/reproducible-time.sh" shim="$root/src/extensions/external/postgis/tools/reproducible-bin/date" -expected_epoch=1776193981 -expected_utc='2026-04-14 19:13:01' +expected_epoch=1780943336 +expected_utc='2026-06-08 18:28:56' test_root="$(mktemp -d "${TMPDIR:-/tmp}/oliphaunt-postgis-time-test.XXXXXX")" original_path="$PATH" cleanup() { @@ -37,14 +37,14 @@ fi grep -Fq 'exactly one canonical source_date_epoch' "$test_root/missing.err" || fail "missing-key error was not actionable" -printf 'source_date_epoch = "1776193981"\n' > "$fake_manifest" +printf 'source_date_epoch = "1780943336"\n' > "$fake_manifest" if oliphaunt_postgis_source_date_epoch "$fake_root" >"$test_root/quoted.out" 2>"$test_root/quoted.err"; then fail "quoted source_date_epoch was accepted" fi grep -Fq 'canonical positive integer' "$test_root/quoted.err" || fail "noncanonical-value error was not actionable" -printf 'source_date_epoch = 1776193981\nsource_date_epoch = 1776193981\n' > "$fake_manifest" +printf 'source_date_epoch = 1780943336\nsource_date_epoch = 1780943336\n' > "$fake_manifest" if oliphaunt_postgis_source_date_epoch "$fake_root" >"$test_root/duplicate.out" 2>"$test_root/duplicate.err"; then fail "duplicate source_date_epoch was accepted" fi diff --git a/src/runtimes/liboliphaunt/native/tools/test-symbol-scope.sh b/src/runtimes/liboliphaunt/native/tools/test-symbol-scope.sh index fba7b205..3c8a1d9b 100755 --- a/src/runtimes/liboliphaunt/native/tools/test-symbol-scope.sh +++ b/src/runtimes/liboliphaunt/native/tools/test-symbol-scope.sh @@ -228,7 +228,7 @@ postgis_dependency_build_roots="$( in_array && /^\)$/ { exit } ' "$macos_build_script" )" -for dependency_build_root in json-c sqlite geos libxml2 proj; do +for dependency_build_root in json-c sqlite geos libxml2 proj gdal; do if ! grep -Fq '"$work_root/'"$dependency_build_root"'-native-build"' <<< "$postgis_dependency_build_roots"; then echo "native PostGIS dependency cache omits build root: $dependency_build_root" >&2 exit 1 diff --git a/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json b/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json index 65323c69..37bf02e4 100644 --- a/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json +++ b/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json @@ -104,7 +104,7 @@ "inputs": [ { "path": "src/extensions/external/postgis/source.toml", - "sha256": "cd720f3bae015515639273795df9fb6be6ba2ad7c9d6714d1b1e330643c33040" + "sha256": "f9f6168aa0733aa64b59c61e1592c7bc2c337defb981569bce87a70f7f185934" }, { "path": "src/extensions/external/postgis/tools/reproducible-bin/date", @@ -124,7 +124,7 @@ "inputs": [ { "path": "src/extensions/external/postgis/tools/build_wasix.sh", - "sha256": "d248aa8a29e89fd17a7a3e44b0bf92cc9084e15ea244ee9bb1e064965825fc66" + "sha256": "e9039cdd4c41a6a1d23b8439256588aa2c1ebab1825da73e54960336facdaa71" } ] }, @@ -162,15 +162,15 @@ }, { "path": "tools/xtask/src/asset_pipeline.rs", - "sha256": "be930c198af0b31432a9fa0dbd98fe5cad31d46474f8948660f4be3c2725ad47" + "sha256": "46121fe811da052c37b7afac640c81815b0fd0f5fb5008d772e6bb505b97ecfe" }, { "path": "tools/xtask/src/extension_catalog.rs", - "sha256": "c67f61826704e8ff71265af85f8552b1a134fba1252b46921d10dea6d51e854a" + "sha256": "b10fbf9af420ec1a4a9757c605a0a1214eede8c278365c15e5c8af0575e5d07d" }, { "path": "tools/xtask/src/fs_utils.rs", - "sha256": "d79e0cf095f3e0a6fd0b533afc17745c2929a21f58ed62f75fc99a1061db9e52" + "sha256": "fd82a4b6407811ed983b02a0e5b308b777d18e1829f5845a818ec2b0cbfe1c24" }, { "path": "tools/xtask/src/main.rs", @@ -212,27 +212,27 @@ }, { "path": "src/extensions/generated/docs/extension-evidence.json", - "sha256": "1b9ae33dc2ca239985c4cd5c1571e2669f2ea905acf45b6d81e4e31261e7f7bb" + "sha256": "76ee16070cd072ff872bd830997ec896f80b54f95f2810ccba8f6e4d3d48290e" }, { "path": "src/extensions/generated/docs/extensions.json", - "sha256": "e0741112aeb1d1a187ba3fda06a06302026048eceef08b389f2e55a94343cd69" + "sha256": "b199a0af1f19934bf48fedde86c92f936c1599b9ab69ab44a4ca0c55af0fae1b" }, { "path": "src/extensions/generated/extensions.build-plan.json", - "sha256": "24dceceb89d3f91da6c66bc309c4767408b71908bafd32027d784b2a5f975ca5" + "sha256": "ed8222fbcb0ce844cc57d0a3a891dc6163f4ab46bdce1c62d1bb3b53ea0206cc" }, { "path": "src/extensions/generated/extensions.catalog.json", - "sha256": "79ba39ba702d247fd975089cc812fbb4c3624ebd325f0fe1f6255dd575efddb7" + "sha256": "f23f6f94ce93eb529acac27647a6b293392f6b4a82a88aa8e5f9a41f88ee4653" }, { "path": "src/extensions/generated/mobile/static-extensions.tsv", - "sha256": "4bff991f8fce3c66f1da9428fd84861c4700a0e7c744cce51c1c5837f0cafd5d" + "sha256": "961262b7a21d53e1753aafdd706808eda3b719f9b82e4d2c2acd27556209bb98" }, { "path": "src/extensions/generated/mobile/static-registry.json", - "sha256": "6a66c127b3a95ce7697e16e8e416caa64a0cec325f3f00c6ff27f439e7b5ad20" + "sha256": "33f56a3a71439845abd043125c2dc9c0c67ad7cd134326116ce93ec021620452" }, { "path": "src/extensions/generated/pgxs-build.tsv", @@ -240,19 +240,19 @@ }, { "path": "src/extensions/generated/sdk/js.json", - "sha256": "d312d3d2b1b4f175eedb8c94c2fdffdf2d7959bcd5c58066137ed3e7f7522568" + "sha256": "32b2f7edae5b9c1be099b527543cc5142297e7002eee1437eb97edd18e589fcb" }, { "path": "src/extensions/generated/sdk/react-native.json", - "sha256": "a6a2a40751ab03ec43e6f4c4122951fdfd447535b380f5c10a6fef5e262ac446" + "sha256": "b8e83476a21082aef84e39af3e42786e55cfa01c84e34db2efe1d3da45f24468" }, { "path": "src/extensions/generated/sdk/rust.json", - "sha256": "fb62026022e218d3aa0cb0a920cd3da47a76e05d03b8066a42e1524894e500c3" + "sha256": "9a7323cb65836f6cc5397e94048c8c5bcfca0d178e9925261f4f1a68b79c1c4e" }, { "path": "src/extensions/generated/wasix/extensions.json", - "sha256": "68c213ed758bede5ff2231cad64e41ac93500633e811b8d352cfafb5cde9a641" + "sha256": "2df56d10e5de24b978773e878bfd16666675ed97b238a9c53133b151fbc32680" } ] }, @@ -264,7 +264,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/kotlin.json", - "sha256": "e6a713ed46ca57edfc92855317865114a54c8b415736759668294cc9c592713b" + "sha256": "39a8f931f2ebb049a51f7a01e5f583895b3bd745ec61c75cc4a057dd71a4cef1" } ] }, @@ -276,7 +276,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/swift.json", - "sha256": "48a6d606f83ab8b28afc7770068671d9e462d7ae5f47360df29a4f798ba374c3" + "sha256": "a1f854cf183d45187e64e16de568208c58ddc9cdbd6c51eb86c4b46d84e022eb" } ] }, @@ -377,5 +377,5 @@ ] } ], - "sha256": "763a5c1635efc9c5275c839eb4870379d19077cb6426f89cc690e9ae1890bbad" + "sha256": "734178655f201aa904bb85ab6904b0e809c911f215da96bc802911b53853b4a5" } diff --git a/src/runtimes/liboliphaunt/wasix/assets/build/build_wasix_gdal.sh b/src/runtimes/liboliphaunt/wasix/assets/build/build_wasix_gdal.sh new file mode 100755 index 00000000..e0ea8831 --- /dev/null +++ b/src/runtimes/liboliphaunt/wasix/assets/build/build_wasix_gdal.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$ROOT/wasix_third_party.sh" + +REPO_ROOT="$(oliphaunt_wasix_repo_root "$ROOT")" +GDAL_SOURCE_DIR="${GDAL_SOURCE_DIR:-$REPO_ROOT/target/oliphaunt-sources/checkouts/gdal}" +GENERATED_ROOT="$(oliphaunt_wasix_generated_root "$REPO_ROOT")" +GDAL_PREFIX="${GDAL_PREFIX:-$GENERATED_ROOT/work/gdal-wasix}" +GDAL_BUILD_DIR="${GDAL_BUILD_DIR:-$GENERATED_ROOT/work/gdal-wasix-build}" +GEOS_PREFIX="${GEOS_PREFIX:-$("$ROOT/build_wasix_geos.sh")}" +JSONC_PREFIX="${JSONC_PREFIX:-$("$ROOT/build_wasix_jsonc.sh")}" +LIBXML2_PREFIX="${LIBXML2_PREFIX:-$("$ROOT/build_wasix_libxml2.sh")}" +LIBICONV_PREFIX="${LIBICONV_PREFIX:-$("$ROOT/build_wasix_libiconv.sh")}" +PROJ_PREFIX="${PROJ_PREFIX:-$("$ROOT/build_wasix_proj.sh")}" +SQLITE_PREFIX="${SQLITE_PREFIX:-$("$ROOT/build_wasix_sqlite.sh")}" +JOBS="${JOBS:-4}" + +if [ ! -f "$GDAL_SOURCE_DIR/CMakeLists.txt" ]; then + echo "missing GDAL source checkout at $GDAL_SOURCE_DIR; run assets fetch/source-spine first" >&2 + exit 1 +fi + +. "$ROOT/docker_wasix_env.sh" +. "$ROOT/profile_flags.sh" +oliphaunt_wasix_apply_wasix_profile build + +source_commit="$(oliphaunt_wasix_source_commit "$GDAL_SOURCE_DIR")" +script_sha256="$(oliphaunt_wasix_script_sha256 "$0")" +helper_sha256="$(oliphaunt_wasix_script_sha256 "$ROOT/wasix_third_party.sh")" +compat_header="$ROOT/wasix_shim/gdal_wasix_compat.h" +compat_sha256="$(oliphaunt_wasix_script_sha256 "$compat_header")" +dependency_stamps="$( + for row in \ + "$GEOS_PREFIX/.oliphaunt-wasix-geos-build" \ + "$JSONC_PREFIX/.oliphaunt-wasix-json-c-build" \ + "$LIBICONV_PREFIX/.oliphaunt-wasix-libiconv-build" \ + "$LIBXML2_PREFIX/.oliphaunt-wasix-libxml2-build" \ + "$PROJ_PREFIX/.oliphaunt-wasix-proj-build" \ + "$SQLITE_PREFIX/.oliphaunt-wasix-sqlite-build" + do + printf '%s=%s\n' "$(basename "$row")" "$(cat "$row")" + done +)" +wasixcc_version="$(wasixcc --version 2>/dev/null)" +wasixcc_version="${wasixcc_version%%$'\n'*}" +stamp="source=$source_commit +script=$script_sha256 +helper=$helper_sha256 +compat=$compat_sha256 +$dependency_stamps +profile=$(oliphaunt_wasix_wasix_profile_signature) +wasixcc=$wasixcc_version +cmake=static-core-vrt-gtiff-internal-codecs-no-apps-no-optional-drivers" + +if [ -f "$GDAL_PREFIX/.oliphaunt-wasix-gdal-build" ] && + [ -f "$GDAL_PREFIX/include/gdal.h" ] && + [ -f "$GDAL_PREFIX/lib/libgdal.a" ] && + [ -x "$GDAL_PREFIX/bin/gdal-config" ] && + [ "$(cat "$GDAL_PREFIX/.oliphaunt-wasix-gdal-build")" = "$stamp" ]; then + echo "$GDAL_PREFIX" + exit 0 +fi + +{ + rm -rf "$GDAL_BUILD_DIR" "$GDAL_PREFIX" + mkdir -p "$GDAL_BUILD_DIR" "$(dirname "$GDAL_PREFIX")" + OLIPHAUNT_WASIX_CMAKE_C_FLAGS_EXTRA="-include $compat_header" \ + OLIPHAUNT_WASIX_CMAKE_CXX_FLAGS_EXTRA="-include $compat_header" \ + oliphaunt_wasix_static_cmake_build \ + "$GDAL_SOURCE_DIR" \ + "$GDAL_BUILD_DIR" \ + "$GDAL_PREFIX" \ + -DBASH_COMPLETIONS_DIR= \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_CSHARP_BINDINGS=OFF \ + -DBUILD_JAVA_BINDINGS=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF \ + -DBUILD_TESTING=OFF \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_ENABLE_DRIVER_GTIFF=ON \ + -DGDAL_ENABLE_DRIVER_VRT=ON \ + -DOGR_ENABLE_DRIVER_GEOJSON=ON \ + -DOGR_ENABLE_DRIVER_SHAPE=ON \ + -DGDAL_USE_EXTERNAL_LIBS=OFF \ + -DGDAL_USE_INTERNAL_LIBS=ON \ + -DGDAL_USE_OPENMP=OFF \ + -DHAVE_DLFCN_H=0 \ + -DHAVE_DL_ITERATE_PHDR=0 \ + -DHAVE_SCHED_GETAFFINITY=0 \ + -DGDAL_USE_CURL=OFF \ + -DGDAL_USE_OPENSSL=OFF \ + -DGDAL_USE_GEOS=ON \ + -DGEOS_INCLUDE_DIR="$GEOS_PREFIX/include" \ + -DGEOS_LIBRARY="$GEOS_PREFIX/lib/libgeos_c.a" \ + -DGDAL_USE_JSONC=ON \ + -DGDAL_USE_JSONC_INTERNAL=OFF \ + -DJSONC_INCLUDE_DIR="$JSONC_PREFIX/include/json-c" \ + -DJSONC_LIBRARY="$JSONC_PREFIX/lib/libjson-c.a" \ + -DGDAL_USE_LIBXML2=ON \ + -DLIBXML2_INCLUDE_DIR="$LIBXML2_PREFIX/include/libxml2" \ + -DLIBXML2_LIBRARY="$LIBXML2_PREFIX/lib/libxml2.a" \ + -DGDAL_USE_ICONV=ON \ + -DIconv_INCLUDE_DIR="$LIBICONV_PREFIX/include" \ + -DIconv_LIBRARY="$LIBICONV_PREFIX/lib/libiconv.a" \ + -DGDAL_USE_PROJ=ON \ + -DPROJ_INCLUDE_DIR="$PROJ_PREFIX/include" \ + -DPROJ_LIBRARY="$PROJ_PREFIX/lib/libproj.a" \ + -DGDAL_USE_SQLITE3=ON \ + -DSQLite3_INCLUDE_DIR="$SQLITE_PREFIX/include" \ + -DSQLite3_LIBRARY="$SQLITE_PREFIX/lib/libsqlite3.a" \ + -DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON +} >&2 + +test -f "$GDAL_PREFIX/include/gdal.h" +test -f "$GDAL_PREFIX/include/ogr_api.h" +test -f "$GDAL_PREFIX/lib/libgdal.a" +test -x "$GDAL_PREFIX/bin/gdal-config" +printf '%s\n' "$stamp" > "$GDAL_PREFIX/.oliphaunt-wasix-gdal-build" +echo "$GDAL_PREFIX" diff --git a/src/runtimes/liboliphaunt/wasix/assets/build/wasix_shim/gdal_wasix_compat.h b/src/runtimes/liboliphaunt/wasix/assets/build/wasix_shim/gdal_wasix_compat.h new file mode 100644 index 00000000..a3a81ec3 --- /dev/null +++ b/src/runtimes/liboliphaunt/wasix/assets/build/wasix_shim/gdal_wasix_compat.h @@ -0,0 +1,22 @@ +#ifndef OLIPHAUNT_GDAL_WASIX_COMPAT_H +#define OLIPHAUNT_GDAL_WASIX_COMPAT_H + +#include +#include + +/* + * GDAL's process-spawn portability layer unconditionally compiles its + * fork-based fallback on non-Windows targets. WASIX intentionally does not + * expose fork(2), and PostGIS raster does not use GDAL's subprocess helpers. + * Keep the API's normal failure behavior while making that unused fallback + * portable to the WASIX libc. + */ +static inline pid_t oliphaunt_gdal_wasix_fork_unavailable(void) +{ + errno = ENOSYS; + return -1; +} + +#define fork oliphaunt_gdal_wasix_fork_unavailable + +#endif diff --git a/src/runtimes/liboliphaunt/wasix/assets/build/wasix_third_party.sh b/src/runtimes/liboliphaunt/wasix/assets/build/wasix_third_party.sh index 9c11727b..b2905383 100755 --- a/src/runtimes/liboliphaunt/wasix/assets/build/wasix_third_party.sh +++ b/src/runtimes/liboliphaunt/wasix/assets/build/wasix_third_party.sh @@ -316,8 +316,8 @@ oliphaunt_wasix_static_cmake_build() { -DCMAKE_C_VISIBILITY_PRESET=hidden \ -DCMAKE_CXX_VISIBILITY_PRESET=hidden \ -DCMAKE_VISIBILITY_INLINES_HIDDEN=ON \ - -DCMAKE_C_FLAGS="$OLIPHAUNT_WASM_PROFILE_CFLAGS -fPIC -fvisibility=hidden -Wno-unused-command-line-argument" \ - -DCMAKE_CXX_FLAGS="$OLIPHAUNT_WASM_PROFILE_CFLAGS -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -Wno-unused-command-line-argument" \ + -DCMAKE_C_FLAGS="$OLIPHAUNT_WASM_PROFILE_CFLAGS -fPIC -fvisibility=hidden -Wno-unused-command-line-argument ${OLIPHAUNT_WASIX_CMAKE_C_FLAGS_EXTRA:-}" \ + -DCMAKE_CXX_FLAGS="$OLIPHAUNT_WASM_PROFILE_CFLAGS -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -Wno-unused-command-line-argument ${OLIPHAUNT_WASIX_CMAKE_CXX_FLAGS_EXTRA:-}" \ "$@" cmake --build "$build_dir" --parallel "$JOBS" cmake --install "$build_dir" diff --git a/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 b/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 index e02e39f5..de6c6e62 100644 --- a/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 +++ b/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 @@ -1 +1 @@ -178f0d74e7367e8dfe4eb44c32fb7ed62f0c17f30001b56b6d7f83617f11b5c5 +bb24309c2afb82a105149a6e27df0c57dab28915b5698d141946c7ea01b3a565 diff --git a/src/runtimes/liboliphaunt/wasix/assets/generated/wasix-dl.exports b/src/runtimes/liboliphaunt/wasix/assets/generated/wasix-dl.exports index a30064b6..c23245cd 100644 --- a/src/runtimes/liboliphaunt/wasix/assets/generated/wasix-dl.exports +++ b/src/runtimes/liboliphaunt/wasix/assets/generated/wasix-dl.exports @@ -140,9 +140,11 @@ GenericXLogRegisterBuffer GenericXLogStart GetAccessStrategy GetActiveSnapshot +GetAttributeByName GetAttributeByNum GetCachedExpression GetCommandTagName +GetConfigOptionByName GetCurrentSubTransactionId GetCurrentTimestamp GetDatabaseEncoding @@ -304,6 +306,7 @@ SPI_copytuple SPI_cursor_close SPI_cursor_fetch SPI_cursor_find +SPI_cursor_open_with_args SPI_cursor_open_with_paramlist SPI_cursor_parse_open SPI_datumTransfer @@ -324,6 +327,7 @@ SPI_getvalue SPI_keepplan SPI_modifytuple SPI_palloc +SPI_pfree SPI_plan_get_cached_plan SPI_plan_get_plan_sources SPI_plan_is_valid @@ -332,6 +336,7 @@ SPI_prepare_extended SPI_processed SPI_register_relation SPI_register_trigger_data +SPI_repalloc SPI_result SPI_result_code_string SPI_returntuple @@ -444,11 +449,11 @@ array_free_iterator array_iterate arraycontjoinsel arraycontsel +asc_tolower asin assign_expr_collations atan2l atexit -atof atoi be_lo_unlink bit_in @@ -683,6 +688,7 @@ free_object_addresses fseek fstat ftell +func_volatile function_parse_error_transpose fwrite gen_random_uuid @@ -710,6 +716,7 @@ get_fn_opclass_options get_func_arg_info get_func_name get_func_namespace +get_func_result_type get_func_support get_function_sibling_type get_mergejoin_opfamilies @@ -871,12 +878,13 @@ max_parallel_maintenance_workers memchr memcmp memset +mmap mul_size +munmap namein nanosleep network_cmp new_object_addresses -nextafterf nocache_index_getattr nocachegetattr nodeToString @@ -1057,7 +1065,6 @@ repalloc_huge reservoir_get_next_S reservoir_init_selection_state resetStringInfo -roundf s_lock sampler_random_fract sampler_random_init_state @@ -1085,7 +1092,6 @@ smgrnblocks smgropen smgrpin smgrtruncate -sprintf sqrtl sscanf standard_ExecutorEnd diff --git a/src/sdks/js/src/generated/extensions.ts b/src/sdks/js/src/generated/extensions.ts index 7536ef8c..f5fff004 100644 --- a/src/sdks/js/src/generated/extensions.ts +++ b/src/sdks/js/src/generated/extensions.ts @@ -37,7 +37,7 @@ export type GeneratedExtensionMetadata = { }; export const GENERATED_EXTENSION_METADATA_SHA256 = - 'cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7' as const; + '2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4' as const; export const GENERATED_EXTENSION_METADATA = [ { @@ -1101,18 +1101,50 @@ export const GENERATED_EXTENSION_METADATA = [ 'share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql', 'share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql', 'share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql', + 'share/postgresql/gdal/GDALLogoBW.svg', + 'share/postgresql/gdal/GDALLogoColor.svg', + 'share/postgresql/gdal/GDALLogoGS.svg', + 'share/postgresql/gdal/LICENSE.TXT', + 'share/postgresql/gdal/cubewerx_extra.wkt', + 'share/postgresql/gdal/ecw_cs.wkt', + 'share/postgresql/gdal/epsg.wkt', + 'share/postgresql/gdal/esri_StatePlane_extra.wkt', + 'share/postgresql/gdal/gdal_algorithm.schema.json', + 'share/postgresql/gdal/gdalicon.png', + 'share/postgresql/gdal/gdalinfo_output.schema.json', + 'share/postgresql/gdal/gdalmdiminfo_output.schema.json', + 'share/postgresql/gdal/gdalvrt.xsd', + 'share/postgresql/gdal/leaflet_template.html', + 'share/postgresql/gdal/ogr_fields_override.schema.json', + 'share/postgresql/gdal/ogrinfo_output.schema.json', + 'share/postgresql/gdal/ozi_datum.csv', + 'share/postgresql/gdal/ozi_ellips.csv', + 'share/postgresql/gdal/pci_datum.txt', + 'share/postgresql/gdal/pci_ellips.txt', + 'share/postgresql/gdal/stateplane.csv', + 'share/postgresql/gdal/template_tiles.mapml', + 'share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json', + 'share/postgresql/gdal/tms_MapML_APSTILE.json', + 'share/postgresql/gdal/tms_MapML_CBMTILE.json', + 'share/postgresql/gdal/tms_NZTM2000.json', 'share/postgresql/proj/proj.db', ], dependencies: [], desktopReleaseReady: true, displayName: 'PostGIS', extensionSqlFileNames: ['uninstall_postgis.sql'], - extensionSqlFilePrefixes: ['postgis_comments', 'postgis_proc_set_search_path', 'rtpostgis'], + extensionSqlFilePrefixes: [ + 'postgis_comments', + 'postgis_proc_set_search_path', + 'postgis_raster', + 'rtpostgis', + ], id: 'postgis', mavenArtifact: 'oliphaunt-extension-postgis', mavenGroup: 'dev.oliphaunt.extensions', mobileReleaseReady: true, nativeDependencies: [ + 'gdal:3.13.2-static', 'geos:3.14.1-static', 'proj:9.8.1-static', 'sqlite:3.53.1-static', @@ -1135,6 +1167,32 @@ export const GENERATED_EXTENSION_METADATA = [ 'contrib/postgis-3.6/spatial_ref_sys.sql', 'contrib/postgis-3.6/uninstall_legacy.sql', 'contrib/postgis-3.6/uninstall_postgis.sql', + 'gdal/GDALLogoBW.svg', + 'gdal/GDALLogoColor.svg', + 'gdal/GDALLogoGS.svg', + 'gdal/LICENSE.TXT', + 'gdal/cubewerx_extra.wkt', + 'gdal/ecw_cs.wkt', + 'gdal/epsg.wkt', + 'gdal/esri_StatePlane_extra.wkt', + 'gdal/gdal_algorithm.schema.json', + 'gdal/gdalicon.png', + 'gdal/gdalinfo_output.schema.json', + 'gdal/gdalmdiminfo_output.schema.json', + 'gdal/gdalvrt.xsd', + 'gdal/leaflet_template.html', + 'gdal/ogr_fields_override.schema.json', + 'gdal/ogrinfo_output.schema.json', + 'gdal/ozi_datum.csv', + 'gdal/ozi_ellips.csv', + 'gdal/pci_datum.txt', + 'gdal/pci_ellips.txt', + 'gdal/stateplane.csv', + 'gdal/template_tiles.mapml', + 'gdal/tms_LINZAntarticaMapTileGrid.json', + 'gdal/tms_MapML_APSTILE.json', + 'gdal/tms_MapML_CBMTILE.json', + 'gdal/tms_NZTM2000.json', 'proj/proj.db', ], selectedExtensionDependencies: [], diff --git a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extension-legal-catalog.json b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extension-legal-catalog.json index c39c7c21..9ff4ab4e 100644 --- a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extension-legal-catalog.json +++ b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extension-legal-catalog.json @@ -1,6 +1,6 @@ { "schema": "oliphaunt-android-extension-legal-catalog-v1", - "sourceCatalogSha256": "cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7", + "sourceCatalogSha256": "2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4", "contracts": [ { "scope": "aggregate", @@ -391,6 +391,7 @@ "target": "android-arm64-v8a", "profile": "external-native", "licenseFiles": [ + "share/licenses/gdal/LICENSE.TXT", "share/licenses/geos/COPYING", "share/licenses/geos/src/deps/ryu/LICENSE", "share/licenses/geos/src/deps/ryu/LICENSE-Apache2", @@ -421,6 +422,12 @@ "sha256": "81765aa852ba082089aceef23be857f36cdf98543c480bf67b764ff011b50619", "mode": "0644" }, + { + "path": "share/licenses/gdal/LICENSE.TXT", + "bytes": 21841, + "sha256": "1dae3468e81d00da56e2936f74d33b8b3ad09d726437f19ce209a5dabea41f77", + "mode": "0644" + }, { "path": "share/licenses/geos/COPYING", "bytes": 26530, @@ -526,6 +533,7 @@ "target": "android-x86_64", "profile": "external-native", "licenseFiles": [ + "share/licenses/gdal/LICENSE.TXT", "share/licenses/geos/COPYING", "share/licenses/geos/src/deps/ryu/LICENSE", "share/licenses/geos/src/deps/ryu/LICENSE-Apache2", @@ -556,6 +564,12 @@ "sha256": "81765aa852ba082089aceef23be857f36cdf98543c480bf67b764ff011b50619", "mode": "0644" }, + { + "path": "share/licenses/gdal/LICENSE.TXT", + "bytes": 21841, + "sha256": "1dae3468e81d00da56e2936f74d33b8b3ad09d726437f19ce209a5dabea41f77", + "mode": "0644" + }, { "path": "share/licenses/geos/COPYING", "bytes": 26530, @@ -2447,6 +2461,7 @@ "target": "android-arm64-v8a", "profile": "external-native", "licenseFiles": [ + "share/licenses/gdal/LICENSE.TXT", "share/licenses/geos/COPYING", "share/licenses/geos/src/deps/ryu/LICENSE", "share/licenses/geos/src/deps/ryu/LICENSE-Apache2", @@ -2477,6 +2492,12 @@ "sha256": "81765aa852ba082089aceef23be857f36cdf98543c480bf67b764ff011b50619", "mode": "0644" }, + { + "path": "files/share/licenses/gdal/LICENSE.TXT", + "bytes": 21841, + "sha256": "1dae3468e81d00da56e2936f74d33b8b3ad09d726437f19ce209a5dabea41f77", + "mode": "0644" + }, { "path": "files/share/licenses/geos/COPYING", "bytes": 26530, @@ -2582,6 +2603,7 @@ "target": "android-x86_64", "profile": "external-native", "licenseFiles": [ + "share/licenses/gdal/LICENSE.TXT", "share/licenses/geos/COPYING", "share/licenses/geos/src/deps/ryu/LICENSE", "share/licenses/geos/src/deps/ryu/LICENSE-Apache2", @@ -2612,6 +2634,12 @@ "sha256": "81765aa852ba082089aceef23be857f36cdf98543c480bf67b764ff011b50619", "mode": "0644" }, + { + "path": "files/share/licenses/gdal/LICENSE.TXT", + "bytes": 21841, + "sha256": "1dae3468e81d00da56e2936f74d33b8b3ad09d726437f19ce209a5dabea41f77", + "mode": "0644" + }, { "path": "files/share/licenses/geos/COPYING", "bytes": 26530, diff --git a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extensions.properties b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extensions.properties index 4758a3db..da0d088f 100644 --- a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extensions.properties +++ b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/main/resources/dev/oliphaunt/android/extensions.properties @@ -1,7 +1,7 @@ # This file is generated by src/extensions/tools/check-extension-model.mjs. # Do not edit by hand. schema=oliphaunt-android-extension-catalog-v1 -catalogSha256=cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7 +catalogSha256=2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4 extension.amcheck.releaseProduct=oliphaunt-extension-contrib-pg18 extension.amcheck.mavenGroup=dev.oliphaunt.extensions extension.amcheck.mavenArtifact=oliphaunt-extension-contrib-pg18 diff --git a/src/sdks/kotlin/oliphaunt/src/generated/extensions.json b/src/sdks/kotlin/oliphaunt/src/generated/extensions.json index 43d02622..113c17b9 100644 --- a/src/sdks/kotlin/oliphaunt/src/generated/extensions.json +++ b/src/sdks/kotlin/oliphaunt/src/generated/extensions.json @@ -1,6 +1,6 @@ { "consumer": "kotlin", - "extension-catalog-sha256": "cd1ce8a2c4746a2f0697595c9203977f2eaf5308e5b6a118212116547a9e8ac7", + "extension-catalog-sha256": "2627b4a5a20c8e79fdd9d3c949f4ed8b5c4f71ece7e76084187f0bf0156fbbe4", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1112,6 +1112,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1123,6 +1149,7 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", @@ -1130,6 +1157,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1144,6 +1172,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1159,6 +1192,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/sdks/react-native/src/generated/extensions.json b/src/sdks/react-native/src/generated/extensions.json index a1818fd5..ba6b3437 100644 --- a/src/sdks/react-native/src/generated/extensions.json +++ b/src/sdks/react-native/src/generated/extensions.json @@ -1,6 +1,6 @@ { "consumer": "react-native", - "extension-catalog-sha256": "112d2060de12e08bf955c9f0f487b075f4ddb7273cb8130f60dc629733b4d4db", + "extension-catalog-sha256": "ec3c183ad919eff787020841ec9f02730a9956db663a8d4b40b61758359860dc", "extensions": [ { "archive": "extensions/amcheck.tar.zst", @@ -1144,6 +1144,32 @@ "share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql", "share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql", "share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql", + "share/postgresql/gdal/GDALLogoBW.svg", + "share/postgresql/gdal/GDALLogoColor.svg", + "share/postgresql/gdal/GDALLogoGS.svg", + "share/postgresql/gdal/LICENSE.TXT", + "share/postgresql/gdal/cubewerx_extra.wkt", + "share/postgresql/gdal/ecw_cs.wkt", + "share/postgresql/gdal/epsg.wkt", + "share/postgresql/gdal/esri_StatePlane_extra.wkt", + "share/postgresql/gdal/gdal_algorithm.schema.json", + "share/postgresql/gdal/gdalicon.png", + "share/postgresql/gdal/gdalinfo_output.schema.json", + "share/postgresql/gdal/gdalmdiminfo_output.schema.json", + "share/postgresql/gdal/gdalvrt.xsd", + "share/postgresql/gdal/leaflet_template.html", + "share/postgresql/gdal/ogr_fields_override.schema.json", + "share/postgresql/gdal/ogrinfo_output.schema.json", + "share/postgresql/gdal/ozi_datum.csv", + "share/postgresql/gdal/ozi_ellips.csv", + "share/postgresql/gdal/pci_datum.txt", + "share/postgresql/gdal/pci_ellips.txt", + "share/postgresql/gdal/stateplane.csv", + "share/postgresql/gdal/template_tiles.mapml", + "share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json", + "share/postgresql/gdal/tms_MapML_APSTILE.json", + "share/postgresql/gdal/tms_MapML_CBMTILE.json", + "share/postgresql/gdal/tms_NZTM2000.json", "share/postgresql/proj/proj.db" ], "dependencies": [], @@ -1155,10 +1181,12 @@ "extension-sql-file-prefixes": [ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis" ], "id": "postgis", "ios-static-dependencies": [ + "gdal", "geos", "geos-c", "json-c", @@ -1170,6 +1198,7 @@ "maven-group": "dev.oliphaunt.extensions", "mobile-release-ready": true, "native-dependencies": [ + "gdal:3.13.2-static", "geos:3.14.1-static", "proj:9.8.1-static", "sqlite:3.53.1-static", @@ -1184,6 +1213,11 @@ "release-product": "oliphaunt-extension-postgis", "runtime-bound": false, "runtime-environment": [ + { + "name": "GDAL_DATA", + "path": "share/postgresql/gdal", + "required_file": "gdalvrt.xsd" + }, { "name": "PROJ_DATA", "path": "share/postgresql/proj", @@ -1199,6 +1233,32 @@ "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db" ], "selected-extension-dependencies": [], diff --git a/src/sdks/react-native/src/generated/extensions.ts b/src/sdks/react-native/src/generated/extensions.ts index 80a6ca69..542eb023 100644 --- a/src/sdks/react-native/src/generated/extensions.ts +++ b/src/sdks/react-native/src/generated/extensions.ts @@ -38,7 +38,7 @@ export type GeneratedExtensionMetadata = { }; export const GENERATED_EXTENSION_METADATA_SHA256 = - '112d2060de12e08bf955c9f0f487b075f4ddb7273cb8130f60dc629733b4d4db' as const; + 'ec3c183ad919eff787020841ec9f02730a9956db663a8d4b40b61758359860dc' as const; export const GENERATED_EXTENSION_METADATA = [ { @@ -1132,19 +1132,51 @@ export const GENERATED_EXTENSION_METADATA = [ 'share/postgresql/contrib/postgis-3.6/spatial_ref_sys.sql', 'share/postgresql/contrib/postgis-3.6/uninstall_legacy.sql', 'share/postgresql/contrib/postgis-3.6/uninstall_postgis.sql', + 'share/postgresql/gdal/GDALLogoBW.svg', + 'share/postgresql/gdal/GDALLogoColor.svg', + 'share/postgresql/gdal/GDALLogoGS.svg', + 'share/postgresql/gdal/LICENSE.TXT', + 'share/postgresql/gdal/cubewerx_extra.wkt', + 'share/postgresql/gdal/ecw_cs.wkt', + 'share/postgresql/gdal/epsg.wkt', + 'share/postgresql/gdal/esri_StatePlane_extra.wkt', + 'share/postgresql/gdal/gdal_algorithm.schema.json', + 'share/postgresql/gdal/gdalicon.png', + 'share/postgresql/gdal/gdalinfo_output.schema.json', + 'share/postgresql/gdal/gdalmdiminfo_output.schema.json', + 'share/postgresql/gdal/gdalvrt.xsd', + 'share/postgresql/gdal/leaflet_template.html', + 'share/postgresql/gdal/ogr_fields_override.schema.json', + 'share/postgresql/gdal/ogrinfo_output.schema.json', + 'share/postgresql/gdal/ozi_datum.csv', + 'share/postgresql/gdal/ozi_ellips.csv', + 'share/postgresql/gdal/pci_datum.txt', + 'share/postgresql/gdal/pci_ellips.txt', + 'share/postgresql/gdal/stateplane.csv', + 'share/postgresql/gdal/template_tiles.mapml', + 'share/postgresql/gdal/tms_LINZAntarticaMapTileGrid.json', + 'share/postgresql/gdal/tms_MapML_APSTILE.json', + 'share/postgresql/gdal/tms_MapML_CBMTILE.json', + 'share/postgresql/gdal/tms_NZTM2000.json', 'share/postgresql/proj/proj.db', ], dependencies: [], desktopReleaseReady: true, displayName: 'PostGIS', extensionSqlFileNames: ['uninstall_postgis.sql'], - extensionSqlFilePrefixes: ['postgis_comments', 'postgis_proc_set_search_path', 'rtpostgis'], + extensionSqlFilePrefixes: [ + 'postgis_comments', + 'postgis_proc_set_search_path', + 'postgis_raster', + 'rtpostgis', + ], id: 'postgis', - iosStaticDependencies: ['geos', 'geos-c', 'json-c', 'libxml2', 'proj', 'sqlite'], + iosStaticDependencies: ['gdal', 'geos', 'geos-c', 'json-c', 'libxml2', 'proj', 'sqlite'], mavenArtifact: 'oliphaunt-extension-postgis', mavenGroup: 'dev.oliphaunt.extensions', mobileReleaseReady: true, nativeDependencies: [ + 'gdal:3.13.2-static', 'geos:3.14.1-static', 'proj:9.8.1-static', 'sqlite:3.53.1-static', @@ -1167,6 +1199,32 @@ export const GENERATED_EXTENSION_METADATA = [ 'contrib/postgis-3.6/spatial_ref_sys.sql', 'contrib/postgis-3.6/uninstall_legacy.sql', 'contrib/postgis-3.6/uninstall_postgis.sql', + 'gdal/GDALLogoBW.svg', + 'gdal/GDALLogoColor.svg', + 'gdal/GDALLogoGS.svg', + 'gdal/LICENSE.TXT', + 'gdal/cubewerx_extra.wkt', + 'gdal/ecw_cs.wkt', + 'gdal/epsg.wkt', + 'gdal/esri_StatePlane_extra.wkt', + 'gdal/gdal_algorithm.schema.json', + 'gdal/gdalicon.png', + 'gdal/gdalinfo_output.schema.json', + 'gdal/gdalmdiminfo_output.schema.json', + 'gdal/gdalvrt.xsd', + 'gdal/leaflet_template.html', + 'gdal/ogr_fields_override.schema.json', + 'gdal/ogrinfo_output.schema.json', + 'gdal/ozi_datum.csv', + 'gdal/ozi_ellips.csv', + 'gdal/pci_datum.txt', + 'gdal/pci_ellips.txt', + 'gdal/stateplane.csv', + 'gdal/template_tiles.mapml', + 'gdal/tms_LINZAntarticaMapTileGrid.json', + 'gdal/tms_MapML_APSTILE.json', + 'gdal/tms_MapML_CBMTILE.json', + 'gdal/tms_NZTM2000.json', 'proj/proj.db', ], selectedExtensionDependencies: [], diff --git a/src/sdks/react-native/tools/stage-ios-app.test.mjs b/src/sdks/react-native/tools/stage-ios-app.test.mjs index 82d319d9..cd3a9859 100755 --- a/src/sdks/react-native/tools/stage-ios-app.test.mjs +++ b/src/sdks/react-native/tools/stage-ios-app.test.mjs @@ -815,7 +815,7 @@ async function createFixture(root) { if (fixture.sqlName === "postgis") { assert.deepEqual( generated["ios-static-dependencies"], - ["geos", "geos-c", "json-c", "libxml2", "proj", "sqlite"], + ["gdal", "geos", "geos-c", "json-c", "libxml2", "proj", "sqlite"], ); } const config = { @@ -977,6 +977,7 @@ async function main() { const frameworkNames = (await fs.readdir(path.join(output, "frameworks", "extensions"))).sort(); assert.deepEqual(frameworkNames, [ + "liboliphaunt_dependency_gdal.xcframework", "liboliphaunt_dependency_geos-c.xcframework", "liboliphaunt_dependency_geos.xcframework", "liboliphaunt_dependency_json-c.xcframework", diff --git a/src/sdks/rust/src/generated/extensions.rs b/src/sdks/rust/src/generated/extensions.rs index 2caf1841..5da915f5 100644 --- a/src/sdks/rust/src/generated/extensions.rs +++ b/src/sdks/rust/src/generated/extensions.rs @@ -687,6 +687,32 @@ pub(super) const fn extension_data_files(extension: Extension) -> &'static [&'st "contrib/postgis-3.6/spatial_ref_sys.sql", "contrib/postgis-3.6/uninstall_legacy.sql", "contrib/postgis-3.6/uninstall_postgis.sql", + "gdal/GDALLogoBW.svg", + "gdal/GDALLogoColor.svg", + "gdal/GDALLogoGS.svg", + "gdal/LICENSE.TXT", + "gdal/cubewerx_extra.wkt", + "gdal/ecw_cs.wkt", + "gdal/epsg.wkt", + "gdal/esri_StatePlane_extra.wkt", + "gdal/gdal_algorithm.schema.json", + "gdal/gdalicon.png", + "gdal/gdalinfo_output.schema.json", + "gdal/gdalmdiminfo_output.schema.json", + "gdal/gdalvrt.xsd", + "gdal/leaflet_template.html", + "gdal/ogr_fields_override.schema.json", + "gdal/ogrinfo_output.schema.json", + "gdal/ozi_datum.csv", + "gdal/ozi_ellips.csv", + "gdal/pci_datum.txt", + "gdal/pci_ellips.txt", + "gdal/stateplane.csv", + "gdal/template_tiles.mapml", + "gdal/tms_LINZAntarticaMapTileGrid.json", + "gdal/tms_MapML_APSTILE.json", + "gdal/tms_MapML_CBMTILE.json", + "gdal/tms_NZTM2000.json", "proj/proj.db", ], Extension::Seg => &[], @@ -738,6 +764,7 @@ pub(super) const fn extension_sql_file_prefixes(extension: Extension) -> &'stati Extension::Postgis => &[ "postgis_comments", "postgis_proc_set_search_path", + "postgis_raster", "rtpostgis", ], Extension::Seg => &[], @@ -835,11 +862,18 @@ pub(super) const fn runtime_environment( Extension::PgWalinspect => &[], Extension::Pgcrypto => &[], Extension::Pgtap => &[], - Extension::Postgis => &[ExtensionRuntimeEnvironment { - name: "PROJ_DATA", - relative_path: "share/postgresql/proj", - required_file: "proj.db", - }], + Extension::Postgis => &[ + ExtensionRuntimeEnvironment { + name: "GDAL_DATA", + relative_path: "share/postgresql/gdal", + required_file: "gdalvrt.xsd", + }, + ExtensionRuntimeEnvironment { + name: "PROJ_DATA", + relative_path: "share/postgresql/proj", + required_file: "proj.db", + }, + ], Extension::Seg => &[], Extension::Tablefunc => &[], Extension::Tcn => &[], diff --git a/src/sdks/rust/src/liboliphaunt/root/extensions.rs b/src/sdks/rust/src/liboliphaunt/root/extensions.rs index fd97d4b6..539de31d 100644 --- a/src/sdks/rust/src/liboliphaunt/root/extensions.rs +++ b/src/sdks/rust/src/liboliphaunt/root/extensions.rs @@ -233,6 +233,14 @@ mod tests { postgis, "postgis_proc_set_search_path.sql" )); + assert!(extension_sql_file_belongs( + postgis, + "postgis_raster.control" + )); + assert!(extension_sql_file_belongs( + postgis, + "postgis_raster--3.6.4.sql" + )); assert!(extension_sql_file_belongs(postgis, "rtpostgis--3.6.sql")); assert!(!extension_sql_file_belongs("pgtap", "postgis_comments.sql")); diff --git a/src/sdks/rust/src/runtime_resources.rs b/src/sdks/rust/src/runtime_resources.rs index 5e3582f5..91eff36e 100644 --- a/src/sdks/rust/src/runtime_resources.rs +++ b/src/sdks/rust/src/runtime_resources.rs @@ -1800,6 +1800,10 @@ fn runtime_extension_sql_file_belongs( .extension_sql_file_prefixes .iter() .any(|prefix| file_name.starts_with(prefix))) + || extension + .extension_sql_file_prefixes + .iter() + .any(|prefix| file_name == format!("{prefix}.control")) } fn require_mobile_static_registry_ready(metadata: &MobileStaticRegistryMetadata) -> Result<()> { diff --git a/src/sdks/rust/tests/fixtures/postgis-smoke.sql b/src/sdks/rust/tests/fixtures/postgis-smoke.sql index 4f05b7be..85c48d46 100644 --- a/src/sdks/rust/tests/fixtures/postgis-smoke.sql +++ b/src/sdks/rust/tests/fixtures/postgis-smoke.sql @@ -1,3 +1,7 @@ +CREATE EXTENSION IF NOT EXISTS postgis_raster; +-- oliphaunt-statement +SET postgis.gdal_enabled_drivers = 'ENABLE_ALL'; +-- oliphaunt-statement DROP TABLE IF EXISTS liboliphaunt_postgis_points; -- oliphaunt-statement CREATE TEMP TABLE liboliphaunt_postgis_points(id int PRIMARY KEY, geom geometry(Point, 4326)); @@ -15,6 +19,9 @@ DECLARE area float8; polygons int; nearby int; + gdal_drivers int; + raster_roundtrip raster; + raster_value float8; BEGIN SELECT ST_Distance(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('POINT(3 4)')) INTO distance; IF distance <> 5 THEN @@ -56,6 +63,29 @@ BEGIN IF nearby <> 2 THEN RAISE EXCEPTION 'postgis dwithin failed: %', nearby; END IF; + SELECT count(*) INTO gdal_drivers + FROM ST_GDALDrivers() + WHERE short_name = 'GTiff' AND can_read AND can_write; + IF gdal_drivers <> 1 THEN + RAISE EXCEPTION 'postgis raster GeoTIFF driver is unavailable'; + END IF; + SELECT ST_FromGDALRaster( + ST_AsGDALRaster( + ST_AddBand( + ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 4326), + '8BUI'::text, + 7::double precision, + 0::double precision + ), + 'GTiff' + ) + ) INTO raster_roundtrip; + SELECT ST_Value(raster_roundtrip, 1, 1, 1) INTO raster_value; + IF raster_value <> 7 OR ST_SRID(raster_roundtrip) <> 4326 THEN + RAISE EXCEPTION 'postgis raster GDAL round-trip failed: value %, srid %', + raster_value, + ST_SRID(raster_roundtrip); + END IF; END $$; -- oliphaunt-statement DROP TABLE IF EXISTS liboliphaunt_postgis_points; diff --git a/src/sdks/rust/tests/sdk_extensions.rs b/src/sdks/rust/tests/sdk_extensions.rs index 28f25d8b..90aa1711 100644 --- a/src/sdks/rust/tests/sdk_extensions.rs +++ b/src/sdks/rust/tests/sdk_extensions.rs @@ -291,13 +291,13 @@ fn native_extension_manifest_matches_build_required_artifacts() { } } - let expected_controls = NATIVE_EXTENSION_MANIFEST + let mut expected_controls = NATIVE_EXTENSION_MANIFEST .iter() .filter(|entry| entry.first_party_artifact()) .filter(|entry| entry.creates_extension) .map(|entry| entry.sql_name.to_owned()) .collect::>(); - let expected_modules = NATIVE_EXTENSION_MANIFEST + let mut expected_modules = NATIVE_EXTENSION_MANIFEST .iter() .filter(|entry| entry.first_party_artifact()) .filter_map(|entry| match entry.module { @@ -306,6 +306,12 @@ fn native_extension_manifest_matches_build_required_artifacts() { }) .collect::>(); + // The PostGIS product owns the separately createable raster companion and + // its dynamic module even though the public SDK selection remains the + // single dependency-closed `Extension::Postgis` product. + expected_controls.insert("postgis_raster".to_owned()); + expected_modules.insert("postgis_raster-3".to_owned()); + assert_eq!( actual_controls, expected_controls, "build-required extension control files must match NATIVE_EXTENSION_MANIFEST" diff --git a/src/sdks/swift/.release-semantic-inputs.json b/src/sdks/swift/.release-semantic-inputs.json index 27355e82..d7f900e5 100644 --- a/src/sdks/swift/.release-semantic-inputs.json +++ b/src/sdks/swift/.release-semantic-inputs.json @@ -46,7 +46,7 @@ "inputs": [ { "path": "src/extensions/generated/sdk/swift.json", - "sha256": "48a6d606f83ab8b28afc7770068671d9e462d7ae5f47360df29a4f798ba374c3" + "sha256": "a1f854cf183d45187e64e16de568208c58ddc9cdbd6c51eb86c4b46d84e022eb" } ] }, @@ -99,5 +99,5 @@ ] } ], - "sha256": "036f517f9b6cb431205dce53ba03f7e7bb4c4d12b30a6156524cd3b5878c07cc" + "sha256": "36b794bd6e4532ae33d24f0a10bb25b7611b253c06cd6a4ada5c3b4a37860f53" } diff --git a/tools/dev/bun.sh b/tools/dev/bun.sh index 8f077c5f..e8fe5e52 100755 --- a/tools/dev/bun.sh +++ b/tools/dev/bun.sh @@ -1,10 +1,14 @@ #!/usr/bin/env bash set -euo pipefail -root="$(git rev-parse --show-toplevel 2>/dev/null)" || { - echo "must run inside the Oliphaunt git checkout" >&2 - exit 1 -} +if ! root="$(git rev-parse --show-toplevel 2>/dev/null)"; then + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + root="$(cd "$script_dir/../.." && pwd)" + if [ ! -f "$root/package.json" ] || [ ! -d "$root/src/runtimes/liboliphaunt" ]; then + echo "must run inside the Oliphaunt git checkout" >&2 + exit 1 + fi +fi cd "$root" fail() { diff --git a/tools/dev/install-pinned-js-runtime.sh b/tools/dev/install-pinned-js-runtime.sh index a48c4f7a..1565e776 100755 --- a/tools/dev/install-pinned-js-runtime.sh +++ b/tools/dev/install-pinned-js-runtime.sh @@ -6,11 +6,15 @@ fail() { exit 1 } +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="${OLIPHAUNT_PINNED_TOOL_ROOT:-}" if [ -z "$root" ]; then - root="$(git rev-parse --show-toplevel 2>/dev/null)" || fail "must run inside the Oliphaunt checkout" + if ! root="$(git rev-parse --show-toplevel 2>/dev/null)"; then + root="$(cd "$script_dir/../.." && pwd)" + [ -f "$root/package.json" ] && [ -d "$root/src/runtimes/liboliphaunt" ] || + fail "must run inside the Oliphaunt checkout" + fi fi -script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" tool="${1:-}" shift || true expected_input="" diff --git a/tools/policy/assertions/assert-source-inputs.mjs b/tools/policy/assertions/assert-source-inputs.mjs index 2ea04f01..4bd450a4 100755 --- a/tools/policy/assertions/assert-source-inputs.mjs +++ b/tools/policy/assertions/assert-source-inputs.mjs @@ -1116,6 +1116,7 @@ function checkExtensions() { 'src/extensions/external/README.md', 'src/extensions/external/vector/source.toml', 'src/extensions/external/postgis/source.toml', + 'src/extensions/external/postgis/dependencies/gdal/source.toml', 'src/extensions/external/postgis/dependencies/geos/source.toml', 'src/extensions/external/postgis/dependencies/proj/source.toml', 'src/extensions/external/postgis/dependencies/sqlite/source.toml', @@ -1164,7 +1165,7 @@ function checkExtensions() { requireFile(path); } - requireText('src/extensions/external/postgis/source.toml', 'source_date_epoch = 1776193981'); + requireText('src/extensions/external/postgis/source.toml', 'source_date_epoch = 1780943336'); const postgisReproducibleTimeInputs = [ '/src/extensions/external/postgis/source.toml', diff --git a/tools/release/extension-upstream-licenses.test.mjs b/tools/release/extension-upstream-licenses.test.mjs index 792d88fd..98ed9a32 100644 --- a/tools/release/extension-upstream-licenses.test.mjs +++ b/tools/release/extension-upstream-licenses.test.mjs @@ -60,6 +60,7 @@ test("every active external release has an exact upstream license contract", () assert.equal(new Set(row.files.map((file) => file.destination)).size, row.files.length); } assert.deepEqual(extensionUpstreamLicenseSources().map((source) => source.id), [ + "gdal", "geos", "json-c", "libiconv", @@ -201,6 +202,7 @@ test("the contract retains dependency licenses and pgtap's complete upstream gra const rows = extensionUpstreamLicenseRows(); const postgis = rows.find((row) => row.sqlName === "postgis"); assert.deepEqual([...new Set(postgis.files.map((file) => file.checkout))], [ + "gdal", "geos", "json-c", "libiconv", @@ -327,6 +329,7 @@ test("carrier legal roles derive exact contrib and external payload closure", () ); assert.deepEqual(postgis.upstreamMembers, ["postgis"]); assert.deepEqual(postgis.licenseFiles, [ + "share/licenses/gdal/LICENSE.TXT", "share/licenses/geos/COPYING", "share/licenses/geos/src/deps/ryu/LICENSE", "share/licenses/geos/src/deps/ryu/LICENSE-Apache2", diff --git a/tools/release/github-content-write-pacer.test.mjs b/tools/release/github-content-write-pacer.test.mjs index 08e1726c..11a074fd 100644 --- a/tools/release/github-content-write-pacer.test.mjs +++ b/tools/release/github-content-write-pacer.test.mjs @@ -332,7 +332,7 @@ test("pacing that crosses the absolute deadline issues no transport attempt", (t assert.equal(spawnCalls, 0); }); -test("the live-derived 18-product/141-asset first release fits both GitHub hourly ceilings", () => { +test("the live-derived 18-product/142-asset first release fits both GitHub hourly ceilings", () => { const graph = loadGraph("github-content-write-pacer.test"); const productCount = Object.keys(graph.products).length; assert.equal(productCount, 18); @@ -348,7 +348,7 @@ test("the live-derived 18-product/141-asset first release fits both GitHub hourl { product, publishedOnly: true, surface: "github-release" }, "github-content-write-pacer.test", ).length, 0); - assert.equal(extensionAssetCount, 108); + assert.equal(extensionAssetCount, 109); assert.equal(binaryAssetCount, 33); const assetCount = extensionAssetCount + binaryAssetCount; const extensionProducts = new Set(exactExtensionProducts("github-content-write-pacer.test")); @@ -379,17 +379,17 @@ test("the live-derived 18-product/141-asset first release fits both GitHub hourl }); assert.equal(sourceTagWriteCount(graph, ["oliphaunt-swift"]), 1); assert.equal(sourceTagWriteCount(graph, ["oliphaunt-rust"]), 0); - assert.equal(budget.preRegistryContentWrites, 185); - assert.equal(budget.totalContentWrites, 209); + assert.equal(budget.preRegistryContentWrites, 186); + assert.equal(budget.totalContentWrites, 210); assert.equal(FIRST_RELEASE_TRANSFER_REQUEST_TOTAL, 88); assert.equal(FIRST_RELEASE_NOMINAL_CORE_REQUESTS, 579); - assert.equal(budget.conservativeCoreRequests, 579); + assert.equal(budget.conservativeCoreRequests, 580); assert.equal(conservativeCoreRequestCount({ - assetCount: 141, + assetCount: 142, assetCounts, attestationWrites: 6, productCount, - }), 579); + }), 580); assert.equal(GITHUB_CONTENT_WRITES_PER_ROLLING_HOUR, 361); assert.equal(GITHUB_CONTENT_WRITES_PER_ROLLING_MINUTE, 7); assert.equal( @@ -407,7 +407,7 @@ test("the live-derived 18-product/141-asset first release fits both GitHub hourl assert.equal(budget.projectedRollingCoreRequests, 832); assert.ok(budget.projectedRollingCoreRequests < 900); assert.ok(500 - GITHUB_CONTENT_WRITES_PER_ROLLING_HOUR >= 130); - assert.equal(budget.totalPacingMs, GITHUB_CONTENT_WRITE_COLD_START_MS + (209 * 10_000)); + assert.equal(budget.totalPacingMs, GITHUB_CONTENT_WRITE_COLD_START_MS + (210 * 10_000)); assert.ok((2 * productCount * GITHUB_CONTENT_WRITE_INTERVAL_MS) < (30 * 60_000), "draft staging fits its operation budget"); assert.ok((Math.max(...assetCounts.values()) * GITHUB_CONTENT_WRITE_INTERVAL_MS) < (20 * 60_000), "largest product pacing fits its count-derived upload budget"); assert.ok( @@ -441,7 +441,7 @@ test("the live-derived 18-product/141-asset first release fits both GitHub hourl assert.ok( budget.assetUploadPlan.productCount === 12 && budget.assetUploadPlan.waves.length === 3 - && budget.assetUploadPlan.totalWindowMs === 82.5 * 60_000, + && budget.assetUploadPlan.totalWindowMs === 5_020_000, "the exact asset topology uses three bounded five-lane shared-pacer waves", ); const admitted = assertReleaseRequestWindow(budget, { @@ -462,11 +462,11 @@ test("the live-derived 18-product/141-asset first release fits both GitHub hourl carrierCounts.jsr.length * NORMAL_REGISTRY_JSR_SECONDS_PER_CARRIER, ) + NORMAL_REGISTRY_EXECUTOR_RESERVE_SECONDS; assert.equal(independentLaneUpperBoundSeconds, 18_300); - assert.equal(admitted.preRegistryOperationSeconds, 14_430); + assert.equal(admitted.preRegistryOperationSeconds, 14_500); assert.equal(admitted.finalizationStepTimeoutSeconds, RELEASE_FINALIZATION_STEP_TIMEOUT_SECONDS); assert.equal(admitted.cleanupMarginSeconds, RELEASE_FINALIZATION_CLEANUP_MARGIN_SECONDS); assert.equal(admitted.minimumFinalizationSeconds, RELEASE_MINIMUM_FINALIZATION_SECONDS); - assert.equal(admitted.simulatedRegistryDeadlineEpochSeconds, 3_510); + assert.equal(admitted.simulatedRegistryDeadlineEpochSeconds, 3_440); assert.ok( admitted.simulatedRegistryDeadlineEpochSeconds < independentLaneUpperBoundSeconds, "the staging simulation honestly exercises dependency-closed subset admission instead of pretending every npm carrier fits", diff --git a/tools/release/github-release-asset-upload-plan.test.mjs b/tools/release/github-release-asset-upload-plan.test.mjs index cf1efc52..b6f2d074 100644 --- a/tools/release/github-release-asset-upload-plan.test.mjs +++ b/tools/release/github-release-asset-upload-plan.test.mjs @@ -44,24 +44,24 @@ function liveAssetCounts() { } describe("bounded concurrent GitHub release asset upload plan", () => { - test("admits the exact 18-product/141-asset topology as three bounded five-lane waves", () => { + test("admits the exact 18-product/142-asset topology as three bounded five-lane waves", () => { const counts = liveAssetCounts(); expect(counts.size).toBe(18); expect(counts.has("oliphaunt-extension-postgis")).toBe(true); const plan = concurrentGithubReleaseAssetUploadPlan(counts); expect(plan.productCount).toBe(12); - expect(plan.assetCount).toBe(141); + expect(plan.assetCount).toBe(142); expect(plan.waves).toHaveLength(3); expect(plan.waves.map(({ rows }) => rows.length)).toEqual([5, 5, 2]); - expect(plan.waves.map(({ assetCount }) => assetCount)).toEqual([74, 57, 10]); - expect(plan.waves[0].largestProductAssetCount).toBe(19); + expect(plan.waves.map(({ assetCount }) => assetCount)).toEqual([75, 57, 10]); + expect(plan.waves[0].largestProductAssetCount).toBe(20); expect(plan.waves.map(({ windowMs }) => windowMs)).toEqual([ - 2_300_000, + 2_370_000, 1_770_000, 820_000, ]); expect(plan.selectionVerificationWindowMs).toBe(GITHUB_RELEASE_ASSET_SELECTION_VERIFY_MS); - expect(plan.totalWindowMs).toBe(82.5 * 60_000); + expect(plan.totalWindowMs).toBe(5_020_000); expect(plan.totalWindowMs).toBeLessThan(MAX_GITHUB_RELEASE_ASSET_HANDOFF_WINDOW_MS); }); diff --git a/tools/release/js-exact-candidate-consumer.test.mjs b/tools/release/js-exact-candidate-consumer.test.mjs index 8e37f245..34fd9f71 100644 --- a/tools/release/js-exact-candidate-consumer.test.mjs +++ b/tools/release/js-exact-candidate-consumer.test.mjs @@ -596,10 +596,10 @@ test("binds the exact indexed iOS extension producer and rejects orphaned or dri const fixture = writeIosExtensionInputFixture(contract); const inspected = validateIosExtensionCandidateInputs(fixture.root, contract); expect(inspected.targetDirectory).toBe(fixture.targetDirectory); - expect(inspected.artifacts).toHaveLength(85); + expect(inspected.artifacts).toHaveLength(86); expect(inspected.artifacts.filter(({ kind }) => kind === "runtime")).toHaveLength(39); expect(inspected.artifacts.filter(({ kind }) => kind === "ios-xcframework")).toHaveLength(38); - expect(inspected.artifacts.filter(({ kind }) => kind === "ios-dependency-xcframework")).toHaveLength(8); + expect(inspected.artifacts.filter(({ kind }) => kind === "ios-dependency-xcframework")).toHaveLength(9); const orphan = path.join(fixture.targetDirectory, "unindexed.zip"); writeFileSync(orphan, "unindexed bytes\n"); diff --git a/tools/release/postgis-reproducible-time.test.mjs b/tools/release/postgis-reproducible-time.test.mjs index 2746fd5e..7a0f8bc3 100644 --- a/tools/release/postgis-reproducible-time.test.mjs +++ b/tools/release/postgis-reproducible-time.test.mjs @@ -6,7 +6,7 @@ import test from "node:test"; import { captureCommandOutput } from "../dev/capture-command-output.mjs"; const ROOT = path.resolve(import.meta.dirname, "../.."); -const EPOCH = 1_776_193_981; +const EPOCH = 1_780_943_336; function read(relative) { return readFileSync(path.join(ROOT, relative), "utf8"); @@ -31,7 +31,7 @@ function assertOrdered(text, first, second, label) { test("PostGIS source pin carries one portable epoch tied to its exact commit", () => { const manifest = Bun.TOML.parse(read("src/extensions/external/postgis/source.toml")); assert.equal(manifest.name, "postgis"); - assert.equal(manifest.commit, "3d12666588a84b23a3147618eaa9b40b0fe5e796"); + assert.equal(manifest.commit, "94d984bd083635c1d253db0f87cf80b32548e406"); assert.equal(manifest.source_date_epoch, EPOCH); assert.ok(manifest.source_date_epoch > 0 && manifest.source_date_epoch <= 253_402_300_799); diff --git a/tools/release/upload-github-release-assets.test.mjs b/tools/release/upload-github-release-assets.test.mjs index 762a3a16..551104ca 100644 --- a/tools/release/upload-github-release-assets.test.mjs +++ b/tools/release/upload-github-release-assets.test.mjs @@ -565,7 +565,7 @@ test("the complete aggregate-extension asset path leaves bounded API headroom", })); assert.equal(products.length, 8); assert.equal(products.includes("oliphaunt-extension-postgis"), true); - assert.equal(catalog.reduce((total, { assetCount }) => total + assetCount, 0), 108); + assert.equal(catalog.reduce((total, { assetCount }) => total + assetCount, 0), 109); assert.equal(MAX_SAFE_EMBEDDED_RELEASE_ASSETS, 0); let requests = 0; let assetIndex = 0; @@ -591,7 +591,7 @@ test("the complete aggregate-extension asset path leaves bounded API headroom", }, })); } - assert.equal(requests, 108 + (4 * products.length)); + assert.equal(requests, 109 + (4 * products.length)); const binaryProducts = [ "liboliphaunt-native", @@ -613,7 +613,7 @@ test("the complete aggregate-extension asset path leaves bounded API headroom", // Swift, Kotlin, and React Native each read one release and one dedicated // exact asset inventory to prove an empty set. + 6; - assert.equal(allUploaderRequests, 195); + assert.equal(allUploaderRequests, 196); const selectedProductCount = Object.keys( loadGraph("upload-github-release-assets.test").products, @@ -626,7 +626,7 @@ test("the complete aggregate-extension asset path leaves bounded API headroom", const releaseApiRequests = allUploaderRequests + ((3 * selectedProductCount) + 6) + (2 * (1 + selectedProductCount)); - assert.equal(releaseApiRequests, 293); + assert.equal(releaseApiRequests, 294); assert.ok( releaseApiRequests + FIRST_RELEASE_TRANSFER_REQUEST_TOTAL + 6 <= FIRST_RELEASE_NOMINAL_CORE_REQUESTS, diff --git a/tools/xtask/src/asset_checks.rs b/tools/xtask/src/asset_checks.rs index f97007a8..de631dff 100644 --- a/tools/xtask/src/asset_checks.rs +++ b/tools/xtask/src/asset_checks.rs @@ -1611,6 +1611,7 @@ fn check_extension_archive_layout(path: &Path) -> Result<()> { | "share/proj" | "share/postgresql" | "share/postgresql/extension" + | "share/postgresql/gdal" | "share/postgresql/tsearch_data" ) { continue; @@ -1618,6 +1619,7 @@ fn check_extension_archive_layout(path: &Path) -> Result<()> { if entry.starts_with("lib/postgresql/") || entry.starts_with("share/proj/") || entry.starts_with("share/postgresql/extension/") + || entry.starts_with("share/postgresql/gdal/") || entry.starts_with("share/postgresql/tsearch_data/") { continue; diff --git a/tools/xtask/src/asset_pipeline.rs b/tools/xtask/src/asset_pipeline.rs index d3fff2a3..ff80657b 100644 --- a/tools/xtask/src/asset_pipeline.rs +++ b/tools/xtask/src/asset_pipeline.rs @@ -1887,7 +1887,7 @@ fn stage_recipe_staged_extension( extension.id, source.display() ); - copy_dir_all(&source, &stage.join(&data_dir.destination))?; + copy_dir_all_overlay(&source, &stage.join(&data_dir.destination))?; } Ok(()) } diff --git a/tools/xtask/src/extension_catalog.rs b/tools/xtask/src/extension_catalog.rs index ce2a47f8..9f35a3e4 100644 --- a/tools/xtask/src/extension_catalog.rs +++ b/tools/xtask/src/extension_catalog.rs @@ -2008,13 +2008,19 @@ mod tests { vec![ "postgis/postgis-3.so", "postgis/liboliphaunt_postgis_deps.so", + "raster/rt_pg/postgis_raster-3.so", "extensions/postgis/postgis.control", + "extensions/postgis_raster/postgis_raster.control", + "share/gdal/gdalvrt.xsd", "share/proj/proj.db", ] ); assert_eq!( postgis.required_build_globs, - vec!["extensions/postgis/sql/postgis--*.sql"] + vec![ + "extensions/postgis/sql/postgis--*.sql", + "extensions/postgis_raster/sql/postgis_raster--*.sql", + ] ); assert_eq!( postgis @@ -2022,10 +2028,10 @@ mod tests { .iter() .map(|module| module.name.as_str()) .collect::>(), - vec!["postgis_deps"] + vec!["postgis_deps", "postgis_raster"] ); assert!( - postgis + !postgis .excluded_sql_extensions .contains(&"postgis_raster".to_owned()) ); @@ -2046,9 +2052,19 @@ mod tests { staging.sql_source_dir.as_deref(), Some("postgis/extensions/postgis/sql") ); - assert_eq!(staging.data_dirs.len(), 1); + assert_eq!(staging.data_dirs.len(), 3); assert_eq!(staging.data_dirs[0].source, "postgis/share/proj"); assert_eq!(staging.data_dirs[0].destination, "share/proj"); + assert_eq!(staging.data_dirs[1].source, "postgis/share/gdal"); + assert_eq!(staging.data_dirs[1].destination, "share/postgresql/gdal"); + assert_eq!( + staging.data_dirs[2].source, + "postgis/share/extension-raster" + ); + assert_eq!( + staging.data_dirs[2].destination, + "share/postgresql/extension" + ); Ok(()) } } diff --git a/tools/xtask/src/fs_utils.rs b/tools/xtask/src/fs_utils.rs index 2c405487..2fa952a7 100644 --- a/tools/xtask/src/fs_utils.rs +++ b/tools/xtask/src/fs_utils.rs @@ -282,6 +282,27 @@ pub(crate) fn copy_dir_all(source: &Path, destination: &Path) -> Result<()> { Ok(()) } +pub(crate) fn copy_dir_all_overlay(source: &Path, destination: &Path) -> Result<()> { + fs::create_dir_all(destination).with_context(|| format!("create {}", destination.display()))?; + for entry in WalkDir::new(source) { + let entry = entry.with_context(|| format!("walk {}", source.display()))?; + let path = entry.path(); + let relative = path + .strip_prefix(source) + .with_context(|| format!("strip {} from {}", source.display(), path.display()))?; + if relative.as_os_str().is_empty() { + continue; + } + let output = destination.join(relative); + if entry.file_type().is_dir() { + fs::create_dir_all(&output).with_context(|| format!("create {}", output.display()))?; + } else if entry.file_type().is_file() { + copy_file(path, &output)?; + } + } + Ok(()) +} + pub(crate) fn ensure_file(path: &Path) -> Result<()> { if !path.is_file() { bail!("expected file missing: {}", path.display()); From 1e8f1cc4c61210afe882a92eba8761dc0a68a148 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Sun, 9 Aug 2026 15:14:45 +0000 Subject: [PATCH 2/9] fix(extensions): close PostGIS cross-platform CI gaps --- .../src/oliphaunt/generated_extensions.rs | 11 ++- .../postgis/.release-semantic-inputs.json | 4 +- .../native/bin/mobile-postgis-extensions.sh | 87 ++++++++++--------- ...OliphauntExtensionCatalogContractTest.java | 4 +- tools/policy/source-fetch-core.mjs | 5 ++ tools/policy/source-fetch-core.test.mjs | 7 ++ tools/xtask/src/asset_checks.rs | 16 ++++ 7 files changed, 86 insertions(+), 48 deletions(-) diff --git a/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/generated_extensions.rs b/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/generated_extensions.rs index ac5c64c0..288d354d 100644 --- a/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/generated_extensions.rs +++ b/src/bindings/wasix-rust/crates/oliphaunt-wasix/src/oliphaunt/generated_extensions.rs @@ -714,11 +714,16 @@ const CANDIDATE_POSTGIS_DEPENDENCIES: &[&str] = EMPTY_SQL_NAMES; const CANDIDATE_POSTGIS_LOAD_SQL: &[&str] = EMPTY_SQL; const CANDIDATE_POSTGIS_POST_CREATE_SQL: &[&str] = EMPTY_SQL; const CANDIDATE_POSTGIS_STARTUP_CONFIG: &[&str] = EMPTY_STARTUP_CONFIG; -const CANDIDATE_POSTGIS_NATIVE_SUPPORT_MODULES: &[ExtensionNativeModule] = - &[ExtensionNativeModule::new( +const CANDIDATE_POSTGIS_NATIVE_SUPPORT_MODULES: &[ExtensionNativeModule] = &[ + ExtensionNativeModule::new( "lib/postgresql/liboliphaunt_postgis_deps.so", Some("extension:postgis:postgis_deps"), - )]; + ), + ExtensionNativeModule::new( + "lib/postgresql/postgis_raster-3.so", + Some("extension:postgis:postgis_raster"), + ), +]; pub(crate) const CANDIDATE_POSTGIS: Extension = Extension::new( "PostGIS", diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index 8e825818..e695ecc6 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -103,7 +103,7 @@ }, { "path": "src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh", - "sha256": "486ef696c48505ba03ca0f979525cabaed699e9e7a53281f37a9416254a693c1" + "sha256": "ac32b1994d06e9e7904414119ee0fe6de48892a5b604931836403e088683c7cc" } ] }, @@ -390,5 +390,5 @@ ] } ], - "sha256": "ad61e99402000cb46d6bb9042ed56beaa13ab91e859e4f6012334636f6b7de8d" + "sha256": "409c477aa045c5b8a318767c9d4df382f3e0d5c2ecab1e4810fea3406ec74c55" } diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh index 7db3ba5a..5d83a8a0 100644 --- a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh +++ b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh @@ -306,7 +306,7 @@ build_postgis_gdal_dependency() { local libxml2_dir="$mobile_static_dependency_root/libxml2" local proj_dir="$mobile_static_dependency_root/proj" local sqlite_dir="$mobile_static_dependency_root/sqlite" - local -a iconv_args=() + local -a cmake_args local build_root="$work_root/gdal-$oliphaunt_mobile_target-build" local archive="$dependency_dir/lib/libgdal.a" if [ -f "$archive" ] && [ -f "$dependency_dir/include/gdal.h" ] && [ -x "$dependency_dir/bin/gdal-config" ]; then @@ -315,11 +315,49 @@ build_postgis_gdal_dependency() { fi [ -f "$source_dir/CMakeLists.txt" ] || oliphaunt_postgis_fail "missing GDAL checkout: $source_dir" [ -f "$proj_dir/lib/libproj.a" ] || oliphaunt_postgis_fail "GDAL dependency requires PROJ first" + cmake_args=( + -DBASH_COMPLETIONS_DIR= + -DBUILD_SHARED_LIBS=OFF + -DBUILD_APPS=OFF + -DBUILD_CSHARP_BINDINGS=OFF + -DBUILD_JAVA_BINDINGS=OFF + -DBUILD_PYTHON_BINDINGS=OFF + -DBUILD_TESTING=OFF + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF + -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF + -DGDAL_ENABLE_DRIVER_GTIFF=ON + -DGDAL_ENABLE_DRIVER_VRT=ON + -DOGR_ENABLE_DRIVER_GEOJSON=ON + -DOGR_ENABLE_DRIVER_SHAPE=ON + -DGDAL_USE_EXTERNAL_LIBS=OFF + -DGDAL_USE_INTERNAL_LIBS=ON + -DGDAL_USE_OPENMP=OFF + -DGDAL_USE_CURL=OFF + -DGDAL_USE_OPENSSL=OFF + -DGDAL_USE_GEOS=ON + "-DGEOS_INCLUDE_DIR=$geos_dir/include" + "-DGEOS_LIBRARY=$geos_dir/lib/libgeos_c.a" + -DGDAL_USE_JSONC=ON + -DGDAL_USE_JSONC_INTERNAL=OFF + "-DJSONC_INCLUDE_DIR=$jsonc_dir/include/json-c" + "-DJSONC_LIBRARY=$jsonc_dir/lib/libjson-c.a" + -DGDAL_USE_LIBXML2=ON + "-DLIBXML2_INCLUDE_DIR=$libxml2_dir/include/libxml2" + "-DLIBXML2_LIBRARY=$libxml2_dir/lib/libxml2.a" + -DGDAL_USE_PROJ=ON + "-DPROJ_INCLUDE_DIR=$proj_dir/include" + "-DPROJ_LIBRARY=$proj_dir/lib/libproj.a" + -DGDAL_USE_SQLITE3=ON + "-DSQLite3_INCLUDE_DIR=$sqlite_dir/include" + "-DSQLite3_LIBRARY=$sqlite_dir/lib/libsqlite3.a" + -DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON + ) case "$oliphaunt_mobile_target" in android-arm64 | android-x86_64) [ -f "$mobile_static_dependency_root/libiconv/lib/libiconv.a" ] || oliphaunt_postgis_fail "GDAL dependency requires libiconv first on Android" - iconv_args=( + cmake_args+=( -DGDAL_USE_ICONV=ON "-DIconv_INCLUDE_DIR=$mobile_static_dependency_root/libiconv/include" "-DIconv_LIBRARY=$mobile_static_dependency_root/libiconv/lib/libiconv.a" @@ -328,43 +366,7 @@ build_postgis_gdal_dependency() { esac rm -rf "$build_root" "$dependency_dir" oliphaunt_postgis_cmake_install "$source_dir" "$build_root" "$dependency_dir" \ - -DBASH_COMPLETIONS_DIR= \ - -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPS=OFF \ - -DBUILD_CSHARP_BINDINGS=OFF \ - -DBUILD_JAVA_BINDINGS=OFF \ - -DBUILD_PYTHON_BINDINGS=OFF \ - -DBUILD_TESTING=OFF \ - -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ - -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON \ - -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ - -DGDAL_ENABLE_DRIVER_GTIFF=ON \ - -DGDAL_ENABLE_DRIVER_VRT=ON \ - -DOGR_ENABLE_DRIVER_GEOJSON=ON \ - -DOGR_ENABLE_DRIVER_SHAPE=ON \ - -DGDAL_USE_EXTERNAL_LIBS=OFF \ - -DGDAL_USE_INTERNAL_LIBS=ON \ - -DGDAL_USE_OPENMP=OFF \ - -DGDAL_USE_CURL=OFF \ - -DGDAL_USE_OPENSSL=OFF \ - -DGDAL_USE_GEOS=ON \ - "-DGEOS_INCLUDE_DIR=$geos_dir/include" \ - "-DGEOS_LIBRARY=$geos_dir/lib/libgeos_c.a" \ - -DGDAL_USE_JSONC=ON \ - -DGDAL_USE_JSONC_INTERNAL=OFF \ - "-DJSONC_INCLUDE_DIR=$jsonc_dir/include/json-c" \ - "-DJSONC_LIBRARY=$jsonc_dir/lib/libjson-c.a" \ - -DGDAL_USE_LIBXML2=ON \ - "-DLIBXML2_INCLUDE_DIR=$libxml2_dir/include/libxml2" \ - "-DLIBXML2_LIBRARY=$libxml2_dir/lib/libxml2.a" \ - -DGDAL_USE_PROJ=ON \ - "-DPROJ_INCLUDE_DIR=$proj_dir/include" \ - "-DPROJ_LIBRARY=$proj_dir/lib/libproj.a" \ - -DGDAL_USE_SQLITE3=ON \ - "-DSQLite3_INCLUDE_DIR=$sqlite_dir/include" \ - "-DSQLite3_LIBRARY=$sqlite_dir/lib/libsqlite3.a" \ - -DACCEPT_MISSING_SQLITE3_MUTEX_ALLOC=ON \ - "${iconv_args[@]}" + "${cmake_args[@]}" [ -f "$archive" ] || oliphaunt_postgis_fail "GDAL build did not produce $archive" [ -x "$dependency_dir/bin/gdal-config" ] || oliphaunt_postgis_fail "GDAL build did not produce gdal-config" oliphaunt_postgis_dependency_archive gdal "$archive" @@ -850,8 +852,11 @@ build_postgis_mobile_static_extension_objects() { make -j"$jobs" -C deps/flatgeobuf all >> "$make_log" 2>&1 make -j"$jobs" -C postgis all >> "$make_log" 2>&1 || true make -j"$jobs" -C raster/rt_core all >> "$make_log" 2>&1 - make -j"$jobs" -C raster/rt_pg all >> "$make_log" 2>&1 || true - [ -f raster/rt_pg/rtpostgis.o ] || oliphaunt_postgis_fail "PostGIS raster objects were not produced" + make -j"$jobs" -C raster/rt_pg postgis_raster-3.so >> "$make_log" 2>&1 || true + if [ ! -f raster/rt_pg/rtpostgis.o ]; then + tail -n 200 "$make_log" >&2 || true + oliphaunt_postgis_fail "PostGIS raster objects were not produced" + fi make -j1 -C extensions postgis_extension_helper.sql >> "$make_log" 2>&1 make -j1 -C extensions all >> "$make_log" 2>&1 ) diff --git a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java index 9c6e93d0..3af15cac 100644 --- a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java +++ b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java @@ -511,8 +511,8 @@ private static void validatesGeneratedExtensionLegalCatalog() throws Exception { OliphauntExtensionLegalCatalog.Contract postgis = OliphauntExtensionLegalCatalog.requireLeaf("postgis", target); equal("external-native", postgis.profile(), target + " PostGIS legal profile"); - equal(16, postgis.licenseFiles().size(), target + " PostGIS upstream license count"); - equal(18, postgis.members().size(), target + " PostGIS exact legal member count"); + equal(17, postgis.licenseFiles().size(), target + " PostGIS upstream license count"); + equal(19, postgis.members().size(), target + " PostGIS exact legal member count"); for (OliphauntExtensionLegalCatalog.LegalMember member : postgis.members()) { equal(0644, member.mode(), target + " PostGIS legal mode " + member.path()); } diff --git a/tools/policy/source-fetch-core.mjs b/tools/policy/source-fetch-core.mjs index c009bbda..cd8fe711 100644 --- a/tools/policy/source-fetch-core.mjs +++ b/tools/policy/source-fetch-core.mjs @@ -71,6 +71,10 @@ export function curlPlatformTlsArgs(platform = process.platform) { return platform === 'win32' ? ['--ssl-revoke-best-effort'] : []; } +export function gitPlatformConfigArgs(platform = process.platform) { + return platform === 'win32' ? ['-c', 'core.longpaths=true'] : []; +} + export function curlDownloadArgs(url, output, {platform = process.platform} = {}) { assertHttpsUrl(url); return [ @@ -700,6 +704,7 @@ export function createSourceFetcher({ // checks. Force one worktree representation even when an upstream marks a // file `text=auto` and the host's native checkout convention is CRLF. return run('git', [ + ...gitPlatformConfigArgs(), '-c', 'core.fsmonitor=false', '-c', diff --git a/tools/policy/source-fetch-core.test.mjs b/tools/policy/source-fetch-core.test.mjs index b7023924..bcd4950f 100644 --- a/tools/policy/source-fetch-core.test.mjs +++ b/tools/policy/source-fetch-core.test.mjs @@ -22,6 +22,7 @@ import { curlDownloadArgs, curlPlatformTlsArgs, defaultRunProcess, + gitPlatformConfigArgs, promotePathTransactional, sameDirectoryIdentity, sha256File, @@ -60,6 +61,12 @@ test('directory identity accepts Windows short and long aliases for the same fil ); }); +test('Git source fetches enable long paths only on Windows', () => { + assert.deepEqual(gitPlatformConfigArgs('win32'), ['-c', 'core.longpaths=true']); + assert.deepEqual(gitPlatformConfigArgs('linux'), []); + assert.deepEqual(gitPlatformConfigArgs('darwin'), []); +}); + test('directory identity rejects different filesystem objects', () => { assert.equal( sameDirectoryIdentity('/expected', '/external', { diff --git a/tools/xtask/src/asset_checks.rs b/tools/xtask/src/asset_checks.rs index de631dff..a04a7455 100644 --- a/tools/xtask/src/asset_checks.rs +++ b/tools/xtask/src/asset_checks.rs @@ -1014,6 +1014,22 @@ pub(crate) fn verify_generated_extension_surface() -> Result<()> { bail!("generated extension API is stale: missing {description} {needle}"); } } + for native_module in &extension.native_modules { + if extension + .native_module + .as_deref() + .is_some_and(|primary| native_module.path == format!("lib/postgresql/{primary}")) + { + continue; + } + let needle = format!("{:?}", native_module.path); + if !generated.contains(&needle) { + bail!( + "generated extension API is stale: missing native support module path {needle} for {}", + extension.sql_name + ); + } + } if extension.smoke_status.promoted { for (needle, description) in [ ( From da24bfa7a93742b4f5aa3b1b7e91bcbbdb5e0320 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 02:47:21 +0000 Subject: [PATCH 3/9] fix(extensions): repair PostGIS cross-platform builds --- .../postgis/.release-semantic-inputs.json | 6 +- .../native/bin/build-postgres18-windows.ps1 | 4 +- .../native/bin/mobile-postgis-extensions.sh | 4 +- .../bin/mobile-postgis-extensions.test.sh | 72 +++++++++++++++++++ src/runtimes/liboliphaunt/native/moon.yml | 10 +++ ...OliphauntExtensionCatalogContractTest.java | 2 +- 6 files changed, 92 insertions(+), 6 deletions(-) create mode 100755 src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index e695ecc6..45f0af0d 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -99,11 +99,11 @@ }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1", - "sha256": "21c8c44a8aa03aac5f8dda9674c630829d03ec8cd0c7a66eecf8e1b57ffa2186" + "sha256": "71db4872b9a8cb106e9ed4604e8fd2d32e982fefe3938cc951f879a16f2eca82" }, { "path": "src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh", - "sha256": "ac32b1994d06e9e7904414119ee0fe6de48892a5b604931836403e088683c7cc" + "sha256": "ee68d707327d4d0c897ea98a913f8face1226a72b7d9a47f0a14cfb3c5594930" } ] }, @@ -390,5 +390,5 @@ ] } ], - "sha256": "409c477aa045c5b8a318767c9d4df382f3e0d5c2ecab1e4810fea3406ec74c55" + "sha256": "c303cf76326f8b38e1c6a2a2bb6b2f13baa9408c8a8bffa112167a99f11e7159" } diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 index 69b6c2b0..3e99c378 100644 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 @@ -945,7 +945,9 @@ function Build-WindowsPostgisGdalDependency { $jsonLib = First-File $jsonPrefix @("json-c.lib", "json-c-static.lib") $libxml2Lib = First-File $libxml2Prefix @("libxml2s.lib", "libxml2.lib", "xml2.lib") $projLib = First-File $projPrefix @("proj.lib", "libproj.lib") - $sqliteLib = First-File $sqlitePrefix @("sqlite3.lib", "libsqlite3.lib") + # CMake writes this value into a generated try_compile project. Use forward + # slashes so Windows path escapes such as \a are not parsed by CMake. + $sqliteLib = (First-File $sqlitePrefix @("sqlite3.lib", "libsqlite3.lib")).Replace("\", "/") Invoke-CmakeInstall "gdal" $sourceDir (Join-Path $WorkRoot "gdal-windows-build") $prefix @( "-DBASH_COMPLETIONS_DIR=", "-DBUILD_SHARED_LIBS=OFF", diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh index 5d83a8a0..ad036abf 100644 --- a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh +++ b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh @@ -322,6 +322,7 @@ build_postgis_gdal_dependency() { -DBUILD_CSHARP_BINDINGS=OFF -DBUILD_JAVA_BINDINGS=OFF -DBUILD_PYTHON_BINDINGS=OFF + -DBUILD_PYTHON_BINDINGS_OLD_VAL=OFF -DBUILD_TESTING=OFF -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF -DGDAL_OBJECT_LIBRARIES_POSITION_INDEPENDENT_CODE=ON @@ -684,7 +685,8 @@ oliphaunt_postgis_patch_raster_makefile() { " -DPg_magic_func=$ENV{OLIPHAUNT_POSTGIS_RASTER_MAGIC_SYMBOL}" . " -D_PG_init=$ENV{OLIPHAUNT_POSTGIS_RASTER_INIT_SYMBOL}" . " -D_PG_fini=$ENV{OLIPHAUNT_POSTGIS_RASTER_FINI_SYMBOL}"; - my $updated = s|^(PG_CPPFLAGS \+= .*)$|$1$defs|m; + die "PostGIS raster PG_CPPFLAGS is missing\n" unless /^PG_CPPFLAGS \+=/m; + my $updated = s|^(SHLIB_LINK_F =)|PG_CPPFLAGS +=$defs\n$1|m; die "could not patch PostGIS raster PG_CPPFLAGS\n" unless $updated; ' "$makefile" } diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh new file mode 100755 index 00000000..b850d5f0 --- /dev/null +++ b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +# shellcheck source=/dev/null +. "$script_dir/mobile-postgis-extensions.sh" + +test_root="$(mktemp -d "${TMPDIR:-/tmp}/oliphaunt-mobile-postgis-test.XXXXXX")" +trap 'rm -rf "$test_root"' EXIT + +repo_root="$test_root/repo" +mobile_static_dependency_root="$test_root/dependencies" +work_root="$test_root/work" +oliphaunt_mobile_target="ios-simulator" +mobile_static_dependency_archives=() + +mkdir -p \ + "$repo_root/target/oliphaunt-sources/checkouts/gdal" \ + "$mobile_static_dependency_root/proj/lib" +: > "$repo_root/target/oliphaunt-sources/checkouts/gdal/CMakeLists.txt" +: > "$mobile_static_dependency_root/proj/lib/libproj.a" + +oliphaunt_postgis_selected() { + return 0 +} + +cmake_args_file="$test_root/cmake-args.txt" +oliphaunt_postgis_cmake_install() { + local dependency_dir="$3" + shift 3 + printf '%s\n' "$@" > "$cmake_args_file" + mkdir -p "$dependency_dir/lib" "$dependency_dir/include" "$dependency_dir/bin" + : > "$dependency_dir/lib/libgdal.a" + : > "$dependency_dir/include/gdal.h" + : > "$dependency_dir/bin/gdal-config" + chmod +x "$dependency_dir/bin/gdal-config" +} + +build_postgis_gdal_dependency +grep -Fx -- '-DBUILD_PYTHON_BINDINGS=OFF' "$cmake_args_file" >/dev/null +grep -Fx -- '-DBUILD_PYTHON_BINDINGS_OLD_VAL=OFF' "$cmake_args_file" >/dev/null + +postgis_build="$test_root/postgis-build" +mkdir -p "$postgis_build/raster/rt_pg" +cat > "$postgis_build/raster/rt_pg/Makefile" <<'MAKEFILE' +PG_CPPFLAGS += \ + -Ifixture-one \ + -Ifixture-two +SHLIB_LINK_F = -lfixture + +.PHONY: print-flags +print-flags: + @printf '%s\n' '$(PG_CPPFLAGS)' +MAKEFILE + +prefix="oliphaunt_static_postgis_3" +oliphaunt_postgis_patch_raster_makefile "$postgis_build" "$prefix" +raster_flags="$(make -s -f "$postgis_build/raster/rt_pg/Makefile" print-flags)" +for expected in \ + "-DPg_magic_func=${prefix}_raster_Pg_magic_func" \ + "-D_PG_init=${prefix}_raster_PG_init" \ + "-D_PG_fini=${prefix}_raster_PG_fini"; do + case " $raster_flags " in + *" $expected "*) ;; + *) + echo "missing raster compile definition: $expected" >&2 + exit 1 + ;; + esac +done + +echo "mobile PostGIS build contracts passed" diff --git a/src/runtimes/liboliphaunt/native/moon.yml b/src/runtimes/liboliphaunt/native/moon.yml index b0e4b3d5..44276eba 100644 --- a/src/runtimes/liboliphaunt/native/moon.yml +++ b/src/runtimes/liboliphaunt/native/moon.yml @@ -50,6 +50,7 @@ tasks: - "liboliphaunt-native:generation-lifecycle-test" - "liboliphaunt-native:ios-extension-packager-test" - "liboliphaunt-native:module-dir-resolver-test" + - "liboliphaunt-native:postgis-build-contract-test" - "liboliphaunt-native:postgis-reproducible-time-test" - "liboliphaunt-native:static-extension-registry-test" - "liboliphaunt-native:symbol-scope-test" @@ -128,6 +129,15 @@ tasks: options: cache: true runFromWorkspaceRoot: true + postgis-build-contract-test: + tags: ["quality", "unit"] + command: "bash src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh" + inputs: + - "/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh" + - "/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh" + options: + cache: true + runFromWorkspaceRoot: true module-dir-resolver-test: tags: ["quality", "unit"] command: "bash src/runtimes/liboliphaunt/native/tools/test-module-dir-resolver.sh" diff --git a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java index 3af15cac..1388b38b 100644 --- a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java +++ b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java @@ -799,7 +799,7 @@ private static void validatesPgcryptoAndPostgisLegalArtifacts() throws Exception try (var files = Files.walk(postgisRoot.resolve("files/share/licenses"))) { upstreamFiles = files.filter(Files::isRegularFile).count(); } - equal(16L, upstreamFiles, "PostGIS exact upstream legal file count"); + equal(17L, upstreamFiles, "PostGIS exact upstream legal file count"); } finally { deleteRecursively(root); } From b1cbe723dee1c20b9112c951e230eec1ae4a017f Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 04:23:37 +0000 Subject: [PATCH 4/9] fix(extensions): repair cross-platform postgis packaging --- .../postgis/.release-semantic-inputs.json | 6 ++-- .../postgis/tools/reproducible-time.sh | 30 +++++++++++++++++-- .../generated/docs/extension-evidence.json | 2 +- .../native/.release-semantic-inputs.json | 4 +-- .../native/bin/build-postgres18-windows.ps1 | 14 +++++++++ .../native/bin/mobile-postgis-extensions.sh | 15 ++++++---- .../bin/mobile-postgis-extensions.test.sh | 23 ++++++++++++-- .../native/bin/mobile-static-extensions.sh | 1 + .../bin/postgis-reproducible-time.test.sh | 2 +- src/runtimes/liboliphaunt/native/moon.yml | 1 + .../wasix/.release-semantic-inputs.json | 6 ++-- .../assets/generated/asset-inputs.sha256 | 2 +- 12 files changed, 86 insertions(+), 20 deletions(-) diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index 45f0af0d..e60c646a 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -99,11 +99,11 @@ }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1", - "sha256": "71db4872b9a8cb106e9ed4604e8fd2d32e982fefe3938cc951f879a16f2eca82" + "sha256": "e55f584dc8045c1af093f01a66e440452fdb379a7aa162394cf118566dc57b59" }, { "path": "src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh", - "sha256": "ee68d707327d4d0c897ea98a913f8face1226a72b7d9a47f0a14cfb3c5594930" + "sha256": "e56a88d24095c44a00bda7390e77a968577e5ad7f6bb57959ec41d95c7d62fa4" } ] }, @@ -390,5 +390,5 @@ ] } ], - "sha256": "c303cf76326f8b38e1c6a2a2bb6b2f13baa9408c8a8bffa112167a99f11e7159" + "sha256": "cee83c4ccff66bb2c1bc17d48137e84beb9aae187b7c8153886957c4f6203fcf" } diff --git a/src/extensions/external/postgis/tools/reproducible-time.sh b/src/extensions/external/postgis/tools/reproducible-time.sh index ab7d409c..ca1c74a1 100755 --- a/src/extensions/external/postgis/tools/reproducible-time.sh +++ b/src/extensions/external/postgis/tools/reproducible-time.sh @@ -5,6 +5,31 @@ oliphaunt_postgis_time_fail() { return 1 } +oliphaunt_postgis_resolve_executable_path() { + local path="${1:-}" + local directory basename + [ -n "$path" ] || return 1 + case "$path" in + */*) ;; + *) path="$(command -v "$path" || true)" ;; + esac + [ -n "$path" ] || return 1 + directory="$(dirname "$path")" + basename="$(basename "$path")" + ( + unset CDPATH + cd -- "$directory" 2>/dev/null || exit 1 + printf '%s/%s\n' "$(pwd -P)" "$basename" + ) +} + +oliphaunt_postgis_same_executable() { + local left right + left="$(oliphaunt_postgis_resolve_executable_path "${1:-}")" || return 1 + right="$(oliphaunt_postgis_resolve_executable_path "${2:-}")" || return 1 + [ "$left" = "$right" ] +} + oliphaunt_postgis_source_date_epoch() { local repo_root="${1:?missing repository root}" local manifest="$repo_root/src/extensions/external/postgis/source.toml" @@ -34,14 +59,15 @@ oliphaunt_postgis_enable_reproducible_time() { oliphaunt_postgis_time_fail "portable date shim is not executable: $shim" || return 1 SOURCE_DATE_EPOCH="$(oliphaunt_postgis_source_date_epoch "$repo_root")" || return 1 resolved_date="$(command -v date || true)" - if [ "$resolved_date" = "$shim" ]; then + if oliphaunt_postgis_same_executable "$resolved_date" "$shim"; then real_date="${OLIPHAUNT_POSTGIS_REAL_DATE:-}" else # Never trust an inherited override on first enable. Capture the date command # selected by the producer's PATH before installing our scoped shim. real_date="$resolved_date" fi - [ -n "$real_date" ] && [ -x "$real_date" ] && [ "$real_date" != "$shim" ] || + [ -n "$real_date" ] && [ -x "$real_date" ] && + ! oliphaunt_postgis_same_executable "$real_date" "$shim" || oliphaunt_postgis_time_fail "could not capture the host date command before installing the shim" || return 1 OLIPHAUNT_POSTGIS_REAL_DATE="$real_date" case ":$PATH:" in diff --git a/src/extensions/generated/docs/extension-evidence.json b/src/extensions/generated/docs/extension-evidence.json index 39963852..f38759a3 100644 --- a/src/extensions/generated/docs/extension-evidence.json +++ b/src/extensions/generated/docs/extension-evidence.json @@ -1347,7 +1347,7 @@ "current-source-status": "requires-exact-candidate-ci", "kind": "exact-sha-ci" }, - "source-digest": "sha256:c5c4209245d495e274c9241f5f3114cc2bf1ad6340c47f98f334894a1851f513", + "source-digest": "sha256:098dee236cb203d8cc1586d1cfed95bde9e05a170895db36a6bc1980bff767cb", "source-digest-inputs": [ "src/postgres/versions/18/source.toml", "src/extensions/catalog/extensions.promoted.toml", diff --git a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json index 248f4424..40a27ce7 100644 --- a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json +++ b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json @@ -112,7 +112,7 @@ }, { "path": "src/extensions/external/postgis/tools/reproducible-time.sh", - "sha256": "08fc52aceb5e5e6d649b89adabe0b5b4ec8af68e49bb576376c147ec686d81bb" + "sha256": "afa6de6175776c546130ae4a72fea7aecf9e3ea492c7c53649960252315ada39" } ] }, @@ -457,5 +457,5 @@ ] } ], - "sha256": "f6482c0e8ce42218eebd81c2324168004855b260a6ba4ae59f3616dab7bd4489" + "sha256": "47e8d4a034b1640db3016017fe7c9e7cdf395f1a3b65889ac575aa70746c88ed" } diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 index 3e99c378..ee794d39 100644 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 @@ -1687,6 +1687,20 @@ function Patch-WindowsPostgisSource([string]$PostgisDir) { #endif "@ + $rasterCoreHeader = Join-Path $PostgisDir "raster/rt_core/librtcore.h" + $rasterCoreText = Get-Content -Raw -Path $rasterCoreHeader + $legacyAttributeFallback = "# define __attribute__ (x)" + $guardedAttributeFallback = @" +# ifndef __attribute__ +# define __attribute__(x) +# endif +"@ + if (-not $rasterCoreText.Contains($legacyAttributeFallback)) { + Fail "PostGIS raster compatibility header is missing the expected __attribute__ fallback" + } + $rasterCoreText = $rasterCoreText.Replace($legacyAttributeFallback, $guardedAttributeFallback) + Set-Content -Path $rasterCoreHeader -Encoding UTF8 -Value $rasterCoreText + $declarationPattern = "(?m)^\s*(?!(?:extern\s+)?PGDLLEXPORT\s+)(?:extern\s+)?Datum\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(PG_FUNCTION_ARGS\);\r?$" $patchedDeclarationCount = 0 foreach ($subdir in @("postgis", "libpgcommon", "liblwgeom", "raster/rt_core", "raster/rt_pg")) { diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh index ad036abf..a3c59468 100644 --- a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh +++ b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh @@ -737,6 +737,15 @@ oliphaunt_postgis_verify_prefixed_legacy_symbols() { fi } +oliphaunt_postgis_build_raster_objects() { + local postgis_build="$1" + make -j"$jobs" -C "$postgis_build/raster/rt_pg" all >> "$make_log" 2>&1 || true + if [ ! -f "$postgis_build/raster/rt_pg/rtpostgis.o" ]; then + tail -n 200 "$make_log" >&2 || true + oliphaunt_postgis_fail "PostGIS raster objects were not produced" + fi +} + build_postgis_mobile_static_extension_objects() { local extension="$1" [ "$extension" = "postgis" ] || return 1 @@ -854,11 +863,7 @@ build_postgis_mobile_static_extension_objects() { make -j"$jobs" -C deps/flatgeobuf all >> "$make_log" 2>&1 make -j"$jobs" -C postgis all >> "$make_log" 2>&1 || true make -j"$jobs" -C raster/rt_core all >> "$make_log" 2>&1 - make -j"$jobs" -C raster/rt_pg postgis_raster-3.so >> "$make_log" 2>&1 || true - if [ ! -f raster/rt_pg/rtpostgis.o ]; then - tail -n 200 "$make_log" >&2 || true - oliphaunt_postgis_fail "PostGIS raster objects were not produced" - fi + oliphaunt_postgis_build_raster_objects "$postgis_build" make -j1 -C extensions postgis_extension_helper.sql >> "$make_log" 2>&1 make -j1 -C extensions all >> "$make_log" 2>&1 ) diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh index b850d5f0..e9397d19 100755 --- a/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh +++ b/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh @@ -3,6 +3,8 @@ set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" # shellcheck source=/dev/null +. "$script_dir/mobile-static-extensions.sh" +# shellcheck source=/dev/null . "$script_dir/mobile-postgis-extensions.sh" test_root="$(mktemp -d "${TMPDIR:-/tmp}/oliphaunt-mobile-postgis-test.XXXXXX")" @@ -32,13 +34,18 @@ oliphaunt_postgis_cmake_install() { mkdir -p "$dependency_dir/lib" "$dependency_dir/include" "$dependency_dir/bin" : > "$dependency_dir/lib/libgdal.a" : > "$dependency_dir/include/gdal.h" - : > "$dependency_dir/bin/gdal-config" + printf '#!/usr/bin/env bash\nexit 0\n' > "$dependency_dir/bin/gdal-config" chmod +x "$dependency_dir/bin/gdal-config" } build_postgis_gdal_dependency grep -Fx -- '-DBUILD_PYTHON_BINDINGS=OFF' "$cmake_args_file" >/dev/null grep -Fx -- '-DBUILD_PYTHON_BINDINGS_OLD_VAL=OFF' "$cmake_args_file" >/dev/null +resolved_gdal_archive="$(oliphaunt_mobile_static_dependency_archive_for_root "$mobile_static_dependency_root" gdal)" +[ "$resolved_gdal_archive" = "$mobile_static_dependency_root/gdal/lib/libgdal.a" ] || { + echo "mobile packager did not resolve the staged GDAL archive" >&2 + exit 1 +} postgis_build="$test_root/postgis-build" mkdir -p "$postgis_build/raster/rt_pg" @@ -48,7 +55,11 @@ PG_CPPFLAGS += \ -Ifixture-two SHLIB_LINK_F = -lfixture -.PHONY: print-flags +.PHONY: all print-flags +all: + @: > rtpostgis.o + @: > all-target-ran + print-flags: @printf '%s\n' '$(PG_CPPFLAGS)' MAKEFILE @@ -69,4 +80,12 @@ for expected in \ esac done +jobs=1 +make_log="$test_root/raster-make.log" +oliphaunt_postgis_build_raster_objects "$postgis_build" +[ -f "$postgis_build/raster/rt_pg/all-target-ran" ] || { + echo "mobile raster build did not use the platform-neutral all target" >&2 + exit 1 +} + echo "mobile PostGIS build contracts passed" diff --git a/src/runtimes/liboliphaunt/native/bin/mobile-static-extensions.sh b/src/runtimes/liboliphaunt/native/bin/mobile-static-extensions.sh index be6214b8..029a2a8e 100644 --- a/src/runtimes/liboliphaunt/native/bin/mobile-static-extensions.sh +++ b/src/runtimes/liboliphaunt/native/bin/mobile-static-extensions.sh @@ -100,6 +100,7 @@ oliphaunt_mobile_static_dependency_archive_candidates() { local dependency_root="${1:?missing mobile static dependency root}" local dependency="${2:?missing mobile static dependency name}" case "$dependency" in + gdal) printf '%s\n' "$dependency_root/gdal/lib/libgdal.a" ;; geos-c) printf '%s\n' "$dependency_root/geos/lib/libgeos_c.a" ;; geos) printf '%s\n' "$dependency_root/geos/lib/libgeos.a" ;; json-c) printf '%s\n' "$dependency_root/json-c/lib/libjson-c.a" ;; diff --git a/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh b/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh index dbf91fc9..97f4d6f8 100755 --- a/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh +++ b/src/runtimes/liboliphaunt/native/bin/postgis-reproducible-time.test.sh @@ -76,7 +76,7 @@ export SOURCE_DATE_EPOCH=333 oliphaunt_postgis_enable_reproducible_time "$root" [ "$SOURCE_DATE_EPOCH" = "$expected_epoch" ] || fail "enable helper retained ambient SOURCE_DATE_EPOCH" -[ "$(command -v date)" = "$shim" ] || +oliphaunt_postgis_same_executable "$(command -v date)" "$shim" || fail "portable date shim was not placed first on PATH" [ "$(date -d "@$SOURCE_DATE_EPOCH" -u '+%Y-%m-%d %H:%M:%S')" = "$expected_utc" ] || fail "GNU-order PostGIS date invocation was not deterministic" diff --git a/src/runtimes/liboliphaunt/native/moon.yml b/src/runtimes/liboliphaunt/native/moon.yml index 44276eba..5272ff04 100644 --- a/src/runtimes/liboliphaunt/native/moon.yml +++ b/src/runtimes/liboliphaunt/native/moon.yml @@ -135,6 +135,7 @@ tasks: inputs: - "/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh" - "/src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.test.sh" + - "/src/runtimes/liboliphaunt/native/bin/mobile-static-extensions.sh" options: cache: true runFromWorkspaceRoot: true diff --git a/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json b/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json index 37bf02e4..f5c76592 100644 --- a/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json +++ b/src/runtimes/liboliphaunt/wasix/.release-semantic-inputs.json @@ -112,7 +112,7 @@ }, { "path": "src/extensions/external/postgis/tools/reproducible-time.sh", - "sha256": "08fc52aceb5e5e6d649b89adabe0b5b4ec8af68e49bb576376c147ec686d81bb" + "sha256": "afa6de6175776c546130ae4a72fea7aecf9e3ea492c7c53649960252315ada39" } ] }, @@ -212,7 +212,7 @@ }, { "path": "src/extensions/generated/docs/extension-evidence.json", - "sha256": "76ee16070cd072ff872bd830997ec896f80b54f95f2810ccba8f6e4d3d48290e" + "sha256": "2e5910f4c231cbacef83eeb4363d60f8cded28fdc93bed5bdd629a9dda3b6360" }, { "path": "src/extensions/generated/docs/extensions.json", @@ -377,5 +377,5 @@ ] } ], - "sha256": "734178655f201aa904bb85ab6904b0e809c911f215da96bc802911b53853b4a5" + "sha256": "e1349e9e6076a60413541ea34b43f9684d10e58196afbab3d8e717869abf72f6" } diff --git a/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 b/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 index de6c6e62..5f4bccf8 100644 --- a/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 +++ b/src/runtimes/liboliphaunt/wasix/assets/generated/asset-inputs.sha256 @@ -1 +1 @@ -bb24309c2afb82a105149a6e27df0c57dab28915b5698d141946c7ea01b3a565 +b4d2b1074ce0afde520789745797c9d3187e3d8348c701fa61f97a18f2f1395c From 9654c96afdb190ae00350fd37b51a32fc25d2e79 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 05:17:00 +0000 Subject: [PATCH 5/9] fix(extensions): patch postgis raster attributes on windows --- .../postgis/.release-semantic-inputs.json | 4 ++-- .../native/bin/build-postgres18-windows.ps1 | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index e60c646a..72c191e4 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -99,7 +99,7 @@ }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1", - "sha256": "e55f584dc8045c1af093f01a66e440452fdb379a7aa162394cf118566dc57b59" + "sha256": "b7e32dd84d1e012c385df6763993e07c3a4673c1b423c341efc576f403375a36" }, { "path": "src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh", @@ -390,5 +390,5 @@ ] } ], - "sha256": "cee83c4ccff66bb2c1bc17d48137e84beb9aae187b7c8153886957c4f6203fcf" + "sha256": "72236219038e10eaed9e47a8202914e720e35319e7ef0ce0f6f4b1f63a8e5b21" } diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 index ee794d39..4fbffd3d 100644 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 @@ -1687,19 +1687,25 @@ function Patch-WindowsPostgisSource([string]$PostgisDir) { #endif "@ - $rasterCoreHeader = Join-Path $PostgisDir "raster/rt_core/librtcore.h" - $rasterCoreText = Get-Content -Raw -Path $rasterCoreHeader $legacyAttributeFallback = "# define __attribute__ (x)" $guardedAttributeFallback = @" # ifndef __attribute__ # define __attribute__(x) # endif "@ - if (-not $rasterCoreText.Contains($legacyAttributeFallback)) { - Fail "PostGIS raster compatibility header is missing the expected __attribute__ fallback" + foreach ($relativePath in @("raster/rt_core/librtcore.h", "raster/rt_pg/rtpostgis.c")) { + $sourcePath = Join-Path $PostgisDir $relativePath + $sourceText = Get-Content -Raw -Path $sourcePath + $fallbackCount = [regex]::Matches( + $sourceText, + [regex]::Escape($legacyAttributeFallback) + ).Count + if ($fallbackCount -ne 1) { + Fail "PostGIS raster source $relativePath must contain exactly one legacy __attribute__ fallback; found $fallbackCount" + } + $sourceText = $sourceText.Replace($legacyAttributeFallback, $guardedAttributeFallback) + Set-Content -Path $sourcePath -Encoding UTF8 -Value $sourceText } - $rasterCoreText = $rasterCoreText.Replace($legacyAttributeFallback, $guardedAttributeFallback) - Set-Content -Path $rasterCoreHeader -Encoding UTF8 -Value $rasterCoreText $declarationPattern = "(?m)^\s*(?!(?:extern\s+)?PGDLLEXPORT\s+)(?:extern\s+)?Datum\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(PG_FUNCTION_ARGS\);\r?$" $patchedDeclarationCount = 0 From 22dd9f09cb16051bd51042578a467e58c87a9b90 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 06:04:15 +0000 Subject: [PATCH 6/9] fix(extensions): link static proj into postgis raster --- .../external/postgis/.release-semantic-inputs.json | 4 ++-- .../native/bin/build-postgres18-windows.ps1 | 4 ++++ .../release/linux-native-compiler-contract.test.mjs | 13 +++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index 72c191e4..06788f17 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -99,7 +99,7 @@ }, { "path": "src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1", - "sha256": "b7e32dd84d1e012c385df6763993e07c3a4673c1b423c341efc576f403375a36" + "sha256": "71ba834a644c6d03be5678e5afca6ca6cc8cf28bd2ceba86500964b7df8030f5" }, { "path": "src/runtimes/liboliphaunt/native/bin/mobile-postgis-extensions.sh", @@ -390,5 +390,5 @@ ] } ], - "sha256": "72236219038e10eaed9e47a8202914e720e35319e7ef0ce0f6f4b1f63a8e5b21" + "sha256": "0b07989d3552ff56a81d511f6daed948b08f7f15bcf0d6fe9578eb19a3a40bf1" } diff --git a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 index 4fbffd3d..4b1820b9 100644 --- a/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 +++ b/src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1 @@ -945,6 +945,8 @@ function Build-WindowsPostgisGdalDependency { $jsonLib = First-File $jsonPrefix @("json-c.lib", "json-c-static.lib") $libxml2Lib = First-File $libxml2Prefix @("libxml2s.lib", "libxml2.lib", "xml2.lib") $projLib = First-File $projPrefix @("proj.lib", "libproj.lib") + $projConfig = First-File $projPrefix @("proj-config.cmake") + $projConfigDir = (Split-Path -Parent $projConfig).Replace("\", "/") # CMake writes this value into a generated try_compile project. Use forward # slashes so Windows path escapes such as \a are not parsed by CMake. $sqliteLib = (First-File $sqlitePrefix @("sqlite3.lib", "libsqlite3.lib")).Replace("\", "/") @@ -979,6 +981,8 @@ function Build-WindowsPostgisGdalDependency { "-DLIBXML2_INCLUDE_DIR=$(Join-Path $libxml2Prefix 'include/libxml2')", "-DLIBXML2_LIBRARY=$libxml2Lib", "-DGDAL_USE_PROJ=ON", + "-DGDAL_FIND_PACKAGE_PROJ_MODE=CONFIG", + "-DPROJ_DIR=$projConfigDir", "-DPROJ_INCLUDE_DIR=$(Join-Path $projPrefix 'include')", "-DPROJ_LIBRARY=$projLib", "-DGDAL_USE_SQLITE3=ON", diff --git a/tools/release/linux-native-compiler-contract.test.mjs b/tools/release/linux-native-compiler-contract.test.mjs index 6dae7196..5f52555d 100644 --- a/tools/release/linux-native-compiler-contract.test.mjs +++ b/tools/release/linux-native-compiler-contract.test.mjs @@ -20,12 +20,17 @@ const BUILD = path.join( ROOT, "src/runtimes/liboliphaunt/native/bin/build-postgres18-linux.sh", ); +const WINDOWS_BUILD = path.join( + ROOT, + "src/runtimes/liboliphaunt/native/bin/build-postgres18-windows.ps1", +); const CACHE = path.join( ROOT, "src/runtimes/liboliphaunt/native/bin/postgis-dependency-cache.sh", ); const setupSource = readFileSync(SETUP, "utf8"); const buildSource = readFileSync(BUILD, "utf8"); +const windowsBuildSource = readFileSync(WINDOWS_BUILD, "utf8"); const ci = parseWorkflow(ROOT, ".github/workflows/ci.yml"); const temporaryDirectories = []; @@ -149,6 +154,14 @@ describe("Windows native toolchain bootstrap contract", () => { "Chocolatey did not install $expected_executable after 3 attempts", ); }); + + test("imports static PROJ usage requirements when building GDAL", () => { + expect(windowsBuildSource).toContain( + '$projConfig = First-File $projPrefix @("proj-config.cmake")', + ); + expect(windowsBuildSource).toContain('"-DGDAL_FIND_PACKAGE_PROJ_MODE=CONFIG"'); + expect(windowsBuildSource).toContain('"-DPROJ_DIR=$projConfigDir"'); + }); }); describe("PostGIS native dependency cache", () => { From b9d4f26c032fbf1ce407b69d112941b3667a0258 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 06:54:51 +0000 Subject: [PATCH 7/9] fix(swift): isolate native bridge errors per thread --- src/sdks/swift/Sources/COliphaunt/bridge.c | 7 +- .../swift/tools/bridge-error-isolation.test.c | 98 +++++++++++++++++++ src/sdks/swift/tools/check-sdk.sh | 14 +++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/sdks/swift/tools/bridge-error-isolation.test.c diff --git a/src/sdks/swift/Sources/COliphaunt/bridge.c b/src/sdks/swift/Sources/COliphaunt/bridge.c index 54ea8f62..1c259076 100644 --- a/src/sdks/swift/Sources/COliphaunt/bridge.c +++ b/src/sdks/swift/Sources/COliphaunt/bridge.c @@ -54,7 +54,12 @@ struct OliphauntSession { char last_error[1024]; }; -static char global_last_error[1024]; +/* + * Failed opens do not have a session to own their error buffer. Swift Testing + * runs tests concurrently, so a process-global buffer lets an unrelated open + * overwrite the diagnostic before the caller reads it. + */ +static _Thread_local char global_last_error[1024]; static void set_global_error(const char *message) { snprintf(global_last_error, sizeof(global_last_error), "%s", message ? message : "unknown liboliphaunt Swift bridge error"); diff --git a/src/sdks/swift/tools/bridge-error-isolation.test.c b/src/sdks/swift/tools/bridge-error-isolation.test.c new file mode 100644 index 00000000..9ab88f49 --- /dev/null +++ b/src/sdks/swift/tools/bridge-error-isolation.test.c @@ -0,0 +1,98 @@ +#include "COliphaunt.h" + +#include +#include +#include + +typedef struct OpenResult { + const char *path; + int32_t rc; + OliphauntSession *session; + char error[1024]; +} OpenResult; + +static pthread_mutex_t coordination_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t coordination_changed = PTHREAD_COND_INITIALIZER; +static int first_open_complete; +static int second_open_complete; + +static void open_missing_library(OpenResult *result) { + OliphauntConfig config = {0}; + result->rc = oliphaunt_swift_open(result->path, &config, &result->session); +} + +static void *run_first_open(void *context) { + OpenResult *result = context; + open_missing_library(result); + + pthread_mutex_lock(&coordination_lock); + first_open_complete = 1; + pthread_cond_broadcast(&coordination_changed); + while (!second_open_complete) { + pthread_cond_wait(&coordination_changed, &coordination_lock); + } + snprintf( + result->error, + sizeof(result->error), + "%s", + oliphaunt_swift_last_error(NULL)); + pthread_mutex_unlock(&coordination_lock); + return NULL; +} + +static int assert_missing_library_error(const OpenResult *result) { + if (result->rc == 0 || result->session != NULL) { + fprintf(stderr, "opening missing library unexpectedly succeeded: %s\n", result->path); + return 1; + } + if (strstr(result->error, result->path) == NULL) { + fprintf( + stderr, + "missing-library error crossed threads: expected %s in %s\n", + result->path, + result->error); + return 1; + } + return 0; +} + +int main(void) { + OpenResult first = { + .path = "/oliphaunt-swift-missing/thread-a/liboliphaunt.dylib", + }; + OpenResult second = { + .path = "/oliphaunt-swift-missing/thread-b/liboliphaunt.dylib", + }; + pthread_t first_thread; + + if (pthread_create(&first_thread, NULL, run_first_open, &first) != 0) { + fputs("failed to create bridge error isolation thread\n", stderr); + return 1; + } + + pthread_mutex_lock(&coordination_lock); + while (!first_open_complete) { + pthread_cond_wait(&coordination_changed, &coordination_lock); + } + pthread_mutex_unlock(&coordination_lock); + + open_missing_library(&second); + snprintf( + second.error, + sizeof(second.error), + "%s", + oliphaunt_swift_last_error(NULL)); + + pthread_mutex_lock(&coordination_lock); + second_open_complete = 1; + pthread_cond_broadcast(&coordination_changed); + pthread_mutex_unlock(&coordination_lock); + + if (pthread_join(first_thread, NULL) != 0) { + fputs("failed to join bridge error isolation thread\n", stderr); + return 1; + } + + return assert_missing_library_error(&first) + || assert_missing_library_error(&second); +} diff --git a/src/sdks/swift/tools/check-sdk.sh b/src/sdks/swift/tools/check-sdk.sh index 290b090d..2103d9f9 100755 --- a/src/sdks/swift/tools/check-sdk.sh +++ b/src/sdks/swift/tools/check-sdk.sh @@ -91,6 +91,19 @@ verification. MSG } +check_bridge_error_isolation() { + bridge_test_dir="$(prepare_scratch_dir bridge-error-isolation)" + set -- -std=c11 -Wall -Wextra -Werror -pthread \ + -I "$package_dir/Sources/COliphaunt/include" \ + "$package_dir/Sources/COliphaunt/bridge.c" \ + "$package_dir/tools/bridge-error-isolation.test.c" + if [ "$(uname -s)" = "Linux" ]; then + set -- "$@" -ldl + fi + run cc "$@" -o "$bridge_test_dir/bridge-error-isolation" + run "$bridge_test_dir/bridge-error-isolation" +} + check_swiftpm_release_asset_manifest() { liboliphaunt_version="$(cat src/sdks/swift/LIBOLIPHAUNT_VERSION)" release_manifest="$scratch_root/Package.swift.release" @@ -625,6 +638,7 @@ for product in COliphaunt Oliphaunt OliphauntExtensionSupport; do fi done check_swiftpm_extension_product_generator +check_bridge_error_isolation if [ "$mode" = "coverage" ]; then exec tools/coverage/run-product oliphaunt-swift From 3192058318bddd3b236ac3a9958266645563e269 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 08:00:54 +0000 Subject: [PATCH 8/9] fix(extensions): admit postgis mobile gdal archive --- .../contrib/.release-semantic-inputs.json | 4 +-- .../pg_hashids/.release-semantic-inputs.json | 4 +-- .../pg_ivm/.release-semantic-inputs.json | 4 +-- .../.release-semantic-inputs.json | 4 +-- .../pg_uuidv7/.release-semantic-inputs.json | 4 +-- .../pgtap/.release-semantic-inputs.json | 4 +-- .../postgis/.release-semantic-inputs.json | 4 +-- .../vector/.release-semantic-inputs.json | 4 +-- .../native/.release-semantic-inputs.json | 4 +-- ...OliphauntExtensionCatalogContractTest.java | 14 +++++---- ...tension-artifact-archive-policy.properties | 6 ++-- src/sdks/rust/src/runtime_resources.rs | 29 +++++++++++-------- .../extension-artifact-inventory.test.mjs | 28 +++++++++++------- 13 files changed, 64 insertions(+), 49 deletions(-) diff --git a/src/extensions/contrib/.release-semantic-inputs.json b/src/extensions/contrib/.release-semantic-inputs.json index c685889b..f3a8951d 100644 --- a/src/extensions/contrib/.release-semantic-inputs.json +++ b/src/extensions/contrib/.release-semantic-inputs.json @@ -158,7 +158,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -377,5 +377,5 @@ ] } ], - "sha256": "98252ebbafb0c1ef632a4d861f423c0cb6e9d09a91e6fbf37c979292dd1e8a10" + "sha256": "51378726560daf6836bd9657bb329afbc8811fe20e584fe297842c41723b42d5" } diff --git a/src/extensions/external/pg_hashids/.release-semantic-inputs.json b/src/extensions/external/pg_hashids/.release-semantic-inputs.json index 26e7b4ef..9fcbbb2f 100644 --- a/src/extensions/external/pg_hashids/.release-semantic-inputs.json +++ b/src/extensions/external/pg_hashids/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "e91c587cc2556d9c456dae649a2c9113c8442a62aa85d6e1f1d5bbe0ae1745b4" + "sha256": "95a299fbbf2e52d1f3314d0422b8a16ffdad2042247ef0621bce5a43132c6bde" } diff --git a/src/extensions/external/pg_ivm/.release-semantic-inputs.json b/src/extensions/external/pg_ivm/.release-semantic-inputs.json index 11b92763..40fae236 100644 --- a/src/extensions/external/pg_ivm/.release-semantic-inputs.json +++ b/src/extensions/external/pg_ivm/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "cb69acade62d6aecf3748f74e1d4f223526177084418ba6305e2af840b828393" + "sha256": "eff0579b32221c3a8768e1f694e9f9f7b26d7dc8d8e7fd2d566ab99cbb70da37" } diff --git a/src/extensions/external/pg_textsearch/.release-semantic-inputs.json b/src/extensions/external/pg_textsearch/.release-semantic-inputs.json index 49507131..9bbce938 100644 --- a/src/extensions/external/pg_textsearch/.release-semantic-inputs.json +++ b/src/extensions/external/pg_textsearch/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "409d6c6986de030409627e7d33954b86b2cba7826560780a89d57cb576c0f3f1" + "sha256": "87e66bdcc785452f6b1b08628a53090f05cf0c5d496a74d69a3516f3ab3a8932" } diff --git a/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json b/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json index c2263ab9..003a980b 100644 --- a/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json +++ b/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "cf1fe73ef32ba83d6eaf8d9858cba1fb8c7f6c5f3763e5cfb9c8cddf1a52039d" + "sha256": "e33b91948958c6bff3054cb09f9f8776db0459694656d205eed00744937830c5" } diff --git a/src/extensions/external/pgtap/.release-semantic-inputs.json b/src/extensions/external/pgtap/.release-semantic-inputs.json index 14533301..586e2b1b 100644 --- a/src/extensions/external/pgtap/.release-semantic-inputs.json +++ b/src/extensions/external/pgtap/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "59fa73e1b278db5b9536a3011b3d86c2b05c3e6f9eda0b72372e47eb05d7463a" + "sha256": "8f2636f8e498111b53e297009146ab3c9f90a6452cfdbb9eadb4abd800940b34" } diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index 06788f17..e61f2277 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -171,7 +171,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -390,5 +390,5 @@ ] } ], - "sha256": "0b07989d3552ff56a81d511f6daed948b08f7f15bcf0d6fe9578eb19a3a40bf1" + "sha256": "2e26241513da4ea3f71c12387baae03c6a17bc158796588d66e6e900777403b9" } diff --git a/src/extensions/external/vector/.release-semantic-inputs.json b/src/extensions/external/vector/.release-semantic-inputs.json index b2dfcfb5..6748040f 100644 --- a/src/extensions/external/vector/.release-semantic-inputs.json +++ b/src/extensions/external/vector/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "e708d2a5749cdcbca9de2abe44abdf36b5faaa5f9eb010edc412496876d955fa" + "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "bbbc8601954d8ad75eefa03a0749eae7e6ba1aee98828b90153504bfe4d49276" + "sha256": "65edced47daad72abe1e39884cdfce877407b512d68d57e81077b904dcc824c6" } diff --git a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json index 40a27ce7..1c31c84e 100644 --- a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json +++ b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json @@ -371,7 +371,7 @@ }, { "path": "src/sdks/rust/src/runtime_resources.rs", - "sha256": "692238b38e26ea3e0e7f31201137fb598de7b3f128ca4e5f9bcfea0c045127b2" + "sha256": "07330bd8ab7d9d7a88281a5bb8a7a7a637d78bc93d323b4b650c549e686b7179" }, { "path": "src/sdks/rust/src/runtime_resources/extension_artifact.rs", @@ -457,5 +457,5 @@ ] } ], - "sha256": "47e8d4a034b1640db3016017fe7c9e7cdf395f1a3b65889ac575aa70746c88ed" + "sha256": "31a7587df6d97aa3291c8fd497a50d468fc7efcd8f832586aef2cd8a795041a8" } diff --git a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java index 1388b38b..78d03dde 100644 --- a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java +++ b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java @@ -94,20 +94,22 @@ private static void validatesPublicTarGzArchivePreflight() throws Exception { try { PublicTarGzArchivePreflight.Limits extensionLimits = PublicTarGzArchivePreflight.extensionArtifactLimits(); - equal(134_217_728L, extensionLimits.maxCompressedBytes(), "extension compressed limit"); - equal(536_870_912L, extensionLimits.maxExpandedBytes(), "extension expanded limit"); - equal(268_435_456L, extensionLimits.maxEntryBytes(), "extension member limit"); + equal(268_435_456L, extensionLimits.maxCompressedBytes(), "extension compressed limit"); + equal(1_073_741_824L, extensionLimits.maxExpandedBytes(), "extension expanded limit"); + equal(536_870_912L, extensionLimits.maxEntryBytes(), "extension member limit"); equal(4_096, extensionLimits.maxEntries(), "extension member-count limit"); equal( extensionLimits.maxExpandedBytes(), PublicTarGzArchivePreflight.expansionLimitForContractTest(1, extensionLimits), "extension policy must not add a Java-only compression-ratio limit"); + // The qualified GDAL leaf exceeded 256 MiB. Combine its minimum proven + // size with the prior exact PostGIS high-water marks conservatively. if (!(64_676_748L <= extensionLimits.maxCompressedBytes() - && 345_621_694L <= extensionLimits.maxExpandedBytes() - && 154_827_564L <= extensionLimits.maxEntryBytes() + && 614_057_151L <= extensionLimits.maxExpandedBytes() + && 268_435_457L <= extensionLimits.maxEntryBytes() && 27 <= extensionLimits.maxEntries())) { throw new AssertionError( - "shared extension archive policy must admit the observed Android ARM64 PostGIS leaf shape"); + "shared extension archive policy must admit the qualified Android ARM64 PostGIS leaf envelope"); } List validEntries = List.of( diff --git a/src/sdks/rust/extension-artifact-archive-policy.properties b/src/sdks/rust/extension-artifact-archive-policy.properties index 2f7a21be..af04bcba 100644 --- a/src/sdks/rust/extension-artifact-archive-policy.properties +++ b/src/sdks/rust/extension-artifact-archive-policy.properties @@ -1,5 +1,5 @@ schema=oliphaunt-extension-artifact-archive-policy-v1 -maxCompressedBytes=134217728 -maxExpandedBytes=536870912 -maxMemberBytes=268435456 +maxCompressedBytes=268435456 +maxExpandedBytes=1073741824 +maxMemberBytes=536870912 maxMembers=4096 diff --git a/src/sdks/rust/src/runtime_resources.rs b/src/sdks/rust/src/runtime_resources.rs index 91eff36e..97c17f6a 100644 --- a/src/sdks/rust/src/runtime_resources.rs +++ b/src/sdks/rust/src/runtime_resources.rs @@ -3327,18 +3327,18 @@ CREATE FUNCTION sql_only(integer) RETURNS integer } #[test] - fn extension_artifact_archive_policy_covers_observed_android_postgis_shape() { + fn extension_artifact_archive_policy_covers_qualified_android_postgis_envelope() { let policy = extension_artifact_archive_policy().unwrap(); - assert_eq!(policy.max_compressed_bytes, 128 * 1024 * 1024); - assert_eq!(policy.max_expanded_bytes, 512 * 1024 * 1024); - assert_eq!(policy.max_member_bytes, 256 * 1024 * 1024); + assert_eq!(policy.max_compressed_bytes, 256 * 1024 * 1024); + assert_eq!(policy.max_expanded_bytes, 1024 * 1024 * 1024); + assert_eq!(policy.max_member_bytes, 512 * 1024 * 1024); assert_eq!(policy.max_members, 4096); - // Exact high-water marks from the qualified Android ARM64 PostGIS leaf - // artifact that exposed the former 48/256 MiB consumer-only limits. + // Exact prior high-water marks plus the smallest GDAL size that proves + // the qualified leaf exceeded the former 256 MiB member ceiling. Do + // not invent an unobserved exact GDAL byte count. assert!(64_676_748 <= policy.max_compressed_bytes); - assert!(345_621_694 <= policy.max_expanded_bytes); - assert!(154_827_564 <= policy.max_member_bytes); + assert!((256 * 1024 * 1024) + 1 <= policy.max_member_bytes); assert!(27 <= policy.max_members); let root = Path::new("android-arm64-v8a/postgis"); @@ -3346,7 +3346,12 @@ CREATE FUNCTION sql_only(integer) RETURNS integer member_count: 0, expanded_bytes: 1024, }; - let mut observed_member_sizes = vec![154_827_564, 110_259_522, 80_534_608]; + let mut observed_member_sizes = vec![ + (256 * 1024 * 1024) + 1, + 154_827_564, + 110_259_522, + 80_534_608, + ]; observed_member_sizes.resize(27, 0); for (index, bytes) in observed_member_sizes.into_iter().enumerate() { record_extension_artifact_archive_member( @@ -3372,7 +3377,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer }, ) .unwrap_err(); - assert!(error.to_string().contains("exceeds 268435456 bytes")); + assert!(error.to_string().contains("exceeds 536870912 bytes")); } #[test] @@ -3399,7 +3404,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer assert!( error .to_string() - .contains("member larger than 268435456 bytes"), + .contains("member larger than 536870912 bytes"), "unexpected oversized-member error: {error}" ); @@ -3423,7 +3428,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer assert!( error .to_string() - .contains("must contain between 1 and 134217728 bytes"), + .contains("must contain between 1 and 268435456 bytes"), "unexpected oversized-carrier error: {error}" ); diff --git a/tools/release/extension-artifact-inventory.test.mjs b/tools/release/extension-artifact-inventory.test.mjs index d1d3e60b..8e14ce52 100644 --- a/tools/release/extension-artifact-inventory.test.mjs +++ b/tools/release/extension-artifact-inventory.test.mjs @@ -206,17 +206,25 @@ async function expectArchiveFailure(root, name, entries, metadata, pattern) { async function main() { assert.deepEqual(EXTENSION_ARTIFACT_ARCHIVE_POLICY, { - maxCompressedBytes: 128 * 1024 * 1024, - maxExpandedBytes: 512 * 1024 * 1024, - maxMemberBytes: 256 * 1024 * 1024, + maxCompressedBytes: 256 * 1024 * 1024, + maxExpandedBytes: 1024 * 1024 * 1024, + maxMemberBytes: 512 * 1024 * 1024, maxMembers: 4096, }); - const observedAndroidPostgisMembers = [154_827_564, 110_259_522, 80_534_608]; - observedAndroidPostgisMembers.length = 27; - observedAndroidPostgisMembers.fill(0, 3); + // The qualified GDAL leaf exceeded the former 256 MiB ceiling. Combine the + // smallest size that proves that failure with the prior exact PostGIS high + // water marks instead of inventing an unobserved exact GDAL byte count. + const qualifiedAndroidPostgisMembers = [ + (256 * 1024 * 1024) + 1, + 154_827_564, + 110_259_522, + 80_534_608, + ]; + qualifiedAndroidPostgisMembers.length = 27; + qualifiedAndroidPostgisMembers.fill(0, 4); const observedAndroidPostgisExpanded = validateExtensionArtifactArchivePlan( - observedAndroidPostgisMembers.map((bytes, index) => ({ name: `member-${index}`, bytes })), - "observed Android ARM64 PostGIS artifact", + qualifiedAndroidPostgisMembers.map((bytes, index) => ({ name: `member-${index}`, bytes })), + "qualified Android ARM64 PostGIS artifact envelope", ); assert.ok(64_676_748 <= EXTENSION_ARTIFACT_ARCHIVE_POLICY.maxCompressedBytes); assert.ok(observedAndroidPostgisExpanded <= EXTENSION_ARTIFACT_ARCHIVE_POLICY.maxExpandedBytes); @@ -1132,7 +1140,7 @@ async function main() { nativeRuntimeVersion: "1.2.3", label: "oversized member", }), - /member .* exceeds 268435456 bytes/u, + /member .* exceeds 536870912 bytes/u, ); assert.throws( @@ -1140,7 +1148,7 @@ async function main() { { name: "one", bytes: EXTENSION_ARTIFACT_ARCHIVE_POLICY.maxMemberBytes }, { name: "two", bytes: EXTENSION_ARTIFACT_ARCHIVE_POLICY.maxMemberBytes }, ]), - /expands beyond 536870912 bytes/u, + /expands beyond 1073741824 bytes/u, ); const excessiveMembers = new Map([["manifest.properties", manifest()]]); From 41988b2c2da2efb58b2281688185f8bec4997a5c Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Mon, 10 Aug 2026 09:08:39 +0000 Subject: [PATCH 9/9] fix(extensions): admit postgis arm64 gdal archive --- .../contrib/.release-semantic-inputs.json | 4 ++-- .../pg_hashids/.release-semantic-inputs.json | 4 ++-- .../pg_ivm/.release-semantic-inputs.json | 4 ++-- .../.release-semantic-inputs.json | 4 ++-- .../pg_uuidv7/.release-semantic-inputs.json | 4 ++-- .../pgtap/.release-semantic-inputs.json | 4 ++-- .../postgis/.release-semantic-inputs.json | 4 ++-- .../vector/.release-semantic-inputs.json | 4 ++-- .../native/.release-semantic-inputs.json | 4 ++-- .../OliphauntExtensionCatalogContractTest.java | 12 ++++++------ ...xtension-artifact-archive-policy.properties | 6 +++--- src/sdks/rust/src/runtime_resources.rs | 18 +++++++++--------- .../extension-artifact-inventory.test.mjs | 14 +++++++------- 13 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/extensions/contrib/.release-semantic-inputs.json b/src/extensions/contrib/.release-semantic-inputs.json index f3a8951d..a8f52e8f 100644 --- a/src/extensions/contrib/.release-semantic-inputs.json +++ b/src/extensions/contrib/.release-semantic-inputs.json @@ -158,7 +158,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -377,5 +377,5 @@ ] } ], - "sha256": "51378726560daf6836bd9657bb329afbc8811fe20e584fe297842c41723b42d5" + "sha256": "5d0fc5e082f72592ab12c71457b9a6840ae7c30d868cb07785a0959a6983cff8" } diff --git a/src/extensions/external/pg_hashids/.release-semantic-inputs.json b/src/extensions/external/pg_hashids/.release-semantic-inputs.json index 9fcbbb2f..9e059280 100644 --- a/src/extensions/external/pg_hashids/.release-semantic-inputs.json +++ b/src/extensions/external/pg_hashids/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "95a299fbbf2e52d1f3314d0422b8a16ffdad2042247ef0621bce5a43132c6bde" + "sha256": "c10becc3898bff217f9eb6d6860856d9cabacd7e91ad46ced107674e8e093a9a" } diff --git a/src/extensions/external/pg_ivm/.release-semantic-inputs.json b/src/extensions/external/pg_ivm/.release-semantic-inputs.json index 40fae236..59046697 100644 --- a/src/extensions/external/pg_ivm/.release-semantic-inputs.json +++ b/src/extensions/external/pg_ivm/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "eff0579b32221c3a8768e1f694e9f9f7b26d7dc8d8e7fd2d566ab99cbb70da37" + "sha256": "000c986be28889a114ca5d32d5f431b6b4f12db50af6f52ff6876d3b5d7d0ccf" } diff --git a/src/extensions/external/pg_textsearch/.release-semantic-inputs.json b/src/extensions/external/pg_textsearch/.release-semantic-inputs.json index 9bbce938..d5cb36b7 100644 --- a/src/extensions/external/pg_textsearch/.release-semantic-inputs.json +++ b/src/extensions/external/pg_textsearch/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "87e66bdcc785452f6b1b08628a53090f05cf0c5d496a74d69a3516f3ab3a8932" + "sha256": "93cd0ff8946b36e8ff28bae681f9386ff69b209cec52710a3466ac1df0088024" } diff --git a/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json b/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json index 003a980b..dca448b3 100644 --- a/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json +++ b/src/extensions/external/pg_uuidv7/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "e33b91948958c6bff3054cb09f9f8776db0459694656d205eed00744937830c5" + "sha256": "df761e3615935b414bfcb2a6b88075665a13ffbe5201522deaf7ded154464afe" } diff --git a/src/extensions/external/pgtap/.release-semantic-inputs.json b/src/extensions/external/pgtap/.release-semantic-inputs.json index 586e2b1b..8fde11a8 100644 --- a/src/extensions/external/pgtap/.release-semantic-inputs.json +++ b/src/extensions/external/pgtap/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "8f2636f8e498111b53e297009146ab3c9f90a6452cfdbb9eadb4abd800940b34" + "sha256": "1b44a50db553a1acdd9994caf983545811d5729ebff594e287a28d135a3d9b9d" } diff --git a/src/extensions/external/postgis/.release-semantic-inputs.json b/src/extensions/external/postgis/.release-semantic-inputs.json index e61f2277..e02af265 100644 --- a/src/extensions/external/postgis/.release-semantic-inputs.json +++ b/src/extensions/external/postgis/.release-semantic-inputs.json @@ -171,7 +171,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -390,5 +390,5 @@ ] } ], - "sha256": "2e26241513da4ea3f71c12387baae03c6a17bc158796588d66e6e900777403b9" + "sha256": "b529ee0e3f512df115757455ec05c58262789357d235f8e1597e06392954b128" } diff --git a/src/extensions/external/vector/.release-semantic-inputs.json b/src/extensions/external/vector/.release-semantic-inputs.json index 6748040f..469ad004 100644 --- a/src/extensions/external/vector/.release-semantic-inputs.json +++ b/src/extensions/external/vector/.release-semantic-inputs.json @@ -124,7 +124,7 @@ }, { "path": "src/sdks/rust/extension-artifact-archive-policy.properties", - "sha256": "f8be28f0d612bf19ee2d415b71863f8a7da0f959bb1f316199496388fb94e4a7" + "sha256": "89f3c0953d3070cc5e594e784488591612f551452c31c59b45547573bb7455bf" }, { "path": "tools/release/bounded-gunzip-to-file.mjs", @@ -343,5 +343,5 @@ ] } ], - "sha256": "65edced47daad72abe1e39884cdfce877407b512d68d57e81077b904dcc824c6" + "sha256": "2c0fcd5d5d280ae72538f453248c1250e1205b9f403344f5b71a9fc173778093" } diff --git a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json index 1c31c84e..25357d95 100644 --- a/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json +++ b/src/runtimes/liboliphaunt/native/.release-semantic-inputs.json @@ -371,7 +371,7 @@ }, { "path": "src/sdks/rust/src/runtime_resources.rs", - "sha256": "07330bd8ab7d9d7a88281a5bb8a7a7a637d78bc93d323b4b650c549e686b7179" + "sha256": "6321238615a678c7b16039c7c5a4a574993409b67c77d7f2d0c5d13e27491f98" }, { "path": "src/sdks/rust/src/runtime_resources/extension_artifact.rs", @@ -457,5 +457,5 @@ ] } ], - "sha256": "31a7587df6d97aa3291c8fd497a50d468fc7efcd8f832586aef2cd8a795041a8" + "sha256": "200f6f83fedd13a84f3ab4f866eb356c4088199da2b1c68877decfa80f22e997" } diff --git a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java index 78d03dde..37fa9003 100644 --- a/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java +++ b/src/sdks/kotlin/oliphaunt-android-gradle-plugin/src/test/java/dev/oliphaunt/android/OliphauntExtensionCatalogContractTest.java @@ -94,19 +94,19 @@ private static void validatesPublicTarGzArchivePreflight() throws Exception { try { PublicTarGzArchivePreflight.Limits extensionLimits = PublicTarGzArchivePreflight.extensionArtifactLimits(); - equal(268_435_456L, extensionLimits.maxCompressedBytes(), "extension compressed limit"); - equal(1_073_741_824L, extensionLimits.maxExpandedBytes(), "extension expanded limit"); - equal(536_870_912L, extensionLimits.maxEntryBytes(), "extension member limit"); + equal(1_073_741_824L, extensionLimits.maxCompressedBytes(), "extension compressed limit"); + equal(2_147_483_648L, extensionLimits.maxExpandedBytes(), "extension expanded limit"); + equal(1_073_741_824L, extensionLimits.maxEntryBytes(), "extension member limit"); equal(4_096, extensionLimits.maxEntries(), "extension member-count limit"); equal( extensionLimits.maxExpandedBytes(), PublicTarGzArchivePreflight.expansionLimitForContractTest(1, extensionLimits), "extension policy must not add a Java-only compression-ratio limit"); - // The qualified GDAL leaf exceeded 256 MiB. Combine its minimum proven + // The qualified GDAL leaf exceeded 512 MiB. Combine its minimum proven // size with the prior exact PostGIS high-water marks conservatively. if (!(64_676_748L <= extensionLimits.maxCompressedBytes() - && 614_057_151L <= extensionLimits.maxExpandedBytes() - && 268_435_457L <= extensionLimits.maxEntryBytes() + && 882_492_607L <= extensionLimits.maxExpandedBytes() + && 536_870_913L <= extensionLimits.maxEntryBytes() && 27 <= extensionLimits.maxEntries())) { throw new AssertionError( "shared extension archive policy must admit the qualified Android ARM64 PostGIS leaf envelope"); diff --git a/src/sdks/rust/extension-artifact-archive-policy.properties b/src/sdks/rust/extension-artifact-archive-policy.properties index af04bcba..4b896911 100644 --- a/src/sdks/rust/extension-artifact-archive-policy.properties +++ b/src/sdks/rust/extension-artifact-archive-policy.properties @@ -1,5 +1,5 @@ schema=oliphaunt-extension-artifact-archive-policy-v1 -maxCompressedBytes=268435456 -maxExpandedBytes=1073741824 -maxMemberBytes=536870912 +maxCompressedBytes=1073741824 +maxExpandedBytes=2147483648 +maxMemberBytes=1073741824 maxMembers=4096 diff --git a/src/sdks/rust/src/runtime_resources.rs b/src/sdks/rust/src/runtime_resources.rs index 97c17f6a..8105c561 100644 --- a/src/sdks/rust/src/runtime_resources.rs +++ b/src/sdks/rust/src/runtime_resources.rs @@ -3329,16 +3329,16 @@ CREATE FUNCTION sql_only(integer) RETURNS integer #[test] fn extension_artifact_archive_policy_covers_qualified_android_postgis_envelope() { let policy = extension_artifact_archive_policy().unwrap(); - assert_eq!(policy.max_compressed_bytes, 256 * 1024 * 1024); - assert_eq!(policy.max_expanded_bytes, 1024 * 1024 * 1024); - assert_eq!(policy.max_member_bytes, 512 * 1024 * 1024); + assert_eq!(policy.max_compressed_bytes, 1024 * 1024 * 1024); + assert_eq!(policy.max_expanded_bytes, 2 * 1024 * 1024 * 1024); + assert_eq!(policy.max_member_bytes, 1024 * 1024 * 1024); assert_eq!(policy.max_members, 4096); // Exact prior high-water marks plus the smallest GDAL size that proves - // the qualified leaf exceeded the former 256 MiB member ceiling. Do + // the qualified leaf exceeded the former 512 MiB member ceiling. Do // not invent an unobserved exact GDAL byte count. assert!(64_676_748 <= policy.max_compressed_bytes); - assert!((256 * 1024 * 1024) + 1 <= policy.max_member_bytes); + assert!((512 * 1024 * 1024) + 1 <= policy.max_member_bytes); assert!(27 <= policy.max_members); let root = Path::new("android-arm64-v8a/postgis"); @@ -3347,7 +3347,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer expanded_bytes: 1024, }; let mut observed_member_sizes = vec![ - (256 * 1024 * 1024) + 1, + (512 * 1024 * 1024) + 1, 154_827_564, 110_259_522, 80_534_608, @@ -3377,7 +3377,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer }, ) .unwrap_err(); - assert!(error.to_string().contains("exceeds 536870912 bytes")); + assert!(error.to_string().contains("exceeds 1073741824 bytes")); } #[test] @@ -3404,7 +3404,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer assert!( error .to_string() - .contains("member larger than 536870912 bytes"), + .contains("member larger than 1073741824 bytes"), "unexpected oversized-member error: {error}" ); @@ -3428,7 +3428,7 @@ CREATE FUNCTION sql_only(integer) RETURNS integer assert!( error .to_string() - .contains("must contain between 1 and 268435456 bytes"), + .contains("must contain between 1 and 1073741824 bytes"), "unexpected oversized-carrier error: {error}" ); diff --git a/tools/release/extension-artifact-inventory.test.mjs b/tools/release/extension-artifact-inventory.test.mjs index 8e14ce52..46fccb51 100644 --- a/tools/release/extension-artifact-inventory.test.mjs +++ b/tools/release/extension-artifact-inventory.test.mjs @@ -206,16 +206,16 @@ async function expectArchiveFailure(root, name, entries, metadata, pattern) { async function main() { assert.deepEqual(EXTENSION_ARTIFACT_ARCHIVE_POLICY, { - maxCompressedBytes: 256 * 1024 * 1024, - maxExpandedBytes: 1024 * 1024 * 1024, - maxMemberBytes: 512 * 1024 * 1024, + maxCompressedBytes: 1024 * 1024 * 1024, + maxExpandedBytes: 2 * 1024 * 1024 * 1024, + maxMemberBytes: 1024 * 1024 * 1024, maxMembers: 4096, }); - // The qualified GDAL leaf exceeded the former 256 MiB ceiling. Combine the + // The qualified GDAL leaf exceeded the former 512 MiB ceiling. Combine the // smallest size that proves that failure with the prior exact PostGIS high // water marks instead of inventing an unobserved exact GDAL byte count. const qualifiedAndroidPostgisMembers = [ - (256 * 1024 * 1024) + 1, + (512 * 1024 * 1024) + 1, 154_827_564, 110_259_522, 80_534_608, @@ -1140,7 +1140,7 @@ async function main() { nativeRuntimeVersion: "1.2.3", label: "oversized member", }), - /member .* exceeds 536870912 bytes/u, + /member .* exceeds 1073741824 bytes/u, ); assert.throws( @@ -1148,7 +1148,7 @@ async function main() { { name: "one", bytes: EXTENSION_ARTIFACT_ARCHIVE_POLICY.maxMemberBytes }, { name: "two", bytes: EXTENSION_ARTIFACT_ARCHIVE_POLICY.maxMemberBytes }, ]), - /expands beyond 1073741824 bytes/u, + /expands beyond 2147483648 bytes/u, ); const excessiveMembers = new Map([["manifest.properties", manifest()]]);