diff options
| author | ruki <[email protected]> | 2024-07-14 23:02:23 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2024-07-15 12:21:42 +0800 |
| commit | e128b029dbfa5e3ab5156afd12a7a412c2bb6aad (patch) | |
| tree | 5074c2d71635d82950c96f0b0ea995fc1e0a19c8 | |
| parent | 6fd249647eb5cf6a44982c35e0564c7733da5457 (diff) | |
rewrite uninstall
| -rw-r--r-- | xmake/modules/target/action/install/main.lua | 2 | ||||
| -rw-r--r-- | xmake/modules/target/action/uninstall/main.lua | 162 | ||||
| -rw-r--r-- | xmake/modules/target/action/uninstall/unix.lua | 137 | ||||
| -rw-r--r-- | xmake/modules/target/action/uninstall/windows.lua | 115 |
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 |
