🐥

神話のプログラム言語 Odin 外部ライブラリのセットアップ編

2024/11/06に公開

表題の前に、11月からOdinのフォーラムサイトが立ち上がりました。今までは、Discordでのやり取りで、正直、見ずらかったのですが、やっと独自のフォーラムが立ち上がりました。(私も英語が下手糞なりに、フォーラムに投稿してみました)
https://forum.odin-lang.org/

それでは、表題の件、説明を記載していきます。
Odinには、パッケージマネージャがありません。ですので、今回は、どうやって外部ライブラリのインストールをするのかについて記載します。

今回取り込む外部のライブラリは、HTTPとSQLiteライブラリです。Odinインストール時に標準でHTTP.requestがないと言う事に気付いて調べて見たら、外部ライブラリとして開発されていました。ですので、今回は、重要と思われる外部ライブラリのうち、HTTPとSQLiteライブラリを取り込む方法を説明をしたいと思います。

HTTPライブラリの設定

基本、外部のライブラリはOdin.exeが入ったフォルダ内の「shared」フォルダに設定されます。
まず、HTTPライブラリは、以下の場所から取り込む事が出来ます。
https://github.com/laytan/odin-http

$> mkdir E:/your_dir/odin/shared  <= sharedフォルダが無ければ作成
$> cd E:/your_dir/odin/shared
$> git clone https://github.com/laytan/odin-http http

Odinの実行モジュールが存在するフォルダに、sharedフォルダを作成します。(外部ライブラリは基本このフォルダ内で管理されます。)
その後、DOSコマンドで、git操作を行い取り込みます。
「shared」フォルダ内に「http」フォルダが作成されていれば、成功です。

ついでに、サンプルを実行して確認してみてください。
odin/shared/http/examples/client/main.odinファイルをプロジェクト直下に入れて正常に動作するか確認するだけです。

examples/client/main.odinを複製してimportを修正
package client_example

import "core:fmt"

// import "../../client" <- コメントアウトして、shared:http/clientに修正
import "shared:http/client"    // 外部ライブラリはshared:で始まるようにします

実行して、問題なくgoogleのトップページを読み込めれば、問題ありません。

SQLiteライブラリの設定

SQLiteはOdin用のラッパーが3つ存在します。Windows環境であれば、下記のライブラリが良いのかと思います。記述方法も他言語と同様ですので、わかりやすいです。
下記のライブラリは、WindowsとLinuxはサポートされていましたが、Macはまだサポートされていません。(静的ライブラリの指定をすれば、Macでも動作するとは思います。)
https://github.com/flysand7/odin-sqlite3

$> cd e:/your_temp_dir   <= テンポラリフォルダに移動して取り込みを行います
$> git clone https://github.com/flysand7/odin-sqlite3 sqlite3
$> cd sqlite3
    以下のVCコンパイラを実行する前に、PATHが設定されているか確認する事
$> cl /nologo /c amalgamation/sqlite3.c -Fo:sqlite3/bin/sqlite3.obj
$> lib /nologo sqlite3/bin/sqlite3.obj /out:"sqlite3/bin/sqlite3.lib"

まず、テンポラリフォルダに移動します。次にgitで「sqlite3」フォルダが作成されているか確認し、「sqlite3」に移動します。最後に、Visual Studio C++ 2002でコンパイルするのですが、パスが通ってなければ、「C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2022\Visual Studio Tools\VC」フォルダに移動し、「x64 Native Tools Command Prompt for VS 2022」を実行すれば、powershellが起動し、そのpowershell内で実行できるはずです。
出来上がったsqlite3.libが存在するか確認します。

$> cd ..
$> copy sqlite3 E:/your_dir/odin/shared  <= sqlite3フォルダをsharedフォルダに丸ごとコピー
$> cd E:/your_dir/odin/shared/sqlite3
$> copy sqlite3_wrap/wrapper.odin .

「sqlite3」フォルダを「shared」フォルダにコピーし、sqlite3_wrap/wrapper.odinを上位フォルダにコピーします。(import時に、import "shared:sqlite3/sqlite3_wrap"と記載するのが嫌だったので。)

wrapper.odin
// import sqlite "../sqlite3"
import sqlite "sqlite3"
  • ディレクトリ構成
    下の構成になってれば、問題ありません。
shared -+- sqlite3 -+- sqlite3 -+- bin -+- sqlite3.lib
                    |           +- sqlite3.odin
                    +- wrapper.odin
  • プログラムを作成し、動作確認をしてみる
    プロジェクト直下に「sql01」フォルダを作成し、以下のmain.odinを作成
sql01/main.odin
package main

import "core:os"
import "core:fmt"
import sqlite "shared:sqlite3"  // sharedフォルダに配置すればshared:として記載可能

main :: proc() {
  DB_FILE :: "test.db"
  db, status := sqlite.open(DB_FILE)
  if status != nil {
    fmt.eprintf("Unable to open database '%s'(%v): %s", DB_FILE, status, sqlite.status_explain(status))
    os.exit(1)
  }

  // Do things with database
  sqlite.sql_exec(db, `
    DROP TABLE IF EXISTS users;
    `)
  sqlite.sql_exec(db, `
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name VARCHAR(64) NOT NULL,
        flag INTEGER NOT NULL
    );
    `)
  sqlite.sql_exec(db, `
    INSERT INTO users (name, flag) VALUES
        ('john', 1),
        ('mary', 0),
        ('alice', 1),
        ('test', 0),
        ('foo', 0),
        ('あいうえお', 0);
    `)
  query, _ := sqlite.sql_bind(db, `
    SELECT name, flag
    FROM users
    WHERE flag = ?1;
    `, false)

  for row in sqlite.sql_row(db, query, struct { name: string, ok: bool }) {
    fmt.printf("ROW: %v ==== %v %v\n", row, row.name, row.ok)
  }

  sqlite.close(db)
}

記述方法が従来のSQLite的なプログラム構文なので、こちらのライブラリがわかりやすいと思います。

$ odin run .\sql01\
ROW: {name = "mary", ok = false} ==== mary false
ROW: {name = "test", ok = false} ==== test false
ROW: {name = "foo", ok = false} ==== foo false
ROW: {name = "\u3042\u3044\u3046\u3048\u304a", ok = false} ==== あいうえお false

おわりに

パッケージマネージャがない分、細かな設定が面倒と思われますが、逆に考えれば、ライブラリの仮想環境も作成しやすい事になります。(言語のバージョン管理は出来ませんけどね。)

Discussion