summaryrefslogtreecommitdiff
path: root/xmake/modules/private/package/impl/actions/install.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2021-02-12 22:53:12 +0800
committerruki <[email protected]>2021-02-12 22:53:12 +0800
commitcc7678dfae7d945b34b8abc70f18e26b8045fd9e (patch)
tree8f5959fb0ac52b39677530b40ad522e2aff385d2 /xmake/modules/private/package/impl/actions/install.lua
parentb29d4891a97dda8bc7a8b805651a77c0bb7698c0 (diff)
move require impl
Diffstat (limited to 'xmake/modules/private/package/impl/actions/install.lua')
-rw-r--r--xmake/modules/private/package/impl/actions/install.lua273
1 files changed, 273 insertions, 0 deletions
diff --git a/xmake/modules/private/package/impl/actions/install.lua b/xmake/modules/private/package/impl/actions/install.lua
new file mode 100644
index 000000000..8de1c3aa8
--- /dev/null
+++ b/xmake/modules/private/package/impl/actions/install.lua
@@ -0,0 +1,273 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed 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-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file install.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.tty")
+import("core.project.target")
+import("lib.detect.find_file")
+import("private.package.impl.actions.test")
+import("private.package.impl.actions.patch_sources")
+import("private.package.impl.actions.download_resources")
+import("private.package.impl.utils.filter")
+
+-- patch pkgconfig if not exists
+function _patch_pkgconfig(package)
+
+ -- only binary? need not pkgconfig
+ if not package:is_library() then
+ return
+ end
+
+ -- get lib/pkgconfig/*.pc file
+ local pkgconfigdir = path.join(package:installdir(), "lib", "pkgconfig")
+ local pcfile = os.isdir(pkgconfigdir) and find_file("*.pc", pkgconfigdir) or nil
+ if pcfile then
+ return
+ end
+
+ -- trace
+ pcfile = path.join(pkgconfigdir, package:name() .. ".pc")
+ vprint("patching %s ..", pcfile)
+
+ -- fetch package
+ local fetchinfo = package:fetchdeps()
+ if not fetchinfo then
+ return
+ end
+
+ -- get libs
+ local libs = ""
+ for _, linkdir in ipairs(fetchinfo.linkdirs) do
+ libs = libs .. "-L" .. linkdir
+ end
+ libs = libs .. " -L${libdir}"
+ for _, link in ipairs(fetchinfo.links) do
+ libs = libs .. " -l" .. link
+ end
+ for _, link in ipairs(fetchinfo.syslinks) do
+ libs = libs .. " -l" .. link
+ end
+
+ -- cflags
+ local cflags = ""
+ for _, includedir in ipairs(fetchinfo.includedirs) do
+ cflags = cflags .. "-I" .. includedir
+ end
+ cflags = cflags .. " -I${includedir}"
+
+ -- patch a *.pc file
+ local file = io.open(pcfile, 'w')
+ if file then
+ file:print("prefix=%s", package:installdir())
+ file:print("exec_prefix=${prefix}")
+ file:print("libdir=${exec_prefix}/lib")
+ file:print("includedir=${prefix}/include")
+ file:print("")
+ file:print("Name: %s", package:name())
+ file:print("Description: %s", package:description())
+ file:print("Version: %s", package:version_str())
+ file:print("Libs: %s", libs)
+ file:print("Libs.private: ")
+ file:print("Cflags: %s", cflags)
+ file:close()
+ end
+end
+
+-- install the given package
+function main(package)
+
+ -- get working directory of this package
+ local workdir = package:cachedir()
+
+ -- lock this package
+ package:lock()
+
+ -- enter the working directory
+ local oldir = nil
+ if #package:urls() > 0 then
+ -- only one root directory? skip it
+ local filedirs = os.filedirs(path.join(workdir, "source", "*"))
+ if #filedirs == 1 and os.isdir(filedirs[1]) then
+ oldir = os.cd(filedirs[1])
+ else
+ oldir = os.cd(path.join(workdir, "source"))
+ end
+ end
+ if not oldir then
+ os.mkdir(workdir)
+ oldir = os.cd(workdir)
+ end
+
+ -- init tipname
+ local tipname = package:name()
+ if package:version_str() then
+ tipname = tipname .. "-" .. package:version_str()
+ end
+
+ -- install it
+ try
+ {
+ function ()
+
+ -- the package scripts
+ local scripts =
+ {
+ package:script("install_before")
+ , package:script("install")
+ , package:script("install_after")
+ }
+
+ -- install the third-party package directly, e.g. brew::pcre2/libpcre2-8, conan::OpenSSL/1.0.2n@conan/stable
+ local installed_now = false
+ if package:is3rd() then
+ local script = package:script("install")
+ if script ~= nil then
+ filter.call(script, package)
+ end
+ else
+
+ -- build and install package to the install directory
+ if option.get("force") or not package:manifest_load() then
+
+ -- clean install directory first
+ os.tryrm(package:installdir())
+
+ -- enter the environments of all package dependencies
+ for _, dep in ipairs(package:orderdeps()) do
+ dep:envs_enter()
+ end
+
+ -- download package resources
+ download_resources(package)
+
+ -- patch source codes of package
+ patch_sources(package)
+
+ -- do install
+ for i = 1, 3 do
+ local script = scripts[i]
+ if script ~= nil then
+ filter.call(script, package)
+ end
+ end
+
+ -- leave the environments of all package dependencies
+ for _, dep in irpairs(package:orderdeps()) do
+ dep:envs_leave()
+ end
+
+ -- save the package info to the manifest file
+ package:manifest_save()
+ installed_now = true
+ end
+ end
+
+ -- enter the package environments
+ for _, dep in ipairs(package:orderdeps()) do
+ dep:envs_enter()
+ end
+ package:envs_enter()
+
+ -- fetch package and force to flush the cache
+ local fetchinfo = package:fetch({force = true})
+ if option.get("verbose") or option.get("diagnosis") then
+ print(fetchinfo)
+ end
+ assert(fetchinfo, "fetch %s failed!", tipname)
+
+ -- this package is installed now
+ if installed_now then
+
+ -- patch pkg-config files for package
+ _patch_pkgconfig(package)
+
+ -- test it
+ test(package)
+ end
+
+ -- leave the package environments
+ package:envs_leave()
+ for _, dep in irpairs(package:orderdeps()) do
+ dep:envs_leave()
+ end
+
+ -- trace
+ tty.erase_line_to_start().cr()
+ cprint("${yellow} => ${clear}install %s %s .. ${color.success}${text.success}", package:displayname(), package:version_str() or "")
+ end,
+
+ catch
+ {
+ function (errors)
+
+ -- show or save the last errors
+ local errorfile = path.join(package:installdir("logs"), "install.txt")
+ if errors then
+ if (option.get("verbose") or option.get("diagnosis")) then
+ cprint("${dim color.error}error: ${clear}%s", errors)
+ else
+ io.writefile(errorfile, errors .. "\n")
+ end
+ end
+
+ -- trace
+ tty.erase_line_to_start().cr()
+ cprint("${yellow} => ${clear}install %s %s .. ${color.failure}${text.failure}", package:displayname(), package:version_str() or "")
+
+ -- leave the package environments
+ package:envs_leave()
+
+ -- copy the invalid package directory to cache
+ local installdir = package:installdir()
+ if os.isdir(installdir) then
+ local installdir_failed = path.join(package:cachedir(), "installdir.failed")
+ os.tryrm(installdir_failed)
+ if not os.isdir(installdir_failed) then
+ os.cp(installdir, installdir_failed)
+ end
+ errorfile = path.join(installdir_failed, "logs", "install.txt")
+ end
+ os.tryrm(installdir)
+
+ -- failed
+ if not package:requireinfo().optional then
+ if os.isfile(errorfile) then
+ print("if you want to get verbose errors, please see:")
+ cprint(" -> ${bright}%s", errorfile)
+ end
+ raise("install failed!")
+ end
+ end
+ }
+ }
+
+ -- clean the empty package directory
+ local installdir = package:installdir()
+ if os.emptydir(installdir) then
+ os.tryrm(installdir)
+ end
+
+ -- unlock this package
+ package:unlock()
+
+ -- leave source codes directory
+ os.cd(oldir)
+end