blob: 8baae08770cad8972afc0e36c81729dc83809484 [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
Tom Rinic88ddb22023-01-07 18:02:26 -050023from setuptools import setup, Extension
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
Tom Rinic88ddb22023-01-07 18:02:26 -050029try:
30 from setuptools import sic
31except ImportError:
32 pass
33
Simon Glass85feff32022-07-30 20:57:11 -060034srcdir = os.path.dirname(__file__)
35
36with open(os.path.join(srcdir, "../README"), "r") as fh:
37 long_description = fh.read()
38
Simon Glassa13d9022017-05-27 07:38:11 -060039# Decodes a Makefile assignment line into key and value (and plus for +=)
40RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
41
Simon Glass85feff32022-07-30 20:57:11 -060042def get_top_builddir():
43 if '--top-builddir' in sys.argv:
44 index = sys.argv.index('--top-builddir')
45 sys.argv.pop(index)
46 return sys.argv.pop(index)
47 else:
48 return os.path.join(srcdir, '..')
49
50top_builddir = get_top_builddir()
Simon Glassa13d9022017-05-27 07:38:11 -060051
52def ParseMakefile(fname):
53 """Parse a Makefile to obtain its variables.
54
55 This collects variable assigments of the form:
56
57 VAR = value
58 VAR += more
59
60 It does not pick out := assignments, as these are not needed here. It does
61 handle line continuation.
62
63 Returns a dict:
64 key: Variable name (e.g. 'VAR')
65 value: Variable value (e.g. 'value more')
66 """
67 makevars = {}
68 with open(fname) as fd:
69 prev_text = '' # Continuation text from previous line(s)
70 for line in fd.read().splitlines():
71 if line and line[-1] == '\\': # Deal with line continuation
72 prev_text += line[:-1]
73 continue
74 elif prev_text:
75 line = prev_text + line
76 prev_text = '' # Continuation is now used up
77 m = RE_KEY_VALUE.match(line)
78 if m:
79 value = m.group('value') or ''
80 key = m.group('key')
81
82 # Appending to a variable inserts a space beforehand
83 if 'plus' in m.groupdict() and key in makevars:
84 makevars[key] += ' ' + value
85 else:
86 makevars[key] = value
87 return makevars
88
89def GetEnvFromMakefiles():
90 """Scan the Makefiles to obtain the settings we need.
91
92 This assumes that this script is being run from the top-level directory,
93 not the pylibfdt directory.
94
95 Returns:
96 Tuple with:
97 List of swig options
98 Version string
99 List of files to build
100 List of extra C preprocessor flags needed
101 Object directory to use (always '')
102 """
103 basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
104 swig_opts = ['-I%s' % basedir]
105 makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
106 version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
107 makevars['SUBLEVEL'])
108 makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
109 files = makevars['LIBFDT_SRCS'].split()
110 files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
Simon Glass85feff32022-07-30 20:57:11 -0600111 files.append('libfdt.i')
Simon Glassa13d9022017-05-27 07:38:11 -0600112 cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
113 objdir = ''
114 return swig_opts, version, files, cflags, objdir
115
116
117progname = sys.argv[0]
118files = os.environ.get('SOURCES', '').split()
119cflags = os.environ.get('CPPFLAGS', '').split()
120objdir = os.environ.get('OBJDIR')
Tom Rinic88ddb22023-01-07 18:02:26 -0500121try:
122 version = sic(os.environ.get('VERSION'))
123except:
124 version = os.environ.get('VERSION')
Simon Glass3d0b9992017-05-27 07:38:16 -0600125swig_opts = os.environ.get('SWIG_OPTS', '').split()
Simon Glassa13d9022017-05-27 07:38:11 -0600126
127# If we were called directly rather than through our Makefile (which is often
128# the case with Python module installation), read the settings from the
129# Makefile.
Simon Glass3d0b9992017-05-27 07:38:16 -0600130if not all((swig_opts, version, files, cflags, objdir)):
Simon Glassa13d9022017-05-27 07:38:11 -0600131 swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
132
133libfdt_module = Extension(
134 '_libfdt',
Simon Glass85feff32022-07-30 20:57:11 -0600135 sources=files,
136 include_dirs=[os.path.join(srcdir, 'libfdt')],
137 library_dirs=[os.path.join(top_builddir, 'libfdt')],
138 swig_opts=swig_opts,
Simon Glassa13d9022017-05-27 07:38:11 -0600139)
140
Simon Glass85feff32022-07-30 20:57:11 -0600141class build_py(_build_py):
142 def run(self):
143 self.run_command("build_ext")
144 return super().run()
145
Simon Glassa13d9022017-05-27 07:38:11 -0600146setup(
147 name='libfdt',
Tom Rinic88ddb22023-01-07 18:02:26 -0500148 version=version,
Simon Glass85feff32022-07-30 20:57:11 -0600149 cmdclass = {'build_py' : build_py},
150 author='Simon Glass',
151 author_email='sjg@chromium.org',
Simon Glassa13d9022017-05-27 07:38:11 -0600152 description='Python binding for libfdt',
153 ext_modules=[libfdt_module],
154 package_dir={'': objdir},
Simon Glass85feff32022-07-30 20:57:11 -0600155 py_modules=['libfdt'],
156
157 long_description=long_description,
158 long_description_content_type="text/plain",
159 url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git",
160 license="BSD",
161 license_files=["GPL", "BSD-2-Clause"],
162
163 classifiers=[
164 "Programming Language :: Python :: 3",
165 "License :: OSI Approved :: BSD License",
166 "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
167 "Operating System :: OS Independent",
168 ],
169
Simon Glassa13d9022017-05-27 07:38:11 -0600170)