summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-07-14 22:39:14 +0800
committerruki <[email protected]>2024-07-15 12:21:42 +0800
commit6fd249647eb5cf6a44982c35e0564c7733da5457 (patch)
tree202e6e520e2ba1b350386cbd2b4a5d38612e3a44
parentc58ab2c62721a69b81a127578b88ab678f5dc112 (diff)
rewrite install
-rw-r--r--xmake/modules/target/action/install/main.lua170
-rw-r--r--xmake/modules/target/action/install/unix.lua161
-rw-r--r--xmake/modules/target/action/install/windows.lua159
-rw-r--r--xmake/plugins/pack/batchcmds.lua68
4 files changed, 188 insertions, 370 deletions
diff --git a/xmake/modules/target/action/install/main.lua b/xmake/modules/target/action/install/main.lua
index c115e836e..07089c60e 100644
--- a/xmake/modules/target/action/install/main.lua
+++ b/xmake/modules/target/action/install/main.lua
@@ -18,6 +18,36 @@
-- @file main.lua
--
+-- imports
+import("core.base.option")
+import("core.base.hashset")
+import("utils.symbols.depend", {alias = "get_depend_libraries"})
+
+function _get_target_package_libfiles(target, opt)
+ local libfiles = {}
+ for _, pkg in ipairs(target:orderpkgs(opt)) do
+ if pkg:enabled() and pkg:get("libfiles") then
+ for _, libfile in ipairs(table.wrap(pkg:get("libfiles"))) do
+ local filename = path.filename(libfile)
+ if filename:endswith(".dll") or filename:endswith(".so") or filename:find("%.so%.%d+$") or filename:endswith(".dylib") then
+ table.insert(libfiles, libfile)
+ end
+ end
+ end
+ end
+ -- we can only reserve used libraries
+ if target:is_binary() or target:is_shared() then
+ local depends = hashset.new()
+ local targetfile = target:targetfile()
+ local depend_libraries = get_depend_libraries(targetfile, {plat = target:plat(), arch = target:arch()})
+ for _, libfile in ipairs(depend_libraries) do
+ depends:insert(path.filename(libfile))
+ end
+ table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end)
+ end
+ return libfiles
+end
+
-- install files
function _install_files(target)
local srcfiles, dstfiles = target:installfiles()
@@ -33,25 +63,143 @@ function _install_files(target)
end
end
--- the builtin install main entry
-function main(target, opt)
+-- install headers
+function _install_headers(target, opt)
+ local includedir = target:includedir()
+ os.mkdir(includedir)
+ local srcheaders, dstheaders = target:headerfiles(includedir, {installonly = true})
+ if srcheaders and dstheaders then
+ local i = 1
+ for _, srcheader in ipairs(srcheaders) do
+ local dstheader = dstheaders[i]
+ if dstheader then
+ os.vcp(srcheader, dstheader)
+ end
+ i = i + 1
+ end
+ end
+end
+
+-- install shared libraries
+function _install_shared_libraries(target, opt)
+ local bindir = target:is_plat("windows", "mingw") and target:bindir() or target:libdir()
+
+ -- get all dependent shared libraries
+ local libfiles = {}
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:kind() == "shared" then
+ local depfile = dep:targetfile()
+ if os.isfile(depfile) then
+ table.insert(libfiles, depfile)
+ end
+ end
+ table.join2(libfiles, _get_target_package_libfiles(dep, {interface = true}))
+ end
+ table.join2(libfiles, _get_target_package_libfiles(target))
+
+ -- deduplicate libfiles, prevent packages using the same libfiles from overwriting each other
+ libfiles = table.unique(libfiles)
+
+ -- do install
+ for _, libfile in ipairs(libfiles) do
+ local filename = path.filename(libfile)
+ local filepath = path.join(bindir, filename)
+ if os.isfile(filepath) then
+ wprint("'%s' already exists in install dir, we are copying '%s' to overwrite it.", filepath, libfile)
+ end
+ os.cp(libfile, filepath)
+ end
+end
+
+-- install binary
+function _install_binary(target, opt)
+ local bindir = target:bindir()
+ os.mkdir(bindir)
+ os.vcp(target:targetfile(), bindir)
+ os.trycp(target:symbolfile(), path.join(bindir, path.filename(target:symbolfile())))
+ _install_shared_libraries(target, opt)
+end
+
+-- install shared library
+function _install_shared(target, opt)
+ local bindir = target:is_plat("windows", "mingw") and target:bindir() or target:libdir()
+ os.mkdir(bindir)
+ local targetfile = target:targetfile()
+
+ if target:is_plat("windows", "mingw") then
+ -- install *.lib for shared/windows (*.dll) target
+ -- @see https://github.com/xmake-io/xmake/issues/714
+ os.vcp(target:targetfile(), bindir)
+ local libdir = target:libdir()
+ local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib"))
+ if os.isfile(targetfile_lib) then
+ os.mkdir(libdir)
+ os.vcp(targetfile_lib, libdir)
+ end
+ else
+ -- install target with soname and symlink
+ if os.islink(targetfile) then
+ local targetfile_with_soname = os.readlink(targetfile)
+ if not path.is_absolute(targetfile_with_soname) then
+ targetfile_with_soname = path.join(target:targetdir(), targetfile_with_soname)
+ end
+ if os.islink(targetfile_with_soname) then
+ local targetfile_with_version = os.readlink(targetfile_with_soname)
+ if not path.is_absolute(targetfile_with_version) then
+ targetfile_with_version = path.join(target:targetdir(), targetfile_with_version)
+ end
+ os.vcp(targetfile_with_version, bindir, {symlink = true, force = true})
+ end
+ os.vcp(targetfile_with_soname, bindir, {symlink = true, force = true})
+ os.vcp(targetfile, bindir, {symlink = true, force = true})
+ else
+ os.vcp(targetfile, bindir)
+ end
+ end
+ os.trycp(target:symbolfile(), path.join(bindir, path.filename(target:symbolfile())))
+
+ _install_headers(target, opt)
+ _install_shared_libraries(target, opt)
+end
- -- get install directory
+-- install static library
+function _install_static(target, opt)
+ local libdir = target:libdir()
+ os.mkdir(libdir)
+ os.vcp(target:targetfile(), libdir)
+ os.trycp(target:symbolfile(), path.join(libdir, path.filename(target:symbolfile())))
+ _install_headers(target, opt)
+end
+
+-- install headeronly library
+function _install_headeronly(target, opt)
+ _install_headers(target, opt)
+end
+
+-- install moduleonly library
+function _install_moduleonly(target, opt)
+ _install_headers(target, opt)
+end
+
+function main(target, opt)
local installdir = target:installdir()
if not installdir then
+ wprint("please use `xmake install -o installdir` or `set_installdir` to set install directory.")
return
end
-
- -- trace
print("installing %s to %s ..", target:name(), installdir)
- -- call script
- local install_style = target:is_plat("windows", "mingw") and "windows" or "unix"
- local script = import(install_style, {anonymous = true})["install_" .. target:kind()]
- if script then
- script(target, opt)
+ if target:is_binary() then
+ _install_binary(target, opt)
+ elseif target:is_shared() then
+ _install_shared(target, opt)
+ elseif target:is_static() then
+ _install_static(target, opt)
+ elseif target:is_headeronly() then
+ _install_headeronly(target, opt)
+ elseif target:is_moduleonly() then
+ _install_moduleonly(target, opt)
end
- -- install other files
_install_files(target)
end
diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua
deleted file mode 100644
index dc1354519..000000000
--- a/xmake/modules/target/action/install/unix.lua
+++ /dev/null
@@ -1,161 +0,0 @@
---!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 unix.lua
---
-
--- imports
-import("core.base.option")
-
--- install headers
-function _install_headers(target, opt)
- local includedir = target:includedir()
- os.mkdir(includedir)
- local srcheaders, dstheaders = target:headerfiles(includedir, {installonly = true})
- if srcheaders and dstheaders then
- local i = 1
- for _, srcheader in ipairs(srcheaders) do
- local dstheader = dstheaders[i]
- if dstheader then
- os.vcp(srcheader, dstheader)
- end
- i = i + 1
- end
- end
-end
-
--- install shared libraries for package
-function _install_shared_for_package(target, pkg, outputdir)
- _g.installed_libfiles = _g.installed_libfiles or {}
- for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do
- if sopath:endswith(".so") or sopath:match(".+%.so%..+$") or sopath:endswith(".dylib") then
- -- prevent packages using the same system libfiles from overwriting each other
- if not _g.installed_libfiles[sopath] then
- local soname = path.filename(sopath)
- local targetname = path.join(outputdir, soname)
- if os.isfile(targetname) then
- wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name())
- -- rm because symlink cannot overwrite existing file
- os.rm(targetname)
- end
- -- we need to reserve symlink
- -- @see https://github.com/xmake-io/xmake/issues/1582
- os.vcp(sopath, outputdir, {symlink = true, force = true})
- _g.installed_libfiles[sopath] = true
- end
- end
- end
-end
-
--- install shared libraries for packages
-function _install_shared_for_packages(target, outputdir)
- if option.get("nopkgs") then
- return
- end
- _g.installed_packages = _g.installed_packages or {}
- for _, pkg in ipairs(target:orderpkgs()) do
- if not _g.installed_packages[pkg:name()] then
- if pkg:enabled() and pkg:get("libfiles") then
- _install_shared_for_package(target, pkg, outputdir)
- end
- _g.installed_packages[pkg:name()] = true
- end
- end
-end
-
--- install binary
-function install_binary(target, opt)
-
- -- install binary
- local bindir = target:bindir()
- os.mkdir(bindir)
- os.vcp(target:targetfile(), bindir)
-
- -- install libraries
- local libdir = target:libdir()
- os.mkdir(libdir)
-
- -- install the dependent shared (*.so) target
- -- @see https://github.com/xmake-io/xmake/issues/961
- for _, dep in ipairs(target:orderdeps()) do
- if dep:kind() == "shared" then
- local depfile = dep:targetfile()
- if os.isfile(depfile) then
- os.vcp(depfile, libdir)
- end
- end
- -- install all shared libraries in packages in all deps
- _install_shared_for_packages(dep, libdir)
- end
-
- -- install shared libraries for all packages
- _install_shared_for_packages(target, libdir)
-end
-
--- install shared library
-function install_shared(target, opt)
-
- -- install libraries
- local libdir = target:libdir()
- os.mkdir(libdir)
- local targetfile = target:targetfile()
- if os.islink(targetfile) then
- local targetfile_with_soname = os.readlink(targetfile)
- if not path.is_absolute(targetfile_with_soname) then
- targetfile_with_soname = path.join(target:targetdir(), targetfile_with_soname)
- end
- if os.islink(targetfile_with_soname) then
- local targetfile_with_version = os.readlink(targetfile_with_soname)
- if not path.is_absolute(targetfile_with_version) then
- targetfile_with_version = path.join(target:targetdir(), targetfile_with_version)
- end
- os.vcp(targetfile_with_version, libdir, {symlink = true, force = true})
- end
- os.vcp(targetfile_with_soname, libdir, {symlink = true, force = true})
- os.vcp(targetfile, libdir, {symlink = true, force = true})
- else
- os.vcp(targetfile, libdir)
- end
-
- -- install shared libraries for all packages
- _install_shared_for_packages(target, libdir)
-
- -- install headers
- _install_headers(target, opt)
-end
-
--- install static library
-function install_static(target, opt)
-
- -- install libraries
- local libdir = target:libdir()
- os.mkdir(libdir)
- os.vcp(target:targetfile(), libdir)
-
- -- install headers
- _install_headers(target, opt)
-end
-
--- install headeronly library
-function install_headeronly(target, opt)
- _install_headers(target, opt)
-end
-
--- install moduleonly library
-function install_moduleonly(target, opt)
- _install_headers(target, opt)
-end
diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua
deleted file mode 100644
index c52c1c934..000000000
--- a/xmake/modules/target/action/install/windows.lua
+++ /dev/null
@@ -1,159 +0,0 @@
---!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 windows.lua
---
-
--- imports
-import("core.base.option")
-import("lib.detect.find_file")
-
--- check install directory
-function _check_installdir(installdir)
- return assert(installdir, "please use `xmake install -o installdir` or `set_installdir` to set install directory on windows.")
-end
-
--- install headers
-function _install_headers(target, opt)
- local includedir = _check_installdir(target:includedir())
- os.mkdir(includedir)
- local srcheaders, dstheaders = target:headerfiles(includedir, {installonly = true})
- if srcheaders and dstheaders then
- local i = 1
- for _, srcheader in ipairs(srcheaders) do
- local dstheader = dstheaders[i]
- if dstheader then
- os.vcp(srcheader, dstheader)
- end
- i = i + 1
- end
- end
-end
-
--- install shared libraries for package
-function _install_shared_for_package(target, pkg, outputdir)
- _g.installed_dllfiles = _g.installed_dllfiles or {}
- for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do
- if dllpath:endswith(".dll") then
- -- prevent packages using the same libfiles from overwriting each other
- if not _g.installed_dllfiles[dllpath] then
- local dllname = path.filename(dllpath)
- if os.isfile(path.join(outputdir, dllname)) then
- wprint("'%s' already exists in install dir, overwriting it from package(%s).", dllname, pkg:name())
- end
- os.vcp(dllpath, outputdir)
- _g.installed_dllfiles[dllpath] = true
- end
- end
- end
-end
-
--- install shared libraries for packages
-function _install_shared_for_packages(target, outputdir)
- if option.get("nopkgs") then
- return
- end
- _g.installed_packages = _g.installed_packages or {}
- for _, pkg in ipairs(target:orderpkgs()) do
- if not _g.installed_packages[pkg:name()] then
- if pkg:enabled() and pkg:get("libfiles") then
- _install_shared_for_package(target, pkg, outputdir)
- end
- _g.installed_packages[pkg:name()] = true
- end
- end
-end
-
--- install binary
-function install_binary(target, opt)
-
- -- install binary
- local installdir = _get_installdir(target)
- local bindir = path.join(installdir, opt and opt.bindir or "bin")
- os.mkdir(bindir)
- os.vcp(target:targetfile(), bindir)
- os.trycp(target:symbolfile(), bindir)
-
- -- install the dependent shared/windows (*.dll) target
- -- @see https://github.com/xmake-io/xmake/issues/961
- _g.installed_dllfiles = _g.installed_dllfiles or {}
- for _, dep in ipairs(target:orderdeps()) do
- if dep:kind() == "shared" then
- local depfile = dep:targetfile()
- if os.isfile(depfile) then
- if not _g.installed_dllfiles[depfile] then
- os.vcp(depfile, bindir)
- _g.installed_dllfiles[depfile] = true
- end
- end
- end
- -- install all shared libraries in packages in all deps
- _install_shared_for_packages(dep, bindir)
- end
-
- -- install shared libraries for all packages
- _install_shared_for_packages(target, bindir)
-end
-
--- install shared library
-function install_shared(target, opt)
-
- -- install dll library to the binary directory
- local bindir = _check_installdir(target:bindir())
- os.mkdir(bindir)
- os.vcp(target:targetfile(), bindir)
- os.trycp(target:symbolfile(), bindir)
-
- -- install *.lib for shared/windows (*.dll) target
- -- @see https://github.com/xmake-io/xmake/issues/714
- local targetfile = target:targetfile()
- local libdir = _check_installdir(target:libdir())
- local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib"))
- if os.isfile(targetfile_lib) then
- os.mkdir(libdir)
- os.vcp(targetfile_lib, libdir)
- end
-
- -- install shared libraries for all packages
- _install_shared_for_packages(target, bindir)
-
- -- install headers
- _install_headers(target, opt)
-end
-
--- install static library
-function install_static(target, opt)
-
- -- install library
- local libdir = _check_installdir(target:libdir())
- os.mkdir(libdir)
- os.vcp(target:targetfile(), libdir)
- os.trycp(target:symbolfile(), libdir)
-
- -- install headers
- _install_headers(target, opt)
-end
-
--- install headeronly
-function install_headeronly(target, opt)
- _install_headers(target, opt)
-end
-
--- install moduleonly
-function install_moduleonly(target, opt)
- _install_headers(target, opt)
-end
diff --git a/xmake/plugins/pack/batchcmds.lua b/xmake/plugins/pack/batchcmds.lua
index 08216b15e..ff20729eb 100644
--- a/xmake/plugins/pack/batchcmds.lua
+++ b/xmake/plugins/pack/batchcmds.lua
@@ -61,6 +61,31 @@ function _get_target_installdir(package, target)
return path.normalize(installdir)
end
+function _get_target_package_libfiles(target, opt)
+ local libfiles = {}
+ for _, pkg in ipairs(target:orderpkgs(opt)) do
+ if pkg:enabled() and pkg:get("libfiles") then
+ for _, libfile in ipairs(table.wrap(pkg:get("libfiles"))) do
+ local filename = path.filename(libfile)
+ if filename:endswith(".dll") or filename:endswith(".so") or filename:find("%.so%.%d+$") or filename:endswith(".dylib") then
+ table.insert(libfiles, libfile)
+ end
+ end
+ end
+ end
+ -- we can only reserve used libraries
+ if target:is_binary() or target:is_shared() then
+ local depends = hashset.new()
+ local targetfile = target:targetfile()
+ local depend_libraries = get_depend_libraries(targetfile, {plat = target:plat(), arch = target:arch()})
+ for _, libfile in ipairs(depend_libraries) do
+ depends:insert(path.filename(libfile))
+ end
+ table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end)
+ end
+ return libfiles
+end
+
-- install headers
function _install_target_headers(target, batchcmds_, opt)
local package = opt.package
@@ -90,35 +115,10 @@ function _install_target_headers(target, batchcmds_, opt)
end
end
-function _get_target_package_libfiles(target, opt)
- local libfiles = {}
- for _, pkg in ipairs(target:orderpkgs(opt)) do
- if pkg:enabled() and pkg:get("libfiles") then
- for _, libfile in ipairs(table.wrap(pkg:get("libfiles"))) do
- local filename = path.filename(libfile)
- if filename:endswith(".dll") or filename:endswith(".so") or filename:find("%.so%.%d+$") or filename:endswith(".dylib") then
- table.insert(libfiles, libfile)
- end
- end
- end
- end
- -- we can only reserve used libraries
- if target:is_binary() or target:is_shared() then
- local depends = hashset.new()
- local targetfile = target:targetfile()
- local depend_libraries = get_depend_libraries(targetfile, {plat = target:plat(), arch = target:arch()})
- for _, libfile in ipairs(depend_libraries) do
- depends:insert(path.filename(libfile))
- end
- table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end)
- end
- return libfiles
-end
-
-- install target shared libraries
function _install_target_shared_libraries(target, batchcmds_, opt)
local package = opt.package
- local bindir = _get_target_bindir(package, target)
+ local bindir = target:is_plat("windows", "mingw") and _get_target_bindir(package, target) or _get_target_libdir(package, target)
-- get all dependent shared libraries
local libfiles = {}
@@ -161,7 +161,7 @@ end
-- uninstall target shared libraries
function _uninstall_target_shared_libraries(target, batchcmds_, opt)
local package = opt.package
- local bindir = _get_target_bindir(package, target)
+ local bindir = target:is_plat("windows", "mingw") and _get_target_bindir(package, target) or _get_target_libdir(package, target)
-- get all dependent shared libraries
local libfiles = {}
@@ -190,24 +190,19 @@ end
function _on_target_installcmd_binary(target, batchcmds_, opt)
local package = opt.package
local bindir = _get_target_bindir(package, target)
-
- -- install target file
batchcmds_:cp(target:targetfile(), path.join(bindir, target:filename()))
if os.isfile(target:symbolfile()) then
batchcmds_:cp(target:symbolfile(), path.join(bindir, path.filename(target:symbolfile())))
end
-
- -- install target shared libraries
_install_target_shared_libraries(target, batchcmds_, opt)
end
-- on install shared target command
function _on_target_installcmd_shared(target, batchcmds_, opt)
local package = opt.package
- local bindir = _get_target_bindir(package, target)
+ local bindir = target:is_plat("windows", "mingw") and _get_target_bindir(package, target) or _get_target_libdir(package, target)
local libdir = _get_target_libdir(package, target)
- -- install target file
batchcmds_:cp(target:targetfile(), path.join(bindir, target:filename()))
if os.isfile(target:symbolfile()) then
batchcmds_:cp(target:symbolfile(), path.join(bindir, path.filename(target:symbolfile())))
@@ -222,10 +217,7 @@ function _on_target_installcmd_shared(target, batchcmds_, opt)
batchcmds_:cp(targetfile_lib, path.join(libdir, path.filename(targetfile_lib)))
end
- -- install headers
_install_target_headers(target, batchcmds_, opt)
-
- -- install target shared libraries
_install_target_shared_libraries(target, batchcmds_, opt)
end
@@ -234,13 +226,11 @@ function _on_target_installcmd_static(target, batchcmds_, opt)
local package = opt.package
local libdir = _get_target_libdir(package, target)
- -- install target file
batchcmds_:cp(target:targetfile(), path.join(libdir, target:filename()))
if os.isfile(target:symbolfile()) then
batchcmds_:cp(target:symbolfile(), path.join(libdir, path.filename(target:symbolfile())))
end
- -- install headers
_install_target_headers(target, batchcmds_, opt)
end
@@ -310,7 +300,7 @@ end
-- on uninstall shared target command
function _on_target_uninstallcmd_shared(target, batchcmds_, opt)
local package = opt.package
- local bindir = _get_target_bindir(package, target)
+ local bindir = target:is_plat("windows", "mingw") and _get_target_bindir(package, target) or _get_target_libdir(package, target)
local libdir = _get_target_libdir(package, target)
-- uninstall target file