Skip to content

Commit a908831

Browse files
authored
Replace Node.js version header generator with C++ implementation (#261)
Replaces the Node.js-based generate-version-header.js script with a C++ implementation to eliminate the Node.js runtime dependency from the build process. The new C++ tool reads package.json and generates the same version.h header file. Also fixes Closure Compiler errors under strict mode in extension_field_binary_info.js and map.js by properly assigning goog.requireType calls to const variables instead of using standalone goog.requireType calls. Changes: - Add generator/generate-version-header.cc with C++ implementation - Remove generate-version-header.js - Update generator/BUILD.bazel to use cc_binary instead of Node.js script - Add rules_cc dependency to MODULE.bazel - Update BUILD.bazel to remove deleted script from exports_files - Fix goog.requireType usage in extension_field_binary_info.js and map.js
1 parent 9f216f3 commit a908831

File tree

7 files changed

+127
-57
lines changed

7 files changed

+127
-57
lines changed

BUILD.bazel

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ load("@rules_pkg//:mappings.bzl", "pkg_attributes", "pkg_files", "strip_prefix")
66
load("@rules_pkg//:pkg.bzl", "pkg_tar", "pkg_zip")
77
load("//:protobuf_javascript_release.bzl", "package_naming")
88

9-
exports_files(["generate-version-header.js", "package.json"])
9+
exports_files(["package.json"])
1010

1111
config_setting(
1212
name = "x64_x86_windows",
@@ -36,13 +36,13 @@ config_setting(
3636
package_naming(
3737
name = "protobuf_javascript_pkg_naming",
3838
platform = select({
39-
":k8": "linux-x86_64", # currently the only supported build type in Github Actions
39+
":k8": "linux-x86_64", # currently the only supported build type in Github Actions
4040
":x64_x86_windows": "win32",
4141
":x64_windows": "win64",
4242
":darwin_arm64": "osx-aarch_64",
4343
":darwin_x86_64": "osx-x86_64",
44-
"//conditions:default": "" # continues with current behavior when no --cpu is specified allowing existing internal builds to function
45-
})
44+
"//conditions:default": "", # continues with current behavior when no --cpu is specified allowing existing internal builds to function
45+
}),
4646
)
4747

4848
pkg_files(
@@ -54,15 +54,18 @@ pkg_files(
5454

5555
pkg_files(
5656
name = "dist_files",
57-
srcs = glob([
58-
"google/protobuf/*.js",
59-
"google/protobuf/compiler/*.js"
60-
], allow_empty = True) + [
61-
"google-protobuf.js",
62-
"package.json",
63-
"README.md",
57+
srcs = glob(
58+
[
59+
"google/protobuf/*.js",
60+
"google/protobuf/compiler/*.js",
61+
],
62+
allow_empty = True,
63+
) + [
6464
"LICENSE.md",
6565
"LICENSE-asserts.md",
66+
"README.md",
67+
"google-protobuf.js",
68+
"package.json",
6669
],
6770
strip_prefix = strip_prefix.from_root(""),
6871
)
@@ -93,5 +96,5 @@ filegroup(
9396
srcs = [
9497
":dist_tar",
9598
":dist_zip",
96-
]
99+
],
97100
)

MODULE.bazel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module(name = "protobuf_javascript", version = "4.0.1")
22

3+
bazel_dep(name = "abseil-cpp", version = "20250512.1")
34
bazel_dep(name = "protobuf", version = "33.0", repo_name = "com_google_protobuf")
5+
bazel_dep(name = "rules_cc", version = "0.2.15")
46
bazel_dep(name = "rules_pkg", version = "1.0.1")
5-
bazel_dep(name = "abseil-cpp", version = "20250512.1")

extension_field_binary_info.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ goog.module('jspb.ExtensionFieldBinaryInfo');
3636
goog.module.declareLegacyNamespace();
3737

3838
const ExtensionFieldInfo = goog.require('jspb.ExtensionFieldInfo');
39-
goog.requireType('jspb.BinaryReader');
40-
goog.requireType('jspb.BinaryWriter');
39+
const BinaryReader = goog.requireType('jspb.BinaryReader');
40+
const BinaryWriter = goog.requireType('jspb.BinaryWriter');
4141

4242
/**
4343
* Stores binary-related information for a single extension field.
4444
* @param {!ExtensionFieldInfo<T>} fieldInfo
45-
* @param {function(this:jspb.BinaryReader,number,?,?)} binaryReaderFn
46-
* @param {function(this:jspb.BinaryWriter,number,?)
47-
* |function(this:jspb.BinaryWriter,number,?,?,?,?,?)} binaryWriterFn
45+
* @param {function(this:BinaryReader,number,?,?)} binaryReaderFn
46+
* @param {function(this:BinaryWriter,number,?)
47+
* |function(this:BinaryWriter,number,?,?,?,?,?)} binaryWriterFn
4848
* @param {function(?,?)=} opt_binaryMessageSerializeFn
4949
* @param {function(?,?)=} opt_binaryMessageDeserializeFn
5050
* @param {boolean=} opt_isPacked

generate-version-header.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

generator/BUILD.bazel

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
load("@rules_cc//cc:defs.bzl", "cc_binary")
2+
3+
cc_binary(
4+
name = "generate-version-header",
5+
srcs = ["generate-version-header.cc"],
6+
)
7+
18
genrule(
29
name = "generate_version_header",
310
srcs = ["//:package.json"],
411
outs = ["version.h"],
5-
cmd = "node $(location //:generate-version-header.js) $(OUTS)",
6-
tools = ["//:generate-version-header.js"],
12+
cmd = "$(location :generate-version-header) $(location //:package.json) $(OUTS)",
13+
tools = [":generate-version-header"],
714
)
815

916
cc_binary(
@@ -18,15 +25,13 @@ cc_binary(
1825
],
1926
visibility = ["//visibility:public"],
2027
deps = [
28+
"@abseil-cpp//absl/strings",
29+
"@abseil-cpp//absl/strings:str_format",
2130
"@com_google_protobuf//:protobuf",
31+
"@com_google_protobuf//:protoc_lib",
2232
"@com_google_protobuf//src/google/protobuf/compiler:code_generator",
2333
"@com_google_protobuf//src/google/protobuf/io",
2434
"@com_google_protobuf//src/google/protobuf/io:printer",
2535
"@com_google_protobuf//src/google/protobuf/io:tokenizer",
26-
"@com_google_protobuf//:protoc_lib",
27-
"@abseil-cpp//absl/strings",
28-
"@abseil-cpp//absl/strings:str_format",
2936
],
3037
)
31-
32-
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <fstream>
16+
#include <iostream>
17+
#include <regex>
18+
#include <sstream>
19+
#include <string>
20+
21+
std::string ReadPackageVersion(const std::string& package_json_path) {
22+
std::ifstream file(package_json_path);
23+
if (!file.is_open()) {
24+
std::cerr << "Error: Could not open " << package_json_path << std::endl;
25+
exit(1);
26+
}
27+
28+
std::stringstream buffer;
29+
buffer << file.rdbuf();
30+
std::string content = buffer.str();
31+
32+
// Simple regex to extract version field from package.json
33+
std::regex version_regex(R"#("version"\s*:\s*"([^"]+)")#");
34+
std::smatch match;
35+
36+
if (std::regex_search(content, match, version_regex)) {
37+
return match[1].str();
38+
}
39+
40+
std::cerr << "Error: Could not find version in " << package_json_path
41+
<< std::endl;
42+
exit(1);
43+
}
44+
45+
void GenerateHeaderFile(const std::string& output_path,
46+
const std::string& version) {
47+
std::ofstream file(output_path);
48+
if (!file.is_open()) {
49+
std::cerr << "Error: Could not write to " << output_path << std::endl;
50+
exit(1);
51+
}
52+
53+
file << "// Generated by generate-version-header.cc\n"
54+
<< "#ifndef PROTOBUF_JAVASCRIPT_VERSION_H__\n"
55+
<< "#define PROTOBUF_JAVASCRIPT_VERSION_H__\n"
56+
<< "\n"
57+
<< "const char* const kProtobufJavascriptVersion = \"" << version
58+
<< "\";\n"
59+
<< "\n"
60+
<< "#endif // PROTOBUF_JAVASCRIPT_VERSION_H__\n";
61+
}
62+
63+
int main(int argc, char* argv[]) {
64+
if (argc != 3) {
65+
std::cerr << "Usage: " << argv[0] << " <package_json_path> <output_header_path>" << std::endl;
66+
return 1;
67+
}
68+
69+
std::string package_json_path = argv[1];
70+
std::string output_path = argv[2];
71+
72+
std::string version = ReadPackageVersion(package_json_path);
73+
GenerateHeaderFile(output_path, version);
74+
75+
std::cout << "Generated " << output_path << " with version " << version
76+
<< std::endl;
77+
78+
return 0;
79+
}

map.js

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,8 @@
6868
goog.module('jspb.Map');
6969
goog.module.declareLegacyNamespace();
7070

71-
7271
const asserts = goog.require('jspb.asserts');
73-
74-
goog.requireType('jspb.BinaryReader');
75-
goog.requireType('jspb.BinaryWriter');
76-
72+
const BinaryReader = goog.requireType('jspb.BinaryReader');
7773

7874

7975
/**
@@ -268,13 +264,13 @@ const ArrayIteratorIterable_ = function (arr) {
268264
/** @override @final */
269265
ArrayIteratorIterable_.prototype.next = function () {
270266
if (this.idx_ < this.arr_.length) {
271-
return {done: false, value: this.arr_[this.idx_++]};
267+
return { done: false, value: this.arr_[this.idx_++] };
272268
} else {
273-
return {done: true, value: undefined};
269+
return { done: true, value: undefined };
274270
}
275271
};
276272

277-
if (typeof(Symbol) != 'undefined') {
273+
if (typeof (Symbol) != 'undefined') {
278274
/** @override */
279275
ArrayIteratorIterable_.prototype[Symbol.iterator] = function () {
280276
return this;
@@ -488,17 +484,17 @@ Map.prototype.has = function (key) {
488484
* we should default it to 0.
489485
* @template K, V
490486
* @param {!Map} map
491-
* @param {!jspb.BinaryReader} reader
492-
* @param {function(this:jspb.BinaryReader):K} keyReaderFn
487+
* @param {!BinaryReader} reader
488+
* @param {function(this:BinaryReader):K} keyReaderFn
493489
* The method on BinaryReader that reads type K from the stream.
494490
*
495-
* @param {function(this:jspb.BinaryReader):V|
496-
* function(this:jspb.BinaryReader,V,
497-
* function(V,!jspb.BinaryReader))} valueReaderFn
491+
* @param {function(this:BinaryReader):V|
492+
* function(this:BinaryReader,V,
493+
* function(V,!BinaryReader))} valueReaderFn
498494
* The method on BinaryReader that reads type V from the stream. May be
499495
* readMessage, in which case the second callback arg form is used.
500496
*
501-
* @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
497+
* @param {?function(V,!BinaryReader)=} opt_valueReaderCallback
502498
* The BinaryReader parsing callback for type V, if V is a message type
503499
*
504500
* @param {K=} opt_defaultKey
@@ -514,8 +510,8 @@ Map.prototype.has = function (key) {
514510
*
515511
*/
516512
Map.deserializeBinary = function (map, reader, keyReaderFn, valueReaderFn,
517-
opt_valueReaderCallback, opt_defaultKey,
518-
opt_defaultValue) {
513+
opt_valueReaderCallback, opt_defaultKey,
514+
opt_defaultValue) {
519515
var key = opt_defaultKey;
520516
var value = opt_defaultValue;
521517

@@ -540,8 +536,8 @@ Map.deserializeBinary = function (map, reader, keyReaderFn, valueReaderFn,
540536
valueReaderFn.call(reader, value, opt_valueReaderCallback);
541537
} else {
542538
value =
543-
(/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn))
544-
.call(reader);
539+
(/** @type {function(this:BinaryReader):?} */ (valueReaderFn))
540+
.call(reader);
545541
}
546542
}
547543
}

0 commit comments

Comments
 (0)