書き捨てコードのmake(rake)
ちょっと試したいコードを書くときに毎回コンパイラを呼ぶのは面倒。Makefileを書くのも面倒。
てなわけでRakeの習作。ソースコードにフラグを書き込んでおけば、それを利用してコンパイルしてくれる。
ソース
#====================================================================== # -*- ruby -*- #====================================================================== require 'rake/clean' #================================================== # Compiler Options #================================================== # warning flags C_AND_CPP_DEFAULT_FLAGS = [ "-Wall -Wextra -Wformat=2 -Wstrict-aliasing=2", "-Wcast-qual -Wcast-align -Wwrite-strings -Wconversion", "-Wfloat-equal -Wpointer-arith -Wswitch-enum" ].join(' ') CC = "gcc" CPP = "g++" CFLAGS = "#{C_AND_CPP_DEFAULT_FLAGS}" INCLUDES = "" LIBS = "" CPPFLAGS = "#{C_AND_CPP_DEFAULT_FLAGS} -Woverloaded-virtual -Weffc++" LDFLAGS = "" RAKE_OPTIONAL_VARIABLES = [ :CC, :CPP, :CFLAGS, :INCLUDES, :LIBS, :CPPFLAGS, :LDFLAGS, ] #================================================== # Files #================================================== SRCS = FileList["*.c"] + FileList["*.cpp"] OBJS = SRCS.ext('') CLEAN.include(OBJS) #================================================== # Utils #================================================== def get_compiler_option(line) re_base = "\\s*:\\s*(.*)$" RAKE_OPTIONAL_VARIABLES.each do |option| return [option, $~.captures[0].strip ] if line =~ /#{option.to_s}#{re_base}/i end nil end def search_compiler_options(src_file) options = Hash.new File.open(src_file, 'r') do |file| file.each_line do |line| option = get_compiler_option(line) options[option[0]] = option[1] if option != nil end end options end def define_cpp_make_rule(src_file) object_file = src_file.sub(/\.cpp/, '') options = search_compiler_options(src_file) cpp = (options[:CPP] ? options[:CPP] : CPP) cppflags = "#{CPPFLAGS} #{(options[:CPPFLAGS] ? options[:CPPFLAGS] : '' )}" includes = "#{INCLUDES} #{(options[:INCLUDES] ? options[:INCLUDES] : '' )}" ldflags = "#{LDFLAGS} #{(options[:LDFLAGS] ? options[:LDFLAGS] : '' )}" libs = "#{LIBS} #{(options[:LIBS] ? options[:LIBS] : '' )}" file object_file => src_file do |t| sh "#{cpp} #{cppflags} #{includes} #{ldflags} -o #{t.name} #{t.prerequisites[0]} #{libs}" end end def define_c_make_rule(src_file) object_file = src_file.sub(/\.c/, '') options = search_compiler_options(src_file) cc = (options[:CC] ? options[:CC] : CC) cflags = "#{CFLAGS} #{(options[:CFLAGS] ? options[:CFLAGS] : '')}" includes = "#{INCLUDES} #{(options[:INCLUDES] ? options[:INCLUDES] : '')}" ldflags = "#{LDFLAGS} #{(options[:LDFLAGS] ? options[:LDFLAGS] : '')}" libs = "#{LIBS} #{(options[:LIBS] ? options[:LIBS] : '')}" file object_file => src_file do |t| sh "#{cc} #{cflags} #{includes} #{ldflags} -o #{t.name} #{t.prerequisites[0]} #{libs}" end end #================================================== # Tasks #================================================== task :default => [:all] task :all => [:make_all_rule] + OBJS task :make_all_rule do SRCS.each do |src_file| case src_file when /\.cpp$/ define_cpp_make_rule(src_file) when /\.c$/ define_c_make_rule(src_file) else puts "no rule #{src_file}" end end end
デフォルトのフラグはbinary hacksを参考にした。
使い方
こんなファイルを用意して
- test.c
#if 0 ファイルのどこかにCFLAGS、LIBS、INCLUDES等を記録しておく LIBS : -lm #endif #include <stdio.h> #include <math.h> int main(void) { printf("%lf\n", sqrt(2.0)); return 0; }
rakeを実行
> rake (in /your/working/directory) gcc -Wall -Wextra -Wformat=2 -Wstrict-aliasing=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion\ -Wfloat-equal -Wpointer-arith -Wswitch-enum -o test test.c -lm