Skip to content

Instantly share code, notes, and snippets.

@locatw
Created March 16, 2014 14:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save locatw/9583870 to your computer and use it in GitHub Desktop.
Save locatw/9583870 to your computer and use it in GitHub Desktop.
rakefile for C++ source build.
# coding: utf-8
require 'fileutils'
### 定数 ###
COMPILER = "g++"
CPPFLAGS = %w{}
LDFLAGS = %w{}
INC_DIRS = []
LIB_DIRS = []
TARGET = "app"
SRC_ROOT = "."
BUILD_ROOT = "./.build"
OBJ_ROOT = BUILD_ROOT + "/objs"
DEP_ROOT = BUILD_ROOT + "/deps"
EXE_EXT = '.exe'
SRC_EXT = '.cpp'
OBJ_EXT = '.o'
DEP_EXT = '.mf'
SRCS = FileList["#{SRC_ROOT}/**/*#{SRC_EXT}"]
LIBS = FileList[]
### メソッド定義 ###
def CPPFLAGS.to_option_s
self.join(' ')
end
def LDFLAGS.to_option_s
self.join(' ')
end
def INC_DIRS.to_option_s
self.map{|dir| "-I\"#{dir}\""}.join(' ')
end
def LIB_DIRS.to_option_s
self.map {|dir| "-L\"#{dir}\""}.join(' ')
end
def change_root(path, from, to)
path.gsub(Regexp.new("\\A" + from), to)
end
# ソースファイル, オブジェクトファイル, 依存情報ファイルのパスを相互変換する
def convert_path(file, to)
ext = File.extname(file)
root_dir =
case ext
when SRC_EXT then SRC_ROOT
when OBJ_EXT then OBJ_ROOT
when DEP_EXT then DEP_ROOT
end
new_root, new_ext =
case to
when :source then [SRC_ROOT, SRC_EXT]
when :object then [OBJ_ROOT, OBJ_EXT]
when :depend then [DEP_ROOT, DEP_EXT]
end
change_root(file, root_dir, new_root).gsub(Regexp.new("\\#{ext}$"), new_ext)
end
def src_path(file)
convert_path(file, :source)
end
def obj_path(file)
convert_path(file, :object)
end
def dep_path(file)
convert_path(file, :depend)
end
def make_depfile(srcfile)
depfile = dep_path(srcfile)
objfile = obj_path(srcfile)
sh "#{COMPILER} #{CPPFLAGS.to_option_s} #{INC_DIRS.to_option_s} -MM -MT #{objfile} #{srcfile} -MF #{depfile}"
end
def load_depfile(depfile)
line = File.readlines(depfile).shift
obj, deps = line.split(':', 2)
deps = deps.split(' ').map{|s| s.strip}
return obj, deps
end
# 依存情報ファイルから依存ファイルリストを読み込んで返す
def dependencies(objfile)
depfile = dep_path(objfile)
# 必要なら依存情報ファイルを生成する
file(depfile).invoke
obj, deps = load_depfile(depfile)
objfile.include?(obj) ? deps : []
end
def cleanup(file_name)
rm_r file_name if File.exist?(file_name)
end
# オブジェクトファイルのリストを生成
OBJS = FileList[SRCS.map {|src| obj_path(src)}]
### タスク ###
task :default => "build"
desc "Setup build environment."
task :setup do
Dir.glob("#{SRC_ROOT}/**/").each do |srcdir|
[OBJ_ROOT, DEP_ROOT].each do |root|
dir = change_root(srcdir, SRC_ROOT, root)
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
end
end
end
desc "Build application."
task :build do |t|
task(:setup).invoke
task(TARGET).invoke
end
desc "Rebuild application."
task :rebuild do |t|
task(:clobber).invoke
task(:build).invoke
end
desc "Remove temporary files."
task :clean do
["#{BUILD_ROOT}/**/*#{OBJ_EXT}", "#{BUILD_ROOT}/**/*#{DEP_EXT}"].each do |file_name|
cleanup(file_name)
end
end
desc "Remove all generated files."
task :clobber => :clean do
["#{TARGET}#{EXE_EXT}", BUILD_ROOT].each do |file_name|
cleanup(file_name)
end
end
### 依存関係 ###
file TARGET => [OBJS, LIBS].flatten do |t|
sh "#{COMPILER} #{LIB_DIRS.to_option_s} #{LDFLAGS.to_option_s} -o #{TARGET} #{t.prerequisites.join(' ')}"
end
rule OBJ_EXT => [proc{|objfile| dependencies(objfile)}] do |r|
objfile = r.name
srcfile = src_path(objfile)
sh "#{COMPILER} #{CPPFLAGS.to_option_s} #{INC_DIRS.to_option_s} -o #{objfile} -c #{srcfile}"
end
rule DEP_EXT do |r|
make_depfile(src_path(r.name))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment