Step by step instruction and example how to create standalone applications for Windows with a [G]UI

After many hours of troubles, discussions and problems, gave this issue a final try and here is my solution.

I created a complete repository called “Juliastic” that provides these features:

  1. step by step instructions how to compile a DLL using PackageCompiler.
    Note: you must use Julia 1.10.x, with 1.11.4 I got a lot of issues I cannot explain.
  2. instructions how to test the DLL in a C program
  3. a small Lazarus example project that uses the DLL you will compile when following the above instructions

Summing it up over the last days, I had to spend many hours to resolve all issues.

Please give it a try and report any errors you encountered. Please also feel free to fix mistakes you see directly at the Juliastic Wiki.
If you have instructions for other UI widgetsets and OSes, you can also directly create a Wiki page.

22 Likes

I have one issue I did not yet understand: In the examples folder of PackageCompiler there is a file “additional_precompile.jl”. What does it do, why is it there and why can’t is content be directly part of “generate_precompile.jl”.

@ianshmean, @kristoffer.carlsson , do you know this maybe?

Glad you figured it out and thanks for reporting back! This is great.

It could be! There’s nothing fundamentally special about either mechanism for specifying what should get compiled. You can either generate such a list of precompile statements by hand, or semi-automatically (e.g., with an interactive julia --trace-compile=additional_precompile.jl session) or fully automatedly with the execution file. I’m sure the example is only using both so it can demonstrate both kwargs in its doc:

julia> create_library("MyLib", "MyLibCompiled";
                      lib_name="libinc",
                      precompile_execution_file="MyLib/build/generate_precompile.jl",
                      precompile_statements_file="MyLib/build/additional_precompile.jl",
                      header_files = ["MyLib/build/mylib.h"])

Neither of these kwargs are required; you can use both methods, one, or none. Use what works best for you!

3 Likes

Thanks. Now I need to understand what precompile(Tuple{typeof(MyLib.increment64), Clong})
actually does.

And last but not least to understand the concept of precompilation correctly. I mean in generate_precompile.jl a function is called 10 times in a row. Why that, why not just once, 4, 9 or 100 times?

It’s just telling Julia what functions to compile for which argument types (ahead of time). precompile(Tuple{typeof(MyLib.increment64), Clong}) means “compile MyLib.increment64(::Clong)”. It’s the mechanism to move Julia’s just-barely-ahead-of-time (JIT) compiler further ahead of time.

What you pass to precompile_execution_file could indeed be just a single iteration. Or maybe two. Whatever Julia compiles in the process of running that file, will effectively become a precompile directive like that. The more representative your precompiles are, the less time you’ll spend waiting for the JIT later on.

4 Likes

Thanks. I performed now some tests and the outcome is:

  • no matter of precompile() is run 10 times or the function is executed 10 times, the resulting library runs in both cases with the same speed
  • executing the function more than 5 times brings no benefit

I updated my repository accordingly.

Do you need a Codeberg account to do this?

great work, thanks.

Yes.
By the way, I recently discovered Codeberg as alternative to GitHub and it is working well (as far as I can tell after just 1 month of actively using it). It is organized the same way as e.g. KDE - a German assembly where everybody can become a member. So in contrast to GitHub and Gitlab, there is no big tech company behind it.

4 Likes

Thanks, this is certainly a step forward!

I didn’t see any mention of codesigning. This is a requirement if you intend to distribute executables. How do you handle it? Perhaps Windows is more lenient in that respect?

Thanks for having a look. Yes, I did not mention this because this is part of the release process of a program (e.g. on Windows you would sign the installer).

My instruction only covers the process of using the compiled DLL for another UI program. From then on the program can be developed as usual (creating installers, beta testing etc.) but this is independent of whether it contains a DLL created with Julia.

3 Likes

This has not been my experience on MacOS. I’m shipping libraries, not executables.

I have no access to MacOS.
That is why I setup a Wiki. I would be happy, if you

  • make a Codeberg login
  • click on the link for the MacOS Wiki page and create a new page
  • fill in the instructions for MacOS.

The aim is to help people. The information can later be put into other Wiki, official docs or whatever. Important is in my opinion to collect them at first.

1 Like

I can help write the instructions once I get it to work.

1 Like

Just for the records: I added now code that shows how Julia structs and tensors can be exported and used in C or Lazarus.