@@ -140,19 +140,7 @@ def parse_cflags(raw_flags):
140140 }
141141
142142IMPORT_NAME = "av"
143-
144- loudnorm_extension = Extension (
145- f"{ IMPORT_NAME } .filter.loudnorm" ,
146- sources = [
147- f"{ IMPORT_NAME } /filter/loudnorm.py" ,
148- f"{ IMPORT_NAME } /filter/loudnorm_impl.c" ,
149- ],
150- include_dirs = [f"{ IMPORT_NAME } /filter" ] + extension_extra ["include_dirs" ],
151- libraries = extension_extra ["libraries" ],
152- library_dirs = extension_extra ["library_dirs" ],
153- define_macros = define_macros ,
154- py_limited_api = py_limited_api ,
155- )
143+ SHARED_MODULE_NAME = f"{ IMPORT_NAME } ._cyutil"
156144
157145compiler_directives = {
158146 "c_string_type" : "str" ,
@@ -163,17 +151,37 @@ def parse_cflags(raw_flags):
163151 "freethreading_compatible" : True ,
164152}
165153
166- # Add the cythonized loudnorm extension to ext_modules
167- ext_modules = cythonize (
168- loudnorm_extension ,
169- compiler_directives = compiler_directives ,
170- build_dir = "src" ,
171- include_path = ["include" ],
172- )
154+
155+ def make_extension (name , sources , extra_include_dirs = ()):
156+ return Extension (
157+ name ,
158+ sources = sources ,
159+ include_dirs = [* extra_include_dirs , * extension_extra ["include_dirs" ]],
160+ libraries = extension_extra ["libraries" ],
161+ library_dirs = extension_extra ["library_dirs" ],
162+ define_macros = define_macros ,
163+ py_limited_api = py_limited_api ,
164+ )
165+
166+
167+ LOUDNORM_SOURCE = os .path .join (IMPORT_NAME , "filter" , "loudnorm.py" )
168+
169+ extensions = [
170+ Extension (
171+ SHARED_MODULE_NAME ,
172+ sources = [],
173+ define_macros = define_macros ,
174+ py_limited_api = py_limited_api ,
175+ ),
176+ make_extension (
177+ f"{ IMPORT_NAME } .filter.loudnorm" ,
178+ [LOUDNORM_SOURCE , os .path .join (IMPORT_NAME , "filter" , "loudnorm_impl.c" )],
179+ [os .path .join (IMPORT_NAME , "filter" )],
180+ ),
181+ ]
173182
174183for dirname , dirnames , filenames in os .walk (IMPORT_NAME ):
175184 for filename in filenames :
176- # We are looking for Cython sources.
177185 if filename .startswith ("." ):
178186 continue
179187 if filename in {"__init__.py" , "__main__.py" , "about.py" , "datasets.py" }:
@@ -182,27 +190,26 @@ def parse_cflags(raw_flags):
182190 continue
183191
184192 pyx_path = os .path .join (dirname , filename )
193+ if pyx_path == LOUDNORM_SOURCE :
194+ continue
195+
185196 base = os .path .splitext (pyx_path )[0 ]
186197
187198 # Need to be a little careful because Windows will accept / or \
188199 # (where os.sep will be \ on Windows).
189200 mod_name = base .replace ("/" , "." ).replace (os .sep , "." )
190201
191- # Cythonize the module.
192- ext_modules += cythonize (
193- Extension (
194- mod_name ,
195- include_dirs = extension_extra ["include_dirs" ],
196- libraries = extension_extra ["libraries" ],
197- library_dirs = extension_extra ["library_dirs" ],
198- sources = [pyx_path ],
199- define_macros = define_macros ,
200- py_limited_api = py_limited_api ,
201- ),
202- compiler_directives = compiler_directives ,
203- build_dir = "src" ,
204- include_path = ["include" ],
205- )
202+ extensions .append (make_extension (mod_name , [pyx_path ]))
203+
204+ # Cythonize in one pass so that the shared module can be generated alongside the
205+ # modules that import from it.
206+ ext_modules = cythonize (
207+ extensions ,
208+ compiler_directives = compiler_directives ,
209+ build_dir = "src" ,
210+ include_path = ["include" ],
211+ shared_utility_qualified_name = SHARED_MODULE_NAME ,
212+ )
206213
207214
208215package_folders = pathlib .Path (IMPORT_NAME ).glob ("**/" )
0 commit comments