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``
62import os
7- import re
8- import platform
93import shutil
4+ import platform
105import 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
8127def 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+
9794if __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