Skip to content

Commit 4a2f55c

Browse files
author
Garrett Barter
authored
Merge pull request #15 from WISDEM/develop
More pythonic build with setuptools
2 parents f42de64 + 97b8125 commit 4a2f55c

1 file changed

Lines changed: 71 additions & 149 deletions

File tree

setup.py

Lines changed: 71 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
#!/usr/bin/env python
2-
# encoding: utf-8
3-
4-
# setup.py
5-
# only if building in place: ``python setup.py build_ext --inplace``
62
import os
7-
import re
8-
import platform
93
import shutil
4+
import platform
105
import setuptools
11-
import subprocess
6+
from setuptools.command.build_ext import build_ext
127

138
#######
149
# This forces wheels to be platform specific
@@ -25,152 +20,79 @@ class BinaryDistribution(Distribution):
2520
def has_ext_modules(foo):
2621
return True
2722
#######
28-
29-
30-
def run_meson_build(staging_dir):
31-
prefix = os.path.join(os.getcwd(), staging_dir)
32-
purelibdir = "."
33-
34-
# check if meson extra args are specified
35-
meson_args = ""
36-
if "MESON_ARGS" in os.environ:
37-
meson_args = os.environ["MESON_ARGS"]
38-
# A weird add-on on mac github action runners needs to be removed
39-
if meson_args.find("buildtype") >= 0: meson_args = ""
40-
41-
if platform.system() == "Windows":
42-
if not "FC" in os.environ:
43-
os.environ["FC"] = "gfortran"
44-
if not "CC" in os.environ:
45-
os.environ["CC"] = "gcc"
46-
47-
# configure
48-
meson_path = shutil.which("meson")
49-
if meson_path is None:
50-
raise OSError("The meson command cannot be found on the system")
51-
52-
meson_call = [meson_path, "setup", staging_dir, "--wipe",
53-
f"--prefix={prefix}", f"-Dpython.purelibdir={purelibdir}",
54-
f"-Dpython.platlibdir={purelibdir}", meson_args]
55-
meson_call = [m for m in meson_call if m != ""]
56-
print(meson_call)
57-
p1 = subprocess.run(meson_call, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
58-
os.makedirs(staging_dir, exist_ok=True)
59-
setup_log = os.path.join(staging_dir, "setup.log")
60-
with open(setup_log, "wb") as f:
61-
f.write(p1.stdout)
62-
if p1.returncode != 0:
63-
with open(setup_log, "r") as f:
64-
print(f.read())
65-
raise OSError(meson_call, f"The meson setup command failed! Check the log at {setup_log} for more information.")
66-
67-
# build
68-
meson_call = [meson_path, "compile", "-vC", staging_dir]
69-
meson_call = [m for m in meson_call if m != ""]
70-
print(meson_call)
71-
p2 = subprocess.run(meson_call, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
72-
compile_log = os.path.join(staging_dir, "compile.log")
73-
with open(compile_log, "wb") as f:
74-
f.write(p2.stdout)
75-
if p2.returncode != 0:
76-
with open(compile_log, "r") as f:
77-
print(f.read())
78-
raise OSError(meson_call, f"The meson compile command failed! Check the log at {compile_log} for more information.")
79-
23+
this_dir = os.path.abspath(os.path.dirname(__file__))
24+
staging_dir = os.path.join(this_dir, "meson_build")
25+
build_dir = os.path.join(this_dir, "build")
8026

8127
def copy_shared_libraries():
8228
build_path = os.path.join(staging_dir, "pyhams")
8329
for root, _dirs, files in os.walk(build_path):
84-
for file in files:
85-
# move pyhams to just under staging_dir
86-
if file.endswith((".so", ".lib", ".pyd", ".pdb", ".dylib", ".dll", ".mod")):
87-
if ".so.p" in root or ".pyd.p" in root: # excludes intermediate object files
88-
continue
89-
file_path = os.path.join(root, file)
90-
new_path = str(file_path)
91-
match = re.search(staging_dir, new_path)
92-
new_path = new_path[match.span()[1] + 1 :]
30+
for f in files:
31+
if f.endswith((".so", ".lib", ".pyd", ".pdb", ".dylib", ".dll")):
32+
file_path = os.path.join(root, f)
33+
new_path = str(file_path).replace(staging_dir + os.sep, "")
9334
print(f"Copying build file {file_path} -> {new_path}")
94-
shutil.move(file_path, new_path)
95-
35+
shutil.copy(file_path, new_path)
9636

37+
#######
38+
class MesonExtension(setuptools.Extension):
39+
40+
def __init__(self, name, sourcedir="", **kwa):
41+
setuptools.Extension.__init__(self, name, sources=[], **kwa)
42+
self.sourcedir = os.path.abspath(sourcedir)
43+
44+
class MesonBuildExt(build_ext):
45+
46+
def copy_extensions_to_source(self):
47+
newext = []
48+
for ext in self.extensions:
49+
if isinstance(ext, MesonExtension): continue
50+
newext.append( ext )
51+
self.extensions = newext
52+
super().copy_extensions_to_source()
53+
54+
def build_extension(self, ext):
55+
if not isinstance(ext, MesonExtension):
56+
super().build_extension(ext)
57+
58+
else:
59+
60+
# Ensure that Meson is present and working
61+
try:
62+
self.spawn(["meson", "--version"])
63+
except OSError:
64+
raise RuntimeError("Cannot find meson executable")
65+
66+
# check if meson extra args are specified
67+
meson_args = ""
68+
if "MESON_ARGS" in os.environ:
69+
meson_args = os.environ["MESON_ARGS"]
70+
71+
if platform.system() == "Windows":
72+
if "FC" not in os.environ:
73+
os.environ["FC"] = "gfortran"
74+
if "CC" not in os.environ:
75+
os.environ["CC"] = "gcc"
76+
77+
purelibdir = "."
78+
configure_call = ["meson", "setup", staging_dir, "--wipe",
79+
f"-Dpython.purelibdir={purelibdir}", f"--prefix={staging_dir}",
80+
f"-Dpython.platlibdir={purelibdir}"] + meson_args.split()
81+
configure_call = [m for m in configure_call if m.strip() != ""]
82+
print(configure_call)
83+
84+
build_call = ["meson", "compile", "-vC", staging_dir]
85+
print(build_call)
86+
87+
self.build_temp = build_dir
88+
89+
self.spawn(configure_call)
90+
self.spawn(build_call)
91+
copy_shared_libraries()
92+
93+
9794
if __name__ == "__main__":
98-
# This is where the meson build system will install to, it is then
99-
# used as the sources for setuptools
100-
staging_dir = "meson_build"
101-
102-
# this keeps the meson build system from running more than once
103-
if "dist" not in str(os.path.abspath(__file__)):
104-
cwd = os.getcwd()
105-
run_meson_build(staging_dir)
106-
os.chdir(cwd)
107-
copy_shared_libraries()
108-
109-
init_file = os.path.join("pyhams", "__init__.py")
110-
#__version__ = re.findall(
111-
# r"""__version__ = ["']+([0-9\.]*)["']+""",
112-
# open(init_file).read(),
113-
#)[0]
114-
115-
setuptools.setup(cmdclass={'bdist_wheel': bdist_wheel}, distclass=BinaryDistribution)
116-
117-
#os.environ['NPY_DISTUTILS_APPEND_FLAGS'] = '1'
118-
119-
# Source order is important for dependencies
120-
#f90src = ['WavDynMods.f90',
121-
# 'PatclVelct.f90',
122-
# 'BodyIntgr.f90',
123-
# 'BodyIntgr_irr.f90',
124-
# 'AssbMatx.f90',
125-
# 'AssbMatx_irr.f90',
126-
# 'SingularIntgr.f90',
127-
# 'InfGreen_Appr.f90',
128-
# 'FinGrnExtSubs.f90',
129-
# 'FinGreen3D.f90',
130-
# 'CalGreenFunc.f90',
131-
# 'HydroStatic.f90',
132-
# 'ImplementSubs.f90',
133-
# 'InputFiles.f90',
134-
# 'NormalProcess.f90',
135-
# 'ReadPanelMesh.f90',
136-
# 'PotentWavForce.f90',
137-
# 'PressureElevation.f90',
138-
# 'PrintOutput.f90',
139-
# 'SolveMotion.f90',
140-
# 'WavDynSubs.f90',
141-
# 'HAMS_Prog.f90',
142-
# 'HAMS_Prog.pyf',
143-
# ]
144-
#root_dir = os.path.join('pyhams','src')
145-
146-
#intel_flag = sysconfig.get_config_var('FC') == 'ifort'
147-
148-
#if not intel_flag:
149-
# for a in sys.argv:
150-
# intel_flag = intel_flag or a.find('intel')>=0
151-
152-
#if not intel_flag:
153-
# try:
154-
# if os.environ['FC'] == 'ifort':
155-
# intel_flag = True
156-
# except KeyError:
157-
# pass
158-
159-
#myargs = ['-O3','-m64','-fPIC','-g']
160-
#mycargs = ['-std=c11']
161-
#if intel_flag:
162-
# myfargs = ['-mkl']
163-
# mylib = ['mkl_rt']
164-
# mylink = []
165-
#else:
166-
# myfargs = ['-fno-align-commons','-fdec-math']
167-
# mylib = ['lapack']
168-
# mylink = []
169-
170-
171-
#pyhamsExt = Extension('pyhams.libhams', sources=[os.path.join(root_dir,m) for m in f90src],
172-
# extra_compile_args=mycargs+myargs,
173-
# extra_f90_compile_args=myfargs+myargs,
174-
# libraries=mylib,
175-
# extra_link_args=['-fopenmp']+mylink)
176-
#extlist = [] if platform.system() == 'Windows' else [pyhamsExt]
95+
setuptools.setup(cmdclass={"bdist_wheel": bdist_wheel, "build_ext": MesonBuildExt},
96+
distclass=BinaryDistribution,
97+
ext_modules=[ MesonExtension("pyhams", this_dir) ],
98+
)

0 commit comments

Comments
 (0)