Skip to content

Commit

Permalink
CMake: Python: fix setup.py to work again in standalone mode
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Jan 10, 2022
1 parent c252ebf commit 6a27688
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 20 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/cmake_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ jobs:
export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/install-gdal/lib
$GITHUB_WORKSPACE/install-gdal/bin/gdalinfo --version
PYTHONPATH=$GITHUB_WORKSPACE/install-gdal/lib/python3/dist-packages python3 -c "from osgeo import gdal;print(gdal.VersionInfo(None))"
- name: Standalone Python bindings build
run: |
(cd $GITHUB_WORKSPACE/superbuild/build/gdal/swig/python && python setup.py sdist)
mv $GITHUB_WORKSPACE/superbuild/build/gdal/swig/python/dist/GDAL-*.tar.gz gdal-python.tar.gz
rm -rf $GITHUB_WORKSPACE/superbuild/build/gdal/swig/python
# Set PATH so that gdal-config is found
PATH=$GITHUB_WORKSPACE/install-gdal/bin:$PATH pip install --user gdal-python.tar.gz
build-windows-msys2-mingw:
runs-on: windows-latest
Expand Down
9 changes: 4 additions & 5 deletions swig/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,7 @@ if (Python_Interpreter_FOUND)
else ()
set(GNM_ENABLED "False")
endif ()
if (Python_NumPy_FOUND)
set(HAVE_NUMPY "True")
else ()
set(HAVE_NUMPY "False")
endif ()

