summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-07-14 23:02:23 +0800
committerruki <[email protected]>2024-07-15 12:21:42 +0800
commite128b029dbfa5e3ab5156afd12a7a412c2bb6aad (patch)
tree5074c2d71635d82950c96f0b0ea995fc1e0a19c8
parent6fd249647eb5cf6a44982c35e0564c7733da5457 (diff)
rewrite uninstall
-rw-r--r--xmake/modules/target/action/install/main.lua2
-rw-r--r--xmake/modules/target/action/uninstall/main.lua162
-rw-r--r--xmake/modules/target/action/uninstall/unix.lua137
-rw-r--r--xmake/modules/target/action/uninstall/windows.lua115
4 files changed, 141 insertions, 275 deletions
diff --git a/xmake/modules/target/action/install/main.lua b/xmake/modules/target/action/install/main.lua
index 07089c60e..09deaabdb 100644
--- a/xmake/modules/target/action/install/main.lua
+++ b/xmake/modules/target/action/install/main.lua
@@ -100,7 +100,7 @@ function _install_shared_libraries(target, opt)
-- deduplicate libfiles, prevent packages using the same libfiles from overwriting each other
libfiles = table.unique(libfiles)
- -- do install
+ -- do install, TODO soname and symlinks
for _, libfile in ipairs(libfiles) do
local filename = path.filename(libfile)
local filepath = path.join(bindir, filename)
diff --git a/xmake/modules/target/action/uninstall/main.lua b/xmake/modules/target/action/uninstall/main.lua
index daa23917c..41f074640 100644
--- a/xmake/modules/target/action/uninstall/main.lua
+++ b/xmake/modules/target/action/uninstall/main.lua
@@ -18,45 +18,163 @@
-- @file main.lua
--
+-- imports
+import("core.base.option")
+import("core.base.hashset")
+import("utils.symbols.depend", {alias = "get_depend_libraries"})
+import("private.action.clean.remove_files")
+
+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
+
-- uninstall files
function _uninstall_files(target)
local _, dstfiles = target:installfiles()
for _, dstfile in ipairs(dstfiles) do
- os.vrm(dstfile)
+ remove_files(dstfile, {emptydir = true})
end
end
--- uninstall modules
-function _uninstall_modules(target, opt)
- local moduledir = path.join(target:installdir(), opt and opt.moduledir or "modules")
- os.vrm(moduledir)
+-- uninstall headers
+function _uninstall_headers(target, opt)
+ local includedir = target:includedir()
+ local _, dstheaders = target:headerfiles(includedir, {installonly = true})
+ for _, dstheader in ipairs(dstheaders) do
+ remove_files(dstheader, {emptydir = true})
+ end
end
--- the builtin uninstall main entry
-function main(target, opt)
+-- uninstall shared libraries
+function _uninstall_shared_libraries(target, opt)
+ local bindir = target:is_plat("windows", "mingw") and target:bindir() or target:libdir()
- -- get install directory
- local installdir = target:installdir()
- if not installdir then
- return
+ -- 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 uninstall
+ for _, libfile in ipairs(libfiles) do
+ local filename = path.filename(libfile)
+ local filepath = path.join(bindir, filename)
+ remove_files(filepath, {emptydir = true})
+ end
+end
- -- trace
- print("uninstalling %s from %s ..", target:name(), installdir)
+-- uninstall binary
+function _uninstall_binary(target, opt)
+ local bindir = target:bindir()
+ remove_files(path.join(bindir, path.filename(target:targetfile())), {emptydir = true})
+ remove_files(path.join(bindir, path.filename(target:symbolfile())), {emptydir = true})
+ _uninstall_shared_libraries(target, opt)
+end
+
+-- uninstall shared library
+function _uninstall_shared(target, opt)
+ local bindir = target:is_plat("windows", "mingw") and target:bindir() or target:libdir()
- -- call script
- if not target:is_phony() then
- local install_style = target:is_plat("windows", "mingw") and "windows" or "unix"
- local script = import(install_style, {anonymous = true})["uninstall_" .. target:kind()]
- if script then
- script(target, opt)
+ if target:is_plat("windows", "mingw") then
+ -- uninstall *.lib for shared/windows (*.dll) target
+ -- @see https://github.com/xmake-io/xmake/issues/714
+ local libdir = target:libdir()
+ local targetfile = target:targetfile()
+ remove_files(path.join(bindir, path.filename(targetfile)), {emptydir = true})
+ remove_files(path.join(libdir, path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib")), {emptydir = true})
+ else
+ local targetfile = path.join(bindir, path.filename(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(bindir, 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(bindir, targetfile_with_version)
+ end
+ remove_files(targetfile_with_version, {emptydir = true})
+ end
+ remove_files(targetfile_with_soname, {emptydir = true})
end
+ remove_files(targetfile, {emptydir = true})
end
+ remove_files(path.join(bindir, path.filename(target:symbolfile())), {emptydir = true})
- -- remove modules
- _uninstall_modules(target, opt)
+ _uninstall_headers(target, opt)
+ _uninstall_shared_libraries(target, opt)
+end
+
+-- uninstall static library
+function _uninstall_static(target, opt)
+ local libdir = target:libdir()
+ remove_files(path.join(libdir, path.filename(target:targetfile())), {emptydir = true})
+ remove_files(path.join(libdir, path.filename(target:symbolfile())), {emptydir = true})
+ _uninstall_headers(target, opt)
+end
+
+-- uninstall headeronly library
+function _uninstall_headeronly(target, opt)
+ _uninstall_headers(target, opt)
+end
+
+-- uninstall moduleonly library
+function _uninstall_moduleonly(target, opt)
+ _uninstall_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
+ print("uninstalling %s to %s ..", target:name(), installdir)
+
+ if target:is_binary() then
+ _uninstall_binary(target, opt)
+ elseif target:is_shared() then
+ _uninstall_shared(target, opt)
+ elseif target:is_static() then
+ _uninstall_static(target, opt)
+ elseif target:is_headeronly() then
+ _uninstall_headeronly(target, opt)
+ elseif target:is_moduleonly() then
+ _uninstall_moduleonly(target, opt)
+ end
- -- uninstall the other files
_uninstall_files(target)
end
diff --git a/xmake/modules/target/action/uninstall/unix.lua b/xmake/modules/target/action/uninstall/unix.lua
deleted file mode 100644
index 4615be820..000000000
--- a/xmake/modules/target/action/uninstall/unix.lua
+++ /dev/null
@@ -1,137 +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("private.action.clean.remove_files")
-
--- uninstall headers
-function _uninstall_headers(target, opt)
- local includedir = target:includedir()
- local _, dstheaders = target:headerfiles(includedir, {installonly = true})
- for _, dstheader in ipairs(dstheaders) do
- remove_files(dstheader, {emptydir = true})
- end
-end
-
--- uninstall shared libraries for package
-function _uninstall_shared_for_package(target, pkg, outputdir)
- for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do
- if sopath:endswith(".so") or sopath:match(".+%.so%..+$") or sopath:endswith(".dylib") then
- local soname = path.filename(sopath)
- local filepath = path.join(outputdir, soname)
- -- https://github.com/xmake-io/xmake/issues/2665#issuecomment-1209619081
- if os.islink(filepath) then
- -- relative link? e.g. libxx.so -> libxx.4.so
- local realitem = os.readlink(filepath)
- if realitem and not path.is_absolute(realitem) then
- local realpath = path.join(outputdir, realitem)
- if os.isfile(realpath) then
- os.vrm(realpath)
- end
- end
- end
- remove_files(filepath, {emptydir = true})
- end
- end
-end
-
--- uninstall shared libraries for packages
-function _uninstall_shared_for_packages(target, outputdir)
- _g.uninstalled_packages = _g.uninstalled_packages or {}
- for _, pkg in ipairs(target:orderpkgs()) do
- if not _g.uninstalled_packages[pkg:name()] then
- if pkg:enabled() and pkg:get("libfiles") then
- _uninstall_shared_for_package(target, pkg, outputdir)
- end
- _g.uninstalled_packages[pkg:name()] = true
- end
- end
-end
-
--- uninstall binary
-function uninstall_binary(target, opt)
-
- -- remove the target file
- local bindir = target:bindir()
- os.vrm(path.join(bindir, path.filename(target:targetfile())))
-
- -- remove the dependent shared (*.so) target
- -- @see https://github.com/xmake-io/xmake/issues/961
- local libdir = target:libdir()
- for _, dep in ipairs(target:orderdeps()) do
- if dep:kind() == "shared" then
- os.vrm(path.join(libdir, path.filename(dep:targetfile())))
- end
- _uninstall_shared_for_packages(dep, libdir)
- end
-
- -- uninstall shared libraries for packages
- _uninstall_shared_for_packages(target, libdir)
-end
-
--- uninstall shared library
-function uninstall_shared(target, opt)
-
- -- remove the target file
- local libdir = target:libdir()
- local targetfile = path.join(libdir, path.filename(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(libdir, 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(libdir, targetfile_with_version)
- end
- os.vrm(targetfile_with_version)
- end
- os.vrm(targetfile_with_soname)
- end
- os.vrm(targetfile)
-
- -- remove headers from the include directory
- _uninstall_headers(target, opt)
-
- -- uninstall shared libraries for packages
- _uninstall_shared_for_packages(target, libdir)
-end
-
--- uninstall static library
-function uninstall_static(target, opt)
-
- -- remove the target file
- local libdir = target:libdir()
- os.vrm(path.join(libdir, path.filename(target:targetfile())))
-
- -- remove headers from the include directory
- _uninstall_headers(target, opt)
-end
-
--- uninstall headeronly library
-function uninstall_headeronly(target, opt)
- _uninstall_headers(target, opt)
-end
-
--- uninstall moduleonly library
-function uninstall_moduleonly(target, opt)
- _uninstall_headers(target, opt)
-end
diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua
deleted file mode 100644
index 2982bbee1..000000000
--- a/xmake/modules/target/action/uninstall/windows.lua
+++ /dev/null
@@ -1,115 +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
---
-
--- uninstall headers
-function _uninstall_headers(target, opt)
- local includedir = target:includedir()
- local _, dstheaders = target:headerfiles(includedir, {installonly = true})
- for _, dstheader in ipairs(dstheaders) do
- os.vrm(dstheader)
- end
-end
-
--- uninstall shared libraries for package
-function _uninstall_shared_for_package(target, pkg, outputdir)
- for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do
- if dllpath:endswith(".dll") then
- local dllname = path.filename(dllpath)
- os.vrm(path.join(outputdir, dllname))
- end
- end
-end
-
--- uninstall shared libraries for packages
-function _uninstall_shared_for_packages(target, outputdir)
- _g.uninstalled_packages = _g.uninstalled_packages or {}
- for _, pkg in ipairs(target:orderpkgs()) do
- if not _g.uninstalled_packages[pkg:name()] then
- if pkg:enabled() and pkg:get("libfiles") then
- _uninstall_shared_for_package(target, pkg, outputdir)
- end
- _g.uninstalled_packages[pkg:name()] = true
- end
- end
-end
-
--- uninstall binary
-function uninstall_binary(target, opt)
-
- -- remove the target file
- local bindir = target:bindir()
- os.vrm(path.join(bindir, path.filename(target:targetfile())))
- os.tryrm(path.join(bindir, path.filename(target:symbolfile())))
-
- -- remove the dependent shared/windows (*.dll) target
- -- @see https://github.com/xmake-io/xmake/issues/961
- for _, dep in ipairs(target:orderdeps()) do
- if dep:kind() == "shared" then
- os.vrm(path.join(bindir, path.filename(dep:targetfile())))
- end
- _uninstall_shared_for_packages(dep, bindir)
- end
-
- -- uninstall shared libraries for packages
- _uninstall_shared_for_packages(target, bindir)
-end
-
--- uninstall shared library
-function uninstall_shared(target, opt)
-
- -- remove the target file
- local bindir = target:bindir()
- os.vrm(path.join(bindir, path.filename(target:targetfile())))
- os.tryrm(path.join(bindir, path.filename(target:symbolfile())))
-
- -- remove *.lib for shared/windows (*.dll) target
- -- @see https://github.com/xmake-io/xmake/issues/714
- local targetfile = target:targetfile()
- local libdir = target:libdir()
- os.vrm(path.join(libdir, path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib")))
-
- -- remove headers from the include directory
- _uninstall_headers(target, opt)
-
- -- uninstall shared libraries for packages
- _uninstall_shared_for_packages(target, bindir)
-end
-
--- uninstall static library
-function uninstall_static(target, opt)
-
- -- remove the target file
- local libdir = target:libdir()
- os.vrm(path.join(libdir, path.filename(target:targetfile())))
- os.tryrm(path.join(libdir, path.filename(target:symbolfile())))
-
- -- remove headers from the include directory
- _uninstall_headers(target, opt)
-end
-
--- uninstall headeronly library
-function uninstall_headeronly(target, opt)
- _uninstall_headers(target, opt)
-end
-
--- uninstall moduleonly library
-function uninstall_moduleonly(target, opt)
- _uninstall_headers(target, opt)
-end