How do I create a binary from .jl files?

I’ve searched in vain for this. How do I create a binary (preferably statically linked) from .jl files? Does julia have a compiler and linker / class loader? All the introductory material I’ve found so far are for notebooks or simple scripts.

Does Julia have build tools? In the Java world there is Maven and Gradle. The Go language comes with its own build tool chain. What does Julia have?

A related question is what is the typical way to structure source files for a Julia project?

3 Likes

Static compilation is still in the early stages for Julia. I’ve never tried but my understanding is that it takes some work to accomplish. You could look at StaticCompiler.jl, it may have what you need.

As for your second question, if you are asking what is a typical directory structure for a Julia package then you can create one using the generate function.

In the REPL enter package mode by typing ] as the first character on the command line. Then type generate followed by the name you want to give the package. It will create a typical package directory.

In package mode type ? for help on the commands available.

Are you planning to do large scale software development? Check out VSCode if you haven’t already. It’s got good support for Julia coding.

Is a package the way I would create a binary? In Go there’s a typical directory structure with a main package and a func main() as the entry point. Normally there will be multiple other packages as well to create one binary.

What would be the entry point in a Julia program with multiple files? Would there be only one package or multiple packages?

I would be using Intellij for my IDE which has a Julia plugin (not sure how good it is).

https://pkgdocs.julialang.org/dev/creating-packages/

it depends on what you wanna do. In Julia, users are usually not invoking main() from terminal, so most packages don’t have a “entry point” per-se.

People simply do

using Upstream1
# or
import Upstream2

in their downstream package if they need to.

1 Like

You might also want to take a look at https://github.com/JuliaLang/PackageCompiler.jl

5 Likes

Also check out this discourse thread, StaticTools, about tools for statically compiling Julia.

1 Like

@brianguenter I really would not at all recommend StaticCompiler.jl or StaticTools.jl to a new user.These packages are still in very early days and are more like proofs of concept than anything. Suggesting them to a new user is just going to end in frustration and wasted time.

@DWSchulze first of all, welcome. Julia is not really designed for static compilation. Rather, Julia is more designed around REPL driven interactive workflows. I would strongly suggest you think about whether that’s something you actually need.

If you do need static compilation, then I’d recommend looking into PackageCompiler.jl. It is quite reliable, but it takes a long time to compile and also produces very large binaries. But, if you need it for something like sending a binary to another machine, or reducing / eliminating your startup compilation overhead for an important piece of code, then it can be quite useful.

15 Likes

I had just assumed that Julia was a mature language being at v 1.7+. Thanks for setting me straight on that.

I’ll do some more work with the Go ecosystem for ML and see how it stacks up against the Julia and Python ecosystems.

Just out of curiosity: Why do you need a compiled binary while doing machine learning?

I have a feeling that this might be an instance of the XY problem. For example, if you think that you need to build a binary in order for your code to run at the speed of compiled C or Go, then that’s a misunderstanding.
Or if you need to call a Julia routine from some external C code (or vice versa) that is also possible to do without explicitly building a binary.

11 Likes

Julia is a mature language. StaticCompiler.jl is a package that is immature.

12 Likes

Notebooks and repls are clunky. I can iterate much faster from an IDE like Intellij. And code laid out as one big script is difficult to test and think about. It’s just bad design.

2 Likes

I have to disagree. Each time I’ve tried Julia I find things that break from one minor version to another. And lacking a decent build chain and dependency management looks pretty immature.

@Mason - I could try driving code from a REPL (or from Intellij), but how are julia projects laid out? Is a Julia program composed of one package or multiple packages? I don’t mean third party packages (using). Do you typically lay out a Julia program in different directories and packages?

I’m used to how Go and Java code is organized, but haven’t been able to find any guidance on how Julia program code is organized.

1 Like

AFAIK, the problem that Julia tries to solve on creating binaries while compiling all possible methods for all type combinations has not been done by any language so far. The problem looks so mighty that I fear it will never be completely solved.

1 Like