file(TO_NATIVE_PATH "${GDAL_PYTHON_CSOURCE_DIR}" GDAL_PYTHON_EXT_SOURCE_DIR)
if (_isMultiConfig)
set(GDAL_LIB_DIR "os.path.dirname('$<TARGET_FILE:${GDAL_LIB_TARGET_NAME}>')")
Expand All @@ -179,6 +175,9 @@ if (Python_Interpreter_FOUND)
set(GDAL_LIB_DIR "'${_gdal_lib_directory}'")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py @ONLY)
endif ()

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.rst ${CMAKE_CURRENT_BINARY_DIR}/README.rst @ONLY)

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/get_suffix.py
"from setuptools.command.build_ext import EXTENSION_SUFFIXES; print(EXTENSION_SUFFIXES[0])\n")
execute_process(
Expand Down
114 changes: 99 additions & 15 deletions swig/python/setup.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,16 @@ from setuptools import Extension
# Switches
# ---------------------------------------------------------------------------

include_dirs = ['@PROJECT_BINARY_DIR@/port', '@PROJECT_SOURCE_DIR@/port', '@PROJECT_BINARY_DIR@/gcore', '@PROJECT_SOURCE_DIR@/gcore', '@PROJECT_SOURCE_DIR@/alg', '@PROJECT_SOURCE_DIR@/ogr/', '@PROJECT_SOURCE_DIR@/ogr/ogrsf_frmts', '@PROJECT_SOURCE_DIR@/gnm', '@PROJECT_SOURCE_DIR@/apps']
library_dirs = [@GDAL_LIB_DIR@]
libraries = ['gdal']
is_standalone_build = not os.path.exists('@PROJECT_BINARY_DIR@/swig/python')

if is_standalone_build:
include_dirs = []
library_dirs = []
libraries = []
else:
include_dirs = ['@PROJECT_BINARY_DIR@/port', '@PROJECT_SOURCE_DIR@/port', '@PROJECT_BINARY_DIR@/gcore', '@PROJECT_SOURCE_DIR@/gcore', '@PROJECT_SOURCE_DIR@/alg', '@PROJECT_SOURCE_DIR@/ogr/', '@PROJECT_SOURCE_DIR@/ogr/ogrsf_frmts', '@PROJECT_SOURCE_DIR@/gnm', '@PROJECT_SOURCE_DIR@/apps']
library_dirs = [@GDAL_LIB_DIR@]
libraries = ['gdal']


# ---------------------------------------------------------------------------
Expand All @@ -32,14 +39,33 @@ libraries = ['gdal']

# Function to find numpy's include directory
def get_numpy_include():
if @HAVE_NUMPY@:
# Fix numpy installation using setuptools
__builtins__.__NUMPY_SETUP__ = False
# Fix numpy installation using setuptools
__builtins__.__NUMPY_SETUP__ = False

import numpy
return numpy.get_include()


class gdal_config_error(Exception):
pass


def fetch_config(option, gdal_config='gdal-config'):

import numpy
return numpy.get_include()
command = gdal_config + " --%s" % option

return '.'
import subprocess
command, args = command.split()[0], command.split()[1]
try:
p = subprocess.Popen([command, args], stdout=subprocess.PIPE)
except OSError:
e = sys.exc_info()[1]
raise gdal_config_error(e)
r = p.stdout.readline().decode('ascii').strip()
p.stdout.close()
p.wait()

return r


def supports_cxx11(compiler, compiler_flag=None):
Expand Down Expand Up @@ -91,23 +117,57 @@ def has_flag(compiler, flagname):
return False
return True

# ---------------------------------------------------------------------------
# Imports
# ---------------------------------------------------------------------------

numpy_include_dir = '.'
try:
numpy_include_dir = get_numpy_include()
HAVE_NUMPY = numpy_include_dir != '.'
if not HAVE_NUMPY:
print("WARNING: numpy found, but numpy headers were not found! Array support will not be enabled")
except ImportError:
HAVE_NUMPY = False
print('WARNING: numpy not available! Array support will not be enabled')


class gdal_ext(build_ext):

GDAL_CONFIG = 'gdal-config'
user_options = build_ext.user_options[:]
user_options.extend([
('gdal-config=', None,
"The name of the gdal-config binary and/or a full path to it"),
])

def run(self):
build_ext.run(self)

def initialize_options(self):
global numpy_include_dir
build_ext.initialize_options(self)

self.numpy_include_dir = get_numpy_include()
self.gdaldir = None
self.numpy_include_dir = numpy_include_dir
self.gdal_config = self.GDAL_CONFIG
self.extra_cflags = []
self.parallel = True

def get_compiler(self):
return self.compiler or ('msvc' if os.name == 'nt' else 'unix')


def get_gdal_config(self, option):
try:
return fetch_config(option, gdal_config=self.gdal_config)
except gdal_config_error:
msg = 'Could not find gdal-config. Make sure you have installed the GDAL native library and development headers.'
import sys
import traceback
traceback_string = ''.join(traceback.format_exception(*sys.exc_info()))
raise gdal_config_error(traceback_string + '\n' + msg)


def build_extensions(self):

# Add a -std=c++11 or similar flag if needed
Expand Down Expand Up @@ -139,6 +199,8 @@ class gdal_ext(build_ext):
def finalize_options(self):
global include_dirs, library_dirs

include_dirs_found = self.include_dirs is not None or len(include_dirs) != 0

if self.include_dirs is None:
self.include_dirs = include_dirs
# Needed on recent MacOSX
Expand All @@ -156,7 +218,28 @@ class gdal_ext(build_ext):

build_ext.finalize_options(self)

self.include_dirs.append(self.numpy_include_dir)
if numpy_include_dir != '.':
self.include_dirs.append(self.numpy_include_dir)

if self.get_compiler() == 'msvc':
return

if not include_dirs_found:
# Get paths from gdal-config
gdaldir = self.get_gdal_config('prefix')
self.library_dirs.append(os.path.join(gdaldir, 'lib'))
self.include_dirs.append(os.path.join(gdaldir, 'include'))

cflags = self.get_gdal_config('cflags')
if cflags:
self.extra_cflags = cflags.split()

def build_extension(self, ext):
# We override this instead of setting extra_compile_args directly on
# the Extension() instantiations below because we want to use the same
# logic to resolve the location of gdal-config throughout.
ext.extra_compile_args.extend(self.extra_cflags)
return build_ext.build_extension(self, ext)


extra_link_args = []
Expand Down Expand Up @@ -198,11 +281,12 @@ ext_modules = [gdal_module,
osr_module,
ogr_module]

if @GNM_ENABLED@:
GNM_ENABLED = @GNM_ENABLED@
if GNM_ENABLED:
ext_modules.append(gnm_module)

extras_require=None
if @HAVE_NUMPY@:
if HAVE_NUMPY:
ext_modules.append(array_module)
extras_require={'numpy': ['numpy > 1.0.0']}

Expand All @@ -211,7 +295,7 @@ packages = find_packages(utils_package_root)
packages = ['osgeo'] + packages
package_dir = {'osgeo': 'osgeo', '': utils_package_root}

readme = open('@CMAKE_CURRENT_SOURCE_DIR@/README.rst', encoding="utf-8").read()
readme = open('README.rst', encoding="utf-8").read()

name = 'GDAL'
version = '@GDAL_VERSION_NO_DEV_SUFFIX@'
Expand Down

0 comments on commit 6a27688

Please sign in to comment.