How to translate bash to .bat

OK, found out why. I’m calling Julia through a batch file. If I call the exe directly then yes, it prints the version number.

C:\Users\joaqu>C:\programs\julia-1.8\bin\julia.exe --version
julia version 1.8.0-beta3

Already found out how to extract the version number from the version string: How to extract part of a string in Windows batch file? - Super User

I’m calling Julia through a batch file as well (that’s what a .bat is, right?)

Yes.

Yes. I have two scripts, one that creates the system image, and one the starts Julia with the correct parameter to make use of the system image.

But because the system image works only with a specific Julia version I include the version number in the image name. In this way I can switch between different Julia versions and it always loads the correct system image.

I even found a way to test my .bat file on Linux:

wine cmd

Very happy :slight_smile:

Is it possible to install Julia in wine?

Is it the content of the bat file then? Mine is:

@echo off
echo.
C:\Users\ngudat\AppData\Local\Programs\Julia-1.7.2\bin\julia.exe %*

(I have no idea how any of this works, just copy pasted from somewhere on the internet - I believe the %* at the end might be responsible for passing along arguments?)

Yes, likely a lot works, but not all (just keep in mind even, if with superficial testing works, always a possibility not all implemented/tested):

Note, Julialang has a Wine label, so they want it to work, but as you can see it’s a problem with (upstream) wine, not Julia. It would always be a problem with wine, as it’s responsible for the conversion from Windows API.

Conversely, Linux Julia builds work in WSL [2], and again there might be bugs in Windows WSL, but I find it more likely to work, since they’re not trying to support a huge kernel API, that is a moving target, or rather it is, but they have the Linux kernel so not reimplementing from scratch. I understand Julia under WSL can sometimes be faster tan the native Windows Julia build (but that’s a problem with the Windows API not Julia).

I’ve been copying mine version-after-version and some (all?) of it is no longer necessary but it was at a certain time. This oi what I have

@ echo off

call C:\programs\WPy64-31020\env2.bat

set pato=C:\programs\ImageMagick;C:\MinGW64\msys64\usr\bin;C:\MinGW64\mingw64\bin;
set path=%pato%;%path%

C:\programs\julia-1.8\bin\julia.exe --sysimage-native-code=yes

Indeed. Adding that %* to mine also prints the version number.

1 Like

Finished my translation (fully tested, but only works if your package is registered):

@echo off
REM This script creates a julia system image with a name that
REM contains the Julia version, e.g. kps-image-1.7.dll
REM It should be placed in the bin folder of the project.
REM It assumes that the following files exist:
REM test/update_packages.jl
REM test/create_sys_image.jl

REM determine basename of current directory
for /F "delims=" %%i in ("%cd%") do set basename=%%~ni

if %basename%==bin cd ..
for /f "delims=" %%i in ('julia --version') do set version_string=%%i
for /f "tokens=3 delims= " %%a in ("%version_string%") do set version=%%a

set julia_major=%version:~0,3%
set image=kps-image-%julia_major%.dll

IF EXIST "bin/%image%" (
  move bin/kps-image-%julia_major%.dll bin/kps-image-%julia_major%.so.bak
)

echo Updating packages...
if EXIST "Manifest.toml" (
    move Manifest.toml Manifest.toml.bak
)

julia --project -e "include(\"./test/update_packages.jl\");"
julia --project -e "using Pkg; Pkg.precompile()"
julia --project -e "include(\"./test/create_sys_image.jl\");"
move kps-image_tmp.so bin/kps-image-%julia_major%.dll
julia --project -e "using Pkg; Pkg.precompile()"
1 Like

Why not write the script in Julia? Then it can be portable to Windows, and you don’t need a second (or third) language.

I thought about it, but I also need a script to launch Julia in the first place, so I also need to rewrite this bash script:

#!/bin/bash
if [[ $(basename $(pwd)) == "bin" ]]; then
    cd ..
fi

julia_version=$(julia --version | awk '{print($3)}')
julia_major=${julia_version:0:3}

export EDITOR="gedit"

if test -f "bin/kps-image-${julia_major}.so"; then
    echo "Found system image!"
    julia -J  bin/kps-image-${julia_major}.so -t 1 --project
else
    julia --project
fi

And if I would replace this script with a Julia script, I guess latency and memory consumption would be significantly higher.

Finally, you cannot fully replace bash or bat or whatever scripts to start Julia itself because if you want to start Julia with parameters you need a script. This would become unnecessary only if Julia

  • would allow to use a config file to configure the launch options
  • and Julia would be able to load a version specific system image automatically

