@@ -117,6 +117,15 @@ def download_protoc_29_1(project_root: Path) -> str:
117117 shutil .copy2 (source_protoc , protoc_bin )
118118 protoc_bin .chmod (0o755 ) # Make executable
119119
120+ # Also copy the include directory with Google protobuf standard library files
121+ source_include = unzip_dir / "include"
122+ if source_include .exists ():
123+ target_include = project_root / ".bin" / "include"
124+ if target_include .exists ():
125+ shutil .rmtree (target_include )
126+ shutil .copytree (source_include , target_include )
127+ print (f"✓ Copied protobuf include files to { target_include } " )
128+
120129 # Clean up
121130 shutil .rmtree (unzip_dir )
122131 zip_path .unlink ()
@@ -231,59 +240,82 @@ def generate_init_file(output_dir: Path) -> None:
231240 print (f" ✓ Generated { init_file } with { len (pb2_files )} modules" )
232241
233242
234- def find_brew_protobuf_include (project_root : Path ) -> str :
235- """Find the protobuf include directory, preferring downloaded protoc 29.1, then brew installations."""
243+ def find_protobuf_include (project_root : Path ) -> str :
244+ """Find the protobuf include directory, preferring downloaded protoc 29.1, then system installations."""
236245 # First, check if we have downloaded protoc 29.1 and use its include directory
237- protoc_29_1_bin = project_root / "bin" / "protoc-29.1"
246+ protoc_29_1_bin = project_root / ". bin" / "protoc-29.1"
238247 if protoc_29_1_bin .exists ():
239248 # The downloaded protoc includes the well-known types in the zip
240- # We'll use the local include directory as fallback
249+ # Check for the include directory in .bin first
250+ bin_include = project_root / ".bin" / "include"
251+ if bin_include .exists ():
252+ print (f"Using .bin protobuf include directory: { bin_include } " )
253+ return str (bin_include )
254+
255+ # Fallback to local include directory
241256 local_include = project_root / "include"
242257 if local_include .exists ():
243258 print (f"Using local include directory: { local_include } " )
244259 return str (local_include )
245260
246- try :
247- # Try to find main brew protobuf installation (version 29.3)
248- result = subprocess .run (["brew" , "--prefix" , "protobuf" ],
249- capture_output = True , text = True , timeout = 5 )
250- if result .returncode == 0 :
251- brew_prefix = result .stdout .strip ()
252- include_path = f"{ brew_prefix } /include"
253- if os .path .exists (include_path ):
254- print (f"Using main protobuf include: { include_path } " )
255- return include_path
256- except (subprocess .TimeoutExpired , FileNotFoundError ):
257- pass
261+ # Check if we're on macOS (using brew)
262+ if platform .system ().lower () == 'darwin' :
263+ try :
264+ # Try to find main brew protobuf installation (version 29.3)
265+ result = subprocess .run (["brew" , "--prefix" , "protobuf" ],
266+ capture_output = True , text = True , timeout = 5 )
267+ if result .returncode == 0 :
268+ brew_prefix = result .stdout .strip ()
269+ include_path = f"{ brew_prefix } /include"
270+ if os .path .exists (include_path ):
271+ print (f"Using main protobuf include: { include_path } " )
272+ return include_path
273+ except (subprocess .TimeoutExpired , FileNotFoundError ):
274+ pass
258275
259- # Check protobuf@29 second (version 29.4)
260- protobuf_29_include = "/opt/homebrew/opt/protobuf@29/include"
261- if os .path .exists (protobuf_29_include ):
262- print (f"Using protobuf@29 include: { protobuf_29_include } " )
263- return protobuf_29_include
264-
265- # Fallback to common brew location
266- common_paths = [
267- "/opt/homebrew/include" ,
268- "/usr/local/include" ,
269- "/opt/homebrew/Cellar/protobuf/*/include"
270- ]
271-
272- for path_pattern in common_paths :
273- if "*" in path_pattern :
274- # Handle wildcard pattern
275- import glob
276- matches = glob .glob (path_pattern )
277- if matches :
278- # Use the latest version
279- latest = sorted (matches )[- 1 ]
280- if os .path .exists (latest ):
281- print (f"Using brew protobuf include: { latest } " )
282- return latest
283- else :
284- if os .path .exists (path_pattern ):
285- print (f"Using brew protobuf include: { path_pattern } " )
286- return path_pattern
276+ # Check protobuf@29 second (version 29.4)
277+ protobuf_29_include = "/opt/homebrew/opt/protobuf@29/include"
278+ if os .path .exists (protobuf_29_include ):
279+ print (f"Using protobuf@29 include: { protobuf_29_include } " )
280+ return protobuf_29_include
281+
282+ # Fallback to common brew location
283+ common_paths = [
284+ "/opt/homebrew/include" ,
285+ "/usr/local/include" ,
286+ "/opt/homebrew/Cellar/protobuf/*/include"
287+ ]
288+
289+ for path_pattern in common_paths :
290+ if "*" in path_pattern :
291+ # Handle wildcard pattern
292+ import glob
293+ matches = glob .glob (path_pattern )
294+ if matches :
295+ # Use the latest version
296+ latest = sorted (matches )[- 1 ]
297+ if os .path .exists (latest ):
298+ print (f"Using brew protobuf include: { latest } " )
299+ return latest
300+ else :
301+ if os .path .exists (path_pattern ):
302+ print (f"Using brew protobuf include: { path_pattern } " )
303+ return path_pattern
304+
305+ # Linux paths
306+ elif platform .system ().lower () == 'linux' :
307+ # Common Linux protobuf include paths
308+ linux_paths = [
309+ "/usr/include" ,
310+ "/usr/local/include" ,
311+ "/opt/protobuf/include" ,
312+ "/usr/share/protobuf/include"
313+ ]
314+
315+ for path in linux_paths :
316+ if os .path .exists (path ):
317+ print (f"Using Linux protobuf include: { path } " )
318+ return path
287319
288320 return None
289321
@@ -362,9 +394,6 @@ def generate_protobuf_files(temp_proto_dir: Path, output_dir: Path, project_root
362394 else :
363395 print ("Warning: grpc_python_plugin not found, skipping gRPC code generation" )
364396
365- # Find brew protobuf include directory
366- brew_include = find_brew_protobuf_include (project_root )
367-
368397 # Generate Python files for each proto file
369398 for proto_file in proto_files :
370399 # Get relative path from temp proto directory
@@ -378,12 +407,7 @@ def generate_protobuf_files(temp_proto_dir: Path, output_dir: Path, project_root
378407 f"--proto_path={ temp_proto_dir } " ,
379408 ]
380409
381- # Add brew protobuf include path if available
382- if brew_include :
383- cmd .append (f"--proto_path={ brew_include } " )
384- else :
385- # Fallback to local include directory
386- cmd .append (f"--proto_path={ project_root } /include" )
410+ cmd .append (f"--proto_path={ project_root } /include" )
387411
388412 cmd .append (str (proto_file ))
389413
@@ -404,12 +428,7 @@ def generate_protobuf_files(temp_proto_dir: Path, output_dir: Path, project_root
404428 f"--proto_path={ temp_proto_dir } " ,
405429 ]
406430
407- # Add brew protobuf include path if available
408- if brew_include :
409- grpc_cmd .append (f"--proto_path={ brew_include } " )
410- else :
411- # Fallback to local include directory
412- grpc_cmd .append (f"--proto_path={ project_root } /include" )
431+ grpc_cmd .append (f"--proto_path={ project_root } /include" )
413432
414433 grpc_cmd .append (str (proto_file ))
415434
@@ -428,12 +447,7 @@ def generate_protobuf_files(temp_proto_dir: Path, output_dir: Path, project_root
428447 f"--proto_path={ temp_proto_dir } " ,
429448 ]
430449
431- # Add brew protobuf include path if available
432- if brew_include :
433- grpc_cmd .append (f"--proto_path={ brew_include } " )
434- else :
435- # Fallback to local include directory
436- grpc_cmd .append (f"--proto_path={ project_root } /include" )
450+ grpc_cmd .append (f"--proto_path={ project_root } /include" )
437451
438452 grpc_cmd .append (str (proto_file ))
439453
0 commit comments