summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkaps316 <[email protected]>2026-04-03 21:17:05 +0530
committerAkaps316 <[email protected]>2026-04-03 21:17:05 +0530
commit482b81ae5d4dc0bca6d2869c94237b48a55a2cfa (patch)
tree57d5ac4e114f091c09acf1c5893cdb305e19ca56
parent39fd35ea9d5d14079e4669b85423d488c9097cd4 (diff)
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.
-rw-r--r--tests/projects/objc/macapp_duplicate_rpath/src/Info.plist18
-rw-r--r--tests/projects/objc/macapp_duplicate_rpath/src/main.m5
-rw-r--r--tests/projects/objc/macapp_duplicate_rpath/test.lua18
-rw-r--r--tests/projects/objc/macapp_duplicate_rpath/xmake.lua9
-rw-r--r--xmake/rules/xcode/application/build.lua8
5 files changed, 56 insertions, 2 deletions
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleExecutable</key>
+ <string>demo</string>
+ <key>CFBundleIdentifier</key>
+ <string>io.xmake.demo.duprpath</string>
+ <key>CFBundleName</key>
+ <string>demo</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+</dict>
+</plist>
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 <AppKit/AppKit.h>
+
+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
-