From 9ce91e3421a5db35bb5aa9e1af267be6c9136abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Sun, 23 Oct 2022 14:54:59 +0200 Subject: [PATCH 01/10] Fix GeosLibrary wrapper to work with GEOS >= 3.8.0 --- packages/basemap/utils/GeosLibrary.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index c7e9460e0..7ee5f64a1 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -138,13 +138,24 @@ def extract(self, overwrite=True): os.chmod(path, 0o755) # Patch CMakeLists so that libgeos_c.so does not depend on libgeos.so. - cmakefile = os.path.join(zipfold, "capi", "CMakeLists.txt") + if self.version_tuple < (3, 8, 0): + cmakefile = os.path.join(zipfold, "capi", "CMakeLists.txt") + oldtext = "target_link_libraries(geos_c geos)" + newtext = "target_link_libraries(geos_c geos-static)" + else: + cmakefile = os.path.join(zipfold, "CMakeLists.txt") + oldtext = 'add_library(geos "")' + newtext = 'add_library(geos STATIC "")' with io.open(cmakefile, "r", encoding="utf-8") as fd: lines = fd.readlines() with io.open(cmakefile, "wb") as fd: - oldtext = "target_link_libraries(geos_c geos)" - newtext = "target_link_libraries(geos_c geos-static)" + found_sharedline = False + shared_oldtext = "if(BUILD_SHARED_LIBS)" + shared_newtext = "if(FALSE)" for line in lines: + if not found_sharedline and shared_oldtext in line: + line = line.replace(shared_oldtext, shared_newtext) + found_sharedline = True fd.write(line.replace(oldtext, newtext).encode()) # Apply specific patches for GEOS < 3.6.0. @@ -184,9 +195,12 @@ def build(self, installdir=None, njobs=1): # Define configure options. config_opts = [ "-DCMAKE_INSTALL_PREFIX={0}".format(installdir), - "-DGEOS_ENABLE_TESTS=OFF", "-DCMAKE_BUILD_TYPE=Release", ] + if self.version_tuple < (3, 8, 0): + config_opts += ["-DGEOS_ENABLE_TESTS=OFF"] + else: + config_opts += ["-DBUILD_TESTING=OFF"] if os.name == "nt" and self.version_tuple < (3, 6, 0): config_opts = ["-G", "NMake Makefiles"] + config_opts From ee4d68b4ee682b110535333f6faf1396bd750588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Sun, 23 Oct 2022 15:02:09 +0200 Subject: [PATCH 02/10] Reformat config/build options in GeosLibrary.build --- packages/basemap/utils/GeosLibrary.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index 7ee5f64a1..909974bfb 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -183,37 +183,33 @@ def build(self, installdir=None, njobs=1): # Download and extract zip file if not present. zipfold = os.path.join(self.root, "geos-{0}".format(self.version)) self.extract(overwrite=True) + version = self.version_tuple - # Define build directory. + # Define build and install directory. builddir = os.path.join(zipfold, "build") - - # Define installation directory. if installdir is None: installdir = os.path.expanduser("~/.local/share/libgeos") installdir = os.path.abspath(installdir) - # Define configure options. + # Define generic configure and build options. config_opts = [ - "-DCMAKE_INSTALL_PREFIX={0}".format(installdir), "-DCMAKE_BUILD_TYPE=Release", + "-DCMAKE_INSTALL_PREFIX={0}".format(installdir), + "-D{0}=OFF".format("GEOS_ENABLE_TESTS" if version < (3, 8, 0) + else "BUILD_TESTING") ] - if self.version_tuple < (3, 8, 0): - config_opts += ["-DGEOS_ENABLE_TESTS=OFF"] - else: - config_opts += ["-DBUILD_TESTING=OFF"] - if os.name == "nt" and self.version_tuple < (3, 6, 0): - config_opts = ["-G", "NMake Makefiles"] + config_opts - - # Define build options. - build_env = os.environ.copy() build_opts = [ "--config", "Release", "--target", "install", ] + build_env = os.environ.copy() + + # Define custom configure and build options. if os.name != "nt": build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs) - elif self.version_tuple < (3, 6, 0): + elif version < (3, 6, 0): win64 = (8 * struct.calcsize("P") == 64) + config_opts = ["-G", "NMake Makefiles"] + config_opts build_opts.extend([ "--", "WIN64={0}".format("YES" if win64 else "NO"), From df26b51000d5d669f3c022a04a1875454802004d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Sun, 23 Oct 2022 15:04:10 +0200 Subject: [PATCH 03/10] Simplify subprocess blocks in GeosLibrary.build --- packages/basemap/utils/GeosLibrary.py | 33 +++++++++++---------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index 909974bfb..7bf6e867c 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -218,24 +218,17 @@ def build(self, installdir=None, njobs=1): else: build_opts = ["-j", "{0:d}".format(njobs)] + build_opts - # Now move to the GEOS source code folder and build with CMake. - cwd = os.getcwd() + # Call cmake configure after ensuring that the build directory exists. try: - # Ensure that the build directory exists. - try: - os.makedirs(builddir) - except OSError: - pass - os.chdir(builddir) - # Call cmake configure. - subprocess.call(["cmake", ".."] + config_opts) - # Ensure that the install directory exists. - try: - os.makedirs(installdir) - except OSError: - pass - # Call cmake build and install. - subprocess.call(["cmake", "--build", "."] + build_opts, - env=build_env) - finally: - os.chdir(cwd) + os.makedirs(builddir) + except OSError: + pass + subprocess.call(["cmake", ".."] + config_opts, cwd=builddir) + + # Call cmake build after ensuring that the install directory exists. + try: + os.makedirs(installdir) + except OSError: + pass + subprocess.call(["cmake", "--build", "."] + build_opts, + cwd=builddir, env=build_env) From 8a0d01e2e0a6ff0ea9a84a177a762f97ddf9764f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Sun, 23 Oct 2022 21:46:40 +0200 Subject: [PATCH 04/10] Fix Antarctica polygon workaround for GEOS >= 3.9.0 --- packages/basemap/src/mpl_toolkits/basemap/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/basemap/src/mpl_toolkits/basemap/__init__.py b/packages/basemap/src/mpl_toolkits/basemap/__init__.py index 653813f34..e89bd9504 100644 --- a/packages/basemap/src/mpl_toolkits/basemap/__init__.py +++ b/packages/basemap/src/mpl_toolkits/basemap/__init__.py @@ -1336,7 +1336,7 @@ def _readboundarydata(self,name,as_polygons=False): b2 = b.copy() # fix Antartica. if name == 'gshhs' and south < -89: - b = b[4:,:] + b = b[3:,:] b2 = b.copy() poly = Shape(b) # if map boundary polygon is a valid one in lat/lon From 5b879d4df8a30a623f9914c6e08fc32ed8daedcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Sun, 23 Oct 2022 22:36:07 +0200 Subject: [PATCH 05/10] Fix GeosLibrary to work with GEOS 3.7.x/3.8.x --- packages/basemap/utils/GeosLibrary.py | 78 ++++++++++++++++----------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index 7bf6e867c..b969413b1 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -137,7 +137,26 @@ def extract(self, overwrite=True): for path in sorted(glob.glob(os.path.join(zipfold, "tools", "*.sh"))): os.chmod(path, 0o755) - # Patch CMakeLists so that libgeos_c.so does not depend on libgeos.so. + # Apply specific patches for GEOS < 3.6.0. + if self.version_tuple < (3, 6, 0): + # The SVN revision file is not created on the fly before 3.6.0. + svn_hfile = os.path.join(zipfold, "geos_svn_revision.h") + if not os.path.exists(svn_hfile): + with io.open(svn_hfile, "wb") as fd: + text = "#define GEOS_SVN_REVISION 0" + fd.write(text.encode()) + # Reduce warnings when compiling with `nmake` on Windows. + cmakefile = os.path.join(zipfold, "CMakeLists.txt") + if os.path.exists(cmakefile): + with io.open(cmakefile, "r", encoding="utf-8") as fd: + lines = fd.readlines() + with io.open(cmakefile, "wb") as fd: + oldtext = 'string(REGEX REPLACE "/W[0-9]" "/W4"' + newtext = oldtext.replace("W4", "W1") + for line in lines: + fd.write(line.replace(oldtext, newtext).encode()) + + # Patch CMakeLists to link shared geos_c with static geos. if self.version_tuple < (3, 8, 0): cmakefile = os.path.join(zipfold, "capi", "CMakeLists.txt") oldtext = "target_link_libraries(geos_c geos)" @@ -158,24 +177,20 @@ def extract(self, overwrite=True): found_sharedline = True fd.write(line.replace(oldtext, newtext).encode()) - # Apply specific patches for GEOS < 3.6.0. - if self.version_tuple < (3, 6, 0): - # The SVN revision file is not created on the fly before 3.6.0. - svn_hfile = os.path.join(zipfold, "geos_svn_revision.h") - if not os.path.exists(svn_hfile): - with io.open(svn_hfile, "wb") as fd: - text = "#define GEOS_SVN_REVISION 0" - fd.write(text.encode()) - # Reduce warnings when compiling with `nmake` on Windows. - cmakefile = os.path.join(zipfold, "CMakeLists.txt") - if os.path.exists(cmakefile): - with io.open(cmakefile, "r", encoding="utf-8") as fd: - lines = fd.readlines() - with io.open(cmakefile, "wb") as fd: - oldtext = 'string(REGEX REPLACE "/W[0-9]" "/W4"' - newtext = oldtext.replace("W4", "W1") - for line in lines: - fd.write(line.replace(oldtext, newtext).encode()) + # Patch doc CMakeLists in GEOS 3.8.x series. + if (3, 8, 0) <= self.version_tuple < (3, 9, 0): + cmakefile = os.path.join(zipfold, "doc", "CMakeLists.txt") + oldtext1 = "target_include_directories(test_geos_unit\n" + newtext1 = "if(BUILD_TESTING)\n {0}".format(oldtext1) + oldtext2 = "$)\n" + newtext2 = "{0}endif()\n".format(oldtext2) + with io.open(cmakefile, "r", encoding="utf-8") as fd: + lines = fd.readlines() + with io.open(cmakefile, "wb") as fd: + for line in lines: + line = line.replace(oldtext1, newtext1) + line = line.replace(oldtext2, newtext2) + fd.write(line.encode()) def build(self, installdir=None, njobs=1): """Build and install GEOS from source.""" @@ -205,18 +220,21 @@ def build(self, installdir=None, njobs=1): build_env = os.environ.copy() # Define custom configure and build options. - if os.name != "nt": - build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs) - elif version < (3, 6, 0): - win64 = (8 * struct.calcsize("P") == 64) - config_opts = ["-G", "NMake Makefiles"] + config_opts - build_opts.extend([ - "--", - "WIN64={0}".format("YES" if win64 else "NO"), - "BUILD_BATCH={0}".format("YES" if njobs > 1 else "NO"), - ]) + if os.name == "nt": + if version < (3, 6, 0): + win64 = (8 * struct.calcsize("P") == 64) + config_opts = ["-G", "NMake Makefiles"] + config_opts + build_opts.extend([ + "--", + "WIN64={0}".format("YES" if win64 else "NO"), + "BUILD_BATCH={0}".format("YES" if njobs > 1 else "NO"), + ]) + else: + build_opts = ["-j", "{0:d}".format(njobs)] + build_opts else: - build_opts = ["-j", "{0:d}".format(njobs)] + build_opts + build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs) + if version >= (3, 7, 0): + config_opts += ["-DCMAKE_CXX_FLAGS=-fPIC"] # Call cmake configure after ensuring that the build directory exists. try: From 1124d08ea18bd9686a048cccbef498a7bf704985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Sun, 23 Oct 2022 23:40:51 +0200 Subject: [PATCH 06/10] Backport extra patches in GeosLibrary from develop branch --- packages/basemap/utils/GeosLibrary.py | 32 ++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index b969413b1..7cdaab265 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -20,6 +20,7 @@ import io import os +import sys import ssl import glob import shutil @@ -126,8 +127,7 @@ def extract(self, overwrite=True): if os.path.exists(zipfold): if not overwrite: raise OSError("folder '{0}' already exists".format(zipfold)) - else: - shutil.rmtree(zipfold) + shutil.rmtree(zipfold) # Decompress zip file. with contextlib.closing(ZipFile(zippath, "r")) as fd: @@ -156,6 +156,27 @@ def extract(self, overwrite=True): for line in lines: fd.write(line.replace(oldtext, newtext).encode()) + # Apply specific patches for 3.6.0 <= GEOS < 3.7.0 on Windows. + if (3, 6, 0) <= self.version_tuple < (3, 7, 0) and os.name == "nt": + autogen_file = os.path.join(zipfold, "autogen.bat") + subprocess.call([autogen_file], cwd=zipfold) + cppfile = os.path.join(zipfold, "src", "geomgraph", "DirectedEdgeStar.cpp") + with io.open(cppfile, "r", encoding="utf-8") as fd: + lines = fd.readlines() + with io.open(cppfile, "wb") as fd: + oldtext = "DirectedEdgeStar::print() const" + newtext = oldtext.replace(" const", "") + for line in lines: + fd.write(line.replace(oldtext, newtext).encode()) + hfile = os.path.join(zipfold, "include", "geos", "geomgraph", "DirectedEdgeStar.h") + with io.open(hfile, "r", encoding="utf-8") as fd: + lines = fd.readlines() + with io.open(hfile, "wb") as fd: + oldtext = "virtual std::string print() const;" + newtext = oldtext.replace(" const", "") + for line in lines: + fd.write(line.replace(oldtext, newtext).encode()) + # Patch CMakeLists to link shared geos_c with static geos. if self.version_tuple < (3, 8, 0): cmakefile = os.path.join(zipfold, "capi", "CMakeLists.txt") @@ -221,16 +242,17 @@ def build(self, installdir=None, njobs=1): # Define custom configure and build options. if os.name == "nt": - if version < (3, 6, 0): + if version >= (3, 6, 0) and sys.version_info[:2] >= (3, 3): + build_opts = ["-j", "{0:d}".format(njobs)] + build_opts + else: win64 = (8 * struct.calcsize("P") == 64) config_opts = ["-G", "NMake Makefiles"] + config_opts build_opts.extend([ "--", "WIN64={0}".format("YES" if win64 else "NO"), "BUILD_BATCH={0}".format("YES" if njobs > 1 else "NO"), + "MSVC_VER=1400", ]) - else: - build_opts = ["-j", "{0:d}".format(njobs)] + build_opts else: build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs) if version >= (3, 7, 0): From b3be0218bc75680058b3e68627300996d6f483d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Mon, 24 Oct 2022 00:01:13 +0200 Subject: [PATCH 07/10] Make GEOS CMake-based compilation on Windows quiet --- packages/basemap/utils/GeosLibrary.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index 7cdaab265..57c26d033 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -242,6 +242,7 @@ def build(self, installdir=None, njobs=1): # Define custom configure and build options. if os.name == "nt": + config_opts += ["-DCMAKE_CXX_FLAGS='/wd4251 /wd4458 /wd4530'"] if version >= (3, 6, 0) and sys.version_info[:2] >= (3, 3): build_opts = ["-j", "{0:d}".format(njobs)] + build_opts else: @@ -256,7 +257,7 @@ def build(self, installdir=None, njobs=1): else: build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs) if version >= (3, 7, 0): - config_opts += ["-DCMAKE_CXX_FLAGS=-fPIC"] + config_opts += ["-DCMAKE_CXX_FLAGS='-fPIC'"] # Call cmake configure after ensuring that the build directory exists. try: From 21d16446d2a26855bc850a5fe92159c4c23dff1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Mon, 24 Oct 2022 00:15:05 +0200 Subject: [PATCH 08/10] Fix wrong value for MSVC_VER in GeosLibrary --- packages/basemap/utils/GeosLibrary.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/basemap/utils/GeosLibrary.py b/packages/basemap/utils/GeosLibrary.py index 57c26d033..84eff4e51 100644 --- a/packages/basemap/utils/GeosLibrary.py +++ b/packages/basemap/utils/GeosLibrary.py @@ -252,8 +252,9 @@ def build(self, installdir=None, njobs=1): "--", "WIN64={0}".format("YES" if win64 else "NO"), "BUILD_BATCH={0}".format("YES" if njobs > 1 else "NO"), - "MSVC_VER=1400", ]) + if sys.version_info[:2] < (3, 3): + build_opts += ["MSVC_VER=1500"] else: build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs) if version >= (3, 7, 0): From 3bb1da45966465ebc356ea9b30a133110eb5f68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Mon, 24 Oct 2022 17:29:55 +0200 Subject: [PATCH 09/10] Update CHANGELOG with bugfix for GEOS issue --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f4415f45..688197773 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ https://semver.org/spec/v2.0.0.html ### Fixed - Fix broken array slicing inside `addcyclic` (PR [#559], solves issue [#555], thanks to @fragkoul). +- Fix wrong Antarctica coastline boundary with GEOS >= 3.9.0 (PR [#560], + solves issue [#522]). ## [1.3.4] - 2022-08-10 @@ -930,6 +932,8 @@ https://semver.org/spec/v2.0.0.html - Fix glitches in drawing of parallels and meridians. +[#560]: +https://github.com/matplotlib/basemap/pull/560 [#559]: https://github.com/matplotlib/basemap/pull/559 [#555]: @@ -966,6 +970,8 @@ https://github.com/matplotlib/basemap/issues/527 https://github.com/matplotlib/basemap/issues/526 [#525]: https://github.com/matplotlib/basemap/issues/525 +[#522]: +https://github.com/matplotlib/basemap/issues/522 [#521]: https://github.com/matplotlib/basemap/issues/521 [#518]: From 0576e3c51174efbae24756d7b10cd61a8ff4ca1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Molina=20Garc=C3=ADa?= Date: Mon, 24 Oct 2022 17:31:54 +0200 Subject: [PATCH 10/10] Add increase in GeosLibrary GEOS version support to CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 688197773..947fe9c5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ https://semver.org/spec/v2.0.0.html ### Fixed - Fix broken array slicing inside `addcyclic` (PR [#559], solves issue [#555], thanks to @fragkoul). +- Fix `GeosLibrary` wrapper to also work with GEOS >= 3.7.0 on Windows + and GNU/Linux. - Fix wrong Antarctica coastline boundary with GEOS >= 3.9.0 (PR [#560], solves issue [#522]).