summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpportunityLiu <[email protected]>2019-06-18 18:10:48 +0800
committerOpportunityLiu <[email protected]>2019-06-18 18:10:48 +0800
commit026a8aa6a02bf9c12790404b9c551abf3dfd261b (patch)
tree13c9acd6bf397fbe8a1d0c121685693b9cffda34
parent9c8b83a61fce275edd3808c54f36ba368378fa5d (diff)
fix find_program & find_file
add path.splitenv
-rw-r--r--tests/modules/path/test.lua27
-rw-r--r--xmake/core/base/path.lua41
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_file.lua36
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_program.lua47
-rw-r--r--xmake/modules/core/tools/nvcc.lua5
-rw-r--r--xmake/modules/detect/sdks/find_cuda.lua1
-rw-r--r--xmake/modules/detect/tools/find_nvcc.lua13
-rw-r--r--xmake/modules/lib/detect/find_cudadevices.lua38
-rw-r--r--xmake/platforms/linux/config.lua4
-rw-r--r--xmake/platforms/macosx/config.lua4
-rw-r--r--xmake/platforms/windows/config.lua4
-rw-r--r--xmake/rules/cuda/devlink/xmake.lua4
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