PackageCompilerX on Windows

I’ve been keeping an eye on @kristoffer.carlsson’s PackageCompilerX and wondering when to try creating a stand-alone executable for some Julia code I have (after previous failures with PackageCompiler).

The documentation for PackageCompilerX includes an example of creating a sysimage that includes the package “Example”.

So I wanted to duplicate the example on my Windows 10 PC, having first installed the minGW compiler toolchain, correctly as far as I can tell.

But I’m seeing an error, as below.

Any suggestions please? Am I jumping the gun by trying to get PackageCompilerX to work on Windows?

C:\Users\Philip>cd NewSysImageEnv

C:\Users\Philip\NewSysImageEnv>julia -q
julia> Revise loaded by code in C:\Users\Philip\AppData\Local\Julia-1.3.1\etc\julia\startup.jl
julia> using PackageCompilerX

(v1.3) pkg> activate .
Activating new environment at `C:\Users\Philip\NewSysImageEnv\Project.toml`

(NewSysImageEnv) pkg> add Example
  Updating registry at `C:\Users\Philip\.julia\registries\General`
  Updating git-repo `https://github.com/JuliaRegistries/General.git`
 Resolving package versions...
  Updating `C:\Users\Philip\NewSysImageEnv\Project.toml`
  [7876af07] + Example v0.5.3
  Updating `C:\Users\Philip\NewSysImageEnv\Manifest.toml`
  [7876af07] + Example v0.5.3

