How to compile Julia code as stand-alone executable with help of StaticCompiler for Windows?

168 views Asked by At

I'd like to compile Julia with help of StaticCompiler on Windows. StaticCompiler is an amazing tool for compiling Julia, and it would be great, if it can be used in Windows, too. I guess there is a big demand. The problem is that the generated executable does not print a string (neither to stdout nor to a file). Do you have any experiences or suggestions to get StaticCompiler or GPUCompiler work to print a string under windows?

For example, I tried:

using StaticCompiler, StaticTools
f() = println(c"h")
compile_executable(f,(),"./")

This produces an object file ("f.o"), but linking fails (linking the objective file with a wrapper-file, wrapper.c, to create an executable). StaticCompiler uses clang for linking. Clang fails here, prompting the error message "f.o unknown file type". The developers of StaticCompiler recommended trying the compiler that PackageCompiler installs as an artifact. This is in my case gcc, and indeed gcc links without error.

However, the generated executable does not print anything to stdout. But generally the executable seems to work. E.g. compiling f() = getchar() works.

Under the hood, StaticTools translates println to a LLVM IR that calls @puts. For example, putting 'h' would be the Julia LLVM IR

function f()
  Base.llvmcall(("""
    declare i32 @puts(i8*)
    define i32 @main() {
      %a = alloca i8
      store i8 104, i8* %a
      call i32 @puts(i8* %a)
      ret i32 0
    }
  """, "main"), Int32, Nothing, Nothing)
end

This works in the Repl, but when applying compile_executable, the generated executable does not print anything to stdout.

StaticCompiler uses GPUCompiler to produce a LLVM IR module that is then translated in machine code. In this case, the LLVM IR module produced from the LLVM IR depicted above is:

source_filename = "start"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-mingw32"

define i32 @t() local_unnamed_addr #0 {
top:
  %0 = call fastcc i32 @julia_t_1040u1042()
  ret i32 %0
}

define internal fastcc i32 @julia_t_1040u1042() unnamed_addr {
  %a = alloca i8, align 1
  store i8 65, i8* %a, align 1
  %1 = call i32 @puts(i8* noundef nonnull %a)
  ret i32 0
}

declare i32 @puts(i8*) local_unnamed_addr

attributes #0 = { "probe-stack"="inline-asm" }

!llvm.module.flags = !{!0, !1}

!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}

My questions: Why does StaticCompiler fails printing output in Windows? Does the Julia LLVM IR, or the string representation in StaticTools, or the GPUCompiler configuration or implementation, or some environment variables, have to be adapted for Windows?

The solution: See this discussion. See the forked repo for testing.

The adaption to Windows is to use clang for generating the native binary out from the LLVM IR produced by GPU Compiler (instead of using GPU Compiler to produce an objective file and using clang for linking only).

0

There are 0 answers