Cool news! Thanks to @simonbyrne, I’ve managed to compile a julia program on one mac, ship it to another mac that’s never even heard of julia, and certainly doesn’t have it installed, and it runs!! (And it’s a 10 year old computer!) Just wanted to share we’ve learned.

I did this using juliac.jl from PackageCompiler , but the below thoughts should apply to anyone trying to run julia with a different cpu target.

Here’s the things I learned:

1. code is compiled for a cpu target

When julia is invoked, all the code it compiles is compiled for a specific cpu target. By default, I believe it uses the " most specific" cpu target it can – presumably to get the best performance possible. On my machine at least, julia calls this the “native” cpu target. This default target, native is what is used when building its default sysimg ( sys.dylib ).

You can specify a different cpu target to use via the -C or --cpu-target command line option. The default is -Cnative . If you wanted to broaden the supported cpu architectures to, say, all Intel 64-bit cpus, you could invoke julia as julia -Cx86-64 .

2. ERROR: Target architecture mismatch. Please delete or regenerate sys.{so,dll,dylib}.

However, if you just change the target architecture, things don’t work. You’ll get the above error, complaining that the machine code its emitting and its sysimg ( sys.dylib ) weren’t built for the same architecture. But fret not! We can simply ask julia to ignore the sysimg. From julia -h :

--precompiled={yes|no} Use precompiled code from system image if available

3. --precompiled=no --compilecache=no

Cool, so now, this works! (but it’s slower of course)

$ julia -Cx86-64 --precompiled=no _ _ _ _(_)_ | A fresh approach to technical computing (_) | (_) (_) | Documentation: https://docs.julialang.org _ _ _| |_ __ _ | Type "?help" for help. | | | | | | |/ _ | | | | |_| | | | (_| | | Version 0.6.2 (2017-12-13 18:08 UTC) _/ |\__'_|_|_|\__'_| | Official http://julialang.org/ release |__/ | x86_64-apple-darwin14.5.0 julia> println("Hooray! it works!") Hooray! it works! julia> # cool, let's do some stuff julia> using UnicodePlots INFO: Precompiling module UnicodePlots. ERROR: Julia and the system image were compiled for different architectures. Please delete or regenerate sys.{so,dll,dylib}. ERROR: write: broken pipe (EPIPE) Stacktrace: [1] try_yieldto(::Base.##296#297{Task}, ::Task) at ./event.jl:189 [2] wait() at ./event.jl:234 [3] uv_write(::Base.PipeEndpoint, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:811 [4] unsafe_write(::Base.PipeEndpoint, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:832 [5] unsafe_write(::Base.PipeEndpoint, ::Base.RefValue{UInt8}, ::Int64) at ./io.jl:293 [6] write(::Base.PipeEndpoint, ::UInt8) at ./stream.jl:873 [7] write_as_tag(::Pipe, ::Int32) at ./serialize.jl:128 [8] serialize(::SerializationState{Pipe}, ::DataType) at ./serialize.jl:542 [9] serialize(::SerializationState{Pipe}, ::Expr) at ./serialize.jl:330 [10] create_expr_cache(::String, ::String, ::Array{Any,1}) at ./loading.jl:633 [11] compilecache(::String) at ./loading.jl:709 [12] _require(::Symbol) at ./loading.jl:497 [13] require(::Symbol) at ./loading.jl:405

— wait what!? So, --precompiled=no is enough to stop using the sysimg, but now we have the problem that the precompiled packages we’re importing were precompiled for the wrong target. So let’s turn off reading from the cached, precompiled packages as well. Right under that last flag in julia -h is this one:

--compilecache={yes|no} Enable/disable incremental precompilation of modules

Turning compilecache off will stop importing precompiled package images.

**** So putting those together, the correct way to invoke julia with a custom cpu target is as follows: ****

$ julia -Cx86-64 --precompiled=no --compilecache=no

Cool! So why did all this come up in the first place? Ah yes, I was trying to compile a distributable binary using juliac.jl . So it turns out juliac.jl already has a flag to specify the cpu target (also -C or --cpu-target ), which just gets forwarded along to julia when it’s invoked. So I just had to change juliac to also set --precompiled=no --compilecache=no when the user sets -C !

So, assuming that PR goes through, or some version of it, you should just be able to pass -C<target> or --cpu-target=<target> to juliac in order to compile for a different target.

If, as in my case, you want your compiled binary to support any intel-based mac, you would invoke it like this!:

julia ~/.julia/v0.6/PackageCompiler/juliac.jl -vaej --cpu-target=x86-64 examples/hello.jl

and it will fill examples/builddir with everything you need to run this binary on another computer:

the binary itself, hello the binary’s “sysimg”: hello.dylib all the julia libs it needs to link against: libjulia.dylib , libLLVM.dylib , libamd.dylib , etc…

(And it will also have the temporary file hello.o in there. You can delete that.)

And now you can simply zip up builddir and send it to another mac computer, and they can open it and run ./hello and

hello, world sin(0.0) = 0.0 ┌────────────────────────────────────────┐ 1 │⠀⠀⠀⠀⠀⠀⠀⡠⠊⠉⠉⠉⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⠘⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⡎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠼⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠬⢦⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⢤│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠇│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡎⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢆⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀│ -1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⣀⣀⣀⠔⠁⠀⠀⠀⠀⠀⠀│ └────────────────────────────────────────┘ 0 100

voila