From 482b81ae5d4dc0bca6d2869c94237b48a55a2cfa Mon Sep 17 00:00:00 2001 From: Akaps316 <48785708+Akaps316@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:17:05 +0530 Subject: fix(xcode.application): avoid duplicate bundle rpath insertion Only add the macOS app bundle framework rpath if it is missing from the copied app binary. This avoids install_name_tool failing when the target already links with @executable_path/../Frameworks, for example via add_rpathdirs(). Add a regression test covering a macOS app target that already carries the bundle rpath before xcode.application generates the app bundle. --- .../objc/macapp_duplicate_rpath/src/Info.plist | 18 ++++++++++++++++++ tests/projects/objc/macapp_duplicate_rpath/src/main.m | 5 +++++ tests/projects/objc/macapp_duplicate_rpath/test.lua | 18 ++++++++++++++++++ tests/projects/objc/macapp_duplicate_rpath/xmake.lua | 9 +++++++++ xmake/rules/xcode/application/build.lua | 8 ++++++-- 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/projects/objc/macapp_duplicate_rpath/src/Info.plist create mode 100644 tests/projects/objc/macapp_duplicate_rpath/src/main.m create mode 100644 tests/projects/objc/macapp_duplicate_rpath/test.lua create mode 100644 tests/projects/objc/macapp_duplicate_rpath/xmake.lua diff --git a/tests/projects/objc/macapp_duplicate_rpath/src/Info.plist b/tests/projects/objc/macapp_duplicate_rpath/src/Info.plist new file mode 100644 index 000000000..e20952d73 --- /dev/null +++ b/tests/projects/objc/macapp_duplicate_rpath/src/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleExecutable + demo + CFBundleIdentifier + io.xmake.demo.duprpath + CFBundleName + demo + CFBundlePackageType + APPL + CFBundleVersion + 1 + CFBundleShortVersionString + 1.0 + + diff --git a/tests/projects/objc/macapp_duplicate_rpath/src/main.m b/tests/projects/objc/macapp_duplicate_rpath/src/main.m new file mode 100644 index 000000000..f481d2909 --- /dev/null +++ b/tests/projects/objc/macapp_duplicate_rpath/src/main.m @@ -0,0 +1,5 @@ +#import + +int main(void) { + return 0; +} diff --git a/tests/projects/objc/macapp_duplicate_rpath/test.lua b/tests/projects/objc/macapp_duplicate_rpath/test.lua new file mode 100644 index 000000000..f2821df14 --- /dev/null +++ b/tests/projects/objc/macapp_duplicate_rpath/test.lua @@ -0,0 +1,18 @@ +function main(t) + if not is_host("macosx") then + return t:skip("wrong host platform") + end + + local homedir = path.absolute("home") + os.setenv("HOME", homedir) + os.mkdir(homedir) + os.mkdir(path.join(homedir, ".xmake")) + + local xmake = path.absolute(path.join(os.projectdir(), "build", "xmake")) + local xmake_program_dir = path.absolute(path.join(os.projectdir(), "xmake")) + os.setenv("XMAKE_PROGRAM_FILE", xmake) + os.setenv("XMAKE_PROGRAM_DIR", xmake_program_dir) + + os.execv(xmake, {"f", "-p", "macosx", "-a", os.arch(), "-c"}) + os.execv(xmake, {"-vD"}) +end diff --git a/tests/projects/objc/macapp_duplicate_rpath/xmake.lua b/tests/projects/objc/macapp_duplicate_rpath/xmake.lua new file mode 100644 index 000000000..a9428203f --- /dev/null +++ b/tests/projects/objc/macapp_duplicate_rpath/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.release", "mode.debug") + +set_languages("c11", "objc") + +target("demo") + add_rules("xcode.application") + add_rpathdirs("@executable_path/../Frameworks") + add_files("src/main.m") + add_files("src/Info.plist") diff --git a/xmake/rules/xcode/application/build.lua b/xmake/rules/xcode/application/build.lua index 8ea734d28..57c3655d5 100644 --- a/xmake/rules/xcode/application/build.lua +++ b/xmake/rules/xcode/application/build.lua @@ -23,6 +23,7 @@ import("core.base.option") import("core.theme.theme") import("core.project.depend") import("private.tools.codesign") +import("utils.binary.rpath", {alias = "rpath_utils"}) import("utils.progress") function main (target, opt) @@ -49,7 +50,11 @@ function main (target, opt) -- @see https://github.com/xmake-io/xmake/issues/2679#issuecomment-1221839215 local targetfile = path.join(binarydir, path.filename(target:targetfile())) try { function () os.vrunv("install_name_tool", {"-delete_rpath", "@loader_path", targetfile}) end } - os.vrunv("install_name_tool", {"-add_rpath", "@executable_path/../Frameworks", targetfile}) + local rpath = "@executable_path/../Frameworks" + local rpathdirs = rpath_utils.list(targetfile, {plat = target:plat(), arch = target:arch()}) or {} + if not table.contains(rpathdirs, rpath) then + os.vrunv("install_name_tool", {"-add_rpath", rpath, targetfile}) + end -- copy dependent dynamic libraries and frameworks for _, dep in ipairs(target:orderdeps()) do @@ -109,4 +114,3 @@ function main (target, opt) end, {dependfile = target:dependfile(bundledir), files = {bundledir, target:targetfile()}, changed = target:is_rebuilt()}) end - -- cgit v1.3.1