matplotlib/basemap

Issue with basemap installation on cygwin

karljchan opened this issue · 16 comments

Hello all, I am trying to install basemap package on cygwin but have encountered an error. Before the installation, i have installed GEOS and PROJ from source and have set the GEOS_DIR/PROJ_DIR environment variable.

I have tried installing basemap from a previous thread here #539 by downloading basemap via python -m pip install basemap but failed to build wheel for basemap.

  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2709:25: note: expected ‘const GEOSGeometry *’ {aka ‘const struct GEOSGeom_t *’} but argument is of type ‘GEOSGeometry **’ {aka ‘struct GEOSGeom_t **’}
   2709 |     const GEOSGeometry* g);
        |     ~~~~~~~~~~~~~~~~~~~~^
  src/_geoslib.c:5116:16: warning: assignment to ‘GEOSCoordSequence **’ {aka ‘struct GEOSCoordSeq_t **’} from incompatible pointer type ‘const GEOSCoordSequence *’ {aka ‘const struct GEOSCoordSeq_t *’} [-Wincompatible-pointer-types]
   5116 |     __pyx_v_cs = GEOSGeom_getCoordSeq(__pyx_v_lr);
        |                ^
  src/_geoslib.c:5136:39: warning: passing argument 1 of ‘GEOSGeom_getCoordSeq’ from incompatible pointer type [-Wincompatible-pointer-types]
   5136 |     __pyx_v_cs = GEOSGeom_getCoordSeq(__pyx_v_geom);
        |                                       ^~~~~~~~~~~~
        |                                       |
        |                                       GEOSGeometry ** {aka struct GEOSGeom_t **}
  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2709:25: note: expected ‘const GEOSGeometry *’ {aka ‘const struct GEOSGeom_t *’} but argument is of type ‘GEOSGeometry **’ {aka ‘struct GEOSGeom_t **’}
   2709 |     const GEOSGeometry* g);
        |     ~~~~~~~~~~~~~~~~~~~~^
  src/_geoslib.c:5136:16: warning: assignment to ‘GEOSCoordSequence **’ {aka ‘struct GEOSCoordSeq_t **’} from incompatible pointer type ‘const GEOSCoordSequence *’ {aka ‘const struct GEOSCoordSeq_t *’} [-Wincompatible-pointer-types]
   5136 |     __pyx_v_cs = GEOSGeom_getCoordSeq(__pyx_v_geom);
        |                ^
  src/_geoslib.c:5147:31: warning: passing argument 1 of ‘GEOSCoordSeq_getSize’ from incompatible pointer type [-Wincompatible-pointer-types]
   5147 |   (void)(GEOSCoordSeq_getSize(__pyx_v_cs, (&__pyx_v_M)));
        |                               ^~~~~~~~~~
        |                               |
        |                               GEOSCoordSequence ** {aka struct GEOSCoordSeq_t **}
  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2319:30: note: expected ‘const GEOSCoordSequence *’ {aka ‘const struct GEOSCoordSeq_t *’} but argument is of type ‘GEOSCoordSequence **’ {aka ‘struct GEOSCoordSeq_t **’}
   2319 |     const GEOSCoordSequence* s,
        |     ~~~~~~~~~~~~~~~~~~~~~~~~~^
  src/_geoslib.c:5255:30: warning: passing argument 1 of ‘GEOSCoordSeq_getX’ from incompatible pointer type [-Wincompatible-pointer-types]
   5255 |     (void)(GEOSCoordSeq_getX(__pyx_v_cs, __pyx_v_i, (&__pyx_v_dx)));
        |                              ^~~~~~~~~~
        |                              |
        |                              GEOSCoordSequence ** {aka struct GEOSCoordSeq_t **}
  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2251:64: note: expected ‘const GEOSCoordSequence *’ {aka ‘const struct GEOSCoordSeq_t *’} but argument is of type ‘GEOSCoordSequence **’ {aka ‘struct GEOSCoordSeq_t **’}
   2251 | extern int GEOS_DLL GEOSCoordSeq_getX(const GEOSCoordSequence* s,
        |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~^
  src/_geoslib.c:5264:30: warning: passing argument 1 of ‘GEOSCoordSeq_getY’ from incompatible pointer type [-Wincompatible-pointer-types]
   5264 |     (void)(GEOSCoordSeq_getY(__pyx_v_cs, __pyx_v_i, (&__pyx_v_dy)));
        |                              ^~~~~~~~~~
        |                              |
        |                              GEOSCoordSequence ** {aka struct GEOSCoordSeq_t **}
  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2262:64: note: expected ‘const GEOSCoordSequence *’ {aka ‘const struct GEOSCoordSeq_t *’} but argument is of type ‘GEOSCoordSequence **’ {aka ‘struct GEOSCoordSeq_t **’}
   2262 | extern int GEOS_DLL GEOSCoordSeq_getY(const GEOSCoordSequence* s,
        |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~^
  src/_geoslib.c: In function ‘__pyx_pymod_exec__geoslib’:
  src/_geoslib.c:6273:3: warning: returning ‘void *’ from a function with return type ‘int’ makes integer from pointer without a cast [-Wint-conversion]
   6273 |   import_array();
        |   ^~~~~~~~~~~~
  src/_geoslib.c:6306:12: warning: passing argument 1 of ‘initGEOS’ from incompatible pointer type [-Wincompatible-pointer-types]
   6306 |   initGEOS(__pyx_f_8_geoslib_notice_h, __pyx_f_8_geoslib_error_h);
        |            ^~~~~~~~~~~~~~~~~~~~~~~~~~
        |            |
        |            void (*)(char *, char *)
  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2074:24: note: expected ‘GEOSMessageHandler’ {aka ‘void (*)(const char *, ...)’} but argument is of type ‘void (*)(char *, char *)’
   2074 |     GEOSMessageHandler notice_function,
        |     ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
  src/_geoslib.c:6306:40: warning: passing argument 2 of ‘initGEOS’ from incompatible pointer type [-Wincompatible-pointer-types]
   6306 |   initGEOS(__pyx_f_8_geoslib_notice_h, __pyx_f_8_geoslib_error_h);
        |                                        ^~~~~~~~~~~~~~~~~~~~~~~~~
        |                                        |
        |                                        void (*)(char *, char *)
  In file included from src/_geoslib.c:751:
  /usr/local/include/geos_c.h:2075:24: note: expected ‘GEOSMessageHandler’ {aka ‘void (*)(const char *, ...)’} but argument is of type ‘void (*)(char *, char *)’
   2075 |     GEOSMessageHandler error_function);
        |     ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
  gcc -shared -Wl,--enable-auto-image-base build/temp.cygwin-3.4.7-x86_64-cpython-39/src/_geoslib.o -L/usr/local/lib -L/usr/local/lib64 -L/usr/lib/python3.9/config -L/usr/lib -Wl,--enable-new-dtags,-R/usr/local/lib -Wl,--enable-new-dtags,-R/usr/local/lib64 -lgeos_c -lpython3.9 -o build/lib.cygwin-3.4.7-x86_64-cpython-39/_geoslib.cpython-39-x86_64-cygwin.dll
  /usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: unrecognized option '--enable-new-dtags'
  /usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: use the --help option for usage information
  collect2: error: ld returned 1 exit status
  error: command '/usr/bin/gcc' failed with exit code 1
  [end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for basemap
Failed to build basemap
ERROR: Could not build wheels for basemap, which is required to install pyproject.toml-based projects

I would appreciate any help or guidance you can provide, thank you.

Looking for the issue with the --enable-new-dtags, I found the following issue related to setuptools (pypa/distutils#171).

I remember that a while ago @DWesl was providing a pull request in the basemap repository to ensure that basemap can be built from the source distribution on PyPI, with Cygwin as particular target (#532). So at some point the basemap source distribution was working for Cygwin.

We might need here a similar patch to the one given by @DWesl for pyproj (pyproj4/pyproj#1120).

DWesl commented

Most likely this section needs to be run when sys.platform == "cygwin", not just when os.name == "nt"

if os.name == "nt":
# On Windows:
# - DLLs get installed under `bin`.
# - We need to inject later the DLL in the wheel using `data_files`.
# - We do not use `runtime_library_dirs` as workaround for a
# `distutils` bug (http://bugs.python.org/issue2437).
library_dirs.append(os.path.join(geos_install_prefix, "bin"))
runtime_library_dirs = []
dlls = glob.glob(os.path.join(geos_install_prefix, "*", "geos_c.dll"))
if dlls:
data_files.append(("../..", sorted(dlls)))

@karljchan I installed Cygwin on my Windows machine but I am unable to reproduce your issue (after installing Cython<3.0.0 manually because the latest version is currently incompatible with _geoslib.pyx):

vic@onyx ~
$ python -m pip install --no-deps --no-build-isolation basemap
Collecting basemap
  Downloading basemap-1.3.7.zip (156 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 156.4/156.4 kB 3.5 MB/s eta 0:00:00
  Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: basemap
  Building wheel for basemap (pyproject.toml) ... done
  Created wheel for basemap: filename=basemap-1.3.7-cp39-cp39-cygwin_3_4_7_x86_64.whl size=237214 sha256=501cf30c38e5db3ac24f7e28ce0123d44e096b1a1bb966b080afeb7472901d7b
  Stored in directory: /home/vic/.cache/pip/wheels/da/26/26/75a84a37edb0066d0540073637bcb40a38e3e8ad02028a930f
Successfully built basemap
Installing collected packages: basemap
Successfully installed basemap-1.3.7

May I ask you to provide a bit more of information on your current Cygwin installation? For example, Python version and GCC version. I am using Python 3.9.16 and GCC 11.4.0.

Still I will apply the suggestion by @DWesl, since your issue appeared already in other projects and the modification is probably harmless.

DWesl commented

I suspect that's due to setting GEOS_DIR or PROJ_DIR; you can set those to /usr if using the Cygwin packages, or installing them yourself defaults to /usr/local.

The other part might be that they've installed GEOS to /usr/local: I'm not sure what precisely that would change, but /usr/ often gets special treatment.

DWesl commented

There's a PR with the proposed changes in #582

@DWesl Thanks! We were just editing at the same time! Give me just a moment to see how I can merge your PR into the hotfix-1.3.8 branch.

DWesl commented

That's what I get for leaving the PR for two weeks, I suppose

DWesl commented

@karljchan, does the hotfix-1.3.8 branch install for you?

@karljchan You can try to see if the hotfix-1.3.8 branch works for you with the following command:

python -m pip install --no-build-isolation git+https://github.com/matplotlib/basemap.git@hotfix-1.3.8#subdirectory=packages/basemap

@DWesl I downgraded the numpy minimum dependency from 1.22 to 1.21 because I saw that numpy is not so up to date in the Cygwin packages. Does the hotfix-1.3.8 branch work for you? In my computer it works, but on the other hand v1.3.7 was also working.

DWesl commented

I pasted that command into a terminal; we'll see what happens in about ten minutes.

I also update NumPy regularly, so I have 1.24.3.

@DWesl Did the hotfix-1.3.8 branch install successfully in the end?

DWesl commented

Cool! I will wait for @karljchan's feedback until end of the week before closing the issue, let's see if I can prepare the 1.3.8 patch release by then.

@karljchan Did you have time to check if the hotfix-1.3.8 branch is working for your use case?

Hi, apologies @molinav for getting back to you so late regarding this issue as I have been away from office.

I have tried applying the hotfix that you’ve provided and the installation is successful! I appreciate your assistance very much!

@karljchan No worries! Great to hear that it is working now. I will prepare the v1.3.8 patch release in the upcoming days and this fix will be included.

Thanks also to @DWesl for providing the PR with the bugfix!