# Using -lto=llvm-full/thin with xcodebuild

**URL:** <https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931>\
**Category:** Using Swift\
**Tags:** xcode, xcodebuild, lto\
**Created:** [May 16, 2025, 9:53am UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931 "2025-05-16T09:53:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![weliveindetail](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/weliveindetail/32/38490_2.png) [@weliveindetail](https://forums.swift.org/u/weliveindetail)\
**Post date:** [May 16, 2025, 9:53am UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/1 "2025-05-16T09:53:53Z")

</div>

Xcode 16.3 ships Apple Swift version 6.1 and I can use it on the command-line to build a hello world example with link-time optimization:

```t
> cat main.swift
print("Hello world")
> swiftc -O main.swift -lto=llvm-full -o lto_full
> ./lto_full
Hello world

```

Verbose output (simplified):

```t
> swiftc -O main.swift -lto=llvm-full -o lto_full -v -Xclang-linker -v
Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
Target: arm64-apple-macosx15.0
swift-frontend -frontend -emit-bc -primary-file main.swift -O -lto=llvm-full ... -o /var/folders/.../main-1.bc
clang /var/folders/.../main-1.bc -flto=full -O3 ... -o lto_full -v
  clang -cc1 ... -flto=full ... -o /var/folders/.../main-1-e1c2b7.o -x ir /var/folders/.../main-1.bc
  ld -o lto_full ... /var/folders/.../main-1-e1c2b7.o

```

Shows the steps:

1. swift-frontend compiles main.swift to LLVM bitcode and writes `main-1.bc`
2. clang runs two steps:  
a. `clang -cc1` optimizes the LLVM bitcode and writes `main-1-e1c2b7.o`  
b. `ld` links `main-1-e1c2b7.o` as `lto_full` executable

The same works with `-lto=llvm-thin`

# How can I do this with Xcode or xcodebuild?

The Xcode UI doesn't seem to expose an option for `-lto`. Passing it as `OTHER_SWIFT_FLAGS` in my hello world Swift command-line app causes a strange error:

```t
> xcodebuild -scheme Test -configuration Release OTHER_SWIFT_FLAGS="-lto=llvm-full"
...
ld: file cannot be open()ed, errno=2 path=/Users/.../Objects-normal/arm64/main.o

```

The linker doesn't find the object file `main.o` because it doesn't exist. We only have the LLVM bitcode file:

```swift
> ls /Users/.../Objects-normal/arm64/main.* 
/Users/.../Objects-normal/arm64/main.bc

```

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [May 16, 2025, 11:40am UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/2 "2025-05-16T11:40:21Z")

</div>

Swift Forums is dedicated to [swift.org](http://swift.org) open source project and closed-source software like Xcode is off-topic here. If you're interested exclusively in Xcode, you should file an issue at [https://feedbackassistant.apple.com](https://feedbackassistant.apple.com).

To possibly keep this on-topic, is it reproducible for you when using [`--build-system swiftbuild`](https://github.com/swiftlang/swift-build?tab=readme-ov-file#with-swiftpm) with latest snapshots, which hopefully should be closer to `xcodebuild` in its behavior? Maybe @jakepetroules or @owenv can provide some other steps to reproduce this with [swift.org](http://swift.org) distributions outside of Xcode and `xcodebuild`.

---

<div class="post-metadata">

**Author:** ![weliveindetail](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/weliveindetail/32/38490_2.png) [@weliveindetail](https://forums.swift.org/u/weliveindetail)\
**Post date:** [May 16, 2025, 12:19pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/3 "2025-05-16T12:19:47Z")

</div>

Thanks for the quick reply. Yes that seems to reproduce with swift-build. Here is what I did.

In the folder with my `Test.xcodeproject` I initialized a swift-build package with `swift package init --type executable`. This is what I get:

```swift
> tree -L2 .
.
├── Package.swift
├── Sources
│ └── main.swift
├── Test
│ └── main.swift
└── Test.xcodeproj
    ├── project.pbxproj
    ├── project.xcworkspace
    ├── xcshareddata
    └── xcuserdata

7 directories, 4 files

```

`swift build -c release` works and `swift run` prints "Hello world" as expected.

Now, I added the `-lto` option to the generated `Package.swift` (and `-v` for clang):

```swift
// swift-tools-version: 6.1
import PackageDescription
let package = Package(
    name: "Test",
    targets: [
        .executableTarget(
            name: "Test",
            swiftSettings: [
                .unsafeFlags(["-lto=llvm-full"], .when(configuration: .release)),
            ],
            linkerSettings: [
                .unsafeFlags(["-Xclang-linker", "-v"], .when(configuration: .release))
            ]
        ),
    ]
)

```

I cleared the build folder and run the build with LTO and verbose output:

```swift
> rm -rf .build
> swift build -c release -v

```

This fails in a very similar way as xcodebuild:

```swift
clang: error: no such file or directory: '/Users/.../Test/.build/arm64-apple-macosx/release/Test.build/main.swift.o'

```

---

<div class="post-metadata">

**Author:** ![weliveindetail](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/weliveindetail/32/38490_2.png) [@weliveindetail](https://forums.swift.org/u/weliveindetail)\
**Post date:** [May 16, 2025, 12:21pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/4 "2025-05-16T12:21:55Z")

</div>

Seems like it's not allowed to attach logs, so I put the log with the full output here: [https://pastebin.com/raw/9U0xs9dg](https://pastebin.com/raw/9U0xs9dg)

---

<div class="post-metadata">

**Author:** ![weliveindetail](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/weliveindetail/32/38490_2.png) [@weliveindetail](https://forums.swift.org/u/weliveindetail)\
**Post date:** [May 16, 2025, 12:39pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/5 "2025-05-16T12:39:46Z")

</div>

This is very similar to the behavior in xcodebuild: swiftc produces a LLVM bitcode file that clang cannot find. In particular (you can find all of it in the log above), I get:

1. swift-build writing the linker input paths to `/Users/.../Test/.build/arm64-apple-macosx/release/Test.product/Objects.LinkFileList`
2. swift-frontend compiling the LLVM bitcode file in my CWD (this is clearly a bug on its own): `swift-frontend -frontend -emit-bc /Users/.../Test/Sources/main.swift -o main.bc`
3. `clang` looking for the LLVM bitcode in the `Objects.LinkFileList` path `/Users/.../Test/.build/arm64-apple-macosx/release/Test.build/main.swift.o`, which doesn't exist

When I change the clang invocation and point it at the actual bitcode file `/Users/.../Test/main.bc` instead, it works perfectly:

```swift
> /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang /Users/.../Test/main.bc -F /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -F /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/PrivateFrameworks --sysroot /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk --target=arm64-apple-macosx10.13 -force_load /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCompatibilityConcurrency.a -force_load /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCompatibility56.a /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCompatibilityPacks.a -L /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -L /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/lib/swift -rpath /usr/lib/swift -L /Users/.../Test/.build/arm64-apple-macosx/release -L /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -Xlinker -no_warn_duplicate_libraries -Xlinker -dead_strip -Xlinker -alias -Xlinker _Test_main -Xlinker _main -Xlinker -rpath -Xlinker @loader_path -Xlinker -rpath -Xlinker /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx -v -flto=full -o /Users/.../Test/.build/arm64-apple-macosx/release/Test
Apple clang version 17.0.0 (clang-1700.0.13.3)
Target: arm64-apple-macosx10.13
Thread model: posix
InstalledDir: /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
 "/Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple arm64-apple-macosx10.13.0 -Wundef-prefix=TARGET_OS_ -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-llvm-bc -flto=full -flto-unit -dumpdir /Users/.../Test/.build/arm64-apple-macosx/release/Test- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.bc -mrelocation-model pic -pic-level 2 -mframe-pointer=non-leaf -fno-strict-return -ffp-contract=on -fno-rounding-math -funwind-tables=1 -fobjc-msgsend-selector-stubs -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -fbuiltin-headers-in-system-modules -fdefine-target-os-macros -fno-assume-unique-vtables -target-cpu apple-m1 -target-feature +zcm -target-feature +zcz -target-feature +v8.5a -target-feature +aes -target-feature +altnzcv -target-feature +ccdp -target-feature +complxnum -target-feature +crc -target-feature +dotprod -target-feature +fp-armv8 -target-feature +fp16fml -target-feature +fptoint -target-feature +fullfp16 -target-feature +jsconv -target-feature +lse -target-feature +neon -target-feature +pauth -target-feature +perfmon -target-feature +predres -target-feature +ras -target-feature +rcpc -target-feature +rdm -target-feature +sb -target-feature +sha2 -target-feature +sha3 -target-feature +specrestrict -target-feature +ssbs -target-abi darwinpcs -debugger-tuning=lldb -fdebug-compilation-dir=/Users/.../Test -target-linker-version 1167.4.1 -v -fcoverage-compilation-dir=/Users/.../Test -resource-dir /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/17 -Wno-reorder-init-list -Wno-implicit-int-float-conversion -Wno-c99-designator -Wno-final-dtor-non-final-class -Wno-extra-semi-stmt -Wno-misleading-indentation -Wno-quoted-include-in-framework-header -Wno-implicit-fallthrough -Wno-enum-enum-conversion -Wno-enum-float-conversion -Wno-elaborated-enum-base -Wno-reserved-identifier -Wno-gnu-folding-constant -ferror-limit 19 -stack-protector 1 -fstack-check -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fmax-type-align=16 -fcommon -fcolor-diagnostics -clang-vendor-feature=+disableNonDependentMemberExprInCurrentInstantiation -fno-odr-hash-protocols -clang-vendor-feature=+enableAggressiveVLAFolding -clang-vendor-feature=+revert09abecef7bbf -clang-vendor-feature=+thisNoAlignAttr -clang-vendor-feature=+thisNoNullAttr -clang-vendor-feature=+disableAtImportPrivateFrameworkInImplementationError -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/folders/_g/4v0k_c211371j17qv5gd5y_h0000gn/T/main-e5d497.o -x ir /Users/.../Test/main.bc
clang -cc1 version 17.0.0 (clang-1700.0.13.3) default target arm64-apple-darwin24.4.0
 "/Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -object_path_lto /var/folders/_g/4v0k_c211371j17qv5gd5y_h0000gn/T/cc-5a4cc4.o -lto_library /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch arm64 -force_load /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCompatibilityConcurrency.a -force_load /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCompatibility56.a -platform_version macos 11.0.0 11.0.0 -syslibroot /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk -mllvm -enable-linkonceodr-outlining -o /Users/.../Test/.build/arm64-apple-macosx/release/Test -L/Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -L/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/lib/swift -L/Users/.../Test/.build/arm64-apple-macosx/release -L/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib /var/folders/_g/4v0k_c211371j17qv5gd5y_h0000gn/T/main-e5d497.o /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCompatibilityPacks.a -rpath /usr/lib/swift -no_warn_duplicate_libraries -dead_strip -alias _Test_main _main -rpath @loader_path -rpath /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx -lSystem /Applications/Xcode_16.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/17/lib/darwin/libclang_rt.osx.a -F/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -F/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/PrivateFrameworks

```

**Edit:** Also added `.unsafeFlags(["-Xclang-linker", "-flto=full"], .when(configuration: .release))` to linkerSettings in Package.swift but that didn't affect the behavior of swift-build

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [May 16, 2025, 1:00pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/6 "2025-05-16T13:00:20Z")

</div>

Thanks for the detailed investigation! This seems to me like something that SwiftPM should be able to handle regardless of the underlying build system. Would you mind filing an issue with your findings [on the SwiftPM repository](https://github.com/swiftlang/swift-package-manager/issues)?

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [May 16, 2025, 1:01pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/7 "2025-05-16T13:01:10Z")

</div>

In general, you're not going to find much success passing unsafe flags, especially if those flags change things like compiler outputs, because the build planning done by Xcode and SwiftPM (and most build systems, typically) won't take those into account beyond passing them opaquely to the compiler/linker. So if a flag changes the compiler's outputs from `.o` to `.bc`, SwiftPM won't be aware of that and it'll still pass expect the former.

It looks like SwiftPM added a [`--experimental-lto-mode={thin,full}` flag](https://github.com/swiftlang/swift-package-manager/pull/6611) a while back that addresses the different expectations in file extensions; that might be worth a try. (But I don't know if there's a way to get Xcode to pass that through.)

---

<div class="post-metadata">

**Author:** ![owenv](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/owenv/32/6137_2.png) [@owenv](https://forums.swift.org/u/owenv)\
**Post date:** [May 16, 2025, 3:09pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/8 "2025-05-16T15:09:28Z")

</div>

It's not wired up to `swift build --build-system swiftbuild right now` (filed [--experimental-lto-mode={thin,full} should override SWIFT\_LTO setting with --build-system swiftbuild · Issue #8682 · swiftlang/swift-package-manager · GitHub](https://github.com/swiftlang/swift-package-manager/issues/8682) to track this), but `SWIFT_LTO=YES` or `SWIFT_LTO=YES_THIN` can be used to enable LTO for Swift sources in the context of an Xcode project, either as a user defined build setting or command line settings override.

> <https://github.com/swiftlang/swift-build/blob/1d66c4fdc1b1caac33c015236ee26e03ef054402/Sources/SWBUniversalPlatform/Specs/Swift.xcspec#L326>

---

<div class="post-metadata">

**Author:** ![rauhul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rauhul/32/35207_2.png) [@rauhul](https://forums.swift.org/u/rauhul)\
**Post date:** [May 16, 2025, 5:02pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/9 "2025-05-16T17:02:29Z")

</div>

As the person who added SwiftPM's `--experimental-lto-mode={thin,full}` flag, I'd like to note that you _will_ find bugs with this implementation currently (like `-lto_object_path` not being set). I assume the new/wip `swiftbuild` backend for SwiftPM will be a lot more robust.

---

<div class="post-metadata">

**Author:** ![weliveindetail](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/weliveindetail/32/38490_2.png) [@weliveindetail](https://forums.swift.org/u/weliveindetail)\
**Post date:** [May 28, 2025, 2:33pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/10 "2025-05-28T14:33:35Z")

</div>

Perfect, thanks! I only tested `LLVM_LTO` before and had no luck. The `SWIFT_LTO` flag is exactly what I was looking for. In Xcode 16.3, this works with my initial hello world example in xcodebuild:

```swift
> xcodebuild -scheme Test -configuration Release SWIFT_LTO=YES
> cat /Users/.../Objects-normal/arm64/Test.LinkFileList
/Users/.../Objects-normal/arm64/main.bc

```

I didn't get anywhere with `swift build` quickly. It seems like `SWIFT_LTO` isn't supported here and `--experimental-lto-mode` isn't yet available in this release of the toolchain.

---

<div class="post-metadata">

**Author:** ![rauhul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rauhul/32/35207_2.png) [@rauhul](https://forums.swift.org/u/rauhul)\
**Post date:** [May 28, 2025, 2:42pm UTC](https://forums.swift.org/t/using-lto-llvm-full-thin-with-xcodebuild/79931/11 "2025-05-28T14:42:02Z")

</div>

FWIW that experimental lto option has been in swift build for a while:

```swift
➜ swiftly use
Swift 6.0.3 (default)
➜ swift build --version
Swift Package Manager - Swift 6.0.3
➜ swift build --help-hidden | rg lto
  --experimental-lto-mode <experimental-lto-mode>

```
