Last active
August 29, 2015 14:19
-
-
Save shoover/f2dc72737d043be56861 to your computer and use it in GitHub Desktop.
A hacky C# script compiler runner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# C# script compiler and runner | |
# | |
# Hash headers at the top can be used to override default csc options. This is | |
# mainly for specifying references, but you can pass anything csc.exe takes. | |
# Extra plain .cs files should work if you put them last. | |
# | |
# References are tricky because practically they have to be in the application | |
# directory, which we stash away in HOME/.csx/something. Any reference csx can | |
# find (relative to the working directory) it will copy, which should work. | |
# | |
# Usage: | |
# > ruby csx.rb filechecker.csx test.txt # test.txt false | |
# | |
# Example: | |
# # /r:liby.dll | |
# # /r:redist/libx.dll | |
# using System.IO; | |
# public static class FileChecker | |
# { | |
# public static void Main(string[] argv) | |
# { | |
# Console.WriteLine("{0}: {1}", argv[0], File.Exists(argv[0])); | |
# } | |
# } | |
# | |
# For additional CLI calling convenience, edit csx_auto_file.reg with your paths. | |
# Then you can invoke scripts on the command line: `filechecker.csx test.txt`. | |
# | |
# Inspired by Lawrence's java_launcher: | |
# https://github.com/lkesteloot/java_launcher/blob/master/java_launcher | |
require 'fileutils' | |
include FileUtils | |
require 'digest' | |
cache = File.join(Dir.home, '.csx') | |
mkdir_p cache | |
script = ARGV.shift | |
script_base = File.basename(script, '.*') | |
script_dir = File.dirname(script) | |
# Use the hash of the .csx script and this script to determine if we | |
# need to recompile. | |
sum = Digest::MD5.hexdigest(File.read(script) + File.read(__FILE__))[0...8] | |
bin = File.join(cache, script_base) | |
src_base = script_base + '.cs' | |
src = File.join(bin, src_base) | |
exe = File.join(bin, script_base + '.exe') | |
cached_sum = bin + '/sum' | |
def dirty_refs?(refs, bin) | |
refs.any? do |ref| | |
target = File.join(bin, File.basename(ref)) | |
File.exists?(ref) && !File.exists?(target) || File.mtime(ref) != File.mtime(target) | |
end | |
end | |
# Options for locating referenced assemblies: | |
# - copy references to the cache directory and do dirty checking | |
# - strong-named references only | |
# - find in the GAC | |
# - specify in codeBase config | |
# - store the exe in the script dir and require the user to reference DLLs that | |
# live there | |
# | |
# For now, we copy DLLs and dirty check. | |
refs = [] | |
File.open script, 'r' do |fin| | |
# Process references so we can check if any DLLs changed. | |
while (line = fin.gets.chomp) =~ /^# / | |
refs << $1 if line =~ /^# \/r(?:eference)?:(.*)/ and File.exists?($1) | |
end | |
end | |
if !File.exists?(exe) or sum != File.read(cached_sum) or dirty_refs?(refs, bin) | |
mkdir_p bin | |
cp script, bin | |
File.write(cached_sum, sum) | |
args = [] | |
File.open script, 'r' do |fin| | |
File.open src, 'w' do |fout| | |
# Process headers by appending them as csc command line parameters. | |
# References are processed separately so we can locate files with | |
# relative paths but copy to the bin directory with a flat structure. | |
while (line = fin.gets.chomp) =~ /^# / | |
arg = $' | |
args << arg unless line =~ /^# \/r(?:eference)?:(.*)/ and File.exists?($1) | |
end | |
# Copy the code to a .cs file. | |
fout.puts line | |
while (line = fin.gets) != nil | |
fout.puts line | |
end | |
end | |
end | |
# Copy any DLLs referenced | |
rm Dir["#{bin}/*.dll"] | |
refs.each do |ref| | |
cp ref, bin, :preserve => true | |
end | |
# Compile | |
Dir.chdir bin do | |
# /lib:#{script_dir} | |
ref_bases = refs.collect{|r|'/r:'+File.basename(r)}.join(' ') | |
cmd = "csc #{ref_bases} /nologo /t:exe #{args.join(' ')} #{src_base}" | |
puts cmd | |
system cmd or fail "csx compilation failed" | |
end | |
puts | |
$stdout.flush | |
end | |
# Run it | |
system "#{exe} #{ARGV.join(' ')}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Windows Registry Editor Version 5.00 | |
[HKEY_CLASSES_ROOT\csx_auto_file] | |
@="" | |
[HKEY_CLASSES_ROOT\csx_auto_file\shell] | |
[HKEY_CLASSES_ROOT\csx_auto_file\shell\open] | |
[HKEY_CLASSES_ROOT\csx_auto_file\shell\open\command] | |
@="c:\\ruby193\\bin\\ruby.exe c:\\usr\\local\\script\\csx.rb \"%1\" %*" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment