読者です 読者をやめる 読者になる 読者になる

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

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 を使っているので、管理者で実行すること。