julia> create_sysimage(:Example; sysimage_path="ExampleSysimage.so")
[ Info: PackageCompilerX: creating system image object file, this might take a while...
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Philip\AppData\Local\Temp\jl_47B6.tmp.o: member C:\Users\Philip\AppData\Local\Temp\jl_47B6.tmp.o(text.o) in archive is not an object
collect2.exe: error: ld returned 1 exit status
ERROR: failed process: Process(`gcc -m64 -shared '-LC:\Users\Philip\AppData\Local\Julia-1.3.1\bin' -o ExampleSysimage.so -Wl,--whole-archive 'C:\Users\Philip\AppData\Local\Temp\jl_47B6.tmp.o' -Wl,--no-whole-archive -ljulia -Wl,--export-all-symbols`, ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] #run#565(::Bool, ::typeof(run), ::Cmd) at .\process.jl:440
 [3] run at .\process.jl:438 [inlined]
 [4] create_sysimg_from_object_file(::String, ::String) at C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\PackageCompilerX.jl:364
 [5] #create_sysimage#5(::String, ::String, ::Array{String,1}, ::Array{String,1}, ::Bool, ::Bool, ::Bool, ::String, ::Nothing, ::Bool, ::typeof(create_sysimage), ::Symbol) at C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\PackageCompilerX.jl:336
 [6] (::PackageCompilerX.var"#kw##create_sysimage")(::NamedTuple{(:sysimage_path,),Tuple{String}}, ::typeof(create_sysimage), ::Symbol) at .\none:0
 [7] top-level scope at REPL[4]:1

julia>

I used it for compiling stuff like Plots, CSV, Knet, Images and others on Windows and it worked great. Tried on Julia 1.3 and 1.3.1.
To be honest every time I compiled the packages from the default environment. But this shouldn’t matter.
You could try compiling another package, like CSV.
One notable difference from your setup is that I didn’t bother with mingw.
I simply installed WinRPM Julia package and then WinRPM.install("gcc"). Of course, I had to add the path to gcc from WinRPM folder in the Windows PATH.
Also I’m not sure if the .so extension, typical for Linux, has anything to do with the code compilation on Windows platform or it could be modified after you get the compiled sysimage.

Maybe also a problem with the compiler, since Julia was compiled with gcc 7.

I know it is sensitive to what mingw you are using. I think this one worked for me: Download x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z (MinGW-w64 - for 32 and 64 bit Windows)

1 Like

Great, thanks to those replies it looks like I’ve got a couple of options to try this morning…

I’ve made progress thanks to guidance from @kristoffer.carlsson and @Iulian.Cioarca. I chose to follow Iulian’s suggestion of getting a working copy of gcc.exe via WinRPM.install("gcc")

Good news:

  • create_sysimage works to create a system image containing the Example package.
  • create_sysimage also works to create a system image containing my own TestPackage1.

Not so good news:

  • I’m running into an error when trying to use create_app. The error (below) makes me think that my PC is still not correctly set up for code compilation since a file string.h can’t be found, and whilst no C++ programmer, I think that’s a file that should be part of any C++ “set up”.

Possible solution to try tomorrow:

  1. Install MinGW from the link that Kristoffer provided. I’ll find out if that will provide string.h and other necessary files…
  2. But if you think that won’t do the trick, what else should I try?

Thanks in advance!

The error:

julia> create_app("TestPackage1","CompiledTestPackage1",precompile_execution_file="c:/Projects/script/Julia/TestPackage1/src/precompile_example.jl",force=true)
┌ Warning: it is not recommended to create an app without a preexisting manifest
└ @ PackageCompilerX C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\PackageCompilerX.jl:485
[ Info: PackageCompilerX: creating base system image (incremental=false)...
[ Info: PackageCompilerX: creating system image object file, this might take a while...
[ Info: PackageCompilerX: creating system image object file, this might take a while...
C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\embedding_wrapper.c:4:10: fatal error: string.h: No such file or directory
    4 | #include <string.h>
      |          ^~~~~~~~~~
compilation terminated.
ERROR: failed process: Process(`gcc '-DJULIAC_PROGRAM_LIBNAME="TestPackage1.dll"' -m64 -o TestPackage1 'C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\embedding_wrapper.c' TestPackage1.dll -O2 -std=gnu99 '-IC:\Users\philip\AppData\Local\Julia-1.3.1\include\julia' '-LC:\Users\philip\AppData\Local\Julia-1.3.1\bin' -Wl,--stack,8388608 -Wl,--export-all-symbols -ljulia -lopenlibm`, ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] #run#565(::Bool, ::typeof(run), ::Cmd) at .\process.jl:440
 [3] run at .\process.jl:438 [inlined]
 [4] #create_executable_from_sysimg#9(::String, ::String, ::typeof(PackageCompilerX.create_executable_from_sysimg)) at C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\PackageCompilerX.jl:560
 [5] #create_executable_from_sysimg at .\none:0 [inlined]
 [6] (::PackageCompilerX.var"#7#8"{String,Bool,Bool,String,String})() at C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\PackageCompilerX.jl:536
 [7] cd(::PackageCompilerX.var"#7#8"{String,Bool,Bool,String,String}, ::String) at .\file.jl:93
 [8] #create_app#6(::String, ::Array{String,1}, ::Bool, ::Bool, ::Bool, ::Bool, ::typeof(create_app), ::String, ::String) at C:\Users\Philip\.julia\packages\PackageCompilerX\49oDH\src\PackageCompilerX.jl:510
 [9] (::PackageCompilerX.var"#kw##create_app")(::NamedTuple{(:precompile_execution_file, :force),Tuple{String,Bool}}, ::typeof(create_app), ::String, ::String) at .\none:0
 [10] top-level scope at REPL[18]:1

julia>

I did a quick search in my WinRPM directory. The string.h is located,in my case, at:

C:\Julia-1.3.0\.julia\packages\WinRPM\BfpQI\deps\usr\x86_64-w64-mingw32\sys-root\mingw\lib\gcc\x86_64-w64-mingw32\8.2.0\include\ssp

And stdint.h at:

C:\Julia-1.3.0\.julia\packages\WinRPM\BfpQI\deps\usr\x86_64-w64-mingw32\sys-root\mingw\lib\gcc\x86_64-w64-mingw32\8.2.0\include

Maybe my approach is not so robust because of all these paths…