Dealing with dependencies

What’s the recommended way of dealing with dependencies? Theres some weird stuff you have to deal with when using external packages and I just don’t know what’s the best solution, specially when i’m making a library instead of a program.

When I use external packages I vendor them as git submodules in a subfolder so the file structure would look something like this:

example/
├── mycode.odin
└── pkgs/
    ├── a/
    │   ├── somecode.odin
    │   ├── README.md
    │   ├── LICENSE
    │   └── b/
    │       ├── othercode.odin
    │       ├── README.md
    │       └── LICENSE
    ├── b/
    │   ├── othercode.odin
    │   ├── README.md
    │   └── LICENSE
    └── c/
        ├── src/
        │   └── otherothercode.odin
        ├── README.md
        └── LICENSE
README.md
LICENSE

I don’t really like having project files like the license and readme with the code, in a program I just move the odin files to a src directory, but in a library that would mean to import it you would actually import the src folder (like in package c) and it’s not clear if you can move the files inside src to c.

Also, if you use 2 dependencies and one of them use the other (in the example a uses b) what do you do? Do you just have duplicates of the same package? This could be solved by everyone agreeing to make an extra collection for dependencies and everyone using the same name for it but that’s not going to happen.

So far, from my usage, I’d recommend the 2 following options.

Assuming a, b, and c are all separate libraries …

example/
├── a/
│   ├── somecode.odin
│   ├── README.md
│   ├── LICENSE
├── b/
│   ├── othercode.odin
│   ├── README.md
│   └── LICENSE
├── c/
│   ├── otherothercode.odin
│   ├── README.md
│   └── LICENSE
└── MyCode Root
    ├──mycode.odin
    ├──README.md
    └──LICENSE

mycode.odin will import ...
import "../a"
import "../b"
import "../c"

b will import ...
import "../a"

Or using the libraries as “shared” or a collection

odin/shared/
├── a/
│   ├── somecode.odin
│   ├── README.md
│   ├── LICENSE
├── b/
│   ├── othercode.odin
│   ├── README.md
│   └── LICENSE
└── c/
    ├── otherothercode.odin
    ├── README.md
    └── LICENSE

example/
├──mycode.odin
├──README.md
└──LICENSE

mycode.odin will import ...
import "shared:a"
import "shared:b"
import "shared:c"

b will import ...
import "shared:a"

And if you prefer README.md and LICENSE to not be in same folder as code, then make a subfolder in a, b, c, named “Docs” or similar, and place them there.

But a, b and c aren’t mine, I cant control how they’re organized or how they import other packages without forking them, and at that point theyre not dependencies

i ran into the same problem and unfortunately, no matter what you do, you can’t deal with this problem without modifying the dependency’s source code in a minor way

  1. put all your dependencies in one directory
  2. change all the import directives to import the package from that directory
  3. collection:NAME=DIR compiler directive helps a bit with this (check in odin help build)

thankfully, it isn’t too inconvenient to update the dependencies’ code because i usually update them manually anyway

even though i don’t agree with this architecture, or this design decision, i’m pretty sure that the author of the language wants it to be like this, so people aren’t abusing microdependencies and package managers and what not

In this case, I’d keep them how they are organized, to reduce too many changes to imports. Also, assuming the second instance of b in your example was created and not from original source, I’d recommend the following. Use aliases to get around directory names from importing “src”.

example/
│  └ MyCodeRoot
│       ├── mycode.odin
│       ├──README.md
│       └──LICENSE
└── 3rdParty/
    ├── a/
    │   ├── somecode.odin
    │   ├── README.md
    │   ├── LICENSE
    │   └── b/
    │       ├── othercode.odin
    │       ├── README.md
    │       └── LICENSE
    └── c/
        ├── src/
        │   └── otherothercode.odin
        ├── README.md
        └── LICENSE
mycode imports ...
import a "../3rdParty/a"
import b "../3rdParty/a/b"
import c "../3rdParty/c/src"

This means my code cant be imported correctly and it will have the same problem as using src. Its not that big of a deal because if aliases but its still annoying and shouldnt be a thing

I think it’s still possible so I’m gonna give it one more try. The key is the main code has it’s own folder, and none of the dependencies as sub-directories. In Odin, a package is a folder, not the files. From there I suppose it’s a matter of taste. So say you wanted to make your project portable, so others could import it into theirs. I might try the following. Lets call the portable project “example” and a project that imports it “myproject”. I’m also leaving a, b, c as is, assuming that’s how they came.

example/
├── build_scripts.sh / .bat
├── README.md
├── LICENSE
├── example/
│   └── example.odin
└── imports/
    ├── a/
    │   ├── somecode.odin
    │   ├── README.md
    │   ├── LICENSE
    │   └── b/
    │       ├── othercode.odin
    │       ├── README.md
    │       └── LICENSE
    ├── b/
    │   ├── othercode.odin
    │   ├── README.md
    │   └── LICENSE
    └── c/
        ├── src/
        │   └── otherothercode.odin
        ├── README.md
        └── LICENSE

example.odin imports ...
import a "../../imports/a"
import b "../../imports/b" or import "../../imports/a/b" - which-ever
import c "../../imports/c/src"

Then I add it to my project as …

myproject/
├── build_scripts.sh / .bat
├── README.md
├── LICENSE
├── myproject/
│   └── myproject.odin
└── imports/
    ├──example/
    ├── build_scripts.sh / .bat
    ├── README.md
    ├── LICENSE
    ├── example/
    │   └── example.odin
    └── imports/
        ├── a/
        │   ├── somecode.odin
        │   ├── README.md
        │   ├── LICENSE
        │   └── b/
        │       ├── othercode.odin
        │       ├── README.md
        │       └── LICENSE
        ├── b/
        │   ├── othercode.odin
        │   ├── README.md
        │   └── LICENSE
        └── c/
            ├── src/
            │   └── otherothercode.odin
            ├── README.md
            └── LICENSE

myproject.odin imports ...
import example "../imports/example/example"

From here, I can just cd into /myproject and either use a build script or do ‘odin build myproject’. Similarly, I could cd into /myproject/imports/example and the run those scripts to setup dependent binaries, etc. If everything is setup to be directory relative, it should work.

Why would I have an example subdirectory? Its doing nothing. In the end the solution is just what I was doing