11from __future__ import annotations
22
3+ import collections
34import dataclasses
45import pathlib
56import pprint
@@ -219,7 +220,9 @@ def _process_extension_module(
219220 self ._prepare_dependency_paths (depends , extension )
220221 )
221222
222- includes = [self .project_root / inc for inc in extension .includes ]
223+ includes = [
224+ self .project_root / pathlib .PurePosixPath (inc ) for inc in extension .includes
225+ ]
223226 search_path .extend (includes )
224227
225228 # Search the package path last
@@ -240,11 +243,42 @@ def _process_extension_module(
240243 # Generate init.py for loading dependencies
241244 #
242245
243- libinit_target = self ._generate_libinit_file (
244- extension , module_name , package_path , libinit_modules
246+ libinit_py = None
247+ if libinit_modules :
248+ libinit_py = extension .libinit or f"_init_{ module_name } .py"
249+ libinit_tgt = BuildTarget (
250+ command = "gen-libinit-py" ,
251+ args = (OutputFile (libinit_py ), * libinit_modules ),
252+ install_path = package_path ,
253+ )
254+
255+ self .pyi_args += [libinit_py , libinit_tgt ]
256+ yield libinit_tgt
257+
258+ #
259+ # Publish a .pc file for this module
260+ #
261+
262+ pc_args = [
263+ package_name ,
264+ varname ,
265+ self .pyproject_input ,
266+ OutputFile (f"{ varname } .pc" ),
267+ ]
268+ if libinit_py :
269+ pc_args += ["--libinit-py" , libinit_py ]
270+
271+ yield BuildTarget (
272+ command = "gen-pkgconf" ,
273+ args = tuple (pc_args ),
274+ install_path = package_path ,
245275 )
246- if libinit_target :
247- yield libinit_target
276+
277+ yield Entrypoint (group = "pkg_config" , name = varname , package = parent_package )
278+
279+ #
280+ # Process the headers
281+ #
248282
249283 # Find and load the yaml
250284 if extension .yaml_path is None :
@@ -326,6 +360,31 @@ def _process_extension_module(
326360 )
327361 )
328362
363+ def _locate_type_caster_json (
364+ self ,
365+ depname : str ,
366+ caster_json_file : T .List [T .Union [BuildTargetOutput , pathlib .Path ]],
367+ ):
368+ checked = set ()
369+ to_check = collections .deque ([depname ])
370+ while to_check :
371+ name = to_check .popleft ()
372+ checked .add (name )
373+ print ("checking" , name )
374+
375+ entry = self .pkgcache .get (name )
376+
377+ if name in self .local_caster_targets :
378+ caster_json_file .append (self .local_caster_targets [name ])
379+ else :
380+ tc = entry .type_casters_path
381+ if tc and tc not in caster_json_file :
382+ caster_json_file .append (tc )
383+
384+ for req in entry .requires :
385+ if req not in checked :
386+ to_check .append (req )
387+
329388 def _prepare_dependency_paths (
330389 self , depends : T .List [str ], extension : ExtensionModuleConfig
331390 ):
@@ -347,34 +406,13 @@ def _prepare_dependency_paths(
347406 if dep in extension .wraps :
348407 search_path .extend (entry .include_path )
349408
350- if dep in self .local_caster_targets :
351- caster_json_file .append (self .local_caster_targets [dep ])
352- elif entry .type_casters_path is not None :
353- caster_json_file .append (entry .type_casters_path )
409+ self ._locate_type_caster_json (dep , caster_json_file )
354410
355411 if entry .libinit_py :
356412 libinit_modules .append (entry .libinit_py )
357413
358414 return search_path , include_directories_uniq , caster_json_file , libinit_modules
359415
360- def _generate_libinit_file (
361- self ,
362- extension : ExtensionModuleConfig ,
363- module_name : str ,
364- package_path : pathlib .Path ,
365- libinit_modules : T .List [str ],
366- ):
367- if libinit_modules :
368- libinit_py = extension .libinit or f"_init_{ module_name } .py"
369- tgt = BuildTarget (
370- command = "gen-libinit-py" ,
371- args = (OutputFile (libinit_py ), * libinit_modules ),
372- install_path = package_path ,
373- )
374-
375- self .pyi_args += [libinit_py , tgt ]
376- return tgt
377-
378416 def _process_headers (
379417 self ,
380418 extension : ExtensionModuleConfig ,
@@ -395,7 +433,8 @@ def _process_headers(
395433 ayml = AutowrapConfigYaml .from_file (self .project_root / yml_input .path )
396434 except FileNotFoundError :
397435 if not self .missing_yaml_ok :
398- raise
436+ msg = f"{ self .project_root / yml_input .path } : use `python3 -m semiwrap.cmd_creategen` to generate"
437+ raise FileNotFoundError (msg ) from None
399438 ayml = AutowrapConfigYaml ()
400439
401440 # find the source header
@@ -491,12 +530,13 @@ def _process_headers(
491530 return datfiles , module_sources , subpackages
492531
493532 def _locate_header (self , hdr : str , search_path : T .List [pathlib .Path ]):
533+ phdr = pathlib .PurePosixPath (hdr )
494534 for p in search_path :
495- h_path = p / hdr
535+ h_path = p / phdr
496536 if h_path .exists ():
497537 return InputFile (h_path .relative_to (self .project_root )), p
498538 raise FileNotFoundError (
499- f"cannot locate { hdr } in { ', ' .join (map (str , search_path ))} "
539+ f"cannot locate { phdr } in { ', ' .join (map (str , search_path ))} "
500540 )
501541
502542
0 commit comments