bake-toolkit 1.8.0.1 → 2.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/bake +14 -53
- data/bin/bakery +50 -43
- data/bin/createVSProjects +3 -3
- data/doc/cmd/install.html +1 -5
- data/doc/cmd/usecmd.html +29 -5
- data/doc/dyk/lint.html +21 -4
- data/doc/dyk/tipps.html +0 -6
- data/doc/eclipse/import.html +3 -1
- data/doc/eclipse/import/Import.png +0 -0
- data/doc/eclipse/use.html +8 -5
- data/doc/further/change.html +134 -1
- data/doc/further/issues.html +1 -0
- data/doc/further/wish.html +24 -21
- data/doc/index.html +1 -1
- data/doc/syntax/subst.html +8 -1
- data/doc/syntax/syntax.html +42 -14
- data/lib/bake/cache.rb +51 -59
- data/lib/bake/config/loader.rb +289 -0
- data/lib/bake/libElement.rb +134 -0
- data/lib/bake/mergeConfig.rb +1 -1
- data/lib/bake/model/language.rb +1 -1
- data/lib/bake/model/loader.rb +88 -0
- data/lib/bake/model/metamodel.rb +24 -16
- data/lib/bake/model/metamodel_ext.rb +9 -4
- data/lib/bake/options/options.rb +222 -0
- data/lib/bake/options/showConfigNames.rb +44 -0
- data/lib/bake/options/showDoc.rb +19 -0
- data/lib/bake/options/showLicense.rb +9 -0
- data/lib/bake/options/showToolchains.rb +39 -0
- data/lib/bake/options/usage.rb +54 -0
- data/lib/bake/process_output.rb +10 -0
- data/lib/bake/subst.rb +105 -40
- data/lib/bake/toolchain/clang.rb +44 -0
- data/lib/bake/toolchain/colorizing_formatter.rb +125 -0
- data/lib/bake/toolchain/diab.rb +53 -0
- data/lib/bake/toolchain/errorparser/diab_compiler_error_parser.rb +40 -0
- data/lib/bake/toolchain/errorparser/diab_linker_error_parser.rb +41 -0
- data/lib/bake/toolchain/errorparser/error_parser.rb +71 -0
- data/lib/bake/toolchain/errorparser/gcc_compiler_error_parser.rb +35 -0
- data/lib/bake/toolchain/errorparser/gcc_linker_error_parser.rb +35 -0
- data/lib/bake/toolchain/errorparser/greenhills_compiler_error_parser.rb +32 -0
- data/lib/bake/toolchain/errorparser/greenhills_linker_error_parser.rb +44 -0
- data/lib/bake/toolchain/errorparser/keil_compiler_error_parser.rb +40 -0
- data/lib/bake/toolchain/errorparser/keil_linker_error_parser.rb +30 -0
- data/lib/bake/toolchain/errorparser/lint_error_parser.rb +34 -0
- data/lib/bake/toolchain/errorparser/process_output.rb +3 -0
- data/lib/bake/toolchain/errorparser/ti_compiler_error_parser.rb +30 -0
- data/lib/bake/toolchain/errorparser/ti_linker_error_parser.rb +30 -0
- data/lib/bake/toolchain/gcc.rb +49 -0
- data/lib/bake/toolchain/gcc_param.rb +7 -0
- data/lib/bake/toolchain/greenhills.rb +52 -0
- data/lib/bake/toolchain/keil.rb +55 -0
- data/lib/bake/toolchain/lint.rb +20 -0
- data/lib/bake/toolchain/provider.rb +136 -0
- data/lib/bake/toolchain/ti.rb +47 -0
- data/lib/bake/util.rb +27 -15
- data/lib/bakery/buildPattern.rb +1 -1
- data/lib/bakery/model/language.rb +1 -1
- data/lib/bakery/model/loader.rb +56 -0
- data/lib/bakery/model/metamodel.rb +1 -1
- data/lib/bakery/options/options.rb +87 -0
- data/lib/bakery/toBake.rb +10 -6
- data/lib/blocks/block.rb +225 -0
- data/lib/blocks/blockBase.rb +155 -0
- data/lib/blocks/commandLine.rb +25 -0
- data/lib/blocks/compile.rb +382 -0
- data/lib/blocks/docu.rb +28 -0
- data/lib/blocks/executable.rb +143 -0
- data/lib/blocks/has_execute_command.rb +31 -0
- data/lib/blocks/library.rb +78 -0
- data/lib/blocks/lint.rb +53 -0
- data/lib/blocks/makefile.rb +87 -0
- data/lib/blocks/showIncludes.rb +114 -0
- data/lib/common/abortException.rb +4 -0
- data/lib/common/cleanup.rb +9 -0
- data/lib/common/exit_helper.rb +28 -0
- data/lib/common/ext/file.rb +88 -0
- data/lib/common/ext/stdout.rb +45 -0
- data/lib/common/ide_interface.rb +194 -0
- data/lib/common/options/option.rb +13 -0
- data/lib/common/options/parser.rb +59 -0
- data/lib/common/process.rb +64 -0
- data/lib/common/utils.rb +52 -0
- data/lib/{bake → common}/version.rb +3 -10
- data/lib/multithread/job.rb +44 -0
- data/lib/tocxx.rb +201 -932
- data/lib/vs/options.rb +3 -2
- data/license.txt +47 -22
- metadata +90 -30
- data/bin/bake-doc +0 -12
- data/lib/alias/loader.rb +0 -56
- data/lib/alias/model/language.rb +0 -22
- data/lib/alias/model/metamodel.rb +0 -29
- data/lib/bake/loader.rb +0 -92
- data/lib/bake/options.rb +0 -421
- data/lib/bakery/loader.rb +0 -57
- data/lib/bakery/options.rb +0 -105
- data/lib/option/parser.rb +0 -73
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bake
|
2
|
+
|
3
|
+
module Blocks
|
4
|
+
|
5
|
+
module HasExecuteCommand
|
6
|
+
|
7
|
+
def executeCommand(commandLine, ignoreStr=nil)
|
8
|
+
puts commandLine if not Bake.options.verboseLow
|
9
|
+
puts "(executed in '#{@projectDir}')" if Bake.options.verboseHigh
|
10
|
+
cmd_result = false
|
11
|
+
output = ""
|
12
|
+
begin
|
13
|
+
Dir.chdir(@projectDir) do
|
14
|
+
cmd_result, output = ProcessHelper.run([commandLine], true)
|
15
|
+
end
|
16
|
+
rescue Exception=>e
|
17
|
+
puts e.message
|
18
|
+
puts e.backtrace if Bake.options.debug
|
19
|
+
end
|
20
|
+
|
21
|
+
if (cmd_result == false and (not ignoreStr or not output.include?ignoreStr))
|
22
|
+
Bake.formatter.printError("Command \"#{commandLine}\" failed", @config)
|
23
|
+
puts "(executed in '#{@projectDir}')" if not Bake.options.verboseHigh
|
24
|
+
raise SystemCommandFailed.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'blocks/blockBase'
|
2
|
+
|
3
|
+
module Bake
|
4
|
+
|
5
|
+
module Blocks
|
6
|
+
|
7
|
+
class Library < BlockBase
|
8
|
+
|
9
|
+
def initialize(block, config, referencedConfigs, tcs, compileBlock)
|
10
|
+
super(block,config, referencedConfigs, tcs)
|
11
|
+
@compileBlock = compileBlock
|
12
|
+
|
13
|
+
block.set_library(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def archive_name()
|
17
|
+
@archive_name ||= File.join([@output_dir, "lib#{@projectName}.a"])
|
18
|
+
end
|
19
|
+
|
20
|
+
def needed?
|
21
|
+
return false if Bake.options.linkOnly
|
22
|
+
return false if Bake.options.prepro
|
23
|
+
|
24
|
+
# lib
|
25
|
+
return "because library does not exist" if not File.exists?(archive_name)
|
26
|
+
|
27
|
+
aTime = File.mtime(archive_name)
|
28
|
+
|
29
|
+
# config
|
30
|
+
return "because config file has been changed" if aTime < File.mtime(@config.file_name)
|
31
|
+
return "because DefaultToolchain has been changed" if aTime < Bake::Config.defaultToolchainTime
|
32
|
+
|
33
|
+
# sources
|
34
|
+
@compileBlock.objects.each do |obj|
|
35
|
+
return "because object #{obj} does not exist" if not File.exists?(obj)
|
36
|
+
return "because object #{obj} is newer than executable" if aTime < File.mtime(obj)
|
37
|
+
end
|
38
|
+
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute
|
43
|
+
|
44
|
+
Dir.chdir(@projectDir) do
|
45
|
+
reason = needed?
|
46
|
+
return unless reason
|
47
|
+
|
48
|
+
prepareOutput(archive_name)
|
49
|
+
|
50
|
+
archiver = @tcs[:ARCHIVER]
|
51
|
+
|
52
|
+
cmd = Utils.flagSplit(archiver[:COMMAND], false) # ar
|
53
|
+
cmd += Bake::Utils::flagSplit(archiver[:FLAGS],true) # --all_load
|
54
|
+
cmd += archiver[:ARCHIVE_FLAGS].split(" ")
|
55
|
+
cmd << archive_name
|
56
|
+
cmd += @compileBlock.objects
|
57
|
+
|
58
|
+
success, consoleOutput = ProcessHelper.run(cmd, false, false)
|
59
|
+
process_result(cmd, consoleOutput, archiver[:ERROR_PARSER], "Creating #{archive_name}", reason, success)
|
60
|
+
|
61
|
+
check_config_file()
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def clean
|
66
|
+
Dir.chdir(@projectDir) do
|
67
|
+
if File.exist?@output_dir
|
68
|
+
puts "Deleting folder #{@output_dir}" if Bake.options.verboseHigh
|
69
|
+
FileUtils.rm_rf(@output_dir)
|
70
|
+
end
|
71
|
+
end unless Bake.options.filename
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
data/lib/blocks/lint.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'blocks/compile'
|
2
|
+
|
3
|
+
module Bake
|
4
|
+
module Blocks
|
5
|
+
class Lint < Compile
|
6
|
+
|
7
|
+
def initialize(block, config, referencedConfigs, tcs)
|
8
|
+
super(block,config, referencedConfigs, tcs)
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
Dir.chdir(@projectDir) do
|
13
|
+
compiler = @tcs[:COMPILER][:CPP]
|
14
|
+
calcSources
|
15
|
+
|
16
|
+
noFilesToLint = (@source_files.length == 0)
|
17
|
+
|
18
|
+
if Bake.options.lint_min >= 1 and Bake.options.lint_min >= @source_files.length
|
19
|
+
noFilesToLint = true
|
20
|
+
end
|
21
|
+
|
22
|
+
if Bake.options.lint_max >= 0 and Bake.options.lint_max < Bake.options.lint_min
|
23
|
+
noFilesToLint = true
|
24
|
+
end
|
25
|
+
|
26
|
+
if noFilesToLint
|
27
|
+
Bake.formatter.printInfo("No files to lint", @config)
|
28
|
+
else
|
29
|
+
@source_files = @source_files[Bake.options.lint_min..Bake.options.lint_max]
|
30
|
+
|
31
|
+
cmd = [compiler[:COMMAND]]
|
32
|
+
cmd += compiler[:COMPILE_FLAGS]
|
33
|
+
|
34
|
+
cmd += @include_array[:CPP]
|
35
|
+
cmd += @define_array[:CPP]
|
36
|
+
|
37
|
+
cmd += @tcs[:LINT_POLICY]
|
38
|
+
|
39
|
+
cmd += @source_files
|
40
|
+
|
41
|
+
printCmd(cmd, "Linting #{@source_files.length} file(s)...", nil, false)
|
42
|
+
success, consoleOutput = ProcessHelper.run(cmd, false)
|
43
|
+
process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], "Linting...", nil, success)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def clean
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'blocks/has_execute_command'
|
2
|
+
|
3
|
+
module Bake
|
4
|
+
module Blocks
|
5
|
+
|
6
|
+
class Makefile
|
7
|
+
include HasExecuteCommand
|
8
|
+
|
9
|
+
MAKE_COMMAND = "make"
|
10
|
+
MAKE_FILE_FLAG = "-f"
|
11
|
+
MAKE_DIR_FLAG = "-C"
|
12
|
+
MAKE_CLEAN = "clean"
|
13
|
+
|
14
|
+
def initialize(config, referencedConfigs, block)
|
15
|
+
@config = config
|
16
|
+
@projectDir = config.get_project_dir
|
17
|
+
@path_to = ""
|
18
|
+
@flags = adjustFlags("",config.flags) if config.flags
|
19
|
+
@makefile = config.name
|
20
|
+
@target = config.target != "" ? config.target : "all"
|
21
|
+
calcPathTo(referencedConfigs)
|
22
|
+
calcCommandLine
|
23
|
+
calcCleanLine
|
24
|
+
|
25
|
+
block.lib_elements[config.line_number] = [LibElement.new(LibElement::LIB_WITH_PATH, config.lib)] if config.lib != ""
|
26
|
+
end
|
27
|
+
|
28
|
+
def calcCommandLine
|
29
|
+
@commandLine = remove_empty_strings_and_join([
|
30
|
+
MAKE_COMMAND, @target,
|
31
|
+
@flags,
|
32
|
+
MAKE_DIR_FLAG, File.dirname(@makefile),
|
33
|
+
MAKE_FILE_FLAG, File.basename(@makefile),
|
34
|
+
@path_to])
|
35
|
+
end
|
36
|
+
|
37
|
+
def calcCleanLine
|
38
|
+
@cleanLine = remove_empty_strings_and_join([
|
39
|
+
MAKE_COMMAND, MAKE_CLEAN,
|
40
|
+
MAKE_DIR_FLAG, File.dirname(@makefile),
|
41
|
+
MAKE_FILE_FLAG, File.basename(@makefile),
|
42
|
+
@path_to])
|
43
|
+
end
|
44
|
+
|
45
|
+
def calcPathTo(referencedConfigs)
|
46
|
+
@path_to = ""
|
47
|
+
if @config.pathTo != ""
|
48
|
+
pathHash = {}
|
49
|
+
@config.pathTo.split(",").each do |p|
|
50
|
+
nameOfP = p.strip
|
51
|
+
dirOfP = nil
|
52
|
+
if referencedConfigs.include?nameOfP
|
53
|
+
dirOfP = referencedConfigs[nameOfP].first.get_project_dir
|
54
|
+
else
|
55
|
+
Bake.options.roots.each do |r|
|
56
|
+
absIncDir = r+"/"+nameOfP
|
57
|
+
if File.exists?(absIncDir)
|
58
|
+
dirOfP = absIncDir
|
59
|
+
break
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
if dirOfP == nil
|
64
|
+
Bake.formatter.printError("Project '#{nameOfP}' not found", @config)
|
65
|
+
ExitHelper.exit(1)
|
66
|
+
end
|
67
|
+
pathHash[nameOfP] = File.rel_from_to_project(File.dirname(@projectDir),File.dirname(dirOfP))
|
68
|
+
end
|
69
|
+
path_to_array = []
|
70
|
+
pathHash.each { |k,v| path_to_array << "PATH_TO_#{k}=#{v}" }
|
71
|
+
@path_to = path_to_array.join(" ")
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
def execute
|
77
|
+
executeCommand(@commandLine)
|
78
|
+
end
|
79
|
+
|
80
|
+
def clean
|
81
|
+
executeCommand(@cleanLine, "No rule to make target 'clean'.") unless Bake.options.filename
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Bake
|
2
|
+
module Blocks
|
3
|
+
class Show
|
4
|
+
|
5
|
+
def self.secureShow
|
6
|
+
begin
|
7
|
+
yield
|
8
|
+
rescue Exception => e
|
9
|
+
if (not SystemExit === e)
|
10
|
+
puts e
|
11
|
+
puts e.backtrace
|
12
|
+
ExitHelper.exit(1)
|
13
|
+
else
|
14
|
+
raise e
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.includes
|
20
|
+
secureShow {
|
21
|
+
Blocks::ALL_COMPILE_BLOCKS.sort.each do |projName, blocks|
|
22
|
+
print projName
|
23
|
+
incs = []
|
24
|
+
blocks.each { |block| incs += block.include_list }
|
25
|
+
incs.uniq.each { |inc| print "##{inc}" }
|
26
|
+
print "\n"
|
27
|
+
end
|
28
|
+
ExitHelper.exit(0) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.readInternalIncludes(mainConfig, mainBlock, mainTcs)
|
32
|
+
intIncs = []
|
33
|
+
iinc = mainConfig.defaultToolchain.internalIncludes
|
34
|
+
Dir.chdir(Bake.options.main_dir) do
|
35
|
+
if (iinc)
|
36
|
+
|
37
|
+
cppExe = File.which(mainTcs[:COMPILER][:CPP][:COMMAND])
|
38
|
+
cExe = File.which(mainTcs[:COMPILER][:C][:COMMAND])
|
39
|
+
asmExe = File.which(mainTcs[:COMPILER][:ASM][:COMMAND])
|
40
|
+
archiverExe = File.which(mainTcs[:ARCHIVER][:COMMAND])
|
41
|
+
linkerExe = File.which(mainTcs[:LINKER][:COMMAND])
|
42
|
+
|
43
|
+
iname = mainBlock.convPath(iinc)
|
44
|
+
if iname != ""
|
45
|
+
if not File.exists?(iname)
|
46
|
+
Bake.formatter.printError("InternalIncludes file #{iname} does not exist", iinc)
|
47
|
+
ExitHelper.exit(1)
|
48
|
+
end
|
49
|
+
IO.foreach(iname) do |x|
|
50
|
+
x.sub!("$(CPPPath)", cppExe)
|
51
|
+
x.sub!("$(CPath)", cExe)
|
52
|
+
x.sub!("$(ASMPath)", asmExe)
|
53
|
+
x.sub!("$(ArchiverPath)", archiverExe)
|
54
|
+
x.sub!("$(LinkerPath)", linkerExe)
|
55
|
+
add_line_if_no_comment(intIncs,x)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
return intIncs
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.readInternalDefines(mainConfig, mainBlock)
|
64
|
+
intDefs = {:CPP => [], :C => [], :ASM => []}
|
65
|
+
Dir.chdir(Bake.options.main_dir) do
|
66
|
+
mainConfig.defaultToolchain.compiler.each do |c|
|
67
|
+
if (c.internalDefines)
|
68
|
+
dname = mainBlock.convPath(c.internalDefines)
|
69
|
+
if dname != ""
|
70
|
+
if not File.exists?(dname)
|
71
|
+
Bake.formatter.printError("InternalDefines file #{dname} does not exist", c.internalDefines)
|
72
|
+
ExitHelper.exit(1)
|
73
|
+
end
|
74
|
+
IO.foreach(dname) {|x| add_line_if_no_comment(intDefs[c.ctype],x) }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
return intDefs
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.includesAndDefines(mainConfig, mainTcs)
|
83
|
+
secureShow {
|
84
|
+
mainBlock = Blocks::ALL_BLOCKS[Bake.options.main_project_name+","+Bake.options.build_config]
|
85
|
+
|
86
|
+
intIncs = readInternalIncludes(mainConfig, mainBlock, mainTcs)
|
87
|
+
intDefs = readInternalDefines(mainConfig, mainBlock)
|
88
|
+
|
89
|
+
|
90
|
+
Blocks::ALL_COMPILE_BLOCKS.sort.each do |projName, blocks|
|
91
|
+
|
92
|
+
blockIncs = []
|
93
|
+
blockDefs = {:CPP => [], :C => [], :ASM => []}
|
94
|
+
blocks.each do |block|
|
95
|
+
blockIncs += block.include_list
|
96
|
+
[:CPP, :C, :ASM].each { |type| blockDefs[type] += block.tcs[:COMPILER][type][:DEFINES] }
|
97
|
+
end
|
98
|
+
|
99
|
+
puts projName
|
100
|
+
puts " includes"
|
101
|
+
(blockIncs + intIncs).uniq.each { |i| puts " #{i}" }
|
102
|
+
[:CPP, :C, :ASM].each do |type|
|
103
|
+
puts " #{type} defines"
|
104
|
+
(blockDefs[type] + intDefs[type]).uniq.each { |d| puts " #{d}" }
|
105
|
+
end
|
106
|
+
puts " done"
|
107
|
+
|
108
|
+
end
|
109
|
+
ExitHelper.exit(0) }
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bake
|
2
|
+
|
3
|
+
class ExitHelper
|
4
|
+
@@exit_code = 0
|
5
|
+
|
6
|
+
def self.set_exit_code(val)
|
7
|
+
@@exit_code = val
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.exit_code()
|
11
|
+
@@exit_code
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.reset_exit_code()
|
15
|
+
@@exit_code = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.exit(val)
|
19
|
+
@@exit_code = val
|
20
|
+
Kernel::exit
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
at_exit do
|
27
|
+
exit(Bake::ExitHelper.exit_code)
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'common/utils'
|
2
|
+
|
3
|
+
class File
|
4
|
+
|
5
|
+
SLASH = '/'
|
6
|
+
|
7
|
+
def self.is_absolute?(filename)
|
8
|
+
filename[0] == SLASH or filename[1] == ':'
|
9
|
+
end
|
10
|
+
|
11
|
+
# seems both are rel or both are abs in all cases
|
12
|
+
def self.rel_from_to_project(from,to,endWithSlash = true)
|
13
|
+
|
14
|
+
return nil if from.nil? or to.nil?
|
15
|
+
|
16
|
+
toSplitted = to.split('/')
|
17
|
+
fromSplitted = from.split('/')
|
18
|
+
|
19
|
+
max = [toSplitted.length, fromSplitted.length].min
|
20
|
+
|
21
|
+
|
22
|
+
return nil if max < 1
|
23
|
+
|
24
|
+
i = 0
|
25
|
+
|
26
|
+
# path letter in windows may be case different
|
27
|
+
toIsWindowsAbs = false
|
28
|
+
if toSplitted[0].length > 1 and fromSplitted[0].length > 1
|
29
|
+
toIsWindowsAbs = toSplitted[0][1] == ':'
|
30
|
+
i = 1 if toIsWindowsAbs and fromSplitted[0][1] == ':' and toSplitted[0][0].downcase == fromSplitted[0][0].downcase
|
31
|
+
end
|
32
|
+
|
33
|
+
if (toIsWindowsAbs and i==0)
|
34
|
+
res = to
|
35
|
+
res += "/" if endWithSlash
|
36
|
+
return res
|
37
|
+
end
|
38
|
+
|
39
|
+
while i < max
|
40
|
+
break if toSplitted[i] != fromSplitted[i]
|
41
|
+
i += 1
|
42
|
+
end
|
43
|
+
j = i
|
44
|
+
|
45
|
+
res = []
|
46
|
+
while i < fromSplitted.length
|
47
|
+
res << ".."
|
48
|
+
i += 1
|
49
|
+
end
|
50
|
+
|
51
|
+
while j < toSplitted.length
|
52
|
+
res << toSplitted[j]
|
53
|
+
j += 1
|
54
|
+
end
|
55
|
+
|
56
|
+
if res.length == 0
|
57
|
+
return ""
|
58
|
+
end
|
59
|
+
|
60
|
+
res = res.join('/')
|
61
|
+
res += "/" if endWithSlash
|
62
|
+
res
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def self.add_prefix(prefix, file)
|
67
|
+
if not prefix or is_absolute?(file)
|
68
|
+
file
|
69
|
+
else
|
70
|
+
prefix + file
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.which(cmd)
|
75
|
+
return "" if not cmd
|
76
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
77
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
78
|
+
exts.each { |ext|
|
79
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
80
|
+
if File.executable?(exe) && !File.directory?(exe)
|
81
|
+
return File.dirname(exe.gsub(/[\\]/,'/'))
|
82
|
+
end
|
83
|
+
}
|
84
|
+
end
|
85
|
+
return ""
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|