1-- 2-- path.lua 3-- Path manipulation functions. 4-- Copyright (c) 2002-2014 Jason Perkins and the Premake project 5-- 6 7 8-- 9-- Appends a file extension to the path. Verifies that the extension 10-- isn't already present, and adjusts quotes as necessary. 11-- 12 13 function path.appendExtension(p, ext) 14 -- if the extension is nil or empty, do nothing 15 if not ext or ext == "" then 16 return p 17 end 18 19 -- if the path ends with a quote, pull it off 20 local endquote 21 if p:endswith('"') then 22 p = p:sub(1, -2) 23 endquote = '"' 24 end 25 26 -- add the extension if it isn't there already 27 if not path.hasextension(p, ext) then 28 p = p .. ext 29 end 30 31 -- put the quote back if necessary 32 if endquote then 33 p = p .. endquote 34 end 35 36 return p 37 end 38 39 path.appendextension = path.appendExtension 40 41 42 43-- 44-- Retrieve the filename portion of a path, without any extension. 45-- 46 47 function path.getbasename(p) 48 local name = path.getname(p) 49 local i = name:findlast(".", true) 50 if (i) then 51 return name:sub(1, i - 1) 52 else 53 return name 54 end 55 end 56 57 58-- 59-- Retrieve the directory portion of a path, or an empty string if 60-- the path does not include a directory. 61-- 62 63 function path.getdirectory(p) 64 local i = p:findlast("/", true) 65 if (i) then 66 if i > 1 then i = i - 1 end 67 return p:sub(1, i) 68 else 69 return "." 70 end 71 end 72 73 74-- 75-- Retrieve the drive letter, if a Windows path. 76-- 77 78 function path.getdrive(p) 79 local ch1 = p:sub(1,1) 80 local ch2 = p:sub(2,2) 81 if ch2 == ":" then 82 return ch1 83 end 84 end 85 86 87 88-- 89-- Retrieve the file extension. 90-- 91 92 function path.getextension(p) 93 p = path.getname(p) 94 local i = p:findlast(".", true) 95 if (i) then 96 return p:sub(i) 97 else 98 return "" 99 end 100 end 101 102 103 104-- 105-- Retrieve the filename portion of a path. 106-- 107 108 function path.getname(p) 109 local i = p:findlast("[/\\]") 110 if (i) then 111 return p:sub(i + 1) 112 else 113 return p 114 end 115 end 116 117 118 119 120-- 121-- Returns true if the filename has a particular extension. 122-- 123-- @param fname 124-- The file name to test. 125-- @param extensions 126-- The extension(s) to test. Maybe be a string or table. 127-- 128 129 function path.hasextension(fname, extensions) 130 local fext = path.getextension(fname):lower() 131 if type(extensions) == "table" then 132 for _, extension in pairs(extensions) do 133 if fext == extension then 134 return true 135 end 136 end 137 return false 138 else 139 return (fext == extensions) 140 end 141 end 142 143 144-- 145-- Returns true if the filename represents various source languages. 146-- 147 148 function path.isasmfile(fname) 149 return path.hasextension(fname, { ".s" }) 150 end 151 152 function path.iscfile(fname) 153 return path.hasextension(fname, { ".c" }) 154 or path.isasmfile(fname) -- is this really right? 155 or path.isobjcfile(fname) -- there is code that depends on this behaviour, which would need to change 156 end 157 158 function path.iscppfile(fname) 159 return path.hasextension(fname, { ".cc", ".cpp", ".cxx" }) 160 or path.isobjcppfile(fname) -- is this really right? 161 or path.iscfile(fname) 162 end 163 164 function path.isobjcfile(fname) 165 return path.hasextension(fname, { ".m" }) 166 end 167 168 function path.isobjcppfile(fname) 169 return path.hasextension(fname, { ".mm" }) 170 end 171 172 function path.iscppheader(fname) 173 return path.hasextension(fname, { ".h", ".hh", ".hpp", ".hxx" }) 174 end 175 176 177-- 178-- Returns true if the filename represents a native language source file. 179-- These checks are used to prevent passing non-code files to the compiler 180-- in makefiles. It is not foolproof, but it has held up well. I'm open to 181-- better suggestions. 182-- 183 184 function path.isnativefile(fname) 185 return path.iscfile(fname) 186 or path.iscppfile(fname) 187 or path.isasmfile(fname) 188 or path.isobjcfile(fname) 189 or path.isobjcppfile(fname) 190 end 191 192 193-- 194-- Returns true if the filename represents an OS X framework. 195-- 196 197 function path.isframework(fname) 198 return path.hasextension(fname, ".framework") 199 end 200 201 202--- 203-- Is this a type of file that can be linked? 204--- 205 206 function path.islinkable(fname) 207 return path.hasextension(fname, { ".o", ".obj", ".a", ".lib", ".so" }) 208 end 209 210 211 212-- 213-- Returns true if the filename represents an object file. 214-- 215 216 function path.isobjectfile(fname) 217 return path.hasextension(fname, { ".o", ".obj" }) 218 end 219 220 221-- 222-- Returns true if the filename represents a Windows resource file. This check 223-- is used to prevent passing non-resources to the compiler in makefiles. 224-- 225 226 function path.isresourcefile(fname) 227 return path.hasextension(fname, ".rc") 228 end 229 230-- 231-- Returns true if the filename represents a Windows idl file. 232-- 233 234 function path.isidlfile(fname) 235 return path.hasextension(fname, ".idl") 236 end 237 238 239-- 240-- Takes a path which is relative to one location and makes it relative 241-- to another location instead. 242-- 243 244 function path.rebase(p, oldbase, newbase) 245 p = path.getabsolute(path.join(oldbase, p)) 246 p = path.getrelative(newbase, p) 247 return p 248 end 249 250 251 252-- 253-- Replace the file extension. 254-- 255 256 function path.replaceextension(p, newext) 257 local ext = path.getextension(p) 258 259 if not ext then 260 return p 261 end 262 263 if #newext > 0 and not newext:findlast(".", true) then 264 newext = "."..newext 265 end 266 267 return p:match("^(.*)"..ext.."$")..newext 268 end 269 270-- 271-- Get the default seperator for path.translate 272-- 273 274 function path.getDefaultSeparator() 275 if os.istarget('windows') then 276 return '\\' 277 else 278 return '/' 279 end 280 end 281