1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
|
# -*- Makefile -*-
# This is a copy from mrbuild 1.10. I'm copying it here because declaring this
# dependency in setup.py is more or less impossible
# 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.
# osx
COND_DARWIN := $(filter Darwin,$(shell uname -s))
SO := $(if $(COND_DARWIN),dylib,so)
# Hacks to get spaces and newlines in places where Make would normally parse
# them out
SPACE :=
SPACE := $(SPACE) $(SPACE)
define NEWLINE
endef
dirs_to_dotdot = $(subst $(SPACE),/,$(patsubst %,..,$(subst /, ,$1)))
get_parentdir_relative_to_childdir = /$(call dirs_to_dotdot,$(patsubst $1%,%,$2))
RPATH_SUFFIX = $(call get_parentdir_relative_to_childdir,$(abspath .),$(dir $(abspath $1)))
ifeq ($(COND_DARWIN),)
RPATH = '$$ORIGIN'$(RPATH_SUFFIX)
else
RPATH = @executable_path$(RPATH_SUFFIX)
endif
RPATH_OPTION = -Wl,-rpath,$(call RPATH,$@)
# 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
ifneq ($(DEB_HOST_MULTIARCH),)
# We have a debian multiarch. We're almost certainly cross-building with
# Debian. Try to get the variables directly, using any-architecture python
define _PYVARS_GET_CONFIG :=
import ast
import sys
prefixes = ("_sysconfigdata_", "_sysconfigdata_m_linux")
sysconfig_paths = [d + "/" + prefix + "_$(DEB_HOST_MULTIARCH).py" for d in sys.path for prefix in prefixes]
for filename in sysconfig_paths:
try:
f = open(filename)
except:
continue
s = f.read()
s = re.sub("^#.*", "", s, flags=re.M)
s = re.sub("^[0-9a-zA-Z_]+ *= *", "", s, flags=re.M)
conf = ast.literal_eval(s)
break
else:
raise Exception("Could not find sysconfig file in any sys.path directories. Tried: {}".format(sysconfig_paths))
endef
else
_PYVARS_GET_CONFIG := conf = sysconfig.get_config_vars()
endif
# Python script to query those variables
define _PYVARS_SCRIPT
from __future__ import print_function
import sysconfig
import re
# get "conf" dict
$(_PYVARS_GET_CONFIG)
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))))
# Add the numpy include path. See https://bugs.debian.org/1067398
_PY_INCLUDEPY += $(shell pkg-config --cflags-only-I numpy 2>/dev/null)
# 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))
_PY_MRBUILD_LDFLAGS = $(RPATH_OPTION) $(_PY_LDFLAGS) -L$(abspath .)
_PY_MRBUILD_LINKER = $(_PY_BLDSHARED) $(_PY_BLDLIBRARY)
endef
# List of variables a user Makefile could touch. These are all PY_...
_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, I use 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 $$(value query_python_extension_building_flags))$$(_$1))
endef
define _PY_DEFINE_API_VAR_EXTSUFFIX
$1 = $$(or $$(_$1),$$(eval $$(value 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. For testing. 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
LDFLAGS += -Wl,-rpath,$1
endef
#### VERSION_FROM_PROJECT variable: parse git tags or, if those aren't
#### available, the debian/changelog. To use this, add to your Makefile:
####
#### VERSION := $(VERSION_FROM_PROJECT)
####
#### Otherwise, we'll use $(ABI_VERSION).$(TAIL_VERSION). VERSION_FROM_PROJECT
#### is useful in mature-ish projects that are actually being distributed to
#### others
# "git describe --tags" says things like "v2.0-17-gcef328f". This converts it to "v2.0"
_VERSION_STRIP_POST_TAG_ANNOTATIONS := s/-\d+-g[0-9a-f]+$$//
# I might have a tag such as "debian/2.0-1". This converts it to "2.0-1"
_VERSION_STRIP_LEADING_PATH := s/^.*\///
# I might have a tag such as "v2.0". This converts it to "2.0"
_VERSION_STRIP_LEADING_V := s/^v//g
# Custom version from git (or from debian/changelog if no git repo available)
# If user says "VERSION_USE_LATEST_TAG=1 make" I'll use the latest tag for the
# version, without annotations about the subsequent commits
PAREN0 := (
PAREN1 := )
_VERSION = $(shell \
if test -e debian/changelog; then \
< debian/changelog perl -ane 'if($$F[1] =~ /^\$(PAREN0)(.+)\$(PAREN1)$$/) { print $$1 } else { print "VERSION_UNKNOWN"}; exit 0'; \
elif test -d .git && git describe --tags >/dev/null 2>/dev/null; then \
git describe --tags | \
perl -pe '$(if $(VERSION_USE_LATEST_TAG),$(_VERSION_STRIP_POST_TAG_ANNOTATIONS)); \
$(_VERSION_STRIP_LEADING_PATH); \
$(_VERSION_STRIP_LEADING_V);'; \
else \
echo "VERSION_UNKNOWN"; \
fi \
)
# Memoize. $(VERSION) will evaluate the result the first time, and use the
# cached result during subsequent calls
VERSION_FROM_PROJECT = $(if $(_VERSION_EXPANDED),,$(eval _VERSION_EXPANDED:=$$(_VERSION)))$(_VERSION_EXPANDED)
|