1+ load ("@bazel_skylib//lib:collections.bzl" , "collections" )
2+ load ("@bazel_skylib//lib:paths.bzl" , "paths" )
13load ("@rules_cc//cc/common:cc_info.bzl" , "CcInfo" )
24load ("//tests/bazel_cc_import/bazel:buildbp.bzl" , "binary_bp_content" , "library_bp_content" )
35load ("//tests/bazel_cc_import/bazel:name.bzl" , "bp_target_name" )
4- load ("@bazel_skylib//lib:collections.bzl" , "collections" )
5- load ("@bazel_skylib//lib:paths.bzl" , "paths" )
66
77ImportCcAspectInfo = provider (fields = ["defines" , "headers" ])
88
@@ -84,18 +84,34 @@ def _symlink_headers(ctx, module_dir, dir_name, headers):
8484
8585 return outputs
8686
87- def _library_file (target ):
87+ def _unique_files_by_path (files ):
88+ seen = {}
89+ deduped = []
90+ for file in files :
91+ if file and not seen .get (file .path ):
92+ seen [file .path ] = True
93+ deduped .append (file )
94+ return deduped
95+
96+ def _file_list (files ):
97+ return ", " .join ([file .short_path for file in files ])
98+
99+ def _library_files (target ):
88100 candidates = []
89101
90102 def add_candidate (file ):
91103 if _is_library_file (file ):
92104 candidates .append (file )
93105
94106 # cc_shared_library has this
95- for file in target [DefaultInfo ].files .to_list ():
96- add_candidate (file )
107+ if DefaultInfo in target :
108+ for file in target [DefaultInfo ].files .to_list ():
109+ add_candidate (file )
110+
111+ if candidates :
112+ return _unique_files_by_path (candidates )
97113
98- if not candidates and CcInfo in target :
114+ if CcInfo in target :
99115 linking_context = target [CcInfo ].linking_context
100116 for linker_input in linking_context .linker_inputs .to_list ():
101117 for library in linker_input .libraries :
@@ -105,8 +121,10 @@ def _library_file(target):
105121 ]:
106122 add_candidate (file )
107123
108- if len (candidates ) > 1 :
109- fail ("More than one lib output in '" + str (target ) + "' " + str (candidates ))
124+ return _unique_files_by_path (candidates )
125+
126+ def _library_file (target ):
127+ candidates = _library_files (target )
110128
111129 if len (candidates ) == 0 :
112130 # header only lib
@@ -117,27 +135,63 @@ def _library_file(target):
117135def _is_library_file (file ):
118136 return file .path .endswith (".a" ) or file .path .endswith (".so" )
119137
120- def _binary_file (target ):
138+ def _binary_files (target ):
121139 if DefaultInfo not in target :
122- return None
140+ return []
123141
124142 candidates = []
125143 for file in target [DefaultInfo ].files .to_list ():
126144 if not file .is_directory and not _is_library_file (file ):
127145 candidates .append (file )
128146
147+ return _unique_files_by_path (candidates )
148+
149+ def _binary_file (target ):
150+ candidates = _binary_files (target )
151+
129152 if len (candidates ) == 1 :
130153 return candidates [0 ]
131154
132155 return None
133156
157+ def _multiple_outputs_reason (output_type , files ):
158+ return "produces multiple " + output_type + " outputs (" + _file_list (files ) + "); " + \
159+ "Bob import generation supports one output per Bazel target"
160+
161+ def _fail_on_unsupported_outputs (target ):
162+ libraries = _library_files (target )
163+ binaries = _binary_files (target )
164+
165+ if len (libraries ) > 1 :
166+ fail (_multiple_outputs_reason ("library" , libraries ))
167+ if len (binaries ) > 1 :
168+ fail (_multiple_outputs_reason ("binary" , binaries ))
169+ if libraries and binaries :
170+ fail (
171+ "produces both library and binary outputs (" + _file_list (libraries + binaries ) + "); " +
172+ "Bob import generation supports either one library or one binary per Bazel target" ,
173+ )
174+
175+ def _target_labels (targets ):
176+ return ", " .join ([str (target .label ) for target in targets ])
177+
178+ def _fail_on_unsupported_dynamic_deps (ctx ):
179+ dynamic_deps = getattr (ctx .rule .attr , "dynamic_deps" , [])
180+ if dynamic_deps :
181+ fail (
182+ "declares dynamic_deps (" + _target_labels (dynamic_deps ) + "); " +
183+ "dynamic dependencies are not supported for Bob imports" ,
184+ )
185+
134186def _symlink_file (ctx , module_dir , dir_name , file ):
135187 destination = paths .join (dir_name , file .basename )
136188 out = ctx .actions .declare_file (module_dir + "/" + destination )
137189 ctx .actions .symlink (output = out , target_file = file )
138190 return destination , out
139191
140192def _bob_import_cc_aspect_impl (target , ctx ):
193+ _fail_on_unsupported_dynamic_deps (ctx )
194+
141195 headers , defines = _compilation_info (target , ctx )
142196
143197 return [
@@ -155,6 +209,8 @@ bob_import_cc_aspect = aspect(
155209def _gen_bob_import_impl (ctx ):
156210 output = []
157211 for dep in ctx .attr .deps :
212+ _fail_on_unsupported_outputs (dep )
213+
158214 target_name = bp_target_name (dep .label )
159215 include_destination = "include"
160216 library_destination = "lib"
0 commit comments