7676#![ deny( missing_docs) ]
7777#![ allow( clippy:: needless_doctest_main) ]
7878
79+ use std:: env;
7980use std:: fs:: { create_dir_all, write} ;
8081use std:: io:: { Error , ErrorKind , Result } ;
8182use std:: path:: { Path , PathBuf } ;
@@ -242,13 +243,26 @@ enum DllToolCommand {
242243 /// MSVC `lib.exe` program (no prefix)
243244 LibExe { command : Command , machine : String } ,
244245 /// `zig dlltool` wrapper (no prefix)
245- #[ allow( dead_code) ]
246246 Zig { command : Command , machine : String } ,
247247}
248248
249249impl DllToolCommand {
250250 /// Attempts to find the best matching `dlltool` flavor for the target.
251251 fn find_for_target ( arch : & str , env : & str ) -> Result < DllToolCommand > {
252+ // LLVM tools use their own target architecture names...
253+ let machine = match arch {
254+ "x86_64" => "i386:x86-64" ,
255+ "x86" => "i386" ,
256+ "aarch64" => "arm64" ,
257+ arch => arch,
258+ }
259+ . to_owned ( ) ;
260+
261+ // If `zig cc` is used as the linker, `zig dlltool` is the best choice.
262+ if let Some ( command) = find_zig ( ) {
263+ return Ok ( DllToolCommand :: Zig { command, machine } ) ;
264+ }
265+
252266 match ( arch, env) {
253267 // 64-bit MinGW-w64 (aka `x86_64-pc-windows-gnu`)
254268 ( "x86_64" , "gnu" ) => Ok ( DllToolCommand :: Mingw {
@@ -274,15 +288,6 @@ impl DllToolCommand {
274288
275289 Ok ( DllToolCommand :: LibExe { command, machine } )
276290 } else {
277- // LLVM tools use their own target architecture names...
278- let machine = match arch {
279- "x86_64" => "i386:x86-64" ,
280- "x86" => "i386" ,
281- "aarch64" => "arm64" ,
282- arch => arch,
283- }
284- . to_owned ( ) ;
285-
286291 let command = Command :: new ( DLLTOOL_MSVC ) ;
287292
288293 Ok ( DllToolCommand :: Llvm { command, machine } )
@@ -352,6 +357,27 @@ impl DllToolCommand {
352357 }
353358}
354359
360+ /// Finds the `zig` executable (when built by ``maturin --zig`).
361+ ///
362+ /// Examines the `ZIG_COMMAND` environment variable
363+ /// to find out if `zig cc` is being used as the linker.
364+ fn find_zig ( ) -> Option < Command > {
365+ // `ZIG_COMMAND` may contain simply `zig` or `/usr/bin/zig`,
366+ // or a more complex construct like `python3 -m ziglang`.
367+ let zig_command = env:: var ( "ZIG_COMMAND" ) . ok ( ) ?;
368+
369+ // Try to emulate `sh -c ${ZIG_COMMAND}`.
370+ let mut zig_cmdlet = zig_command. split_ascii_whitespace ( ) ;
371+
372+ // Extract the main program component (e.g. `zig` or `python3`).
373+ let mut zig = Command :: new ( zig_cmdlet. next ( ) ?) ;
374+
375+ // Append the rest of the commandlet.
376+ zig. args ( zig_cmdlet) ;
377+
378+ Some ( zig)
379+ }
380+
355381/// Finds Visual Studio `lib.exe` when running on Windows.
356382#[ cfg( windows) ]
357383fn find_lib_exe ( arch : & str ) -> Option < Command > {
0 commit comments