Skip to content

Commit 0f08f58

Browse files
committed
Merge branch 'feat/print-workflow-run-errors' into feature/storage-list-api
2 parents 61e6bbb + 6ba2558 commit 0f08f58

File tree

70 files changed

+4872
-213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+4872
-213
lines changed

AGENTS.md

Lines changed: 679 additions & 0 deletions
Large diffs are not rendered by default.

Android/firebase_dependencies.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ project.afterEvaluate {
164164

165165
// Add the bill-of-materials
166166
project.dependencies {
167-
implementation platform('com.google.firebase:firebase-bom:33.14.0')
167+
implementation platform('com.google.firebase:firebase-bom:33.15.0')
168168
}
169169
for (String lib : firebaseCpp.dependencies.libSet) {
170170
// Generate and include the proguard file

STYLE_GUIDE.md

Lines changed: 378 additions & 0 deletions
Large diffs are not rendered by default.

analytics/generate_windows_stubs.py

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
#!/usr/bin/env python3
2+
# Copyright 2025 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""Generate stubs and function pointers for Windows SDK"""
17+
18+
import argparse
19+
import os
20+
import re
21+
import sys
22+
23+
HEADER_GUARD_PREFIX = "FIREBASE_ANALYTICS_SRC_WINDOWS_"
24+
INCLUDE_PATH = "src/windows/"
25+
INCLUDE_PREFIX = "analytics/" + INCLUDE_PATH
26+
COPYRIGHT_NOTICE = """// Copyright 2025 Google LLC
27+
//
28+
// Licensed under the Apache License, Version 2.0 (the "License");
29+
// you may not use this file except in compliance with the License.
30+
// You may obtain a copy of the License at
31+
//
32+
// http://www.apache.org/licenses/LICENSE-2.0
33+
//
34+
// Unless required by applicable law or agreed to in writing, software
35+
// distributed under the License is distributed on an "AS IS" BASIS,
36+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37+
// See the License for the specific language governing permissions and
38+
// limitations under the License.
39+
40+
"""
41+
42+
def generate_function_pointers(header_file_path, output_h_path, output_c_path):
43+
"""
44+
Parses a C header file to generate a self-contained header with typedefs,
45+
extern function pointer declarations, and a source file with stub functions,
46+
initialized pointers, and a dynamic loading function for Windows.
47+
48+
Args:
49+
header_file_path (str): The path to the input C header file.
50+
output_h_path (str): The path for the generated C header output file.
51+
output_c_path (str): The path for the generated C source output file.
52+
"""
53+
print(f"Reading header file: {header_file_path}")
54+
try:
55+
with open(header_file_path, 'r', encoding='utf-8') as f:
56+
header_content = f.read()
57+
except FileNotFoundError:
58+
print(f"Error: Header file not found at '{header_file_path}'")
59+
return
60+
61+
# --- Extract necessary definitions from the original header ---
62+
63+
# Find all standard includes (e.g., <stdint.h>)
64+
includes = re.findall(r"#include\s+<.*?>", header_content)
65+
66+
# Find all typedefs, including their documentation comments
67+
typedefs = re.findall(r"/\*\*(?:[\s\S]*?)\*/\s*typedef[\s\S]*?;\s*", header_content)
68+
69+
# --- Extract function prototypes ---
70+
function_pattern = re.compile(
71+
r"ANALYTICS_API\s+([\w\s\*]+?)\s+(\w+)\s*\((.*?)\);",
72+
re.DOTALL
73+
)
74+
matches = function_pattern.finditer(header_content)
75+
76+
extern_declarations = []
77+
macro_definitions = []
78+
stub_functions = []
79+
pointer_initializations = []
80+
function_details_for_loader = []
81+
82+
for match in matches:
83+
return_type = match.group(1).strip()
84+
function_name = match.group(2).strip()
85+
params_str = match.group(3).strip()
86+
87+
cleaned_params_for_decl = re.sub(r'\s+', ' ', params_str) if params_str else ""
88+
stub_name = f"Stub_{function_name}"
89+
90+
# Generate return statement for the stub
91+
if "void" in return_type:
92+
return_statement = " // No return value."
93+
elif "*" in return_type:
94+
return_statement = f' return ({return_type})(&g_stub_memory);'
95+
else: # bool, int64_t, etc.
96+
return_statement = " return 1;"
97+
98+
stub_function = (
99+
f"// Stub for {function_name}\n"
100+
f"static {return_type} {stub_name}({params_str}) {{\n"
101+
f"{return_statement}\n"
102+
f"}}"
103+
)
104+
stub_functions.append(stub_function)
105+
106+
declaration = f"extern {return_type} (*ptr_{function_name})({cleaned_params_for_decl});"
107+
extern_declarations.append(declaration)
108+
109+
macro = f'#define {function_name} ptr_{function_name}'
110+
macro_definitions.append(macro)
111+
112+
pointer_init = f"{return_type} (*ptr_{function_name})({cleaned_params_for_decl}) = &{stub_name};"
113+
pointer_initializations.append(pointer_init)
114+
115+
function_details_for_loader.append((function_name, return_type, cleaned_params_for_decl))
116+
117+
print(f"Found {len(pointer_initializations)} functions. Generating output files...")
118+
119+
# --- Write the self-contained Header File (.h) ---
120+
header_guard = f"{HEADER_GUARD_PREFIX}{os.path.basename(output_h_path).upper().replace('.', '_')}_"
121+
with open(output_h_path, 'w', encoding='utf-8') as f:
122+
f.write(f"{COPYRIGHT_NOTICE}")
123+
f.write(f"// Generated from {os.path.basename(header_file_path)} by {os.path.basename(sys.argv[0])}\n\n")
124+
f.write(f"#ifndef {header_guard}\n")
125+
f.write(f"#define {header_guard}\n\n")
126+
f.write("#include <stdbool.h> // needed for bool type in pure C\n\n")
127+
128+
f.write("// --- Copied from original header ---\n")
129+
f.write("\n".join(includes) + "\n\n")
130+
f.write("".join(typedefs))
131+
f.write("// --- End of copied section ---\n\n")
132+
133+
f.write("#ifdef __cplusplus\n")
134+
f.write('extern "C" {\n')
135+
f.write("#endif\n\n")
136+
f.write("// --- Function Pointer Declarations ---\n")
137+
f.write("// clang-format off\n")
138+
f.write("\n".join(extern_declarations))
139+
f.write("\n\n")
140+
f.write("\n".join(macro_definitions))
141+
f.write("\n// clang-format on\n")
142+
f.write("\n\n// --- Dynamic Loader Declaration for Windows ---\n")
143+
f.write("#if defined(_WIN32)\n")
144+
f.write('#include <windows.h> // For HMODULE\n')
145+
f.write('// Load Google Analytics functions from the given DLL handle into function pointers.\n')
146+
f.write(f'// Returns the number of functions successfully loaded (out of {len(function_details_for_loader)}).\n')
147+
f.write("int FirebaseAnalytics_LoadAnalyticsFunctions(HMODULE dll_handle);\n\n")
148+
f.write('// Reset all function pointers back to stubs.\n')
149+
f.write("void FirebaseAnalytics_UnloadAnalyticsFunctions(void);\n\n")
150+
f.write("#endif // defined(_WIN32)\n")
151+
f.write("\n#ifdef __cplusplus\n")
152+
f.write("}\n")
153+
f.write("#endif\n\n")
154+
f.write(f"#endif // {header_guard}\n")
155+
156+
print(f"Successfully generated header file: {output_h_path}")
157+
158+
# --- Write the Source File (.c) ---
159+
with open(output_c_path, 'w', encoding='utf-8') as f:
160+
f.write(f"{COPYRIGHT_NOTICE}")
161+
f.write(f"// Generated from {os.path.basename(header_file_path)} by {os.path.basename(sys.argv[0])}\n\n")
162+
f.write(f'#include "{INCLUDE_PREFIX}{os.path.basename(output_h_path)}"\n')
163+
f.write('#include <stddef.h>\n\n')
164+
f.write("// clang-format off\n\n")
165+
f.write("static void* g_stub_memory = NULL;\n\n")
166+
f.write("// --- Stub Function Definitions ---\n")
167+
f.write("\n\n".join(stub_functions))
168+
f.write("\n\n\n// --- Function Pointer Initializations ---\n")
169+
f.write("\n".join(pointer_initializations))
170+
f.write("\n\n// --- Dynamic Loader Function for Windows ---\n")
171+
loader_lines = [
172+
'#if defined(_WIN32)',
173+
'int FirebaseAnalytics_LoadAnalyticsFunctions(HMODULE dll_handle) {',
174+
' int count = 0;\n',
175+
' if (!dll_handle) {',
176+
' return count;',
177+
' }\n'
178+
]
179+
for name, ret_type, params in function_details_for_loader:
180+
pointer_type_cast = f"({ret_type} (*)({params}))"
181+
proc_check = [
182+
f' FARPROC proc_{name} = GetProcAddress(dll_handle, "{name}");',
183+
f' if (proc_{name}) {{',
184+
f' ptr_{name} = {pointer_type_cast}proc_{name};',
185+
f' count++;',
186+
f' }}'
187+
]
188+
loader_lines.extend(proc_check)
189+
loader_lines.append('\n return count;')
190+
loader_lines.append('}\n')
191+
loader_lines.append('void FirebaseAnalytics_UnloadAnalyticsFunctions(void) {')
192+
for name, ret_type, params in function_details_for_loader:
193+
loader_lines.append(f' ptr_{name} = &Stub_{name};');
194+
loader_lines.append('}\n')
195+
loader_lines.append('#endif // defined(_WIN32)\n')
196+
f.write('\n'.join(loader_lines))
197+
f.write("// clang-format on\n")
198+
199+
print(f"Successfully generated C source file: {output_c_path}")
200+
201+
202+
if __name__ == '__main__':
203+
parser = argparse.ArgumentParser(
204+
description="Generate C stubs and function pointers from a header file."
205+
)
206+
parser.add_argument(
207+
"--windows_header",
208+
default = os.path.join(os.path.dirname(sys.argv[0]), "windows/include/public/c/analytics.h"),
209+
#required=True,
210+
help="Path to the input C header file."
211+
)
212+
parser.add_argument(
213+
"--output_header",
214+
default = os.path.join(os.path.dirname(sys.argv[0]), INCLUDE_PATH, "analytics_dynamic.h"),
215+
#required=True,
216+
help="Path for the generated output header file."
217+
)
218+
parser.add_argument(
219+
"--output_source",
220+
default = os.path.join(os.path.dirname(sys.argv[0]), INCLUDE_PATH, "analytics_dynamic.c"),
221+
#required=True,
222+
help="Path for the generated output source file."
223+
)
224+
225+
args = parser.parse_args()
226+
227+
generate_function_pointers(
228+
args.windows_header,
229+
args.output_header,
230+
args.output_source
231+
)

analytics/integration_test/Podfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ use_frameworks! :linkage => :static
55

66
target 'integration_test' do
77
platform :ios, '13.0'
8-
pod 'Firebase/Analytics', '11.13.0'
8+
pod 'Firebase/Analytics', '11.14.0'
99
end
1010

1111
target 'integration_test_tvos' do
1212
platform :tvos, '13.0'
13-
pod 'Firebase/Analytics', '11.13.0'
13+
pod 'Firebase/Analytics', '11.14.0'
1414
end
1515

1616
post_install do |installer|

analytics/ios_headers/FIREventNames.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2025 Google LLC
22

3-
// Copied from Firebase Analytics iOS SDK 11.13.0.
3+
// Copied from Firebase Analytics iOS SDK 11.14.0.
44

55
/// @file FIREventNames.h
66
///

analytics/ios_headers/FIRParameterNames.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2025 Google LLC
22

3-
// Copied from Firebase Analytics iOS SDK 11.13.0.
3+
// Copied from Firebase Analytics iOS SDK 11.14.0.
44

55
/// @file FIRParameterNames.h
66
///

analytics/ios_headers/FIRUserPropertyNames.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2025 Google LLC
22

3-
// Copied from Firebase Analytics iOS SDK 11.13.0.
3+
// Copied from Firebase Analytics iOS SDK 11.14.0.
44

55
/// @file FIRUserPropertyNames.h
66
///

0 commit comments

Comments
 (0)