Here the translation of the run_julia script to .bat for Windows users:

@echo off
REM This script launches julia and loads a version specific
REM system image from the folder bin if it exists.
REM The name of the system image must be similar to
REM kps-image-1.7.dll
REM It launches julia with one thread.

REM determine basename of current directory
for /F "delims=" %%i in ("%cd%") do set basename=%%~ni

if %basename%==bin cd ..
for /f "delims=" %%i in ('julia --version') do set version_string=%%i
for /f "tokens=3 delims= " %%a in ("%version_string%") do set version=%%a

set julia_major=%version:~0,3%
set image=kps-image-%julia_major%.dll

set EDITOR="code"

IF EXIST "bin/%image%" (
    echo Found system image!
    julia -J  bin/kps-image-%julia_major%.so -t 1 --project
) else julia --project

tested! :slight_smile:

Why is that easier than just running a Julia script (which can launch additional Julia processes as needed, see below)?

Surely any differences here are negligible compared to the cost of creating a system image.

Sure you can:

julia> run(`$(joinpath(Sys.BINDIR, Sys.iswindows() ? "julia.exe" : "julia")) --version`)
julia version 1.7.1
Process(`/Applications/Julia-1.7.app/Contents/Resources/julia/bin/julia --version`, ProcessExited(0))

You can literally do everything in Julia that you would do in a shell script (except more easily and portably), including launching additional julia processes, with the added advantage that Julia knows its own path.

Well, but I cannot:

  1. launch a Julia script just by typing its name
  2. launch Julia with multiple threads from a script that runs on one thread

Sure you can. At least on Unix, you can put #!/path/to/julia at the top, exactly as you would with a shell script (to avoid having to do bash foo.sh).

Otherwise, you have to type julia foo.jl, but why is a few extra characters a big deal for a script like this?

Sure you can. As I said above, you can launch additional julia processes from a Julia script, just as you would launch julia processes from a bash script.

1 Like

Well, on Linux you can do that, but - as far as I know - not on Windows.
Furthermore the path to Julia is system dependent, and if you want to write generic code I would not know what to put there.
And as I said, it is not only about the script that creates a system image, but also about the script that launches julia and loads the correct system image…

Created a feature request: Julia should read a config file when launching · Issue #45455 · JuliaLang/julia · GitHub

Sure, on Windows you could instead write a one-line foo.bat script that runs julia foo.jl. A lot easier than porting a complicated shell script to .bat and maintaining both.

Why is easier to find the path to a .bat or .sh script than a path to Julia? Why not just put julia in your path, or a link to Julia in the directory of your script, or…?

Registering a julia script file type/extension in Windows

Suggested here → How to write a program as a Julia package? - #26 by MA_Laforge
repo here → GitHub - ma-laforge/JuliaScripting.jl

In short, Windows allows you to register a file type, say *.jl_script to be executed with Julia in order to run. A sample file could be:

#!JLScript -iq --startup-file=no --project=@SomeGlobalEnvironment
using ModuleFrom_SomeGlobalEnvironment

result = ModuleFrom_SomeGlobalEnvironment.run_important_tasks()
display(result)

:DONE

Comments

  • (Doesn’t actually need to use some global environment - but practical in terms of getting a stable Julia run environment)
  • In the working example I provided, I pattern mach #!JLScript and pass the remaining arguments to the julia command.
  • But if you want to be cross-compatible with how Linux shell scripts work, this could be changed to match some #!/path/to/julia pattern instead to match what @stevengj suggested to make julia scripts runnable on Unix/Linux.

What already works

  • Automatically loads the script using the desired, CLEAN, environment (starts with a clean JULIA_LOAD_PATH - see install_files/launch_julia_script.ps1.).
  • Right now, my code *auto-registers an “Excecute with Julia vX” Exprlorer menu item for the .jl_script type (though I’m pretty certain I am using Win-XP Legacy registry settings).
  • You can launch .jl_script files using RMB from explorer.

*auto-registers: when you call JuliaScripting.install()

image

What’s missing.

  • Probably would be better to use newer methodology/registry settings if you are better at deciphering MS docs than I am.
  • If you can figure out how to make this “Execute with Julia vX” item the default: then executing any .jl_script file from PowerShell or cmd will automatically run the script as intended.

Try it out for yourself: You can launch any .txt file from Windows PowerShell by typing in its the file name at the prompt. Doing so gets windows to figure out which “default program/action” to use to launch the .txt file.

2 Likes