@@ -31,9 +31,17 @@ fn protoc_version() -> Option<Version> {
3131
3232fn download_protoc ( ) {
3333 let protoc_version = "26.1" ;
34-
3534 let tmp_folder = tempfile:: tempdir ( ) . unwrap ( ) ;
3635
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 ) {
3745 let os = match std:: env:: consts:: OS {
3846 "linux" => "linux" ,
3947 "macos" => "osx" ,
@@ -88,6 +96,80 @@ fn download_protoc() {
8896 std:: env:: set_var ( "PROTOC" , out_bin) ;
8997}
9098
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+
91173fn main ( ) -> Result < ( ) > {
92174 println ! ( "cargo:rerun-if-changed=build.rs" ) ;
93175
0 commit comments