Codebase list python-numpysane / upstream/0.28 Makefile.common.header
upstream/0.28

Tree @upstream/0.28 (Download .tar.gz)

Makefile.common.header @upstream/0.28raw · history · blame

# -*- Makefile -*-

# This is a part of the mrbuild project: https://github.com/dkogan/mrbuild
#
# Released under an MIT-style license. Modify and distribute as you like:
#
# Copyright 2016-2019 California Institute of Technology
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# This stuff defines variables (PY_EXT_SUFFIX) that could be used by the user
# Makefile at parsing time. So this must be included BEFORE the rest of the user
# Makefile

PYTHON_VERSION_FOR_EXTENSIONS ?= 3 # 2 or 3
# Flags for python extension modules. See
# http://notes.secretsauce.net/notes/2017/11/14_python-extension-modules-without-setuptools-or-distutils.html
#
# I build the python extension module without any setuptools or anything.
# Instead I ask python about the build flags it likes, and build the DSO
# normally using those flags.
#
# There's some sillyness in Make I need to work around. First, I produce a
# python script to query the various build flags, but replacing all whitespace
# with __whitespace__. The string I get when running this script will then have
# a number of whitespace-separated tokens, each setting ONE variable
#
# I set up a number of variables:
#
#   These come from Python queries. I ask Python about XXX and store the result
#   into PY_XXX
#
#     PY_CC
#     PY_CFLAGS
#     PY_CCSHARED
#     PY_INCLUDEPY
#     PY_BLDSHARED
#     PY_LDFLAGS
#     PY_EXT_SUFFIX
#     PY_MULTIARCH
#
#  These process the above into a single set of CFLAGS:
#
#    PY_MRBUILD_CFLAGS
#
#  These process the above into a single set of LDFLAGS:
#
#    PY_MRBUILD_LDFLAGS
#
#  These process the above into a DSO-building linker command
#
#    PY_MRBUILD_LINKER
#
# When the user Makefile evaluates ANY of these variables I query python, and
# memoize the results. So the python is invoked at MOST one time. Any Makefiles
# that don't touch the PY_... variables will not end up invoking the python
# thing at all
#
# Variables to ask Python about
_PYVARS_LIST := CC CFLAGS CCSHARED INCLUDEPY BLDSHARED BLDLIBRARY LDFLAGS EXT_SUFFIX MULTIARCH

# Python script to query those variables
define _PYVARS_SCRIPT
from __future__ import print_function
import sysconfig
import re
conf = sysconfig.get_config_vars()
for v in ($(foreach v,$(_PYVARS_LIST),"$v",)):
    if v in conf:
        print(re.sub("[\t ]+", "__whitespace__", "_PY_{}:={}".format(v, conf[v])))
endef

# I eval this to actually invoke the Python and to ingest its results. I only
# eval this ONLY when necessary.
define query_python_extension_building_flags
_PYVARS := $$(shell python$(PYTHON_VERSION_FOR_EXTENSIONS) -c '$$(_PYVARS_SCRIPT)')
# I then $(eval) these tokens one at a time, restoring the whitespace
$$(foreach setvarcmd,$$(_PYVARS),$$(eval $$(subst __whitespace__, ,$$(setvarcmd))))
# pull out flags from CC, throw out the compiler itself, since I know better
_FLAGS_FROM_PYCC    := $$(wordlist 2,$$(words $$(_PY_CC)),$$(_PY_CC))
_PY_MRBUILD_CFLAGS  := $$(filter-out -O%,$$(_FLAGS_FROM_PYCC) $$(_PY_CFLAGS) $$(_PY_CCSHARED) -I$$(_PY_INCLUDEPY))
# I add an RPATH to the python extension DSO so that it runs in-tree. Will pull
# it out at install time
_PY_MRBUILD_LDFLAGS := $$(_PY_LDFLAGS) -L$$(abspath .) -Wl,-rpath=$$(abspath .)
_PY_MRBUILD_LINKER  := $$(_PY_BLDSHARED) $$(_PY_BLDLIBRARY)
endef

# List of variables a user Makefile could touch
_PYVARS_API := $(foreach v,$(_PYVARS_LIST),PY_$v) PY_MRBUILD_CFLAGS PY_MRBUILD_LDFLAGS PY_MRBUILD_LINKER

# The first time the user touches these variables, ask Python. Each subsequent
# time, use the previously-returned value. So we query Python at most once. If a
# project isn't using the Python extension modules, we will not query Python at
# all
#
# I handle all the Python API variables identically, except for PY_EXT_SUFFIX.
# If Python gives me a suffix, Iuse it (this is available in python3; it has
# ABI, architecture details). Otherwise, I try the multiarch suffix, or if even
# THAT isn't available, just do .so. I need to handle it specially to make the
# self-referential logic work with the memoization logic
define _PY_DEFINE_API_VAR
$1 = $$(or $$(_$1),$$(eval $$(query_python_extension_building_flags))$$(_$1))
endef
define _PY_DEFINE_API_VAR_EXTSUFFIX
$1 = $$(or $$(_$1),$$(eval $$(query_python_extension_building_flags))$$(or $$(_$1),$$(if $$(PY_MULTIARCH),.$$(PY_MULTIARCH)).so))
endef

$(foreach v,$(filter-out PY_EXT_SUFFIX,$(_PYVARS_API)),$(eval $(call _PY_DEFINE_API_VAR,$v)))
$(eval $(call _PY_DEFINE_API_VAR_EXTSUFFIX,PY_EXT_SUFFIX))



# Useful to pull in a local build of some library. Sets the compiler and linker
# (runtime and build-time) flags. Invoke like this:
#   $(eval $(call add_local_library_path,/home/user/library))
define add_local_library_path
CFLAGS   += -I$1
CXXFLAGS += -I$1
LDFLAGS += -L$1 -Wl,-rpath=$1
endef