From 2a76dd45ab4f06a1adfb1bbbcaeba3859024fcc6 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 24 Jul 2025 00:54:59 +0800 Subject: improve depfiles --- xmake/modules/utils/binary/deplibs.lua | 92 ++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 11 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index 03a85c9fe..10917dfc0 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -20,10 +20,12 @@ -- imports import("core.base.option") +import("core.base.graph") +import("core.base.hashset") import("core.tool.toolchain") import("lib.detect.find_tool") -function _get_all_depends_by_dumpbin(binaryfile, opt) +function _get_depends_by_dumpbin(binaryfile, opt) local depends local plat = opt.plat or os.host() local arch = opt.arch or os.arch() @@ -48,7 +50,7 @@ function _get_all_depends_by_dumpbin(binaryfile, opt) return depends end -function _get_all_depends_by_objdump(binaryfile, opt) +function _get_depends_by_objdump(binaryfile, opt) local depends local plat = opt.plat or os.host() local arch = opt.arch or os.arch() @@ -102,7 +104,7 @@ end -- libc.so.6 => /lib64/libc.so.6 (0x00007fe240ccd000) -- /lib64/ld-linux-x86-64.so.2 (0x00007fe24123a000) -- -function _get_all_depends_by_ldd(binaryfile, opt) +function _get_depends_by_ldd(binaryfile, opt) local plat = opt.plat or os.host() local arch = opt.arch or os.arch() if plat ~= "linux" and plat ~= "bsd" then @@ -143,7 +145,7 @@ end -- 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] -- 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] -- 0x000000000000001d (RUNPATH) Library runpath: [$ORIGIN] -function _get_all_depends_by_readelf(binaryfile, opt) +function _get_depends_by_readelf(binaryfile, opt) local plat = opt.plat or os.host() local arch = opt.arch or os.arch() if plat ~= "linux" and plat ~= "bsd" and plat ~= "android" and plat ~= "cross" then @@ -178,7 +180,7 @@ end -- /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.151.0) -- /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0) -- -function _get_all_depends_by_otool(binaryfile, opt) +function _get_depends_by_otool(binaryfile, opt) local plat = opt.plat or os.host() local arch = opt.arch or os.arch() if plat ~= "macosx" and plat ~= "iphoneos" and plat ~= "appletvos" and plat ~= "watchos" then @@ -203,18 +205,18 @@ function _get_all_depends_by_otool(binaryfile, opt) return depends end -function main(binaryfile, opt) +function _get_depends(binaryfile, opt) opt = opt or {} local ops = { - _get_all_depends_by_objdump, - _get_all_depends_by_readelf + _get_depends_by_objdump, + _get_depends_by_readelf } if is_host("windows") then - table.insert(ops, 1, _get_all_depends_by_dumpbin) + table.insert(ops, 1, _get_depends_by_dumpbin) elseif is_host("linux", "bsd") then - table.insert(ops, 1, _get_all_depends_by_ldd) + table.insert(ops, 1, _get_depends_by_ldd) elseif is_host("macosx") then - table.insert(ops, 1, _get_all_depends_by_otool) + table.insert(ops, 1, _get_depends_by_otool) end for _, op in ipairs(ops) do local depends = op(binaryfile, opt) @@ -224,3 +226,71 @@ function main(binaryfile, opt) end end +-- TODO +function _resolve_filepath(binaryfile) + if binaryfile:startswith("@rpath/") then + print("binaryfile", binaryfile) + end + return binaryfile +end + +function _get_plain_depends(binaryfile, opt) + opt = opt or {} + local depends = _get_depends(binaryfile, opt) + if depends and opt.resolve_path then + local result = {} + for _, dependfile in ipairs(depends) do + dependfile = _resolve_filepath(dependfile) + table.insert(result, dependfile) + end + depends = result + end + return depends +end + +function _get_recursive_depends(binaryfile, dag, depends, opt) + local dependfiles = _get_plain_depends(binaryfile, opt) + if dependfiles then + for _, dependfile in ipairs(dependfiles) do + dag:add_edge(binaryfile, dependfile) + if not depends:has(dependfile) then + depends:insert(dependfile) + _get_recursive_depends(dependfile, dag, depends, opt) + end + end + end +end + +-- get the library dependencies of the give binary files +-- +-- @param binaryfile the binary file +-- @param opt the option, e.g. {recursive = false, resolve_path = true} +-- - recursive: recursively get all sub-dependencies, sorted by topology +-- - resolve_path: try to resolve the file full path, e.g. @rpath, @loader_path, $ORIGIN, relative path .. +-- +function main(binaryfile, opt) + opt = opt or {} +-- opt.recursive = true +-- opt.resolve_path = true + if opt.recursive then + local dag = graph.new(true) + _get_recursive_depends(binaryfile, dag, hashset.new(), opt) + local depends, has_cycle = dag:topo_sort() + if has_cycle then + local files = {} + local cycle = dag:find_cycle() + if cycle then + for _, file in ipairs(cycle) do + table.insert(files, file) + end + table.insert(files, binaryfile) + end + raise("deplibs(%s): circular library dependencies detected!\n%s", binaryfile, table.concat(files, "\n -> ")) + end + if depends and #depends > 1 then + return table.slice(depends, 2) + end + else + return _get_plain_depends(binaryfile, opt) + end +end -- cgit v1.3.1 From fbb062e201d403a662230bc643f527afe14b8b76 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 24 Jul 2025 22:44:51 +0800 Subject: improve to resolve path --- xmake/modules/utils/binary/deplibs.lua | 58 ++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index 10917dfc0..3c85bc1ff 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -24,6 +24,7 @@ import("core.base.graph") import("core.base.hashset") import("core.tool.toolchain") import("lib.detect.find_tool") +import("utils.binary.rpath", {alias = "rpath_utils"}) function _get_depends_by_dumpbin(binaryfile, opt) local depends @@ -226,12 +227,41 @@ function _get_depends(binaryfile, opt) end end --- TODO -function _resolve_filepath(binaryfile) - if binaryfile:startswith("@rpath/") then - print("binaryfile", binaryfile) +-- resolve file path with @rpath, @loader_path, and $ORIGIN +function _resolve_filepath(binaryfile, dependfile, opt) + local rpath_cache = opt._rpath_cache + if dependfile:startswith("@rpath/") then + local rpath_list = rpath_cache[binaryfile] + if rpath_list == nil then + rpath_list = rpath_utils.list(binaryfile) + rpath_cache[binaryfile] = rpath_list or false + end + if rpath_list then + for _, rpath in ipairs(rpath_list) do + local filepath = dependfile:replace("@rpath/", rpath .. "/", {plain = true}) + if os.isfile(filepath) then + dependfile = filepath + break + elseif filepath:startswith("@loader_path/") then + filepath = filepath:replace("@loader_path/", path.directory(binaryfile) .. "/", {plain = true}) + if os.isfile(filepath) then + dependfile = filepath + break + end + elseif filepath:startswith("$ORIGIN/") then + filepath = filepath:replace("$ORIGIN/", path.directory(binaryfile) .. "/", {plain = true}) + if os.isfile(filepath) then + dependfile = filepath + break + end + end + end + end + end + dependfile = path.normalize(dependfile) + if binaryfile ~= dependfile then + return dependfile end - return binaryfile end function _get_plain_depends(binaryfile, opt) @@ -240,8 +270,10 @@ function _get_plain_depends(binaryfile, opt) if depends and opt.resolve_path then local result = {} for _, dependfile in ipairs(depends) do - dependfile = _resolve_filepath(dependfile) - table.insert(result, dependfile) + dependfile = _resolve_filepath(binaryfile, dependfile, opt) + if dependfile then + table.insert(result, dependfile) + end end depends = result end @@ -255,7 +287,9 @@ function _get_recursive_depends(binaryfile, dag, depends, opt) dag:add_edge(binaryfile, dependfile) if not depends:has(dependfile) then depends:insert(dependfile) - _get_recursive_depends(dependfile, dag, depends, opt) + if os.isfile(dependfile) then + _get_recursive_depends(dependfile, dag, depends, opt) + end end end end @@ -270,8 +304,12 @@ end -- function main(binaryfile, opt) opt = opt or {} --- opt.recursive = true --- opt.resolve_path = true + --opt.recursive = true + --opt.resolve_path = true + if opt.resolve_path then + opt._rpath_cache = {} + end + binaryfile = path.normalize(path.absolute(binaryfile)) if opt.recursive then local dag = graph.new(true) _get_recursive_depends(binaryfile, dag, hashset.new(), opt) -- cgit v1.3.1 From 8f3b582019d38f1aa9d774b1c752f9a5f18507fc Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 25 Jul 2025 00:48:54 +0800 Subject: improve to resolve rpath --- xmake/modules/utils/binary/deplibs.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index 3c85bc1ff..fdc873b31 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -229,27 +229,27 @@ end -- resolve file path with @rpath, @loader_path, and $ORIGIN function _resolve_filepath(binaryfile, dependfile, opt) - local rpath_cache = opt._rpath_cache + local loaderfile = opt._loaderfile if dependfile:startswith("@rpath/") then - local rpath_list = rpath_cache[binaryfile] - if rpath_list == nil then - rpath_list = rpath_utils.list(binaryfile) - rpath_cache[binaryfile] = rpath_list or false + local rpathlist = opt._rpathlist + if rpathlist == nil then + rpathlist = rpath_utils.list(loaderfile) + opt._rpathlist = rpathlist or false end - if rpath_list then - for _, rpath in ipairs(rpath_list) do + if rpathlist then + for _, rpath in ipairs(rpathlist) do local filepath = dependfile:replace("@rpath/", rpath .. "/", {plain = true}) if os.isfile(filepath) then dependfile = filepath break elseif filepath:startswith("@loader_path/") then - filepath = filepath:replace("@loader_path/", path.directory(binaryfile) .. "/", {plain = true}) + filepath = filepath:replace("@loader_path/", path.directory(loaderfile) .. "/", {plain = true}) if os.isfile(filepath) then dependfile = filepath break end elseif filepath:startswith("$ORIGIN/") then - filepath = filepath:replace("$ORIGIN/", path.directory(binaryfile) .. "/", {plain = true}) + filepath = filepath:replace("$ORIGIN/", path.directory(loaderfile) .. "/", {plain = true}) if os.isfile(filepath) then dependfile = filepath break @@ -307,7 +307,7 @@ function main(binaryfile, opt) --opt.recursive = true --opt.resolve_path = true if opt.resolve_path then - opt._rpath_cache = {} + opt._loaderfile = binaryfile end binaryfile = path.normalize(path.absolute(binaryfile)) if opt.recursive then -- cgit v1.3.1 From 53d106bc017dc2e7db4bdff583ebe863c957ab9f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:44:04 +0800 Subject: improve deplibs --- xmake/modules/target/action/install/main.lua | 34 ++++++---------- xmake/modules/target/action/uninstall/main.lua | 33 +++++----------- xmake/modules/utils/binary/deplibs.lua | 55 ++++++++++++++------------ xmake/plugins/pack/batchcmds.lua | 33 +++++----------- 4 files changed, 60 insertions(+), 95 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/target/action/install/main.lua b/xmake/modules/target/action/install/main.lua index 753503eaa..0d102ffd7 100644 --- a/xmake/modules/target/action/install/main.lua +++ b/xmake/modules/target/action/install/main.lua @@ -49,26 +49,6 @@ function _get_target_includedir(target, opt) return path.join(opt.installdir, opt.includedir) end --- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... --- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 -function _get_target_package_deplibs(binaryfile, depends, libfiles, opt) - local deplibs = get_depend_libraries(binaryfile, {plat = opt.plat, arch = opt.arch}) - local depends_new = hashset.new() - for _, deplib in ipairs(deplibs) do - local libname = path.filename(deplib) - if not depends:has(libname) then - depends:insert(libname) - depends_new:insert(libname) - end - end - for _, libfile in ipairs(libfiles) do - local libname = path.filename(libfile) - if depends_new:has(libname) then - _get_target_package_deplibs(libfile, depends, libfiles, opt) - end - end -end - function _get_target_package_libfiles(target, opt) if option.get("nopkgs") then return {} @@ -88,9 +68,17 @@ function _get_target_package_libfiles(target, opt) -- we can only reserve used libraries if project.policy("install.strip_packagelibs") then if target:is_binary() or target:is_shared() or opt.binaryfile then - local depends = hashset.new() - _get_target_package_deplibs(opt.binaryfile or target:targetfile(), depends, libfiles, {plat = target:plat(), arch = target:arch()}) - table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + -- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... + -- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 + local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), { + recursive = true, plat = target:plat(), arch = target:arch()}) + if deplibs then + local depends = hashset.new() + for _, deplib in ipairs(deplibs) do + depends:insert(path.filename(deplib)) + end + table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + end end end return libfiles diff --git a/xmake/modules/target/action/uninstall/main.lua b/xmake/modules/target/action/uninstall/main.lua index e94a29897..6eff73529 100644 --- a/xmake/modules/target/action/uninstall/main.lua +++ b/xmake/modules/target/action/uninstall/main.lua @@ -49,26 +49,6 @@ function _get_target_includedir(target, opt) return path.join(opt.installdir, opt.includedir) end --- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... --- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 -function _get_target_package_deplibs(binaryfile, depends, libfiles, opt) - local deplibs = get_depend_libraries(binaryfile, {plat = opt.plat, arch = opt.arch}) - local depends_new = hashset.new() - for _, deplib in ipairs(deplibs) do - local libname = path.filename(deplib) - if not depends:has(libname) then - depends:insert(libname) - depends_new:insert(libname) - end - end - for _, libfile in ipairs(libfiles) do - local libname = path.filename(libfile) - if depends_new:has(libname) then - _get_target_package_deplibs(libfile, depends, libfiles, opt) - end - end -end - function _get_target_package_libfiles(target, opt) if option.get("nopkgs") then return {} @@ -88,9 +68,16 @@ function _get_target_package_libfiles(target, opt) -- we can only reserve used libraries if project.policy("install.strip_packagelibs") then if target:is_binary() or target:is_shared() or opt.binaryfile then - local depends = hashset.new() - _get_target_package_deplibs(opt.binaryfile or target:targetfile(), depends, libfiles, {plat = target:plat(), arch = target:arch()}) - table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + -- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... + -- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 + local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), {recursive = true, plat = target:plat(), arch = target:arch()}) + if deplibs then + local depends = hashset.new() + for _, deplib in ipairs(deplibs) do + depends:insert(path.filename(deplib)) + end + table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + end end end return libfiles diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index fdc873b31..b81d644d8 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -67,27 +67,29 @@ function _get_depends_by_objdump(binaryfile, opt) if result then for _, line in ipairs(result:split("\n")) do line = line:trim() - if plat == "windows" or plat == "mingw" then - if line:startswith("DLL Name:") then - local filename = line:split(":")[2]:trim() - if filename:endswith(".dll") then - depends = depends or {} - table.insert(depends, filename) + if not line:endswith(":") then + if plat == "windows" or plat == "mingw" then + if line:startswith("DLL Name:") then + local filename = line:split(":")[2]:trim() + if filename:endswith(".dll") then + depends = depends or {} + table.insert(depends, filename) + end end - end - elseif plat == "macosx" or plat == "iphoneos" or plat == "appletvos" or plat == "watchos" then - local filename = line:match(".-%.dylib") or line:match(".-%.framework") - if filename then - depends = depends or {} - table.insert(depends, filename) - end - else - if line:startswith("NEEDED") then - local filename = line:split("%s+")[2] - if filename and filename:endswith(".so") or filename:find("%.so[%.%d+]+$") then + elseif plat == "macosx" or plat == "iphoneos" or plat == "appletvos" or plat == "watchos" then + local filename = line:match(".-%.dylib") or line:match(".-%.framework") + if filename then depends = depends or {} table.insert(depends, filename) end + else + if line:startswith("NEEDED") then + local filename = line:split("%s+")[2] + if filename and filename:endswith(".so") or filename:find("%.so[%.%d+]+$") then + depends = depends or {} + table.insert(depends, filename) + end + end end end end @@ -195,10 +197,13 @@ function _get_depends_by_otool(binaryfile, opt) local result = try { function () return os.iorunv(otool.program, {"-L", binaryfile}) end } if result then for _, line in ipairs(result:split("\n")) do - local filename = line:match(".-%.dylib") or line:match(".-%.framework") - if filename then - depends = depends or {} - table.insert(depends, filename:trim()) + line = line:trim() + if not line:endswith(":") then + local filename = line:match(".-%.dylib") or line:match(".-%.framework") + if filename then + depends = depends or {} + table.insert(depends, filename:trim()) + end end end end @@ -240,18 +245,18 @@ function _resolve_filepath(binaryfile, dependfile, opt) for _, rpath in ipairs(rpathlist) do local filepath = dependfile:replace("@rpath/", rpath .. "/", {plain = true}) if os.isfile(filepath) then - dependfile = filepath + dependfile = path.absolute(filepath) break elseif filepath:startswith("@loader_path/") then filepath = filepath:replace("@loader_path/", path.directory(loaderfile) .. "/", {plain = true}) if os.isfile(filepath) then - dependfile = filepath + dependfile = path.absolute(filepath) break end elseif filepath:startswith("$ORIGIN/") then filepath = filepath:replace("$ORIGIN/", path.directory(loaderfile) .. "/", {plain = true}) if os.isfile(filepath) then - dependfile = filepath + dependfile = path.absolute(filepath) break end end @@ -304,8 +309,6 @@ end -- function main(binaryfile, opt) opt = opt or {} - --opt.recursive = true - --opt.resolve_path = true if opt.resolve_path then opt._loaderfile = binaryfile end diff --git a/xmake/plugins/pack/batchcmds.lua b/xmake/plugins/pack/batchcmds.lua index c768453d0..df0c506e0 100644 --- a/xmake/plugins/pack/batchcmds.lua +++ b/xmake/plugins/pack/batchcmds.lua @@ -62,26 +62,6 @@ function _get_target_installdir(package, target) return path.normalize(installdir) end --- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... --- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 -function _get_target_package_deplibs(binaryfile, depends, libfiles, opt) - local deplibs = get_depend_libraries(binaryfile, {plat = opt.plat, arch = opt.arch}) - local depends_new = hashset.new() - for _, deplib in ipairs(deplibs) do - local libname = path.filename(deplib) - if not depends:has(libname) then - depends:insert(libname) - depends_new:insert(libname) - end - end - for _, libfile in ipairs(libfiles) do - local libname = path.filename(libfile) - if depends_new:has(libname) then - _get_target_package_deplibs(libfile, depends, libfiles, opt) - end - end -end - function _get_target_package_libfiles(target, opt) if option.get("nopkgs") then return {} @@ -101,9 +81,16 @@ function _get_target_package_libfiles(target, opt) -- we can only reserve used libraries if project.policy("install.strip_packagelibs") then if target:is_binary() or target:is_shared() or opt.binaryfile then - local depends = hashset.new() - _get_target_package_deplibs(opt.binaryfile or target:targetfile(), depends, libfiles, {plat = target:plat(), arch = target:arch()}) - table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + -- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... + -- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 + local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), {recursive = true, plat = target:plat(), arch = target:arch()}) + if deplibs then + local depends = hashset.new() + for _, deplib in ipairs(deplibs) do + depends:insert(path.filename(deplib)) + end + table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + end end end return libfiles -- cgit v1.3.1 From e3759b8bd56d614b49d95256c04c7d093100d64a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:47:48 +0800 Subject: add resolve_hint_paths --- xmake/modules/target/action/install/main.lua | 10 ++++------ xmake/modules/target/action/uninstall/main.lua | 11 +++++------ xmake/modules/utils/binary/deplibs.lua | 17 ++++++++++++++++- xmake/plugins/pack/batchcmds.lua | 11 +++++------ 4 files changed, 30 insertions(+), 19 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/target/action/install/main.lua b/xmake/modules/target/action/install/main.lua index 0d102ffd7..d9faa80ad 100644 --- a/xmake/modules/target/action/install/main.lua +++ b/xmake/modules/target/action/install/main.lua @@ -71,13 +71,11 @@ function _get_target_package_libfiles(target, opt) -- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... -- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), { - recursive = true, plat = target:plat(), arch = target:arch()}) + plat = target:plat(), arch = target:arch(), + recursive = true, resolve_path = true, resolve_hint_paths = libfiles}) if deplibs then - local depends = hashset.new() - for _, deplib in ipairs(deplibs) do - depends:insert(path.filename(deplib)) - end - table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + local depends = hashset.from(deplibs) + table.remove_if(libfiles, function (_, libfile) return not depends:has(libfile) end) end end end diff --git a/xmake/modules/target/action/uninstall/main.lua b/xmake/modules/target/action/uninstall/main.lua index 6eff73529..2273ff76d 100644 --- a/xmake/modules/target/action/uninstall/main.lua +++ b/xmake/modules/target/action/uninstall/main.lua @@ -70,13 +70,12 @@ function _get_target_package_libfiles(target, opt) if target:is_binary() or target:is_shared() or opt.binaryfile then -- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... -- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 - local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), {recursive = true, plat = target:plat(), arch = target:arch()}) + local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), { + plat = target:plat(), arch = target:arch(), + recursive = true, resolve_path = true, resolve_hint_paths = libfiles}) if deplibs then - local depends = hashset.new() - for _, deplib in ipairs(deplibs) do - depends:insert(path.filename(deplib)) - end - table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + local depends = hashset.from(deplibs) + table.remove_if(libfiles, function (_, libfile) return not depends:has(libfile) end) end end end diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index b81d644d8..15ca0b12b 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -235,6 +235,7 @@ end -- resolve file path with @rpath, @loader_path, and $ORIGIN function _resolve_filepath(binaryfile, dependfile, opt) local loaderfile = opt._loaderfile + local resolve_hint_paths = opt.resolve_hint_paths if dependfile:startswith("@rpath/") then local rpathlist = opt._rpathlist if rpathlist == nil then @@ -263,6 +264,19 @@ function _resolve_filepath(binaryfile, dependfile, opt) end end end + if not path.is_absolute(dependfile) then + if os.isfile(dependfile) then + dependfile = path.absolute(dependfile) + elseif resolve_hint_paths then + local filename = path.filename(dependfile) + for _, filepath in ipairs(resolve_hint_paths) do + if filename == path.filename(filepath) then + dependfile = path.absolute(filepath) + break + end + end + end + end dependfile = path.normalize(dependfile) if binaryfile ~= dependfile then return dependfile @@ -303,9 +317,10 @@ end -- get the library dependencies of the give binary files -- -- @param binaryfile the binary file --- @param opt the option, e.g. {recursive = false, resolve_path = true} +-- @param opt the option, e.g. {recursive = false, resolve_path = true, resolve_hint_paths = {}} -- - recursive: recursively get all sub-dependencies, sorted by topology -- - resolve_path: try to resolve the file full path, e.g. @rpath, @loader_path, $ORIGIN, relative path .. +-- - resolve_hint_paths: we can resolve and match path from them -- function main(binaryfile, opt) opt = opt or {} diff --git a/xmake/plugins/pack/batchcmds.lua b/xmake/plugins/pack/batchcmds.lua index df0c506e0..2418f39ac 100644 --- a/xmake/plugins/pack/batchcmds.lua +++ b/xmake/plugins/pack/batchcmds.lua @@ -83,13 +83,12 @@ function _get_target_package_libfiles(target, opt) if target:is_binary() or target:is_shared() or opt.binaryfile then -- we need to get all deplibs, e.g. app -> libfoo.so -> libbar.so ... -- @see https://github.com/xmake-io/xmake/issues/5325#issuecomment-2242597732 - local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), {recursive = true, plat = target:plat(), arch = target:arch()}) + local deplibs = get_depend_libraries(opt.binaryfile or target:targetfile(), { + plat = target:plat(), arch = target:arch(), + recursive = true, resolve_path = true, resolve_hint_paths = libfiles}) if deplibs then - local depends = hashset.new() - for _, deplib in ipairs(deplibs) do - depends:insert(path.filename(deplib)) - end - table.remove_if(libfiles, function (_, libfile) return not depends:has(path.filename(libfile)) end) + local depends = hashset.from(deplibs) + table.remove_if(libfiles, function (_, libfile) return not depends:has(libfile) end) end end end -- cgit v1.3.1 From b1080f1934d960f7b48b26fdee5f5bfaed96170a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:49:15 +0800 Subject: improve dumpbin --- xmake/modules/utils/binary/deplibs.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index 15ca0b12b..dbfdd8a66 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -40,7 +40,7 @@ function _get_depends_by_dumpbin(binaryfile, opt) if result then for _, line in ipairs(result:split("\n")) do line = line:trim() - if line:endswith(".dll") then + if not line:startswith("Dump of file") and line:endswith(".dll") then depends = depends or {} table.insert(depends, line) end -- cgit v1.3.1 From e2f78c5d480c987f68fa74ca8fb114c20c6bb726 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:51:29 +0800 Subject: improve to resolve path --- xmake/modules/utils/binary/deplibs.lua | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index dbfdd8a66..937570f14 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -236,7 +236,10 @@ end function _resolve_filepath(binaryfile, dependfile, opt) local loaderfile = opt._loaderfile local resolve_hint_paths = opt.resolve_hint_paths - if dependfile:startswith("@rpath/") then + local resolved = false + + -- resolve path from rpath + if not resolved and dependfile:startswith("@rpath/") then local rpathlist = opt._rpathlist if rpathlist == nil then rpathlist = rpath_utils.list(loaderfile) @@ -247,36 +250,58 @@ function _resolve_filepath(binaryfile, dependfile, opt) local filepath = dependfile:replace("@rpath/", rpath .. "/", {plain = true}) if os.isfile(filepath) then dependfile = path.absolute(filepath) + resolved = true break elseif filepath:startswith("@loader_path/") then filepath = filepath:replace("@loader_path/", path.directory(loaderfile) .. "/", {plain = true}) if os.isfile(filepath) then dependfile = path.absolute(filepath) + resolved = true break end elseif filepath:startswith("$ORIGIN/") then filepath = filepath:replace("$ORIGIN/", path.directory(loaderfile) .. "/", {plain = true}) if os.isfile(filepath) then dependfile = path.absolute(filepath) + resolved = true break end end end end end + if not path.is_absolute(dependfile) then - if os.isfile(dependfile) then + + -- resolve absolute path + if not resolved and os.isfile(dependfile) then dependfile = path.absolute(dependfile) - elseif resolve_hint_paths then + resolved = true + end + + -- resolve path from the hint paths + if not resolved and resolve_hint_paths then local filename = path.filename(dependfile) for _, filepath in ipairs(resolve_hint_paths) do if filename == path.filename(filepath) then dependfile = path.absolute(filepath) + resolved = true break end end end + + -- resolve path from the current loader directory on windows + if not resolved and is_host("windows") then + local loaderdir = path.directory(loaderfile) + local filepath = parh.absolute(dependfile, loaderdir) + if os.isfile(filepath) then + dependfile = filepath + resolved = true + end + end end + dependfile = path.normalize(dependfile) if binaryfile ~= dependfile then return dependfile -- cgit v1.3.1 From 163ed4a33a78904a2425c5ca7a6e9b53262b737f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:52:22 +0800 Subject: fix resolve path --- xmake/modules/utils/binary/deplibs.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index 937570f14..b04604bf8 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -294,9 +294,9 @@ function _resolve_filepath(binaryfile, dependfile, opt) -- resolve path from the current loader directory on windows if not resolved and is_host("windows") then local loaderdir = path.directory(loaderfile) - local filepath = parh.absolute(dependfile, loaderdir) + local filepath = path.join(loaderdir, dependfile) if os.isfile(filepath) then - dependfile = filepath + dependfile = path.absolute(filepath) resolved = true end end -- cgit v1.3.1 From 3eb8749861478f3d396d6a4692dcf23e35a237dd Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:52:29 +0800 Subject: add todo --- xmake/modules/utils/binary/deplibs.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index b04604bf8..b3c1c257d 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -300,6 +300,9 @@ function _resolve_filepath(binaryfile, dependfile, opt) resolved = true end end + + -- TODO + -- resolve path from LD_LIBRARY_PATH, ... end dependfile = path.normalize(dependfile) -- cgit v1.3.1 From 67ef64a4a1d823f93029dab849dd0b64702c7b7e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:54:18 +0800 Subject: resolve path form path envs --- xmake/modules/utils/binary/deplibs.lua | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index b3c1c257d..5ed9108a4 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -236,6 +236,7 @@ end function _resolve_filepath(binaryfile, dependfile, opt) local loaderfile = opt._loaderfile local resolve_hint_paths = opt.resolve_hint_paths + local resolve_search_paths = opt.resolve_search_paths local resolved = false -- resolve path from rpath @@ -301,8 +302,28 @@ function _resolve_filepath(binaryfile, dependfile, opt) end end - -- TODO + -- resolve path from the searth paths + if resolve_search_paths then + for _, searchdir in ipairs(resolve_search_paths) do + local filepath = path.join(searchdir, dependfile) + if os.isfile(filepath) then + dependfile = path.absolute(filepath) + resolved = true + end + end + end + -- resolve path from LD_LIBRARY_PATH, ... + local library_paths = is_host("macosx") and os.getenv("DYLD_LIBRARY_PATH") or os.getenv("LD_LIBRARY_PATH") + if library_paths then + for _, searchdir in ipairs(path.splitenv(library_paths)) do + local filepath = path.join(searchdir, dependfile) + if os.isfile(filepath) then + dependfile = path.absolute(filepath) + resolved = true + end + end + end end dependfile = path.normalize(dependfile) @@ -349,6 +370,7 @@ end -- - recursive: recursively get all sub-dependencies, sorted by topology -- - resolve_path: try to resolve the file full path, e.g. @rpath, @loader_path, $ORIGIN, relative path .. -- - resolve_hint_paths: we can resolve and match path from them +-- - resolve_search_paths: the search library paths, like: LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, ... -- function main(binaryfile, opt) opt = opt or {} -- cgit v1.3.1 From 82600499728ebde05c988a10a3970123bf438e35 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 26 Jul 2025 00:56:56 +0800 Subject: add args --- xmake/modules/utils/binary/deplibs.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'xmake/modules/utils/binary/deplibs.lua') diff --git a/xmake/modules/utils/binary/deplibs.lua b/xmake/modules/utils/binary/deplibs.lua index 5ed9108a4..54b3ed4a2 100644 --- a/xmake/modules/utils/binary/deplibs.lua +++ b/xmake/modules/utils/binary/deplibs.lua @@ -367,6 +367,7 @@ end -- -- @param binaryfile the binary file -- @param opt the option, e.g. {recursive = false, resolve_path = true, resolve_hint_paths = {}} +-- - plat, arch: the platform and architecture -- - recursive: recursively get all sub-dependencies, sorted by topology -- - resolve_path: try to resolve the file full path, e.g. @rpath, @loader_path, $ORIGIN, relative path .. -- - resolve_hint_paths: we can resolve and match path from them -- cgit v1.3.1