Windows でシンボリックリンクを作成してまわる Ruby スクリプトのメモ

32bit 用と 64bit 用に分けてビルドが必要な .NET ソリューションがあるんだけど、諸悪の根源である SQLite のライブラリを差し替えてビルドするのが面倒なので、ディレクトリを2つ作ることにした。

32bit 用と 64bit 用にディレクトリを分けて、32bit 用ディレクトリのソースに 64bit 用ディレクトリからシンボリックリンクを張ってやれば、別々にビルドできる。

さいわい、アセンブリの出力先はソリューションのルート直下に BIN ディレクトリを作り、そこに出力するようになっていた。32bit 用でビルドしたやつを 64bit 用で上書きしてしまう、といのは避けられそうだ。

手動でシンボリックリンクを張ってまわるのは面倒だし、後でまた同じ作業をするかもしれないので、Ruby でスクリプトを書いてみた。ちなみに動作環境は Windows Vista 以降。

# coding: utf-8
require "fileutils"

ROOT_DIR = File.expand_path(File.dirname(__FILE__))
SRC_DIR = File.join(ROOT_DIR, "32bit")
DEST_DIR = File.join(ROOT_DIR, "64bit")
SUB_DIRS = [
  "Sample",
  "Common",
  "Tools",
  "Lib",
]

def copy_dir(src, dest)
  # コピー先のディレクトリが無ければ作成する
  unless File.exist?(dest)
    FileUtils.mkpath(dest)
  end

  pattern = File.join(src, "*")
  Dir.glob(pattern) do |path|
    # ファイル名またはディレクトリ名を取得
    basename = File.basename(path)

    if basename.upcase == "SQLITE"
      # 再帰的にコピー
      FileUtils.cp_r(path, dest)
    elsif File.file?(path)
      # ファイルは単純にコピー
      FileUtils.cp(path, dest)
    elsif ["BIN", "BIND"].include?(basename.upcase) == false
      # ディレクトリはシンボリックリンクを作成
      # BIN と BIND は無視
      link = File.join(dest, basename)
      command = "cmd.exe /C mklink /D \"#{link}\" \"#{path}\""
      system(command)
    end
  end
end

SUB_DIRS.each do |dir|
  src = File.join(SRC_DIR, dir)
  dest = File.join(DEST_DIR, dir) 
  copy_dir(src, dest)
end

Windows だと File.symlink は使えないので、cmd.exe の mklink コマンドを呼び出している。mklink を使っているので、管理者で実行すること。