diff options
| author | ruki <[email protected]> | 2017-08-14 11:27:19 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-08-14 11:29:30 +0800 |
| commit | dba45d143d8aff047da82cbe1a881056e6e4bc00 (patch) | |
| tree | 7b80d5de264c17b538a7c9d0fbb234ded39ac683 /xmake | |
| parent | 34706ba053dda9dd86902cacf42a6c1878c85234 (diff) | |
merge repo and require codes
Diffstat (limited to 'xmake')
44 files changed, 3261 insertions, 46 deletions
diff --git a/xmake/actions/install/install_admin.lua b/xmake/actions/install/install_admin.lua index f641628ea..7028e5c09 100644 --- a/xmake/actions/install/install_admin.lua +++ b/xmake/actions/install/install_admin.lua @@ -41,9 +41,6 @@ function main(targetname, installdir) -- load platform platform.load(config.plat()) - -- laod project - project.load() - -- save the current option and push a new option context option.save() diff --git a/xmake/actions/require/action/build.lua b/xmake/actions/require/action/build.lua new file mode 100644 index 000000000..0ae19a44c --- /dev/null +++ b/xmake/actions/require/action/build.lua @@ -0,0 +1,193 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file build.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.sandbox.sandbox") + +-- build for xmake file +function _build_for_xmakefile(package, buildfile) + + -- configure it first + os.vrun("xmake f -p $(plat) -a $(arch) -m $(mode) -c") + + -- build it + os.vrun("xmake -r") + + -- ok + return true +end + +-- build for makefile +function _build_for_makefile(package, buildfile) + + -- build it + os.vrun("make") + + -- ok + return true +end + +-- build for configure +function _build_for_configure(package, buildfile) + + -- make prefix directory + os.mkdir(".prefix") + + -- configure it first + os.vrun("./configure --prefix=%s", path.absolute(".prefix")) + + -- build it + os.vrun("make") + + -- install to .prefix + os.vrun("make install") + + -- ok + return true +end + +-- build for cmakelist +function _build_for_cmakelists(package, buildfile) + + -- make makefile first + os.vrun("cmake -DCMAKE_INSTALL_PREFIX=%s .", path.absolute(".prefix")) + + -- build it + os.vrun("make") + + -- install to .prefix + os.vrun("make install") + + -- ok + return true +end + +-- build for *.sln +function _build_for_sln(package, buildfile) + + -- build it for windows + if config.plat() == "windows" then + os.vrun("msbuild %s -nologo -t:Rebuild -p:Configuration=Release", buildfile) + return true + end + return false +end + +-- on build the given package +function _on_build_package(package) + + -- TODO *.vcproj, premake.lua, scons, autogen.sh, Makefile.am, ... + -- init build scripts + local buildscripts = + { + {"xmake.lua", _build_for_xmakefile } + , {"*.sln", _build_for_sln } + , {"CMakeLists.txt", _build_for_cmakelists } + , {"configure", _build_for_configure } + , {"[mM]akefile", _build_for_makefile } + } + + -- attempt to build it + for _, buildscript in pairs(buildscripts) do + + -- save the current directory + local oldir = os.curdir() + + -- try building + local ok = try + { + function () + + -- attempt to build it if file exists + local files = os.files(buildscript[1]) + if #files > 0 then + return buildscript[2](package, files[1]) + end + end, + + catch + { + function (errors) + + -- trace verbose info + if errors then + vprint(errors) + end + end + } + } + + -- restore directory + os.cd(oldir) + + -- ok? + if ok then return end + end + + -- failed + raise("attempt to build package %s failed!", package:name()) +end + +-- run script +function _run_script(script, package) + + -- TODO + -- register filter handler before building +-- sandbox.filter_register(script, "package.build", function (var) +-- end) + + -- run it + script(package) + + -- cancel filter handler before building +-- sandbox.filter_register(script, "package.build", nil) +end + +-- build the given package +function main(package) + + -- the package scripts + local scripts = + { + package:script("build_before") + , package:script("build", _on_build_package) + , package:script("build_after") + } + + -- save the current directory + local oldir = os.curdir() + + -- build it + for i = 1, 3 do + local script = scripts[i] + if script ~= nil then + _run_script(script, package) + end + end + + -- restore the current directory + os.cd(oldir) +end diff --git a/xmake/actions/require/action/download.lua b/xmake/actions/require/action/download.lua new file mode 100644 index 000000000..cfc41706f --- /dev/null +++ b/xmake/actions/require/action/download.lua @@ -0,0 +1,201 @@ +--!The Make-like download Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file download.lua +-- + +-- imports +import("core.base.option") +import("net.http") +import("devel.git") +import("utils.archive") + +-- empty chars +function _emptychars() + return " " +end + +-- checkout codes from git +function _checkout(package, url, sourcedir) + + -- use previous source directory if exists + local packagedir = path.join(sourcedir, package:name()) + if os.isdir(packagedir) and not option.get("force") then + + -- clean the previous build files + git.clean({repodir = packagedir, force = true}) + return + end + + -- remove temporary directory + os.rm(sourcedir .. ".tmp") + + -- download package from branches? + packagedir = path.join(sourcedir .. ".tmp", package:name()) + if package:version_from("branches") then + + -- only shadow clone this branch + git.clone(url, {depth = 1, branch = package:version_str(), outputdir = packagedir}) + + -- download package from tags or versions? + else + + -- clone whole history and tags + git.clone(url, {outputdir = packagedir}) + + -- attempt to checkout the given version + git.checkout(package:version_str(), {repodir = packagedir}) + end + + -- move to source directory + os.rm(sourcedir) + os.mv(sourcedir .. ".tmp", sourcedir) + + -- trace + cprint("\r${yellow} => ${clear}clone %s %s .. ${green}ok%s", url, package:version_str(), _emptychars()) +end + +-- download codes from ftp/http/https +function _download(package, url, sourcedir) + + -- get package file + local packagefile = path.filename(url) + + -- the package file have been downloaded? + local sha256 = package:sha256() + if option.get("force") or not os.isfile(packagefile) or (sha256 and sha256 ~= hash.sha256(packagefile)) then + + -- attempt to remove package file first + os.rm(packagefile) + + -- download package file + http.download(url, packagefile) + + -- check hash + if sha256 and sha256 ~= hash.sha256(packagefile) then + raise("unmatched checksum!") + end + end + + -- extract package file + os.rm(sourcedir .. ".tmp") + archive.extract(packagefile, sourcedir .. ".tmp") + + -- move to source directory + os.rm(sourcedir) + os.mv(sourcedir .. ".tmp", sourcedir) + + -- trace + cprint("\r${yellow} => ${clear}download %s .. ${green}ok%s", url, _emptychars()) +end + +-- get sorted urls +function _urls(package) + + -- sort urls from the version source + local urls = {{}, {}} + for _, url in ipairs(package:urls()) do + if git.checkurl(url) then + table.insert(urls[1], url) + else + table.insert(urls[2], url) + end + end + if package:version_from("tags", "branches") then + return table.join(urls[1], urls[2]) + else + return table.join(urls[2], urls[1]) + end +end + +-- download the given package +function main(package) + + -- skip phony package without urls + if #package:urls() == 0 then + return + end + + -- get working directory of this package + local workdir = package:cachedir() + + -- ensure the working directory first + os.mkdir(workdir) + + -- enter the working directory + local oldir = os.cd(workdir) + + -- download package from urls + local urls = _urls(package) + for idx, url in ipairs(urls) do + + -- filter url + url = package:filter():handle(url) + + -- download url + local ok = try + { + function () + + -- download package + local sourcedir = "source" + if git.checkurl(url) then + _checkout(package, url, sourcedir) + else + _download(package, url, sourcedir) + end + + -- ok + return true + end, + catch + { + function (errors) + + -- verbose? + if option.get("verbose") and errors then + cprint("${bright red}error: ${clear}%s", errors) + end + + -- trace + if git.checkurl(url) then + cprint("\r${yellow} => ${clear}clone %s %s .. ${red}failed%s", url, package:version_str(), _emptychars()) + else + cprint("\r${yellow} => ${clear}download %s .. ${red}failed%s", url, _emptychars()) + end + + -- failed? break it + if idx == #urls then + raise("download failed!") + end + end + } + } + + -- ok? break it + if ok then break end + end + + -- leave working directory + os.cd(oldir) +end + + diff --git a/xmake/actions/require/action/install.lua b/xmake/actions/require/action/install.lua new file mode 100644 index 000000000..a5a3292cc --- /dev/null +++ b/xmake/actions/require/action/install.lua @@ -0,0 +1,260 @@ +--!The Make-like install Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file install.lua +-- + +-- imports +import("core.base.option") +import("core.project.target") +import("build") + +-- install for xmake file +function _install_for_xmakefile(package) + + -- package to install directory + os.vrun("xmake p -o %s", package:installdir()) + + -- ok + return true +end + +-- install for generic +function _install_for_generic(package) + + -- the package name + local name = package:name() + + -- the install directory + local installdir = path.join(package:installdir(), name .. ".pkg") + + -- the linkdir + local linkdir = path.join(installdir, "lib/$(mode)/$(plat)/$(arch)") + os.mkdir(linkdir) + + -- the includedir + local includedir = path.join(installdir, "inc") + os.mkdir(includedir) + + -- the prefix directory exists? + local prefixdir = "" + if os.isdir(".prefix") and not os.emptydir(".prefix") then + prefixdir = ".prefix" .. path.seperator() + end + + -- install the library files and ignore hidden files (.xxx) + if not os.trycp(prefixdir .. "**" .. target.filename("*", "static"), linkdir) and + not os.trycp(prefixdir .. "**" .. target.filename("*", "shared"), linkdir) then + raise("the library files not found in package %s", name) + end + + -- install the header files + for _, headerfile in ipairs(table.join((os.files(prefixdir .. "**.h")), (os.files(prefixdir .. "**.hpp")))) do + + -- the destinate header + local dstheaderfile = nil + if #prefixdir > 0 then + dstheaderfile = path.absolute(path.relative(headerfile, path.join(prefixdir, "include")), includedir) + else + dstheaderfile = path.join(includedir, path.filename(headerfile)) + end + + -- install header file + os.cp(headerfile, dstheaderfile) + end + + -- make xmake.lua + local file = io.open(path.join(installdir, "xmake.lua"), "w") + if file then + + -- the xmake.lua content + local content = [[ +-- the %s package +option("%s") + + -- show menu + set_showmenu(true) + + -- set category + set_category("package") + + -- set description + set_description("The %s package") + + -- add defines to config.h if checking ok + add_defines_h_if_ok("$(prefix)_PACKAGE_HAVE_%s") + + -- add links for checking + add_links("%s") + + -- add link directories + add_linkdirs("lib/$(mode)/$(plat)/$(arch)") + + -- add include directories + add_includedirs("inc") +]] + + -- save file + file:writef(content, name, name, name, name:upper(), name) + + -- exit file + file:close() + end + + -- ok + return true +end + +-- on install the given package +function _on_install_package(package) + + -- init install scripts + local installscripts = + { + {"xmake.lua", _install_for_xmakefile } + , {"*", _install_for_generic } + } + + -- attempt to install it + for _, installscript in pairs(installscripts) do + + -- save the current directory + local oldir = os.curdir() + + -- try installing + local ok = try + { + function () + + -- attempt to install it if file exists + local files = os.files(installscript[1]) + if #files > 0 then + return installscript[2](package) + end + end, + + catch + { + function (errors) + + -- trace verbose info + if errors then + vprint(errors) + end + end + } + } + + -- restore directory + os.cd(oldir) + + -- ok? + if ok then return end + end + + -- failed + raise("attempt to install package %s failed!", package:name()) +end + +-- install the given package +function main(package) + + -- skip phony package without urls + if #package:urls() == 0 then + return + end + + -- get working directory of this package + local workdir = package:cachedir() + + -- enter source files directory + local oldir = nil + for _, srcdir in ipairs(os.dirs(path.join(workdir, "source", "*"))) do + oldir = os.cd(srcdir) + break + end + + -- trace + cprintf("${yellow} => ${clear}installing %s-%s .. ", package:name(), package:version_str()) + if option.get("verbose") then + print("") + end + + -- install it + try + { + function () + + -- the package scripts + local scripts = + { + package:script("install_before") + , package:script("install", _on_install_package) + , package:script("install_after") + } + + -- create the install task + local installtask = function () + + -- build it + build(package) + + -- install it + for i = 1, 3 do + local script = scripts[i] + if script ~= nil then + script(package) + end + end + end + + -- install package + if option.get("verbose") then + installtask() + else + process.asyncrun(installtask) + end + + -- trace + cprint("${green}ok") + end, + + catch + { + function (errors) + + -- verbose? + if option.get("verbose") and errors then + cprint("${bright red}error: ${clear}%s", errors) + end + + -- trace + cprint("${red}failed") + + -- failed + raise("install failed!") + end + } + } + + -- leave source codes directory + os.cd(oldir) +end diff --git a/xmake/actions/require/clear.lua b/xmake/actions/require/clear.lua new file mode 100644 index 000000000..169723ef3 --- /dev/null +++ b/xmake/actions/require/clear.lua @@ -0,0 +1,40 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file clear.lua +-- + +-- imports +import("core.project.cache") +import("core.package.package") + +-- clear all installed package caches +function main() + + -- clear cache directory + os.rm(package.cachedir()) + + -- clear require cache + cache.enter("local.require") + cache.clear() + cache.flush() +end + diff --git a/xmake/actions/require/environment.lua b/xmake/actions/require/environment.lua new file mode 100644 index 000000000..937ede435 --- /dev/null +++ b/xmake/actions/require/environment.lua @@ -0,0 +1,218 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file environment.lua +-- + +-- imports +import("core.base.option") +import("core.platform.environment") +import("net.http") +import("net.fasturl") +import("utils.archive") + +-- enter linux environment +function _enter_linux() + + -- add $programdir to $path for running xmake + os.addenv("PATH", os.programdir()) +end + +-- enter macosx environment +function _enter_macosx() + + -- add $programdir to $path for running xmake + os.addenv("PATH", os.programdir()) +end + +-- enter windows environment (xmake/winenv/cmd) +-- +-- @note curl and tar has been placed in the xmake installation package +-- +function _enter_windows() + + -- init winenv directory + local winenv_dir = path.translate("~/.xmake/winenv") + + -- add $programdir/winenv/cmd to $path + os.addenv("PATH", path.join(os.programdir(), "winenv", "bin")) + + -- load winenv + for _, script_dir in ipairs(os.files(path.join(winenv_dir, "**", "winenv.lua")), path.directory) do + import("winenv", {rootdir = script_dir}).main(script_dir) + return + end + + -- trace + cprintf("installing winenv .. ") + if option.get("verbose") then + print("") + end + + -- init winenv.zip file path + local winenv_zip = os.tmpfile() .. ".zip" + local winenv_zip_tmp = winenv_zip .. ".tmp" + + -- init winenv.zip urls + local winenv_arch = ifelse(os.arch() == "x64", "win64", "win32") + local winenv_urls = + { + format("https://github.com/tboox/xmake-%senv/archive/master.zip", winenv_arch) + , format("https://coding.net/u/waruqi/p/xmake-%senv/git/archive/master", winenv_arch) + } + fasturl.add(winenv_urls) + + -- download winenv.zip file + for _, winenv_url in ipairs(fasturl.sort(winenv_urls)) do + local ok = try + { + function () + + -- no cached winenv.zip file? + if not os.isfile(winenv_zip) or option.get("force") then + + -- remove winenv.zip.tmp file first + os.rm(winenv_zip_tmp) + + -- create a download task + local task = function () + http.download(winenv_url, winenv_zip_tmp) + end + + -- download winenv.zip + if option.get("verbose") then + task() + else + process.asyncrun(task) + end + + -- attempt to remove previous winenv.zip first + os.rm(winenv_zip) + + -- rename winenv.zip.tmp to winenv.zip + os.mv(winenv_zip_tmp, winenv_zip) + end + + -- ok + return true + end, + + catch + { + function (errors) + + -- verbose? + if option.get("verbose") then + cprint("${bright red}error: ${clear}%s", errors) + end + end + } + } + + -- ok? + if ok then + + -- remove winenv directory first + os.rm(winenv_dir) + + -- extract winenv.zip file + archive.extract(winenv_zip, winenv_dir) + + -- load winenv + for _, script_dir in ipairs(os.files(path.join(winenv_dir, "**", "winenv.lua")), path.directory) do + import("winenv", {rootdir = script_dir}).main(script_dir) + break + end + + -- trace + cprint("${green}ok") + + -- ok + return + end + end + + -- failed + cprint("${red}failed") + raise() +end + +-- enter host environment +function _enter_host() + + -- save old $path environment + _g._PATH_ENV = os.getenv("PATH") + + -- init loaders + local loaders = + { + linux = _enter_linux + , macosx = _enter_macosx + , windows = _enter_windows + } + + -- enter host environment + local loader = loaders[os.host()] + if loader then + loader() + end +end + +-- leave host environment +function _leave_host() + + -- restore old $path environment + os.setenv("PATH", _g._PATH_ENV) +end + +-- enter environment +-- +-- ensure that we can find some basic tools: git, make/nmake/cmake, msbuild ... +-- +-- If these tools not exist, we will install it first. +-- +function enter() + + -- enter host environment + _enter_host() + + -- set search pathes of toolchains + environment.enter("toolchains") + + -- TODO set toolchains for CC, LD, .. + + -- TODO set flags of toolchains +end + +-- leave environment +function leave() + + -- restore search pathes of toolchains + environment.leave("toolchains") + + -- TODO restore toolchains for CC, LD + + -- TODO set flags of toolchains + + + -- leave host environment + _leave_host() +end diff --git a/xmake/actions/require/info.lua b/xmake/actions/require/info.lua new file mode 100644 index 000000000..1e5d95a80 --- /dev/null +++ b/xmake/actions/require/info.lua @@ -0,0 +1,29 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file info.lua +-- + +-- show the given package info +function main(packages) + -- TODO +end + diff --git a/xmake/actions/require/install.lua b/xmake/actions/require/install.lua new file mode 100644 index 000000000..421945d52 --- /dev/null +++ b/xmake/actions/require/install.lua @@ -0,0 +1,89 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file package.lua +-- + +-- imports +import("core.base.option") +import("core.project.project") +import("action") +import("package") +import("repository") +import("environment") + +-- install packages +function main(requires) + + -- enter environment + environment.enter() + + -- TODO need optimization + -- pull all repositories first + repository.pull() + + -- load packages + local packages = package.load_packages(requires or project.requires()) + + -- download packages + local waitindex = 0 + local waitchars = {'\\', '|', '/', '-'} + process.runjobs(function (index) + + local instance = packages[index] + if instance then + + -- download package + action.download(instance) + end + + end, #packages, ifelse(option.get("verbose"), 1, 4), 300, function (indices) + + -- do not print progress info if be verbose + if option.get("verbose") then + return + end + + -- update waitchar index + waitindex = ((waitindex + 1) % #waitchars) + + -- make downloading packages list + local downloading = {} + for _, index in ipairs(indices) do + local instance = packages[index] + if instance then + table.insert(downloading, instance:name()) + end + end + + -- trace + cprintf("\r${yellow} => ${clear}downloading %s .. %s", table.concat(downloading, ", "), waitchars[waitindex + 1]) + end) + + -- install all required packages from repositories + for _, instance in ipairs(packages) do + action.install(instance) + end + + -- leave environment + environment.leave() +end + diff --git a/xmake/actions/require/list.lua b/xmake/actions/require/list.lua new file mode 100644 index 000000000..056fdab16 --- /dev/null +++ b/xmake/actions/require/list.lua @@ -0,0 +1,38 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file list.lua +-- + +-- imports +import("core.project.project") +import("package") + +-- list packages +function main() + + -- list all requires + print("Tha package dependencies:") + for packagename, requireinfo in pairs(package.load_requires(project.requires())) do + print(" %s %s", packagename, requireinfo.version) + end +end + diff --git a/xmake/actions/require/main.lua b/xmake/actions/require/main.lua new file mode 100644 index 000000000..23fce2766 --- /dev/null +++ b/xmake/actions/require/main.lua @@ -0,0 +1,100 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file main.lua +-- + +-- imports +import("core.base.option") +import("core.base.task") +import("core.project.config") +import("core.project.project") +import("core.platform.platform") +import("list") +import("info") +import("clear") +import("search") +import("install") + +-- +-- the default repositories: +-- xmake-repo https://github.com/tboox/xmake-repo.git +-- +-- add other repositories: +-- xmake repo --add other-repo https://github.com/other/other-repo.git +-- or +-- add_repositories("other-repo https://github.com/other/other-repo.git") +-- +-- add requires: +-- +-- add_requires("tboox.tbox >=1.5.1", "zlib >=1.2.11") +-- add_requires("zlib master") +-- add_requires("[email protected] >=1.5.1") +-- add_requires("https://github.com/tboox/[email protected] >=1.5.1") +-- +-- add package dependencies: +-- +-- target("test") +-- add_packages("tboox.tbox", "zlib") +-- + +-- load project +function _load_project() + + -- config it first + task.run("config") + + -- enter project directory + os.cd(project.directory()) +end + +-- main +function main() + + -- load project first + _load_project() + + -- clear all installed packages cache + if option.get("clear") then + + clear(option.get("global")) + + -- search for the given packages from repositories + elseif option.get("search") then + + search(option.get("packages")) + + -- show the given package info + elseif option.get("info") then + + info(option.get("packages")) + + -- list all package dependencies + elseif option.get("list") then + + list() + + -- install and update all outdated package dependencies by default if no arguments + else + install(option.get("requires")) + end +end + diff --git a/xmake/actions/require/package.lua b/xmake/actions/require/package.lua new file mode 100644 index 000000000..6b401ab73 --- /dev/null +++ b/xmake/actions/require/package.lua @@ -0,0 +1,360 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file package.lua +-- + +-- imports +import("core.base.semver") +import("core.base.option") +import("core.base.global") +import("core.project.cache") +import("core.project.project") +import("core.package.package", {alias = "core_package"}) +import("devel.git") +import("net.fasturl") +import("repository") + +-- +-- parse require string +-- +-- add_requires("tboox.tbox >=1.5.1", "zlib >=1.2.11") +-- add_requires("zlib master") +-- add_requires("[email protected] >=1.5.1") +-- add_requires("https://github.com/tboox/[email protected] >=1.5.1") +-- add_requires("tboox.tbox >=1.5.1 <1.6.0 optional") +-- +function _parse_require(require_str) + + -- get it from cache first + local requires = _g._REQUIRES or {} + local required = requires[require_str] + if required then + return required.packagename, required.requireinfo + end + + -- split package and version info + local splitinfo = require_str:split('%s+') + assert(splitinfo and #splitinfo > 0, "require(\"%s\"): invalid!", require_str) + + -- get package info + local packageinfo = splitinfo[1] + + -- get mode at last position + -- + -- .e.g + -- + -- must + -- optional + -- + local mode = "must" + if #splitinfo > 1 then + + -- get mode + local modes = {must = true, optional = true} + local value = splitinfo[#splitinfo]:lower() + if modes[value] then + mode = value + table.remove(splitinfo) + end + end + + -- get version + -- + -- .e.g + -- + -- >=1.5.1 <1.6.0 + -- master || >1.4 + -- ~1.2.3 + -- ^1.1 + -- + local version = "master" + if #splitinfo > 1 then + version = table.concat(table.slice(splitinfo, 2), " ") + end + assert(version, "require(\"%s\"): unknown version!", require_str) + + -- get repository name, package name and package url + local reponame = nil + local packageurl = nil + local packagename = nil + local pos = packageinfo:find_last('@', true) + if pos then + + -- get package name + packagename = packageinfo:sub(pos + 1) + + -- get reponame or packageurl + local repo_or_pkgurl = packageinfo:sub(1, pos - 1) + + -- is package url? + if repo_or_pkgurl:find('[/\\]') then + packageurl = repo_or_pkgurl + else + reponame = repo_or_pkgurl + end + else + packagename = packageinfo + end + + -- check package name + assert(packagename, "require(\"%s\"): the package name not found!", require_str) + + -- init required item + local required = {} + required.packagename = packagename + required.requireinfo = {reponame = reponame, packageurl = packageurl, version = version, mode = mode} + + -- save this required item to cache + requires[require_str] = required + _g._REQUIRES = requires + + -- ok + return required.packagename, required.requireinfo +end + +-- load package instance from the given package url +function _load_package_from_url(packagename, packageurl) + + -- load it + return core_package.load_from_url(packagename, packageurl) +end + +-- load package instance from project +function _load_package_from_project(packagename) + + -- load it + return core_package.load_from_project(packagename) +end + +-- load package instance from repositories +function _load_package_from_repository(packagename, reponame) + + -- get package directory from the given package name + local packagedir, is_global = repository.packagedir(packagename, reponame) + if packagedir then + -- load it + return core_package.load_from_repository(packagename, is_global, packagedir) + end +end + +-- load required packages +function _load_package(packagename, requireinfo) + + -- attempt to get it from cache first + local packages = _g._PACKAGES or {} + local instance = packages[packagename] + if instance then + + -- satisfy required version? + if not semver.satisfies(instance:version(), requireinfo.version) then + raise("package(%s): version conflict, '%s' does not satisfy '%s'!", packagename, instance:version(), requireinfo.version) + end + + -- ok + return instance + end + + -- load package instance + instance = nil + if requireinfo.packageurl then + -- load package from the given package url + instance = _load_package_from_url(packagename, requireinfo.packageurl) + else + -- load package from project first + instance = _load_package_from_project(packagename) + if not instance then + -- load package from repositories + instance = _load_package_from_repository(packagename, requireinfo.reponame) + end + end + + -- check + assert(instance, "package(%s) not found!", packagename) + + -- save require info to package + instance:requireinfo_set(requireinfo) + + -- save this package instance to cache + packages[packagename] = instance + _g._PACKAGES = packages + + -- ok + return instance +end + +-- load all required packages +function _load_packages(requires) + + -- no requires? + if not requires or #requires == 0 then + return {} + end + + -- load packages + local packages = {} + for packagename, requireinfo in pairs(load_requires(requires)) do + + -- load package instance + local package = _load_package(packagename, requireinfo) + + -- load required packages and save them first of this package + requires = package:get("requires") + if requires then + table.join2(packages, _load_packages(requires)) + end + + -- save this package instance + table.insert(packages, package) + end + + -- ok? + return packages +end + +-- load all git refs from packages +function _load_packages_gitrefs(packages) + + -- enter cache scope + cache.enter("local.require") + + -- load cache + local gitrefs = nil + if option.get("force") then + gitrefs = {} + else + gitrefs = cache.get("gitrefs") or {} + end + + -- run tasks + local results = {} + process.runjobs(function (index) + local package = packages[index] + if package then + + -- attempt to get refs from cache first + local refs = gitrefs[package:name()] + if refs then + results[package:name()] = {tags = refs.tags, branches = refs.branches} + else + -- attempt to get refs from the git url + local tags = {} + local branches = {} + for _, url in ipairs(package:urls()) do + if git.checkurl(url) then + + -- fetch refs + tags, branches = git.refs(url) + + -- save result + results[package:name()] = {tags = tags, branches = branches} + + -- cache result + gitrefs[package:name()] = {tags = tags, branches = branches} + break + end + end + end + end + end, #packages) + + -- save cache + cache.set("gitrefs", gitrefs) + cache.flush() + + -- ok? + return results +end + +-- select package version +function _select_package_version(package, required_ver, gitrefs) + + -- get versions + local versions = package:get("versions") + + -- attempt to get tags and branches from the git url + local refs = {} + if gitrefs then + refs = gitrefs[package:name()] or {} + end + + -- select required version + return semver.select(required_ver, versions, refs.tags, refs.branches) +end + +-- the cache directory +function cachedir() + return path.join(global.directory(), "cache", "packages") +end + +-- load requires +function load_requires(requires) + + -- parse requires + local requireinfos = {} + for _, require_str in ipairs(requires) do + + -- parse require info + local packagename, requireinfo = _parse_require(require_str) + + -- save this required package + requireinfos[packagename] = requireinfo + end + + -- ok + return requireinfos +end + +-- load all required packages +function load_packages(requires) + + -- laod all required packages recursively + local packages = _load_packages(requires) + + -- add all urls to fasturl and prepare to sort them together + for _, package in ipairs(packages) do + fasturl.add(package:urls()) + end + + -- load git refs from packages + local gitrefs = _load_packages_gitrefs(packages) + + -- sort and update urls + for _, package in ipairs(packages) do + + -- sort package urls + package:urls_set(fasturl.sort(package:urls())) + + -- exists urls? otherwise be phony package (only as package group) + if #package:urls() > 0 then + + -- select package version + local version, source = _select_package_version(package, package:requireinfo().version, gitrefs) + + -- save version to package + package:version_set(version, source) + end + end + + -- ok + return packages +end + diff --git a/xmake/actions/require/repository.lua b/xmake/actions/require/repository.lua new file mode 100644 index 000000000..5576b4103 --- /dev/null +++ b/xmake/actions/require/repository.lua @@ -0,0 +1,152 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file repository.lua +-- + +-- imports +import("core.base.option") +import("core.package.repository") +import("devel.git") + +-- get all repositories +function repositories() + + -- get it from cache it + if _g._REPOSITORIES then + return _g._REPOSITORIES + end + + -- get all repositories (local first) + local repos = table.join(repository.repositories(false), repository.repositories(true)) + + -- save repositories + _g._REPOSITORIES = repos + + -- ok + return repos +end + +-- pull repositories +function pull(position) + + -- trace + printf("updating repositories .. ") + if option.get("verbose") then + print("") + end + + -- create a pull task + local task = function () + + -- pull all repositories + local pulled = {} + for _, repo in ipairs(repositories()) do + + -- the repository directory + local repodir = path.join(repository.directory(repo.global), repo.name) + + -- remove repeat and only pull the first repository + if not pulled[repodir] then + if os.isdir(repodir) then + + -- trace + vprint("pulling repository(%s): %s to %s ..", repo.name, repo.url, repodir) + + -- pull it + git.pull({verbose = option.get("verbose"), branch = "master", repodir = repodir}) + else + -- trace + vprint("cloning repository(%s): %s to %s ..", repo.name, repo.url, repodir) + + -- clone it + git.clone(repo.url, {verbose = option.get("verbose"), branch = "master", outputdir = repodir}) + end + + -- pull this repository ok + pulled[repodir] = true + end + end + end + + -- pull repositories + if option.get("verbose") then + task() + else + process.asyncrun(task) + end + + -- trace + cprint("${green}ok") +end + +-- get package directory from repositories +function packagedir(packagename, reponame) + + -- get it from cache it + local packagedirs = _g._PACKAGEDIRS or {} + local foundir = packagedirs[packagename] + if foundir then + return foundir[1], foundir[2] + end + + -- find the package directory from the given repository + if reponame then + for _, from in ipairs({"local", "global"}) do + local is_global = (from == "global") + for _, repodir in ipairs(repository.directory(is_global)) do + local dir = path.join(repodir, reponame, "packages", (packagename:gsub('%.', path.seperator()))) + if os.isdir(dir) then + foundir = {dir, is_global} + break + end + end + if foundir then + break + end + end + else + -- find the package directory from all repositories + for _, repo in ipairs(repositories()) do + + -- the package directory + local dir = path.join(repository.directory(repo.global), repo.name, "packages", (packagename:gsub('%.', path.seperator()))) + if os.isdir(dir) then + foundir = {dir, repo.global} + break + end + end + end + + -- found? + if foundir then + + -- save package directory + packagedirs[packagename] = foundir + + -- update cache + _g._PACKAGEDIRS = packagedirs + end + + -- ok + return foundir[1], foundir[2] +end + diff --git a/xmake/actions/require/search.lua b/xmake/actions/require/search.lua new file mode 100644 index 000000000..569f99115 --- /dev/null +++ b/xmake/actions/require/search.lua @@ -0,0 +1,29 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file search.lua +-- + +-- search for the given packages from repositories +function main(packages) + -- TODO +end + diff --git a/xmake/actions/require/xmake.lua b/xmake/actions/require/xmake.lua new file mode 100644 index 000000000..6c5b7cacd --- /dev/null +++ b/xmake/actions/require/xmake.lua @@ -0,0 +1,61 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file require.lua +-- + +-- define task +task("require") + + -- set category + set_category("action") + + -- on run + on_run("main") + + -- set menu + set_menu { + -- usage + usage = "xmake require [options] [packages]" + + -- description + , description = "Install and update required packages." + + -- xmake q + , shortname = 'q' + + -- options + , options = + { + {'c', "clear", "k", nil, "Clear all installed package caches." } + , {'f', "force", "k", nil, "Force to reinstall all package dependencies." } + , {'l', "list", "k", nil, "List all package dependencies." } + , { } + , {nil, "info", "k", nil, "Show the given package info." } + , {'s', "search", "k", nil, "Search for the given packages from repositories." } + , { } + , {nil, "requires", "vs", nil, "The package requires.", + ".e.g", + " $ xmake require zlib tboox.tbox", + " $ xmake require \"zlib >=1.2.11\" \"tboox.tbox master\"", + " $ xmake require \"[email protected]:tboox/[email protected] >=1.6.0 <1.6.1 || master\"" } + } + } diff --git a/xmake/actions/uninstall/uninstall_admin.lua b/xmake/actions/uninstall/uninstall_admin.lua index 891b4a857..a8ac07468 100644 --- a/xmake/actions/uninstall/uninstall_admin.lua +++ b/xmake/actions/uninstall/uninstall_admin.lua @@ -41,9 +41,6 @@ function main(targetname, installdir) -- load platform platform.load(config.plat()) - -- laod project - project.load() - -- save the current option and push a new option context option.save() diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index ad01c67f1..fbe208b9b 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -468,7 +468,7 @@ end function os.tmpfile() -- make it - return path.join(os.tmpdir(), "_" .. (os.uuid():gsub("-", ""))) + return path.join(os.tmpdir(), "_" .. (hash.uuid():gsub("-", ""))) end -- run command diff --git a/xmake/core/main.lua b/xmake/core/main.lua index ef0edd874..227d0e970 100644 --- a/xmake/core/main.lua +++ b/xmake/core/main.lua @@ -36,6 +36,7 @@ local privilege = require("base/privilege") local task = require("base/task") local project = require("project/project") local history = require("project/history") +local package = require("package/package") -- init the option menu local menu = @@ -51,7 +52,6 @@ local menu = } - -- show logo function main._show_logo() @@ -62,6 +62,7 @@ function main._show_logo() \ \/ / | \/ |/ _ | |/ / __ \ > < | \__/ | /_| | < ___/ /_/\_\_|_| |_|\__ \|_|\_\____| + by ruki, ${underline}tboox.org${clear} ${point_right} ${bright}Manual${clear}: ${underline}http://xmake.io/#/home${clear} @@ -162,6 +163,7 @@ function main._init() -- define task and package apis first before loading project's xmake.lua - calling option.init() project.define_apis(task.apis()) + project.define_apis(package.apis()) end -- the main function diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua new file mode 100644 index 000000000..e5ca87b84 --- /dev/null +++ b/xmake/core/package/package.lua @@ -0,0 +1,419 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific package governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file package.lua +-- + +-- define module +local package = package or {} +local _instance = _instance or {} + +-- load modules +local os = require("base/os") +local io = require("base/io") +local path = require("base/path") +local utils = require("base/utils") +local table = require("base/table") +local filter = require("base/filter") +local global = require("base/global") +local interpreter = require("base/interpreter") +local sandbox = require("sandbox/sandbox") +local config = require("project/config") +local project = require("project/project") +local platform = require("platform/platform") + +-- new an instance +function _instance.new(name, info, rootdir) + + -- new an instance + local instance = table.inherit(_instance) + + -- init instance + instance._NAME = name + instance._INFO = info + instance._ROOTDIR = rootdir + instance._FILTER = filter.new() + + -- register filter handler + instance._FILTER:register("package", function (variable) + + -- init maps + local maps = + { + version = instance:version_str() + } + + -- map it + return maps[variable] + end) + + -- ok + return instance +end + +-- get the package configure +function _instance:get(name) + + -- the info + local info = self._INFO + + -- get if from info first + local value = info[name] + if value ~= nil then + return value + end +end + +-- get the package name +function _instance:name() + return self._NAME +end + +-- get the package filter +function _instance:filter() + return self._FILTER +end + +-- get urls +function _instance:urls() + return self._URLS or table.wrap(self:get("urls")) +end + +-- get urls +function _instance:urls_set(urls) + self._URLS = urls +end + +-- get sha256 +function _instance:sha256() + + -- get it from cache first + if self._SHA256 then + return self._SHA256 + end + + -- find sha256 + local version = self:version() + local sha256s = table.wrap(self:get("sha256s")) + local versions = table.wrap(self:get("versions")) + if version then + for idx, ver in ipairs(versions) do + if ver == version then + self._SHA256 = sha256s[idx] + break + end + end + end + + -- get it + return self._SHA256 +end + +-- is global package? +function _instance:global() + return self._ISGLOBAL +end + +-- is optional package? +function _instance:optional() + + -- optional? + return self._REQUIREINFO.mode == "optional" +end + +-- get the cached directory of this package +function _instance:cachedir() + return path.join(package.cachedir(), self:name() .. "-" .. (self:version_str() or "group")) +end + +-- get the installed directory of this package +function _instance:installdir() + return path.join(package.installdir(self:global()), self:name() .. "-" .. (self:version_str() or "group")) +end + +-- get the version +function _instance:version() + + -- get it + return self._VERSION or {} +end + +-- get the version string +function _instance:version_str() + + -- get it + return self:version().raw or self:version().version +end + +-- the verson from tags, branches or versions? +function _instance:version_from(...) + + -- from source? + for _, source in ipairs({...}) do + return self:version().source == source + end +end + +-- set the version +function _instance:version_set(version, source) + + -- init package version + if type(version) == "string" then + version = {version = version, source = source} + else + version.source = source + end + + -- save version + self._VERSION = version +end + +-- get the require info +function _instance:requireinfo() + return self._REQUIREINFO +end + +-- set the require info +function _instance:requireinfo_set(requireinfo) + self._REQUIREINFO = requireinfo +end + +-- get xxx_script +function _instance:script(name, generic) + + -- get script + local script = self:get(name) + if type(script) == "function" then + return script + elseif type(script) == "table" then + + -- match script for special plat and arch + local plat = (config.get("plat") or "") + local pattern = plat .. '|' .. (config.get("arch") or "") + for _pattern, _script in pairs(script) do + if not _pattern:startswith("__") and pattern:find('^' .. _pattern .. '$') then + return _script + end + end + + -- match script for special plat + for _pattern, _script in pairs(script) do + if not _pattern:startswith("__") and plat:find('^' .. _pattern .. '$') then + return _script + end + end + + -- get generic script + return script["__generic__"] or generic + end + + -- only generic script + return generic +end + +-- the interpreter +function package._interpreter() + + -- the interpreter has been initialized? return it directly + if package._INTERPRETER then + return package._INTERPRETER + end + + -- init interpreter + local interp = interpreter.new() + assert(interp) + + -- define apis + interp:api_define(package.apis()) + + -- save interpreter + package._INTERPRETER = interp + + -- ok? + return interp +end + +-- get package apis +function package.apis() + + return + { + values = + { + -- package.set_xxx + "package.set_urls" + , "package.set_sha256s" + , "package.set_versions" + , "package.set_homepage" + , "package.set_description" + -- package.add_xxx + , "package.add_requires" + } + , script = + { + -- package.on_xxx + "package.on_build" + , "package.on_install" + , "package.on_test" + + -- package.before_xxx + , "package.before_build" + , "package.before_install" + , "package.before_test" + + -- package.before_xxx + , "package.after_build" + , "package.after_install" + , "package.after_test" + } + } +end + +-- get install directory +function package.installdir(is_global) + + -- get directory + if is_global then + return path.join(global.directory(), "packages") + else + return path.join(config.directory(), "packages") + end +end + +-- the cache directory +function package.cachedir() + return path.join(global.directory(), "cache", "packages") +end + +-- load the package from the package url +function package.load_from_url(packagename, packageurl) + + -- make a temporary package file + local packagefile = os.tmpfile() .. ".lua" + + -- make package description + local packagedata = string.format([[ + package("%s") + set_urls("%s") + ]], packagename, packageurl) + + -- write a temporary package description to file + local ok, errors = io.writefile(packagefile, packagedata) + if not ok then + return nil, errors + end + + -- load package instance + local instance, errors = package.load_from_repository(packagename, false, nil, packagefile) + + -- remove the package file + os.rm(packagefile) + + -- ok? + return instance, errors +end + +-- load the package from the project file +function package.load_from_project(packagename) + + -- get it directly from cache first + package._PACKAGES = package._PACKAGES or {} + if package._PACKAGES[packagename] then + return package._PACKAGES[packagename] + end + + -- load packages (with cache) + local packages, errors = project.packages() + if not packages then + return nil, errors + end + + -- get interpreter + local interp = errors or package._interpreter() + + -- not found? + if not packages[packagename] then + return + end + + -- new an instance + local instance, errors = _instance.new(packagename, packages[packagename], interp:rootdir()) + if not instance then + return nil, errors + end + + -- mark as loval package + instance._ISGLOBAL = false + + -- save instance to the cache + package._PACKAGES[packagename] = instance + + -- ok + return instance +end + +-- load the package from the package directory or package description file +function package.load_from_repository(packagename, is_global, packagedir, packagefile) + + -- get it directly from cache first + package._PACKAGES = package._PACKAGES or {} + if package._PACKAGES[packagename] then + return package._PACKAGES[packagename] + end + + -- find the package script path + local scriptpath = packagefile + if not packagefile and packagedir then + scriptpath = path.join(packagedir, "xmake.lua") + end + if not scriptpath or not os.isfile(scriptpath) then + return nil, string.format("the package %s not found!", packagename) + end + + -- load package and disable filter, we will process filter after a while + local results, errors = package._interpreter():load(scriptpath, "package", true, false) + if not results and os.isfile(scriptpath) then + return nil, errors + end + + -- check the package name + if not results[packagename] then + return nil, string.format("the package %s not found!", name) + end + + -- new an instance + local instance, errors = _instance.new(packagename, results[packagename], package._interpreter():rootdir()) + if not instance then + return nil, errors + end + + -- mark as global package? + instance._ISGLOBAL = is_global + + -- save instance to the cache + package._PACKAGES[packagename] = instance + + -- ok + return instance +end + +-- return module +return package diff --git a/xmake/core/package/repository.lua b/xmake/core/package/repository.lua new file mode 100644 index 000000000..6a4bcc9f0 --- /dev/null +++ b/xmake/core/package/repository.lua @@ -0,0 +1,134 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file repository.lua +-- + +-- define module +local repository = repository or {} + +-- load modules +local utils = require("base/utils") +local string = require("base/string") +local global = require("base/global") +local cache = require("project/cache") +local config = require("project/config") + +-- get cache +function repository._cache(is_global) + + -- get position + local position = utils.ifelse(is_global, "global", "local") + + -- get it from cache first if exists + if repository._CACHE and repository._CACHE[position] then + return repository._CACHE[position] + end + + -- init cache + repository._CACHE = repository._CACHE or {} + repository._CACHE[position] = cache(position .. ".repository") + + -- ok + return repository._CACHE[position] +end + +-- get the local or global package directory +function repository.directory(is_global) + + -- get directory + if is_global then + return path.join(global.directory(), "repositories") + else + return path.join(config.directory(), "repositories") + end +end + +-- get repository url from the given name +function repository.get(name, is_global) + + -- get it + local repositories = repository.repositories(is_global) + if repositories then + return repositories[name] + end +end + +-- add repository url to the given name +function repository.add(name, url, is_global) + + -- no name? + if not name then + return false, string.format("please set name to repository: %s", url) + end + + -- get repositories + local repositories = repository.repositories(is_global) or {} + + -- set it + repositories[name] = url + + -- save repositories + repository._cache(is_global):set("repositories", repositories) + + -- flush it + return repository._cache(is_global):flush() +end + +-- remove repository from gobal or local directory +function repository.remove(name, is_global) + + -- get repositories + local repositories = repository.repositories(is_global) or {} + if not repositories[name] then + return false, string.format("repository(%s): not found!", name) + end + + -- remove it + repositories[name] = nil + + -- save repositories + repository._cache(is_global):set("repositories", repositories) + + -- flush it + return repository._cache(is_global):flush() +end + +-- clear all repositories +function repository.clear(is_global) + + -- clear repositories + repository._cache(is_global):set("repositories", {}) + + -- flush it + return repository._cache(is_global):flush() +end + + +-- get all repositories from global or local directory +function repository.repositories(is_global) + + -- get repositories + return repository._cache(is_global):get("repositories") +end + +-- return module +return repository diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 6c844e4f0..d57721d76 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -209,6 +209,9 @@ function project.interpreter() "set_project" , "set_version" , "set_modes" + -- add_xxx + , "add_requires" + , "add_repositories" -- target.set_xxx , "target.set_kind" , "target.set_strip" @@ -235,8 +238,8 @@ function project.interpreter() -- option.add_xxx , "option.add_deps" , "option.add_vectorexts" - , "option.add_bindings" -- deprecated - , "option.add_rbindings" -- deprecated + , "option.add_bindings" -- deprecated + , "option.add_rbindings" -- deprecated } , pathes = { @@ -633,6 +636,36 @@ function project.tasks() return results, interp end +-- get packages +function project.packages() + + -- get it from cache first + if project._PACKAGES then + return project._PACKAGES, interp + end + + -- get interpreter + local interp = project.interpreter() + assert(interp) + + -- the project file is not found? + if not os.isfile(os.projectfile()) then + return {}, nil + end + + -- load the tasks from the the project file and disable filter, we will process filter after a while + local results, errors = interp:load(os.projectfile(), "package", true, false) + if not results then + return nil, errors + end + + -- save results to cache + project._PACKAGES = results + + -- ok? + return results, interp +end + -- get the mtimes function project.mtimes() return project.interpreter():mtimes() diff --git a/xmake/core/sandbox/modules/hash.lua b/xmake/core/sandbox/modules/hash.lua new file mode 100644 index 000000000..7143aa511 --- /dev/null +++ b/xmake/core/sandbox/modules/hash.lua @@ -0,0 +1,59 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file hash.lua +-- + +-- load modules +local raise = require("sandbox/modules/raise") + +-- define module +local sandbox_hash = sandbox_hash or {} + +-- make a new uuid +function sandbox_hash.uuid(name) + + -- make it + local uuid = hash.uuid(name) + if not uuid then + raise("cannot make uuid %s", name) + end + + -- ok? + return uuid +end + +-- make sha256 from the given file +function sandbox_hash.sha256(file) + + -- make it + local sha256 = hash.sha256(file) + if not sha256 then + raise("cannot make sha256 for %s", file) + end + + -- ok? + return sha256 +end + +-- return module +return sandbox_hash + diff --git a/xmake/core/sandbox/modules/import/core/base/semver.lua b/xmake/core/sandbox/modules/import/core/base/semver.lua new file mode 100644 index 000000000..ee4c6e685 --- /dev/null +++ b/xmake/core/sandbox/modules/import/core/base/semver.lua @@ -0,0 +1,86 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file semver.lua +-- + +-- define module +local sandbox_core_base_semver = sandbox_core_base_semver or {} + +-- load modules +local table = require("base/table") +local raise = require("sandbox/modules/raise") + +-- parse a version string into a props table containing all semver infos +-- +-- semver.parse('1.2.3') => { major = 1, minor = 2, patch = 3, ... } +-- semver.parse('a.b.c') => nil +-- +function sandbox_core_base_semver.parse(version) + + -- compare version + local result, errors = semver.parse(version) + if errors then + raise(errors) + end + + -- ok + return result +end + +-- this version satisfies in the given version range +-- +-- semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') => true +-- +function sandbox_core_base_semver.satisfies(version, range) + -- satisfies version + local result, errors = semver.satisfies(version, range) + if errors then + raise(errors) + end + + -- ok + return result +end + +-- select required version from versions, tags and branches +-- +-- .e.g +-- +-- local version, source = semver.select(">=1.5.0 <1.6", {"1.5.0", "1.5.1"}, {"v1.5.0", ..}, {"master", "dev"}) +-- +-- @version the selected version number +-- @source the version source, .e.g versions, tags, branchs +-- +function sandbox_core_base_semver.select(range, versions, tags, branches) + + -- select version + local verinfo, errors = semver.select(range, versions or {}, tags or {}, branches or {}) + if not verinfo then + raise(errors) + end + + -- ok + return verinfo.version, verinfo.source +end + +-- return module +return sandbox_core_base_semver diff --git a/xmake/core/sandbox/modules/import/core/package/package.lua b/xmake/core/sandbox/modules/import/core/package/package.lua new file mode 100644 index 000000000..10d62f493 --- /dev/null +++ b/xmake/core/sandbox/modules/import/core/package/package.lua @@ -0,0 +1,82 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file package.lua +-- + +-- define module +local sandbox_core_package_package = sandbox_core_package_package or {} + +-- load modules +local package = require("package/package") +local raise = require("sandbox/modules/raise") + +-- get cache directory +function sandbox_core_package_package.cachedir() + return package.cachedir() +end + +-- get install directory +function sandbox_core_package_package.installdir(is_global) + return package.installdir(is_global) +end + +-- load the package from the project file +function sandbox_core_package_package.load_from_project(packagename) + + -- load package instance + local instance, errors = package.load_from_project(packagename) + if errors then + raise(errors) + end + + -- ok + return instance +end + +-- load the package from repositories +function sandbox_core_package_package.load_from_repository(packagename, is_global, packagedir, packagefile) + + -- load package instance + local instance, errors = package.load_from_repository(packagename, is_global, packagedir, packagefile) + if not instance then + raise(errors) + end + + -- ok + return instance +end + +-- load the package from the package url +function sandbox_core_package_package.load_from_url(packagename, packageurl) + + -- load package instance + local instance, errors = package.load_from_url(packagename, packageurl) + if not instance then + raise(errors) + end + + -- ok + return instance +end + +-- return module +return sandbox_core_package_package diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua new file mode 100644 index 000000000..3336ab4e1 --- /dev/null +++ b/xmake/core/sandbox/modules/import/core/package/repository.lua @@ -0,0 +1,119 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file repository.lua +-- + +-- define module +local sandbox_core_package_repository = sandbox_core_package_repository or {} + +-- load modules +local project = require("project/project") +local repository = require("package/repository") +local raise = require("sandbox/modules/raise") +local import = require("sandbox/modules/import") + +-- get repository directory +function sandbox_core_package_repository.directory(is_global) + return repository.directory(is_global) +end + +-- get repository url from the given name +function sandbox_core_package_repository.get(name, is_global) + + -- get it + return repository.get(name, is_global) +end + +-- add repository url to the given name +function sandbox_core_package_repository.add(name, url, is_global) + + -- add it + local ok, errors = repository.add(name, url, is_global) + if not ok then + raise(errors) + end +end + +-- remove repository from gobal or local directory +function sandbox_core_package_repository.remove(name, is_global) + + -- remove it + local ok, errors = repository.remove(name, is_global) + if not ok then + raise(errors) + end +end + +-- clear all repositories from global or local directory +function sandbox_core_package_repository.clear(is_global) + + -- clear all repositories + local ok, errors = repository.clear(is_global) + if not ok then + raise(errors) + end +end + +-- get all repositories from global or local directory +function sandbox_core_package_repository.repositories(is_global) + + -- add main global xmake repository + local repositories = {} + if is_global then + + -- import fasturl + import("net.fasturl") + + -- sort main urls + local mainurls = {"https://github.com/tboox/xmake-repo.git", "https://git.oschina.net/tboox/xmake-repo.git"} + fasturl.add(mainurls) + mainurls = fasturl.sort(mainurls) + + -- add main urls + for _, mainurl in ipairs(mainurls) do + table.insert(repositories, {name = "xmake-repo", url = mainurl, global = true}) + end + end + + -- load repositories from repository cache + for name, url in pairs(table.wrap(repository.repositories(is_global))) do + table.insert(repositories, {name = name, url = url, global = is_global}) + end + + -- load repositories from project file + if not is_global then + for _, repo in ipairs(table.wrap(project.get("repositories"))) do + local repoinfo = repo:split(' ') + if #repoinfo == 2 then + table.insert(repositories, {name = repoinfo[1], url = repoinfo[2], global = is_global}) + else + raise("invalid repository: %s", repo) + end + end + end + + -- get the repositories + return repositories +end + +-- return module +return sandbox_core_package_repository diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 4a7beb3e0..bae02f7a0 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -34,6 +34,7 @@ local project = require("project/project") local sandbox = require("sandbox/sandbox") local raise = require("sandbox/modules/raise") local environment = require("platform/environment") +local package = require("package/package") -- load project function sandbox_core_project.load() @@ -161,5 +162,10 @@ function sandbox_core_project.modes() return project.get("modes") end +-- get the project requires +function sandbox_core_project.requires() + return project.get("requires") +end + -- return module return sandbox_core_project diff --git a/xmake/core/sandbox/modules/interpreter/os.lua b/xmake/core/sandbox/modules/interpreter/os.lua index b956726eb..ec650a212 100644 --- a/xmake/core/sandbox/modules/interpreter/os.lua +++ b/xmake/core/sandbox/modules/interpreter/os.lua @@ -44,7 +44,7 @@ sandbox_os.programdir = os.programdir sandbox_os.programfile = os.programfile sandbox_os.projectdir = os.projectdir sandbox_os.projectfile = os.projectfile -sandbox_os.uuid = os.uuid +sandbox_os.uuid = hash.uuid -- match files function sandbox_os.files(pattern, ...) diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index 839d5cbba..65608327b 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -443,17 +443,6 @@ function sandbox_os.exists(file_or_dir) return os.exists(file_or_dir) end --- make a new uuid -function sandbox_os.uuid(name) - - -- make it - local uuid = os.uuid(name) - assert(uuid) - - -- ok? - return uuid -end - -- return module return sandbox_os diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index 40d2c6170..e282ef80e 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -26,6 +26,7 @@ local io = require("base/io") local utils = require("base/utils") local colors = require("base/colors") +local option = require("base/option") local try = require("sandbox/modules/try") local catch = require("sandbox/modules/catch") local vformat = require("sandbox/modules/vformat") @@ -72,7 +73,7 @@ function sandbox_utils.print(format, ...) { function () -- attempt to print format string first - utils._iowrite(vformat(format, unpack(args)) .. "\n") + utils._print(vformat(format, unpack(args))) end, catch { @@ -100,7 +101,7 @@ end function sandbox_utils.cprint(format, ...) -- done - utils._iowrite(colors(vformat(format, ...)) .. "\n") + utils._print(colors(vformat(format, ...))) end -- print format string, the builtin variables and colors without newline @@ -110,6 +111,20 @@ function sandbox_utils.cprintf(format, ...) utils._iowrite(colors(vformat(format, ...))) end +-- print() if enable verbose +function sandbox_utils.vprint(format, ...) + if option.get("verbose") then + sandbox_utils.print(format, ...) + end +end + +-- vprintf() if enable verbose +function sandbox_utils.vprintf(format, ...) + if option.get("verbose") then + sandbox_utils.printf(format, ...) + end +end + -- assert function sandbox_utils.assert(value, format, ...) @@ -126,7 +141,6 @@ function sandbox_utils.assert(value, format, ...) return value end - -- return module return sandbox_utils diff --git a/xmake/core/sandbox/modules/vprint.lua b/xmake/core/sandbox/modules/vprint.lua new file mode 100644 index 000000000..49064afae --- /dev/null +++ b/xmake/core/sandbox/modules/vprint.lua @@ -0,0 +1,27 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file vprint.lua +-- + +-- load module +return require("sandbox/modules/utils").vprint + diff --git a/xmake/core/sandbox/modules/vprintf.lua b/xmake/core/sandbox/modules/vprintf.lua new file mode 100644 index 000000000..58f211666 --- /dev/null +++ b/xmake/core/sandbox/modules/vprintf.lua @@ -0,0 +1,27 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file vprintf.lua +-- + +-- load module +return require("sandbox/modules/utils").vprintf + diff --git a/xmake/modules/detect/tools/find_ping.lua b/xmake/modules/detect/tools/find_ping.lua new file mode 100644 index 000000000..ae3d571bf --- /dev/null +++ b/xmake/modules/detect/tools/find_ping.lua @@ -0,0 +1,48 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_ping.lua +-- + +-- imports +import("lib.detect.find_program") + +-- find ping +-- +-- +-- @param opt the argument options +-- +-- @return program +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + return find_program(opt.program or "ping", opt.pathes, opt.check or function (program) + if os.host() == "windows" then + os.run("%s -n 1 127.0.0.1", program) + else + os.run("%s -c 1 127.0.0.1", program) + end + end) +end diff --git a/xmake/modules/devel/git/checkurl.lua b/xmake/modules/devel/git/checkurl.lua new file mode 100644 index 000000000..225351458 --- /dev/null +++ b/xmake/modules/devel/git/checkurl.lua @@ -0,0 +1,35 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file checkurl.lua +-- + +-- check git url +-- +-- @param url is git url? +-- +-- @return true or false +-- +function main(url) + + -- check it + return url:endswith(".git") or os.isdir(url .. ".git") +end diff --git a/xmake/modules/devel/git/refs.lua b/xmake/modules/devel/git/refs.lua index 306b2fd26..7af98b854 100644 --- a/xmake/modules/devel/git/refs.lua +++ b/xmake/modules/devel/git/refs.lua @@ -30,13 +30,13 @@ import("ls_remote") -- -- @param url the remote url, optional -- --- @return the refs +-- @return the tags, branches -- -- @code -- -- import("devel.git") -- --- local refs = git.refs(url) +-- local tags, branches = git.refs(url) -- -- @endcode -- @@ -45,7 +45,7 @@ function main(url) -- get refs local refs = ls_remote("refs", url) if not refs or #refs == 0 then - return {} + return {}, {} end -- get tags and branches @@ -60,5 +60,5 @@ function main(url) end -- ok - return {tags = tags, branches = branches} + return tags, branches end diff --git a/xmake/modules/net/fasturl.lua b/xmake/modules/net/fasturl.lua new file mode 100644 index 000000000..8cc90f035 --- /dev/null +++ b/xmake/modules/net/fasturl.lua @@ -0,0 +1,92 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file fasturl.lua +-- + +-- imports +import("ping") + +-- parse host from url +function _parse_host(url) + + -- init host cache + _g._URLHOSTS = _g._URLHOSTS or {} + + -- http[s]://xxx.com/.. or [email protected]:xxx/xxx.git + local host = _g._URLHOSTS[url] or url:match("://(.-)/") or url:match("@(.-):") + + -- save to cache + _g._URLHOSTS[url] = host + + -- ok + return host +end + +-- add urls +function add(urls) + + -- get current ping info + local pinginfo = _g._PINGINFO or {} + + -- add ping hosts + _g._PINGHOSTS = _g._PINGHOSTS or {} + for _, url in ipairs(urls) do + + -- parse host + local host = _parse_host(url) + + -- this host has not been tested? + if host and not pinginfo[host] then + table.insert(_g._PINGHOSTS, host) + end + end +end + +-- sort urls +function sort(urls) + + -- ping hosts + local pinghosts = table.unique(_g._PINGHOSTS or {}) + if pinghosts and #pinghosts > 0 then + + -- ping them and test speed + local pinginfo = ping(unpack(pinghosts)) + + -- merge to ping info + _g._PINGINFO = table.join(_g._PINGINFO or {}, pinginfo) + end + + -- sort urls by the ping info + local pinginfo = _g._PINGINFO or {} + table.sort(urls, function(a, b) + a = pinginfo[_parse_host(a) or ""] or 65536 + b = pinginfo[_parse_host(b) or ""] or 65536 + return a < b + end) + + -- clear hosts + _g._PINGHOSTS = {} + + -- ok + return urls +end + diff --git a/xmake/modules/net/ping.lua b/xmake/modules/net/ping.lua new file mode 100644 index 000000000..9a2bd21f2 --- /dev/null +++ b/xmake/modules/net/ping.lua @@ -0,0 +1,73 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file ping.lua +-- + +-- imports +import("detect.tools.find_ping") + +-- send ping to hosts +-- +-- @param ... the hosts +-- +-- @return the time or -1 +-- +function main(...) + + -- find ping + local ping = find_ping() + if not ping then + return {} + end + + -- run tasks + local hosts = {...} + local results = {} + process.runjobs(function (index) + local host = hosts[index] + if host then + try + { + function () + + -- ping it + local data = nil + if os.host() == "windows" then + data = os.iorun("%s -n 1 %s", ping, host) + else + data = os.iorun("%s -c 1 %s", ping, host) + end + + -- find time + local time = data:match("time=(.-)ms", 1, true) + if time then + results[host] = tonumber(time:trim()) + end + end + } + end + end, #hosts) + + -- ok? + return results +end + diff --git a/xmake/plugins/doxygen/main.lua b/xmake/plugins/doxygen/main.lua index c13327959..fe9c0df4d 100644 --- a/xmake/plugins/doxygen/main.lua +++ b/xmake/plugins/doxygen/main.lua @@ -44,9 +44,6 @@ function main() -- load configure config.load() - -- load project - project.load() - -- enable recursive -- -- RECURSIVE = YES diff --git a/xmake/plugins/macro/macros/package.lua b/xmake/plugins/macro/macros/package.lua index 27f15969c..c9fef7977 100644 --- a/xmake/plugins/macro/macros/package.lua +++ b/xmake/plugins/macro/macros/package.lua @@ -73,9 +73,6 @@ function main(argv) -- load configure config.load() - -- load project - project.load() - -- enter the project directory os.cd(project.directory()) diff --git a/xmake/plugins/project/vstudio/impl/vs200x_solution.lua b/xmake/plugins/project/vstudio/impl/vs200x_solution.lua index b076d35bd..26117a557 100644 --- a/xmake/plugins/project/vstudio/impl/vs200x_solution.lua +++ b/xmake/plugins/project/vstudio/impl/vs200x_solution.lua @@ -43,12 +43,12 @@ function _make_projects(slnfile, vsinfo) if not target:isphony() then -- enter project - slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.vcproj\", \"{%s}\"", vctool, targetname, targetname, targetname, os.uuid(targetname)) + slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.vcproj\", \"{%s}\"", vctool, targetname, targetname, targetname, hash.uuid(targetname)) -- add dependences for _, dep in ipairs(target:get("deps")) do slnfile:enter("ProjectSection(ProjectDependencies) = postProject") - slnfile:print("{%s} = {%s}", os.uuid(dep), os.uuid(dep)) + slnfile:print("{%s} = {%s}", hash.uuid(dep), hash.uuid(dep)) slnfile:leave("EndProjectSection") end @@ -73,8 +73,8 @@ function _make_global(slnfile, vsinfo) slnfile:enter("GlobalSection(ProjectConfigurationPlatforms) = postSolution") for targetname, target in pairs(project.targets()) do if not target:isphony() then - slnfile:print("{%s}.$(mode)|Win32.ActiveCfg = $(mode)|Win32", os.uuid(targetname)) - slnfile:print("{%s}.$(mode)|Win32.Build.0 = $(mode)|Win32", os.uuid(targetname)) + slnfile:print("{%s}.$(mode)|Win32.ActiveCfg = $(mode)|Win32", hash.uuid(targetname)) + slnfile:print("{%s}.$(mode)|Win32.Build.0 = $(mode)|Win32", hash.uuid(targetname)) end end slnfile:leave("EndGlobalSection") diff --git a/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua b/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua index 102ab8399..eb0706cf8 100644 --- a/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua @@ -133,7 +133,7 @@ function _make_header(vcprojfile, vsinfo, target) vcprojfile:print("ProjectType=\"Visual C++\"") vcprojfile:print("Version=\"%s0\"", assert(versions["vs" .. vsinfo.vstudio_version])) vcprojfile:print("Name=\"%s\"", targetname) - vcprojfile:print("ProjectGUID=\"{%s}\"", os.uuid(targetname)) + vcprojfile:print("ProjectGUID=\"{%s}\"", hash.uuid(targetname)) vcprojfile:print("RootNamespace=\"%s\"", targetname) vcprojfile:print("TargetFrameworkVersion=\"196613\"") vcprojfile:print(">") diff --git a/xmake/plugins/project/vstudio/impl/vs201x_solution.lua b/xmake/plugins/project/vstudio/impl/vs201x_solution.lua index 40ac3e0f5..73bc1655d 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_solution.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_solution.lua @@ -43,12 +43,12 @@ function _make_projects(slnfile, vsinfo) if not target:isphony() then -- enter project - slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.vcxproj\", \"{%s}\"", vctool, targetname, targetname, targetname, os.uuid(targetname)) + slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.vcxproj\", \"{%s}\"", vctool, targetname, targetname, targetname, hash.uuid(targetname)) -- add dependences for _, dep in ipairs(target:get("deps")) do slnfile:enter("ProjectSection(ProjectDependencies) = postProject") - slnfile:print("{%s} = {%s}", os.uuid(dep), os.uuid(dep)) + slnfile:print("{%s} = {%s}", hash.uuid(dep), hash.uuid(dep)) slnfile:leave("EndProjectSection") end @@ -79,8 +79,8 @@ function _make_global(slnfile, vsinfo) if not target:isphony() then for _, mode in ipairs(vsinfo.modes) do for _, arch in ipairs({"x86", "x64"}) do - slnfile:print("{%s}.%s|%s.ActiveCfg = %s|%s", os.uuid(targetname), mode, arch, mode, arch) - slnfile:print("{%s}.%s|%s.Build.0 = %s|%s", os.uuid(targetname), mode, arch, mode, arch) + slnfile:print("{%s}.%s|%s.ActiveCfg = %s|%s", hash.uuid(targetname), mode, arch, mode, arch) + slnfile:print("{%s}.%s|%s.Build.0 = %s|%s", hash.uuid(targetname), mode, arch, mode, arch) end end end diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 7abe20a54..fbff38a72 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -157,7 +157,7 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) -- make Globals vcxprojfile:enter("<PropertyGroup Label=\"Globals\">") - vcxprojfile:print("<ProjectGuid>{%s}</ProjectGuid>", os.uuid(targetname)) + vcxprojfile:print("<ProjectGuid>{%s}</ProjectGuid>", hash.uuid(targetname)) vcxprojfile:print("<RootNamespace>%s</RootNamespace>", targetname) if vsinfo.vstudio_version >= "2015" then vcxprojfile:print("<WindowsTargetPlatformVersion>%s</WindowsTargetPlatformVersion>", sdkver or sdk_versions["vs" .. vsinfo.vstudio_version]) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua index f15fa9c5f..7361611e2 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua @@ -75,7 +75,7 @@ function _make_filters(filtersfile, vsinfo, target, vcxprojdir) while filter and filter ~= '.' do
if not exists[filter] then
filtersfile:enter("<Filter Include=\"%s\">", filter)
- filtersfile:print("<UniqueIdentifier>{%s}</UniqueIdentifier>", os.uuid(filter))
+ filtersfile:print("<UniqueIdentifier>{%s}</UniqueIdentifier>", hash.uuid(filter))
filtersfile:leave("</Filter>")
exists[filter] = true
end
diff --git a/xmake/plugins/repo/main.lua b/xmake/plugins/repo/main.lua new file mode 100644 index 000000000..58d9b2090 --- /dev/null +++ b/xmake/plugins/repo/main.lua @@ -0,0 +1,158 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file main.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.project") +import("core.platform.platform") +import("core.package.repository") +import("devel.git") + +-- add repository url +function _add(name, url, is_global) + + -- add url + repository.add(name, url, is_global) + + -- remove previous repository if exists + local repodir = path.join(repository.directory(is_global), name) + if os.isdir(repodir) then + os.rmdir(repodir) + end + + -- clone repository + git.clone(url, {verbose = option.get("verbose"), branch = "master", outputdir = repodir}) + + -- trace + cprint("${bright}add %s repository(%s): %s ok!", ifelse(is_global, "global", "local"), name, url) +end + +-- remove repository url +function _remove(name, is_global) + + -- remove url + repository.remove(name, is_global) + + -- remove repository + local repodir = path.join(repository.directory(is_global), name) + if os.isdir(repodir) then + os.rmdir(repodir) + end + + -- trace + cprint("${bright}remove %s repository(%s): %s ok!", ifelse(is_global, "global", "local"), name, url) +end + +-- clear all repositories +function _clear(is_global) + + -- clear all urls + repository.clear(is_global) + + -- remove all repositories + local repodir = repository.directory(is_global) + if os.isdir(repodir) then + os.rmdir(repodir) + end + + -- trace + cprint("${bright}clear %s repositories: ok!", ifelse(is_global, "global", "local")) +end + +-- list all repositories +function _list(is_global) + + -- list all repositories + local count = 0 + for _, position in ipairs({"local", "global"}) do + + -- trace + print("%s repositories:", position) + + -- list all + for _, repo in pairs(repository.repositories(position == "global")) do + + -- trace + print(" %s %s", repo.name, repo.url) + + -- update count + count = count + 1 + end + + -- trace + print("") + end + + -- trace + print("%d repositories were found!", count) +end + +-- load project +function _load_project() + + -- enter project directory + os.cd(project.directory()) + + -- load config + config.load() + + -- load platform + platform.load(config.plat()) +end + +-- main +function main() + + -- load project if operate local repositories + if not option.get("global") then + _load_project() + end + + -- add repository url + if option.get("add") then + + _add(option.get("name"), option.get("url"), option.get("global")) + + -- remove repository url + elseif option.get("remove") then + + _remove(option.get("name"), option.get("global")) + + -- clear all repositories + elseif option.get("clear") then + + _clear(option.get("global")) + + -- list all repositories + elseif option.get("list") then + + _list(option.get("global")) + + -- show help + else + option.show_help() + end +end + diff --git a/xmake/plugins/repo/xmake.lua b/xmake/plugins/repo/xmake.lua new file mode 100644 index 000000000..6f38fdc12 --- /dev/null +++ b/xmake/plugins/repo/xmake.lua @@ -0,0 +1,54 @@ +--!The Make-like Build Utility based on Lua +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2017, TBOOX Open Source Group. +-- +-- @author ruki +-- @file repo.lua +-- + +-- define task +task("repo") + + -- set category + set_category("plugin") + + -- on run + on_run("main") + + -- set menu + set_menu { + -- usage + usage = "xmake repo [options] [name] [url]" + + -- description + , description = "Manage package repositories." + + -- options + , options = + { + {'a', "add", "k", nil, "Add the given remote repository url." } + , {'r', "remove", "k", nil, "Remove the given remote repository url." } + , {'l', "list", "k", nil, "List all added repositories." } + , {'g', "global", "k", nil, "Save repository to global. (default: local)" } + , {'c', "clear", "k", nil, "Clear all added repositories." } + , { } + , {nil, "name", "v", nil, "The repository name." } + , {nil, "url", "v", nil, "The repository url" } + } + } |
