blob: c07f65e6bcaf1c6ba3497966ccf331d26fdce568 [file] [log] [blame]
Simon Glass7ccca832019-10-31 07:42:59 -06001#!/usr/bin/env python3
Simon Glass85feff32022-07-30 20:57:11 -06002# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
Simon Glassa13d9022017-05-27 07:38:11 -06003
4"""
5setup.py file for SWIG libfdt
6Copyright (C) 2017 Google, Inc.
7Written by Simon Glass <sjg@chromium.org>
8
Simon Glass85feff32022-07-30 20:57:11 -06009This script is modified from the upstream version, to fit in with the U-Boot
10build system.
Simon Glassa13d9022017-05-27 07:38:11 -060011
12Files to be built into the extension are provided in SOURCES
13C flags to use are provided in CPPFLAGS
14Object file directory is provided in OBJDIR
15Version is provided in VERSION
16
17If these variables are not given they are parsed from the Makefiles. This
18allows this script to be run stand-alone, e.g.:
19
20 ./pylibfdt/setup.py install [--prefix=...]
21"""
22
Philippe Schenkerc61791e2023-01-04 15:43:33 +010023from setuptools import setup, Extension, sic
Simon Glass85feff32022-07-30 20:57:11 -060024from setuptools.command.build_py import build_py as _build_py
Simon Glassa13d9022017-05-27 07:38:11 -060025import os
26import re
27import sys
28
Simon Glass85feff32022-07-30 20:57:11 -060029srcdir = os.path.dirname(__file__)
30
31with open(os.path.join(srcdir, "../README"), "r") as fh:
32 long_description = fh.read()
33
Simon Glassa13d9022017-05-27 07:38:11 -060034# Decodes a Makefile assignment line into key and value (and plus for +=)
35RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
36
Simon Glass85feff32022-07-30 20:57:11 -060037def get_top_builddir():
38 if '--top-builddir' in sys.argv:
39 index = sys.argv.index('--top-builddir')
40 sys.argv.pop(index)
41 return sys.argv.pop(index)
42 else:
43 return os.path.join(srcdir, '..')
44
45top_builddir = get_top_builddir()
Simon Glassa13d9022017-05-27 07:38:11 -060046
47def ParseMakefile(fname):
48 """Parse a Makefile to obtain its variables.
49
50 This collects variable assigments of the form:
51
52 VAR = value
53 VAR += more
54
55 It does not pick out := assignments, as these are not needed here. It does
56 handle line continuation.
57
58 Returns a dict:
59 key: Variable name (e.g. 'VAR')
60 value: Variable value (e.g. 'value more')
61 """
62 makevars = {}
63 with open(fname) as fd:
64 prev_text = '' # Continuation text from previous line(s)
65 for line in fd.read().splitlines():
66 if line and line[-1] == '\\': # Deal with line continuation
67 prev_text += line[:-1]
68 continue
69 elif prev_text:
70 line = prev_text + line
71 prev_text = '' # Continuation is now used up
72 m = RE_KEY_VALUE.match(line)
73 if m:
74 value = m.group('value') or ''
75 key = m.group('key')
76
77 # Appending to a variable inserts a space beforehand
78 if 'plus' in m.groupdict() and key in makevars:
79 makevars[key] += ' ' + value
80 else:
81 makevars[key] = value
82 return makevars
83
84def GetEnvFromMakefiles():
85 """Scan the Makefiles to obtain the settings we need.
86
87 This assumes that this script is being run from the top-level directory,
88 not the pylibfdt directory.
89
90 Returns:
91 Tuple with:
92 List of swig options
93 Version string
94 List of files to build
95 List of extra C preprocessor flags needed
96 Object directory to use (always '')
97 """
98 basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
99 swig_opts = ['-I%s' % basedir]
100 makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
101 version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
102 makevars['SUBLEVEL'])
103 makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
104 files = makevars['LIBFDT_SRCS'].split()
105 files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
Simon Glass85feff32022-07-30 20:57:11 -0600106 files.append('libfdt.i')
Simon Glassa13d9022017-05-27 07:38:11 -0600107 cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
108 objdir = ''
109 return swig_opts, version, files, cflags, objdir
110
111
112progname = sys.argv[0]
113files = os.environ.get('SOURCES', '').split()
114cflags = os.environ.get('CPPFLAGS', '').split()
115objdir = os.environ.get('OBJDIR')
116version = os.environ.get('VERSION')
Simon Glass3d0b9992017-05-27 07:38:16 -0600117swig_opts = os.environ.get('SWIG_OPTS', '').split()
Simon Glassa13d9022017-05-27 07:38:11 -0600118
119# If we were called directly rather than through our Makefile (which is often
120# the case with Python module installation), read the settings from the
121# Makefile.
Simon Glass3d0b9992017-05-27 07:38:16 -0600122if not all((swig_opts, version, files, cflags, objdir)):
Simon Glassa13d9022017-05-27 07:38:11 -0600123 swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
124
125libfdt_module = Extension(
126 '_libfdt',
Simon Glass85feff32022-07-30 20:57:11 -0600127 sources=files,
128 include_dirs=[os.path.join(srcdir, 'libfdt')],
129 library_dirs=[os.path.join(top_builddir, 'libfdt')],
130 swig_opts=swig_opts,
Simon Glassa13d9022017-05-27 07:38:11 -0600131)
132
Simon Glass85feff32022-07-30 20:57:11 -0600133class build_py(_build_py):
134 def run(self):
135 self.run_command("build_ext")
136 return super().run()
137
Simon Glassa13d9022017-05-27 07:38:11 -0600138setup(
139 name='libfdt',
Philippe Schenkerc61791e2023-01-04 15:43:33 +0100140 version=sic(version),
Simon Glass85feff32022-07-30 20:57:11 -0600141 cmdclass = {'build_py' : build_py},
142 author='Simon Glass',
143 author_email='sjg@chromium.org',
Simon Glassa13d9022017-05-27 07:38:11 -0600144 description='Python binding for libfdt',
145 ext_modules=[libfdt_module],
146 package_dir={'': objdir},
Simon Glass85feff32022-07-30 20:57:11 -0600147 py_modules=['libfdt'],
148
149 long_description=long_description,
150 long_description_content_type="text/plain",
151 url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git",
152 license="BSD",
153 license_files=["GPL", "BSD-2-Clause"],
154
155 classifiers=[
156 "Programming Language :: Python :: 3",
157 "License :: OSI Approved :: BSD License",
158 "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
159 "Operating System :: OS Independent",
160 ],
161
Simon Glassa13d9022017-05-27 07:38:11 -0600162)