@@ -31,9 +31,17 @@ fn protoc_version() -> Option<Version> {
31
31
32
32
fn download_protoc ( ) {
33
33
let protoc_version = "26.1" ;
34
-
35
34
let tmp_folder = tempfile:: tempdir ( ) . unwrap ( ) ;
36
35
36
+ #[ cfg( not( windows) ) ]
37
+ download_protoc_unix ( protoc_version, & tmp_folder) ;
38
+
39
+ #[ cfg( windows) ]
40
+ download_protoc_windows ( protoc_version, & tmp_folder) ;
41
+ }
42
+
43
+ #[ cfg( not( windows) ) ]
44
+ fn download_protoc_unix ( protoc_version : & str , tmp_folder : & tempfile:: TempDir ) {
37
45
let os = match std:: env:: consts:: OS {
38
46
"linux" => "linux" ,
39
47
"macos" => "osx" ,
@@ -88,6 +96,80 @@ fn download_protoc() {
88
96
std:: env:: set_var ( "PROTOC" , out_bin) ;
89
97
}
90
98
99
+ #[ cfg( windows) ]
100
+ fn download_protoc_windows ( protoc_version : & str , tmp_folder : & tempfile:: TempDir ) {
101
+ // Determine Windows architecture (win32 or win64)
102
+ let win_arch = match std:: env:: consts:: ARCH {
103
+ "x86_64" => "win64" ,
104
+ "x86" => "win32" ,
105
+ arch => panic ! ( "Unsupported Windows architecture: {arch}" ) ,
106
+ } ;
107
+
108
+ // Windows-specific checksums
109
+ let checksum = match win_arch {
110
+ "win64" => "9090d135a1159042b13b4e51b210e40cb820d85a5032a6eca5f9b3ca3bdfb539" ,
111
+ "win32" => "11fc8f280922e86d917e30f7b9960a1e77453f64990d965080697b394a8d9d74" ,
112
+ _ => unreachable ! ( ) ,
113
+ } ;
114
+
115
+ // Windows-specific URL format
116
+ let download_url = format ! (
117
+ "https://github.com/protocolbuffers/protobuf/releases/download/v{protoc_version}/protoc-{protoc_version}-{win_arch}.zip"
118
+ ) ;
119
+
120
+ eprintln ! ( "Downloading protoc from: {download_url}" ) ;
121
+
122
+ // Download using curl (assuming curl is available on Windows)
123
+ let mut download_command = Command :: new ( "curl" ) ;
124
+ download_command
125
+ . arg ( "-Lf" )
126
+ . arg ( download_url)
127
+ . arg ( "-o" )
128
+ . arg ( tmp_folder. path ( ) . join ( "protoc.zip" ) ) ;
129
+ assert ! ( download_command. spawn( ) . unwrap( ) . wait( ) . unwrap( ) . success( ) ) ;
130
+
131
+ // Verify checksum using PowerShell
132
+ let mut checksum_command = Command :: new ( "powershell" ) ;
133
+ checksum_command. arg ( "-Command" ) . arg ( format ! (
134
+ "(Get-FileHash -Path '{}' -Algorithm SHA256).Hash.ToLower()" ,
135
+ tmp_folder. path( ) . join( "protoc.zip" ) . display( )
136
+ ) ) ;
137
+ let checksum_output = checksum_command. output ( ) . unwrap ( ) ;
138
+ let checksum_output = String :: from_utf8 ( checksum_output. stdout ) . unwrap ( ) . trim ( ) . to_lowercase ( ) ;
139
+
140
+ eprintln ! ( "checksum: {checksum_output:?}" ) ;
141
+ assert_eq ! (
142
+ checksum_output,
143
+ checksum. to_lowercase( ) ,
144
+ "Checksum verification failed. Expected: {}, Got: {}" ,
145
+ checksum. to_lowercase( ) ,
146
+ checksum_output
147
+ ) ;
148
+
149
+ // Extract using PowerShell
150
+ let mut unzip_command = Command :: new ( "powershell" ) ;
151
+ unzip_command. arg ( "-Command" ) . arg ( format ! (
152
+ "Expand-Archive -Path '{}' -DestinationPath '{}' -Force" ,
153
+ tmp_folder. path( ) . join( "protoc.zip" ) . display( ) ,
154
+ tmp_folder. path( ) . display( )
155
+ ) ) ;
156
+ assert ! ( unzip_command. spawn( ) . unwrap( ) . wait( ) . unwrap( ) . success( ) ) ;
157
+
158
+ // Set output path with .exe extension for Windows
159
+ let out_bin = PathBuf :: from ( std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ) . join ( "protoc.exe" ) ;
160
+
161
+ // Copy the protoc binary using PowerShell
162
+ let mut copy_command = Command :: new ( "powershell" ) ;
163
+ copy_command. arg ( "-Command" ) . arg ( format ! (
164
+ "Copy-Item -Path '{}' -Destination '{}'" ,
165
+ tmp_folder. path( ) . join( "bin" ) . join( "protoc.exe" ) . display( ) ,
166
+ out_bin. display( )
167
+ ) ) ;
168
+ assert ! ( copy_command. spawn( ) . unwrap( ) . wait( ) . unwrap( ) . success( ) ) ;
169
+
170
+ std:: env:: set_var ( "PROTOC" , out_bin) ;
171
+ }
172
+
91
173
fn main ( ) -> Result < ( ) > {
92
174
println ! ( "cargo:rerun-if-changed=build.rs" ) ;
93
175
0 commit comments