diff options
| author | OpportunityLiu <[email protected]> | 2019-06-18 18:10:48 +0800 |
|---|---|---|
| committer | OpportunityLiu <[email protected]> | 2019-06-18 18:10:48 +0800 |
| commit | 026a8aa6a02bf9c12790404b9c551abf3dfd261b (patch) | |
| tree | 13c9acd6bf397fbe8a1d0c121685693b9cffda34 | |
| parent | 9c8b83a61fce275edd3808c54f36ba368378fa5d (diff) | |
fix find_program & find_file
add path.splitenv
| -rw-r--r-- | tests/modules/path/test.lua | 27 | ||||
| -rw-r--r-- | xmake/core/base/path.lua | 41 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/lib/detect/find_file.lua | 36 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/lib/detect/find_program.lua | 47 | ||||
| -rw-r--r-- | xmake/modules/core/tools/nvcc.lua | 5 | ||||
| -rw-r--r-- | xmake/modules/detect/sdks/find_cuda.lua | 1 | ||||
| -rw-r--r-- | xmake/modules/detect/tools/find_nvcc.lua | 13 | ||||
| -rw-r--r-- | xmake/modules/lib/detect/find_cudadevices.lua | 38 | ||||
| -rw-r--r-- | xmake/platforms/linux/config.lua | 4 | ||||
| -rw-r--r-- | xmake/platforms/macosx/config.lua | 4 | ||||
| -rw-r--r-- | xmake/platforms/windows/config.lua | 4 | ||||
| -rw-r--r-- | xmake/rules/cuda/devlink/xmake.lua | 4 |
12 files changed, 148 insertions, 76 deletions
diff --git a/tests/modules/path/test.lua b/tests/modules/path/test.lua new file mode 100644 index 000000000..bba15810c --- /dev/null +++ b/tests/modules/path/test.lua @@ -0,0 +1,27 @@ +function test_splitenv_win(t) + if not is_host("windows") then + return + end + t:are_equal(path.splitenv(""), {}) + t:are_equal(path.splitenv("a"), {'a'}) + t:are_equal(path.splitenv("a;b"), {'a','b'}) + t:are_equal(path.splitenv(";;a;;b;"), {'a','b'}) + t:are_equal(path.splitenv('c:/a;c:\\b'), {'c:/a', 'c:\\b'}) + t:are_equal(path.splitenv('"a;aa;aa;;"'), {"a;aa;aa;;"}) + t:are_equal(path.splitenv('"a;aa;aa;;";bb;;'), {"a;aa;aa;;", 'bb'}) + t:are_equal(path.splitenv('"a;aa;aa;;";"a;cc;aa;;";bb;"d";'), {"a;aa;aa;;","a;cc;aa;;", 'bb', 'd' }) +end + +function test_splitenv_unix(t) + if is_host("windows") then + return + end + t:are_equal(path.splitenv(""), {}) + t:are_equal(path.splitenv("a"), {'a'}) + t:are_equal(path.splitenv("a:b"), {'a','b'}) + t:are_equal(path.splitenv("::a::b:"), {'a','b'}) + t:are_equal(path.splitenv('a%tag:b'), {'a','b'}) + t:are_equal(path.splitenv('a%tag:b%tag'), {'a','b'}) + t:are_equal(path.splitenv('a%tag:b%%tag%%'), {'a','b'}) + t:are_equal(path.splitenv('a%tag:b:%tag:'), {'a','b'}) +end
\ No newline at end of file diff --git a/xmake/core/base/path.lua b/xmake/core/base/path.lua index 9499799f1..c5ba7423b 100644 --- a/xmake/core/base/path.lua +++ b/xmake/core/base/path.lua @@ -118,6 +118,47 @@ function path.envsep() return xmake._HOST == "windows" and ';' or ':' end +-- split environment variable with `path.envsep()`, +-- also handles more speical cases such as posix flags and windows quoted pathes +function path.splitenv(env_path) + + -- check + assert(env_path) + + local result = {} + if xmake._HOST == "windows" then + while #env_path > 0 do + if env_path:startswith(path.envsep()) then + env_path = env_path:sub(2) + elseif env_path:startswith('"') then + -- path quoted with, can contain `;` + local p_end = env_path:find('"' .. path.envsep(), 2, true) or env_path:find('"$', 2) or (#env_path + 1) + table.insert(result, env_path:sub(2, p_end - 1)) + env_path = env_path:sub(p_end + 1) + else + local p_end = env_path:find(path.envsep(), 2, true) or (#env_path + 1) + table.insert(result, env_path:sub(1, p_end - 1)) + env_path = env_path:sub(p_end) + end + end + else + -- see https://git.kernel.org/pub/scm/utils/dash/dash.git/tree/src/exec.c?h=v0.5.9.1&id=afe0e0152e4dc12d84be3c02d6d62b0456d68580#n173 + -- no escape sequences, so `:` and `%` is invalid in environment variable + for _, v in ipairs(env_path:split(path.envsep(), { plain = true })) do + -- flag for shells, style `<path>%<flag>` + local flag = v:find("%", 1, true) + if flag then + v = v:sub(1, flag - 1) + end + if #v > 0 then + table.insert(result, v) + end + end + end + + return result +end + -- the last character is the path seperator? function path.islastsep(p) diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua index 1543d8bd6..2d64d6067 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua @@ -75,31 +75,37 @@ function sandbox_lib_detect_find_file.main(name, pathes, opt) -- format path for builtin variables if type(_path) == "function" then - local ok, results = sandbox.load(_path) + local ok, results = sandbox.load(_path) if ok then _path = results or "" - else + else raise(results) end - else - _path = vformat(_path) + elseif type(_path) == "string" then + if _path:match("^%$%($s*env%s+%S+%s*%)$") then + _path = path.splitenv(vformat(_path)) + else + _path = vformat(_path) + end end - -- find file with suffixes - if #suffixes > 0 then - for _, suffix in ipairs(suffixes) do - local filedir = path.join(_path, suffix) - local results = sandbox_lib_detect_find_file._find(filedir, name) + for _, _s_path in ipairs(table.wrap(_path)) do + -- find file with suffixes + if #suffixes > 0 then + for _, suffix in ipairs(suffixes) do + local filedir = path.join(_s_path, suffix) + local results = sandbox_lib_detect_find_file._find(filedir, name) + if results then + return results + end + end + else + -- find file in the given path + local results = sandbox_lib_detect_find_file._find(_s_path, name) if results then return results end end - else - -- find file in the given path - local results = sandbox_lib_detect_find_file._find(_path, name) - if results then - return results - end end end end diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua index d9cfbf484..bfc21f35c 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua @@ -63,7 +63,7 @@ function sandbox_lib_detect_find_program._check(program, opt) if type(opt.check) == "string" then ok, errors = os.runv(program, {opt.check}) else - ok, errors = sandbox.load(opt.check, program) + ok, errors = sandbox.load(opt.check, program) end -- check failed? print verbose error info @@ -84,29 +84,36 @@ function sandbox_lib_detect_find_program._find_from_pathes(name, pathes, opt) -- format path for builtin variables if type(_path) == "function" then - local ok, results = sandbox.load(_path) + local ok, results = sandbox.load(_path) if ok then _path = results or "" - else + else raise(results) end - else - _path = vformat(_path) + elseif type(_path) == "string" then + if _path:match("^%$%($s*env%s+%S+%s*%)$") then + _path = path.splitenv(vformat(_path)) + else + _path = vformat(_path) + end end - -- get program path - local program_path = nil - if os.isfile(_path) then - program_path = _path - elseif os.isdir(_path) then - program_path = path.join(_path, name) - end + for _, _s_path in ipairs(table.wrap(_path)) do - -- the program path - if program_path and (os.isexec(program_path) or os.isexec(program_path:split("%s")[1])) then - -- check it - if sandbox_lib_detect_find_program._check(program_path, opt) then - return program_path + -- get program path + local program_path = nil + if os.isfile(_s_path) then + program_path = _s_path + elseif os.isdir(_s_path) then + program_path = path.join(_s_path, name) + end + + -- the program path + if program_path and (os.isexec(program_path) or os.isexec(program_path:split("%s")[1])) then + -- check it + if sandbox_lib_detect_find_program._check(program_path, opt) then + return program_path + end end end end @@ -119,7 +126,7 @@ function sandbox_lib_detect_find_program._find_from_packages(name, opt) -- get the manifest file of package, .e.g ~/.xmake/packages/g/git/1.1.12/ed41d5327fad3fc06fe376b4a94f62ef/manifest.txt local manifest_file = path.join(package.installdir(), name:sub(1, 1), name, opt.version, opt.buildhash, "manifest.txt") if not os.isfile(manifest_file) then - return + return end -- get install directory of this package @@ -250,7 +257,7 @@ function sandbox_lib_detect_find_program.main(name, opt) end -- attempt to get result from cache first - local cacheinfo = cache.load(cachekey) + local cacheinfo = cache.load(cachekey) local result = cacheinfo[name] if result ~= nil and not opt.force then return utils.ifelse(result, result, nil) @@ -258,7 +265,7 @@ function sandbox_lib_detect_find_program.main(name, opt) -- find executable program checking = utils.ifelse(coroutine_running, name, nil) - result = sandbox_lib_detect_find_program._find(name, opt.pathes, opt) + result = sandbox_lib_detect_find_program._find(name, opt.pathes, opt) checking = nil -- cache result diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index 1ddcdc562..e72857a93 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -29,11 +29,8 @@ import("private.tools.nvcc.parse_deps") -- init it function init(self) - -- init culdflags - self:set("shared.culdflags", "-shared") - -- init cuflags - if not is_plat("windows") then + if not is_plat("windows", "mingw") then self:set("shared.cuflags", "-Xcompiler -fPIC") end diff --git a/xmake/modules/detect/sdks/find_cuda.lua b/xmake/modules/detect/sdks/find_cuda.lua index f9077a485..b7fb4911e 100644 --- a/xmake/modules/detect/sdks/find_cuda.lua +++ b/xmake/modules/detect/sdks/find_cuda.lua @@ -37,6 +37,7 @@ function _find_sdkdir() else table.insert(pathes, "/usr/local/cuda*/bin") end + table.insert(pathes, "$(env PATH)") -- attempt to find nvcc local nvcc = find_file(os.host() == "windows" and "nvcc.exe" or "nvcc", pathes) diff --git a/xmake/modules/detect/tools/find_nvcc.lua b/xmake/modules/detect/tools/find_nvcc.lua index 5b00510c1..5cd11e3dc 100644 --- a/xmake/modules/detect/tools/find_nvcc.lua +++ b/xmake/modules/detect/tools/find_nvcc.lua @@ -43,8 +43,12 @@ function main(opt) opt = opt or {} opt.parse = opt.parse or "V(%d+%.?%d*%.?%d*.-)%s" + local program = nil + -- find program - local program = find_program(opt.program or "nvcc", opt) + if opt.program then + program = find_program(opt.program, opt) + end -- not found? attempt to find program from cuda toolchains if not program then @@ -54,9 +58,14 @@ function main(opt) end end + -- not found? attempt to find program from PATH + if not program then + program = find_program("nvcc", opt) + end + -- find program version local version = nil - if program and opt and opt.version then + if program and opt.version then version = find_programver(program, opt) end diff --git a/xmake/modules/lib/detect/find_cudadevices.lua b/xmake/modules/lib/detect/find_cudadevices.lua index 8df34568e..63874685d 100644 --- a/xmake/modules/lib/detect/find_cudadevices.lua +++ b/xmake/modules/lib/detect/find_cudadevices.lua @@ -32,7 +32,7 @@ local _PRINT_SUFFIX = "<find_cudadevices>" -- filter stdout and stderr with _PRINT_SUFFIX function _get_lines(str) local result = {} - for _, l in ipairs(str:split('\n')) do + for _, l in ipairs(str:split("\n")) do if l:startswith(_PRINT_SUFFIX) then table.insert(result, l:sub(#_PRINT_SUFFIX + 1)) end @@ -57,8 +57,8 @@ function _parse_value(value) return value:sub(2, -2) end - if value:startswith('(') and value:endswith(')') then - local values = value:sub(2, -2):split(',') + if value:startswith("(") and value:endswith(")") then + local values = value:sub(2, -2):split(",") local result = {} for _, v in ipairs(values) do table.insert(result, _parse_value(v:trim())) @@ -79,7 +79,7 @@ function _parse_line(line, device) if key and value then key = key:trim() value = value:trim() - assert(not device[key], 'duplicate key: ' .. key) + assert(not device[key], "duplicate key: " .. key) device[key] = _parse_value(value) end end @@ -101,7 +101,7 @@ function _parse_result(lines, verbose) end local devId = tonumber(l:match("%s*DEVICE #(%d+)")) if devId then - currentDevice = { ['$id'] = devId } + currentDevice = { ["$id"] = devId } table.insert(devices, currentDevice) elseif currentDevice then _parse_line(l, currentDevice) @@ -113,27 +113,21 @@ end -- find devices function _find_devices(verbose) - - local cuda = find_cuda(get_config("cuda")) - local nvcc = find_tool("nvcc", { program = path.join(cuda.bindir, "nvcc") }) - - if nvcc == nil then - raise('nvcc not found') - end + local nvcc = assert(find_tool("nvcc"), "nvcc not found") if verbose then cprint("${dim}checking for cuda devices") end - local sourcefile = path.join(os.programdir(), 'scripts', 'find_cudadevices.cpp') + local sourcefile = path.join(os.programdir(), "scripts", "find_cudadevices.cpp") local outfile = os.tmpfile() + local args = { sourcefile, "-run", "-o", outfile , '-DPRINT_SUFFIX="' .. _PRINT_SUFFIX .. '"' } + local compile_errors = nil local results, errors = try { function () - local archs = { i386 = "-m32", x86 = "-m32", x86_64 = "-m64", x64 = "-m64" } - local arch = archs[config.get("arch")] or "" - return os.iorunv(nvcc.program, { sourcefile, arch, '-run', '-o', outfile , '-DPRINT_SUFFIX="' .. _PRINT_SUFFIX .. '"' }) + return os.iorunv(nvcc.program, args) end, catch { @@ -153,13 +147,13 @@ function _find_devices(verbose) -- clean up os.tryrm(outfile) - os.tryrm(outfile .. '.*') + os.tryrm(outfile .. ".*") -- get results local results_lines = _get_lines(results) local errors_lines = _get_lines(errors) if #errors_lines ~= 0 then - utils.warning("failed to find cuda devices: " .. table.concat(errors_lines, '\n')) + utils.warning("failed to find cuda devices: " .. table.concat(errors_lines, "\n")) return nil end @@ -167,7 +161,7 @@ function _find_devices(verbose) local devices = _parse_result(results_lines, option.get("diagnosis")) if verbose then for _, v in ipairs(devices) do - cprint("${dim}> found device #%d: ${green bright}%s${reset dim} with compute ${bright}%d.%d${reset dim} capability", v['$id'], v.name, v.major, v.minor) + cprint("${dim}> found device #%d: ${green bright}%s${reset dim} with compute ${bright}%d.%d${reset dim} capability", v["$id"], v.name, v.major, v.minor) end end return devices @@ -248,10 +242,10 @@ function _order_by_flops(devices) else sm_per_multiproc = ngpu_arch_cores_per_sm[dev.major * 10 + dev.minor] or 64; end - dev['$flops'] = dev.multiProcessorCount * sm_per_multiproc * dev.clockRate + dev["$flops"] = dev.multiProcessorCount * sm_per_multiproc * dev.clockRate end - table.sort(devices, function (a,b) return a['$flops'] > b['$flops'] end) + table.sort(devices, function (a,b) return a["$flops"] > b["$flops"] end) return devices end @@ -260,7 +254,7 @@ end -- @param opt the options -- e.g. { verbose = false, force = false, cachekey = "xxxx", min_sm_arch = 35, skip_compute_mode_prohibited = false, order_by_flops = true } -- --- @return { { ['$id'] = 0, name = "GeForce GTX 960M", major = 5, minor = 0, ... }, ... } +-- @return { { ["$id"] = 0, name = "GeForce GTX 960M", major = 5, minor = 0, ... }, ... } -- for all keys, see https://docs.nvidia.com/cuda/cuda-runtime-api/structcudaDeviceProp.html#structcudaDeviceProp -- keys might be differ as your cuda version varies -- diff --git a/xmake/platforms/linux/config.lua b/xmake/platforms/linux/config.lua index 4f133120f..c86144804 100644 --- a/xmake/platforms/linux/config.lua +++ b/xmake/platforms/linux/config.lua @@ -77,7 +77,6 @@ function _toolchains() local rc_ar = toolchain("the rust static library archiver") local cu = toolchain("the cuda compiler") local cu_ld = toolchain("the cuda linker") - local cu_sh = toolchain("the cuda shared library linker") local cu_ccbin = toolchain("the cuda host c++ compiler") local toolchains = {cc = cc, cxx = cxx, as = as, ld = ld, sh = sh, ar = ar, ex = ex, mm = mm, mxx = mxx, @@ -147,9 +146,8 @@ function _toolchains() rc_ar:add("$(env RC)", "rustc") -- init the cuda compiler and linker - cu:add("nvcc") + cu:add("nvcc", "clang++", "clang") cu_ld:add("nvcc") - cu_sh:add("nvcc") if not cross or cross == "" then cu_ccbin:add("$(env CXX)", "$(env CC)", "gcc", "clang", "g++", "clang++") end diff --git a/xmake/platforms/macosx/config.lua b/xmake/platforms/macosx/config.lua index 2a8a4e080..3db232687 100644 --- a/xmake/platforms/macosx/config.lua +++ b/xmake/platforms/macosx/config.lua @@ -59,7 +59,6 @@ function _toolchains() local rc_ar = toolchain("the rust static library archiver") local cu = toolchain("the cuda compiler") local cu_ld = toolchain("the cuda linker") - local cu_sh = toolchain("the cuda shared library linker") local cu_ccbin = toolchain("the cuda host c++ compiler") local toolchains = {cc = cc, cxx = cxx, as = as, ld = ld, sh = sh, ar = ar, ex = ex, mm = mm, mxx = mxx, sc = sc, ["sc-ld"] = sc_ld, ["sc-sh"] = sc_sh, @@ -130,9 +129,8 @@ function _toolchains() rc_ar:add("$(env RC)", "rustc") -- init the cuda compiler and linker - cu:add("nvcc") + cu:add("nvcc", "clang") cu_ld:add("nvcc") - cu_sh:add("nvcc") cu_ccbin:add("$(env CXX)", "$(env CC)", "clang", "gcc") return toolchains diff --git a/xmake/platforms/windows/config.lua b/xmake/platforms/windows/config.lua index fecc9d909..1ba24cb65 100644 --- a/xmake/platforms/windows/config.lua +++ b/xmake/platforms/windows/config.lua @@ -56,7 +56,6 @@ function _toolchains() local rc_ar = toolchain("the rust static library archiver") local cu = toolchain("the cuda compiler") local cu_ld = toolchain("the cuda linker") - local cu_sh = toolchain("the cuda shared library linker") local toolchains = {cc = cc, cxx = cxx, mrc = mrc, as = as, ld = ld, sh = sh, ar = ar, ex = ex, gc = gc, ["gc-ld"] = gc_ld, ["gc-ar"] = gc_ar, dc = dc, ["dc-ld"] = dc_ld, ["dc-sh"] = dc_sh, ["dc-ar"] = dc_ar, @@ -109,9 +108,8 @@ function _toolchains() rc_ar:add("$(env RC)", "rustc") -- init the cuda compiler and linker - cu:add("nvcc") + cu:add("nvcc", "clang") cu_ld:add("nvcc") - cu_sh:add("nvcc") return toolchains end diff --git a/xmake/rules/cuda/devlink/xmake.lua b/xmake/rules/cuda/devlink/xmake.lua index 2d4644781..1cdfb2fb7 100644 --- a/xmake/rules/cuda/devlink/xmake.lua +++ b/xmake/rules/cuda/devlink/xmake.lua @@ -29,10 +29,6 @@ rule("cuda.devlink") import("core.platform.platform") -- disable devlink? - -- local cu_tool, cu_toolname = platform.tool("cu") - -- if (cu_toolname or path.basename(cu_tool)) ~= "nvcc" then - -- return - -- end if target:values("cuda.devlink") == false then return end |