This does indeed seem to be a XY Problem.
IDE support, and breaking things up into multiple files is unrelated to compiling a binary.

I use VS-code all the time, as my IDE,
and i work on packages that are typically broken up into 6-12 files.
And on larger production systems that are broken up into dozens of packages and net hundreds of files.

I have never compiled a julia binary.
(keep meaning to, but never got around to it).

8 Likes

It’s a bit like getting in an electric car and saying “okay, but where do I put the gasoline?” The answer is that you don’t, but that’s okay and your user experience can be pretty much the same or better.

Fortunately though, getting static compilation working in Julia is easier than sticking a combustion engine in a Tesla.

7 Likes

Yeap, hopefully :smile:

1 Like

@oxinabox - That sounds like what I want to do.

How are the large production systems organized so Julia can find all of your packages and files? I won’t be writing a large system, but I don’t want my project layout to become a problem as I add packages and files.

Thanks.

This would be an example for a Julia program (not a package): https://github.com/ufechner7/KiteViewer

ufechner@tuxedi:~/repos/KiteViewer$ tree
.
├── create_sys_image.sh
├── data
│   ├── kite.obj
│   ├── KiteViewer.desktop.template
│   ├── KiteViewer.png
│   ├── log_8700W_8ms.arrow
│   ├── log_8700W_8ms.csv
│   ├── log_8700W_8ms.csv.xz
│   ├── settings.yaml
│   ├── system.yaml
│   └── Test_flight.arrow
├── doc
│   ├── KiteViewer.png
│   ├── notes.txt
│   ├── SystemImage.md
│   ├── Tests.md
│   └── Windows.md
├── install.sh
├── kiteviewer_pure.sh
├── kiteviewer.sh
├── LICENSE
├── MakieSys-1.6-main.so
├── MakieSys-1.7-main.so
├── Manifest-1.6.toml.default
├── Manifest-1.7.toml.default
├── Manifest.toml
├── Manifest.toml.bak
├── performance.sh
├── Project.toml
├── README.md
├── run_julia.sh
├── src
│   ├── common.jl
│   ├── Components.jl
│   ├── DAE_Example.jl
│   ├── FPC.jl
│   ├── Importer.jl
│   ├── KiteViewer.jl
│   ├── KiteViewerPure.jl
│   ├── KiteViewers.jl
│   ├── Plot2D.jl
│   └── RTSim.jl
├── test
│   ├── create_sys_image.jl
│   ├── runtests.jl
│   ├── test_for_precompile.jl
│   ├── test_load_log.jl
│   ├── TestNLsolve.jl
│   ├── test_rt_sim.jl
│   ├── TestWindProfile.jl
│   └── update_packages.jl
└── TODO.txt

It will never break because I store the Manifest files in the Project. It includes an installer and a script to create a system image. But this is just the top level program, I am in the process of moving more and more code to separate packages.

4 Likes

For organization, break your project up into separate packages with well defined functionality of limited scope. Then have specific project scripts (with a Project.toml file to version the dependencies) to tie them together for actual tasks you need to do. Pkg.activate creates such a project in any folder, adding packages will add to it.

All of you packages can just go in your .julia/dev folder, and also should be on github or similar, and registered if they are broadly useful. Registering also makes local management easier, because you get package versioning and resolution.

This structure scales pretty well, Some of my projects have nested dependencies of my own packages that are 5 packages deep, because I keep building on old work, or abstracting new lower level packages instead of duplicating the code.

When you have your tools in packages you can use Pkg.add to add them to a specific project, even for specific branches and commits if you have multiple projects that are not in sync. Dependency management in Julia is actually amazing. You can have multiple exactly reproducible projects in use at the same time, even containing 3rd party C++ libraries. And packages and even external libraries in them can be at different versions and it will still work.

On the other hand, Julias’ binary compilation story is very immature, basically everyone will acknowledge that. Because Julia is primarily a dynamic language attempting to also be compiled. Its a much harder problem than compiling go.

But the REPL is first class. You should suspend judgement and give it a try.

8 Likes