diff --git a/Makefile b/Makefile index 52ff72c..154f5bf 100644 --- a/Makefile +++ b/Makefile @@ -267,6 +267,7 @@ TESTS_BIN += convert-dtsv0 TESTS_BIN += fdtput TESTS_BIN += fdtget TESTS_BIN += fdtdump +TESTS_PYLIBFDT += maybe_pylibfdt include tests/Makefile.tests diff --git a/README b/README index 5add557..17dc845 100644 --- a/README +++ b/README @@ -50,12 +50,18 @@ If you add new features, please check code coverage: # Open 'htmlcov/index.html' in your browser -To install the library use: +To install the library via the normal setup.py method, use: - make install_pylibfdt SETUP_PREFIX=/path/to/install_dir + ./pylibfdt/setup.py [--prefix=/path/to/install_dir] -If SETUP_PREFIX is not provided, the default prefix is used, typically '/usr' -or '/usr/local'. See Python's distutils documentation for details. +If --prefix is not provided, the default prefix is used, typically '/usr' +or '/usr/local'. See Python's distutils documentation for details. You can +also install via the Makefile if you like, but the above is more common. + +To install both libfdt and pylibfdt you can use: + + make install [SETUP_PREFIX=/path/to/install_dir] \ + [PREFIX=/path/to/install_dir] To disable building the python library, even if swig and Python are available, use: diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 06f9296..0e8ac5f 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -5,13 +5,16 @@ PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) WRAP = $(PYLIBFDT_objdir)/libfdt_wrap.c PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so -run_setup = SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" \ - VERSION="$(dtc_version)" \ - python $(PYLIBFDT_objdir)/setup.py --quiet $(2) +define run_setup + SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" + VERSION="$(dtc_version)" + $(PYLIBFDT_objdir)/setup.py --quiet $(2) +endef $(PYMODULE): $(PYLIBFDT_srcs) $(WRAP) @$(VECHO) PYMOD $@ $(call run_setup, $^, build_ext --inplace) + mv _libfdt.so $@ $(WRAP): $(PYLIBFDT_srcdir)/libfdt.i @$(VECHO) SWIG $@ diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py old mode 100644 new mode 100755 index 1597b44..90e80f3 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -2,26 +2,112 @@ """ setup.py file for SWIG libfdt +Copyright (C) 2017 Google, Inc. +Written by Simon Glass Files to be built into the extension are provided in SOURCES C flags to use are provided in CPPFLAGS Object file directory is provided in OBJDIR +Version is provided in VERSION + +If these variables are not given they are parsed from the Makefiles. This +allows this script to be run stand-alone, e.g.: + + ./pylibfdt/setup.py install [--prefix=...] """ from distutils.core import setup, Extension import os +import re import sys +# Decodes a Makefile assignment line into key and value (and plus for +=) +RE_KEY_VALUE = re.compile('(?P\w+) *(?P[+])?= *(?P.*)$') + + +def ParseMakefile(fname): + """Parse a Makefile to obtain its variables. + + This collects variable assigments of the form: + + VAR = value + VAR += more + + It does not pick out := assignments, as these are not needed here. It does + handle line continuation. + + Returns a dict: + key: Variable name (e.g. 'VAR') + value: Variable value (e.g. 'value more') + """ + makevars = {} + with open(fname) as fd: + prev_text = '' # Continuation text from previous line(s) + for line in fd.read().splitlines(): + if line and line[-1] == '\\': # Deal with line continuation + prev_text += line[:-1] + continue + elif prev_text: + line = prev_text + line + prev_text = '' # Continuation is now used up + m = RE_KEY_VALUE.match(line) + if m: + value = m.group('value') or '' + key = m.group('key') + + # Appending to a variable inserts a space beforehand + if 'plus' in m.groupdict() and key in makevars: + makevars[key] += ' ' + value + else: + makevars[key] = value + return makevars + +def GetEnvFromMakefiles(): + """Scan the Makefiles to obtain the settings we need. + + This assumes that this script is being run from the top-level directory, + not the pylibfdt directory. + + Returns: + Tuple with: + List of swig options + Version string + List of files to build + List of extra C preprocessor flags needed + Object directory to use (always '') + """ + basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) + swig_opts = ['-I%s' % basedir] + makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) + version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'], + makevars['SUBLEVEL']) + makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt')) + files = makevars['LIBFDT_SRCS'].split() + files = [os.path.join(basedir, 'libfdt', fname) for fname in files] + files.append('pylibfdt/libfdt.i') + cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir] + objdir = '' + return swig_opts, version, files, cflags, objdir + + progname = sys.argv[0] -files = os.environ['SOURCES'].split() -cflags = os.environ['CPPFLAGS'].split() -objdir = os.environ['OBJDIR'] -version = os.environ['VERSION'] +files = os.environ.get('SOURCES', '').split() +cflags = os.environ.get('CPPFLAGS', '').split() +objdir = os.environ.get('OBJDIR') +version = os.environ.get('VERSION') +swig_opts = [] + +# If we were called directly rather than through our Makefile (which is often +# the case with Python module installation), read the settings from the +# Makefile. +if not all((version, files, cflags, objdir)): + swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles() libfdt_module = Extension( '_libfdt', sources = files, - extra_compile_args = cflags + extra_compile_args = cflags, + swig_opts = swig_opts, ) setup( @@ -31,5 +117,5 @@ setup( description='Python binding for libfdt', ext_modules=[libfdt_module], package_dir={'': objdir}, - py_modules=['libfdt'], + py_modules=['pylibfdt/libfdt'], ) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 3d7a4f8..2258135 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -72,13 +72,13 @@ tests_clean: rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) -check: tests ${TESTS_BIN} +check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -checkm: tests ${TESTS_BIN} +checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ -checkv: tests ${TESTS_BIN} +checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -v ifneq ($(DEPTARGETS),)