Created
March 16, 2014 14:14
-
-
Save locatw/9583870 to your computer and use it in GitHub Desktop.
rakefile for C++ source build.
This file contains 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
# 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