summaryrefslogtreecommitdiff
path: root/xmake/core/package/package.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2017-08-14 11:27:19 +0800
committerruki <[email protected]>2017-08-14 11:29:30 +0800
commitdba45d143d8aff047da82cbe1a881056e6e4bc00 (patch)
tree7b80d5de264c17b538a7c9d0fbb234ded39ac683 /xmake/core/package/package.lua
parent34706ba053dda9dd86902cacf42a6c1878c85234 (diff)
merge repo and require codes
Diffstat (limited to 'xmake/core/package/package.lua')
-rw-r--r--xmake/core/package/package.lua419
1 files changed, 419 insertions, 0 deletions
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