compile_protos.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/env php
  2. <?php
  3. /**
  4. * 自动编译 protos 目录下所有 .proto 文件
  5. * 使用方法:php compile_protos.php [输出目录]
  6. */
  7. // 参数检查
  8. if ($argc < 2) {
  9. echo "使用方法: php compile_protos.php <输出目录>\n";
  10. exit(1);
  11. }
  12. $protoDir = __DIR__ . '/protos';
  13. $outputDir = rtrim($argv[1], '/');
  14. // 检查 protoc 是否安装
  15. exec('protoc --version 2>&1', $output, $retval);
  16. if ($retval !== 0) {
  17. echo "错误: 找不到 protoc 编译器,请先安装:\n";
  18. echo "MacOS: brew install protobuf\n";
  19. echo "Linux: sudo apt-get install protobuf-compiler\n";
  20. echo "Windows: choco install protoc\n";
  21. exit(1);
  22. }
  23. // 创建输出目录
  24. if (!file_exists($outputDir)) {
  25. if (!mkdir($outputDir, 0755, true)) {
  26. echo "错误: 无法创建输出目录 {$outputDir}\n";
  27. exit(1);
  28. }
  29. }
  30. // 递归查找所有 .proto 文件
  31. $iterator = new RecursiveIteratorIterator(
  32. new RecursiveDirectoryIterator($protoDir),
  33. RecursiveIteratorIterator::LEAVES_ONLY
  34. );
  35. $protoFiles = [];
  36. foreach ($iterator as $file) {
  37. if ($file->getExtension() === 'proto') {
  38. $protoFiles[] = $file->getRealPath();
  39. }
  40. }
  41. if (empty($protoFiles)) {
  42. echo "在 {$protoDir} 目录中没有找到 .proto 文件\n";
  43. exit(0);
  44. }
  45. // 编译每个文件
  46. $successCount = 0;
  47. foreach ($protoFiles as $protoFile) {
  48. $relativePath = substr($protoFile, strlen($protoDir) + 1);
  49. echo "正在编译 {$relativePath}... ";
  50. $command = sprintf(
  51. 'protoc --php_out=%s --proto_path=%s %s 2>&1',
  52. escapeshellarg($outputDir),
  53. escapeshellarg(dirname($protoFile)),
  54. escapeshellarg($protoFile)
  55. );
  56. exec($command, $output, $retval);
  57. if ($retval === 0) {
  58. echo "成功\n";
  59. $successCount++;
  60. } else {
  61. echo "失败\n";
  62. echo "错误信息:\n" . implode("\n", $output) . "\n";
  63. }
  64. }
  65. echo "\n编译结果: 成功 {$successCount} 个,共 " . count($protoFiles) . " 个文件\n";
  66. // 生成自动加载文件
  67. generateAutoload($outputDir);
  68. /**
  69. * 生成 composer 自动加载配置
  70. */
  71. function generateAutoload(string $outputDir) {
  72. $autoloadFile = $outputDir . '/composer.json';
  73. if (!file_exists($autoloadFile)) {
  74. $data = [
  75. 'name' => 'generated/protobuf-messages',
  76. 'description' => '自动生成的 Protocol Buffers 消息类',
  77. 'autoload' => [
  78. 'psr-4' => [
  79. 'GPBMetadata\\' => 'GPBMetadata/',
  80. 'Common_pack\\' => 'Common_pack/',
  81. '' => './'
  82. ]
  83. ],
  84. 'require' => [
  85. "google/protobuf" => "^3.22"
  86. ]
  87. ];
  88. if (file_put_contents($autoloadFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
  89. echo "\n已生成 composer.json 自动加载配置,请执行以下命令完成设置:\n";
  90. echo "cd {$outputDir} && composer install && composer dump-autoload\n";
  91. // 自动创建必要的子目录
  92. @mkdir("{$outputDir}/GPBMetadata", 0755, true);
  93. @mkdir("{$outputDir}/Common_pack", 0755, true);
  94. } else {
  95. echo "\n警告: 无法生成 composer.json 文件\n";
  96. }
  97. }
  98. }