Julia Local Packaging

Julia language logo

So I wanted to move all my common Julia code to a support dir. My filesystem has for 30+ years contained:

$HOME/
    Code/
        CodeC/
            foo/
                src/
                    bar.c
        CodeJava/
            foo/
                src/
                    com/
                        mdh/
                            bar/
                                Quux.java
        et fucking cetera

Build scripts for most languages expect something very like this, and it's easy to import one package's source into another, so I could put common code in a "Marklib" project, and get work done.

Making this happen in Julia was a lot more difficult. With a little help from Slack I made sense of the terrible package documentation for Julia and the incomprehensible errors, and wrote a script juliaMakePackage.zsh:

#!/bin/zsh
if [[ $# -ne 1 ]]; then
    echo "Usage: juliaMakePackage.zsh NAME"
    exit 1
fi
name=$1
devdir=$HOME/Code/CodeJulia
cd $devdir
julia -E "using Pkg; Pkg.activate(\".\"); Pkg.generate(\"${name}\")"
cd $name
git init
git add .
git commit -m "Initial commit"
cd ..
julia -E "using Pkg; Pkg.develop(PackageSpec(url=\"${devdir}/${name}\"))"

And then added the main dir and all packages I make to ~/.julia/config/startup.jl:

# startup.jl

push!(LOAD_PATH, pwd())
push!(LOAD_PATH, "$(homedir())/Code/CodeJulia")
push!(LOAD_PATH, "$(homedir())/Code/CodeJulia/Marklib")

println("READY $(pwd())")

Now finally I can:

% julia
READY /Users/mdh
julia> using Marklib
julia> Marklib.greet()
Hello World!
julia> 

And from there start putting in my libs. Each one needs a package and a startup entry; I may have to automate that by walking my code dir. Waste of several hours figuring that out.

Comments are closed.

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)

Mentions

  • I don't just drink coffee or booze, watch movies and Internet drama, and look cool. I code sometimes, too! Who knew?!
    Carrying on with my experiment in Julia, packaging has another step needed to make references. For instance, Ansi uses Geometry, so:
    Geometry/Project.toml:

    authors = ["Mark Damon Hughes "]
    name = "Geometry"
    uuid = "e3172796-a620-11e8-2cbf-612649bb77f8"
    version = "0.1.0"

    [deps]

    Ansi/Project.toml:

    authors = ["Mark Damon Hughes "]
    name = "Ansi"
    uuid = "72992c94-a620-11e8-3d05-55611ea0dbd0"
    version = "0.1.0"

    [deps]

    Geometry = "e3172796-a620-11e8-2cbf-612649bb77f8"

    Ansi/Manifest.toml:

    [[Geometry]]
    repo-rev = "master"
    repo-url = "/Users/mdh/Code/CodeJulia/Geometry"
    uuid = "e3172796-a620-11e8-2cbf-612649bb77f8"
    version = "0.1.0"

    All the boldface code is what I wrote/copy-pasted, the rest is generated by juliaMakePackage.zsh. I may go ahead and make a tool to link projects, because it's so error-prone. In fact, I cheated, and made a single Manifest.toml which I copy to all projects so far, and can replace whenever something updates.
    Anyway, this gets me to a nice state where I can write using Ansi in my project and it'll just find it. IIUC, if I move all the libraries to a public repository, I can just change the repo-url and the packages are downloaded into ~/.julia cache somewhere.
    I still haven't followed up on making a binary application; the more I look into that, the jankier it seems, more like something to defer until there's an official solution. Putting a real UI on it is also something to work on, but that's much more doable.
    Coding
    I've written a lot more code, over 1000 LOC, not just screwing around with packages. Mostly this is enjoyable, it's a nice systems programming language. The ugly parts haven't yet driven me insane, they're just things to work around or ignore. Far less frustrating than almost any other new language; Rusty Nail In Your Head and Go Fuck Yourself Its Google aren't my favorites.
    Strong typing really is a pain in the ass. Declare a variable or struct field foo, and it takes anything. Type it with foo::AbstractString, and you soon learn nothing is not a string; foo::Union{AbstractString,Nothing} is necessary to be nullable. Ick.
    Enumerations
    Enumerated types @enum are disappointing. They're a little smarter than C enums, but not as useful as Java enums. They just represent a value; but you have to cast them to Int every time you use them for their value, so too painful to use them as array indices. Or as characters, a thing I like a lot for debugging. And they're not easy to reflect on:
    julia> @enum Terrains begin
    Ter_Floor = Int('.')
    Ter_Wall = Int('#')
    end
    julia> Ter_Wall
    Ter_Wall::Terrains = 35
    julia> Int(Ter_Wall)
    35
    julia> Char(Int(Ter_Wall))
    '#': ASCII/Unicode U+0023 (category Po: Punctuation, other)
    julia> String(Char(Int(Ter_Wall)))
    ERROR: MethodError: no method matching String(::Char)
    julia> string(Char(Int(Ter_Wall)))
    "#"
    julia> # FFS
    julia> string(Ter_Floor)
    "Ter_Floor"
    julia> # Surprisingly easy!
    julia> instances(Terrains)
    (Ter_Floor::Terrains = 46, Ter_Wall::Terrains = 35)
    julia> # Shit, this is a named tuple, not a dictionary!
    julia> useful_instances = Dict()
    Dict{Any,Any} with 0 entries
    julia> for v in values(instances(Terrains))
    useful_instances[ string(v) ] = v
    useful_instances[ string(Char(Int(v))) ] = v
    end
    julia> useful_instances
    Dict{Any,Any} with 4 entries:
    "Ter_Floor" => Ter_Floor
    "Ter_Wall" => Ter_Wall
    "#" => Ter_Wall
    "." => Ter_Floor
    julia> # JFHC

    That was an annoying adventure to get a simple reverse lookup.