Skip to content

feat(swift) add swift to C++ and objective-C interop#6967

Merged
waruqi merged 26 commits intoxmake-io:devfrom
Arthapz:add-swift-cxxinterop
Oct 28, 2025
Merged

feat(swift) add swift to C++ and objective-C interop#6967
waruqi merged 26 commits intoxmake-io:devfrom
Arthapz:add-swift-cxxinterop

Conversation

@Arthapz
Copy link
Member

@Arthapz Arthapz commented Oct 23, 2025

this PR introduces the swift.interop rule (automatically enabled when swift.interop is set)
and these target values

"swift.modulename"         (bool)                 : set the swift module name
"swift.interop"            (string "objc"|"cxx")  : enable swift <=> obj / c++ interop
"swift.interop.headername" (string)               : define the output header name
"swift.interop.cxxmain"    (bool)                 : force -parse-as-library flag to avoid  duplicate main symbols
// fibonacci.swift
public func fibonacciSwift(_ x: CInt) -> CInt {
  print("x [swift]: \(x)")
  if x <= 1 {
    return 1
  }
  return fibonacciSwift(x - 1) + fibonacciSwift(x - 2)
}
// main.cpp
#include <fibonacci-Swift.h>
#include <iostream>

int main(int argc, char ** argv) {
  std::cout << SwiftFibonacci::fibonacciSwift(5) << std::endl;
  return 0;
}
-- xmake.lua
target("cxx_interop")
    set_kind("binary")
    set_languages("cxx20")
    add_files("lib/**.swift", {public = true})
    add_files("src/**.cpp")
    set_values("swift.modulename", "SwiftFibonacci")
    set_values("swift.interop", "cxx")
    set_values("swift.interop.headername", "fibonacci-Swift.h")
    set_values("swift.interop.cxxmain", true)
> xmake
checking for platform ... macosx
checking for architecture ... x86_64
checking for Xcode directory ... /Applications/Xcode.app
checking for SDK version of Xcode for macosx (x86_64) ... 26.0
checking for Minimal target version of Xcode for macosx (x86_64) ... 15.7
[  3%]: <cxx_interop> generating.swift.header fibonacci-Swift.h
[ 38%]: cache compiling.release src/fibonacci.cpp
[ 56%]: compiling.release lib/fibonacci/fibonacci.swift
[ 76%]: linking.release cxx_interop
[100%]: build ok, spent 1.785s

> xmake run
x [swift]: 5
x [swift]: 4
x [swift]: 3
x [swift]: 2
x [swift]: 1
x [swift]: 0
x [swift]: 1
x [swift]: 2
x [swift]: 1
x [swift]: 0
x [swift]: 3
x [swift]: 2
x [swift]: 1
x [swift]: 0
x [swift]: 1
8

Summary by CodeRabbit

  • New Features

    • Added Swift-C++ bidirectional interoperability support enabling seamless mixing of Swift and C++ code
    • Added Swift static library archiver toolset for enhanced Swift compilation workflows
    • Extended toolchain support for Apple platforms with unified configuration management
  • Tests

    • Added comprehensive test projects demonstrating Swift-C++ interoperation patterns and build configurations

@Arthapz Arthapz marked this pull request as draft October 23, 2025 20:11
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Arthapz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the build system by introducing robust support for Swift interoperability with C++ and Objective-C. It achieves this by implementing a new rule for automated generation of bridging headers and by deeply integrating Swift compiler tools into the build process. The changes ensure that Swift components can be easily consumed by C++ and Objective-C codebases, facilitating the development of mixed-language projects.

Highlights

  • Swift Interoperability: Adds comprehensive support for Swift to C++ and Objective-C interoperability within the build system, allowing seamless integration of Swift code with C++ and Objective-C projects.
  • Automated Header Generation: Introduces a new swift.interop rule that automatically generates Swift-generated headers (e.g., ModuleName-Swift.h) required for C++ and Objective-C to call Swift code, simplifying mixed-language development.
  • Swift Static Library Archiver: Integrates swiftc as the dedicated tool for archiving Swift static libraries (scar), replacing the generic archiver and ensuring correct build flags for static library creation across various platforms.
  • Enhanced Build Configuration: Updates Swift build rules to correctly handle module naming and library parsing, and extends Xcode toolchain configurations with specific flags for Swift executables, shared, and static libraries across Apple platforms (iOS, macOS, tvOS, watchOS, xrOS).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces Swift to C++ and Objective-C interoperability support, which is a significant feature. The changes include a new swift.interop rule for generating C/C++ headers from Swift code, and updates across various toolchain and language definition files to accommodate a new scar tool for Swift static library archiving. The implementation looks solid, but I've found a few potential issues: a correctness bug in a test file that could lead to a crash, a couple of potential nil dereferences in the new Lua rule, and a missing configuration in one of the Xcode toolchain files. Overall, great work on adding this complex feature.

Comment on lines +14 to +17
if x <= 1 {
return 1
}
return fibonacciSwift(x - 1) + fibonacciSwift(x - 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation does not handle negative input values. If a negative number is passed, it will lead to infinite recursion and a stack overflow. It's best to add a check for negative numbers to ensure the function is robust.

  if x < 0 {
    // Fibonacci of a negative number is not defined.
    // The original implementation would lead to infinite recursion.
    return 0
  }
  if x <= 1 {
    return 1
  }
  return fibonacciSwift(x - 1) + fibonacciSwift(x - 2)

@Arthapz Arthapz force-pushed the add-swift-cxxinterop branch from 245ff14 to 94c00aa Compare October 23, 2025 20:35
@Arthapz Arthapz force-pushed the add-swift-cxxinterop branch from 94c00aa to 9a88678 Compare October 23, 2025 21:41
@Arthapz Arthapz marked this pull request as ready for review October 24, 2025 17:53
@Arthapz Arthapz force-pushed the add-swift-cxxinterop branch from f8c24a0 to da18615 Compare October 24, 2025 18:55
@Arthapz Arthapz force-pushed the add-swift-cxxinterop branch from c2d14c6 to 44d5134 Compare October 24, 2025 20:44
@coderabbitai
Copy link

coderabbitai bot commented Oct 25, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This pull request introduces Swift-C++ bidirectional interoperability support to XMake through new test projects, comprehensive toolchain enhancements including Swift interop rules, new compiler toolsets (sc, scsh, scar, scld), and refactored Xcode platform-specific loaders that consolidate configuration logic.

Changes

Cohort / File(s) Summary
Swift-C++ Interop Test Projects (Bidirectional)
tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/fibonacci.h, tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/module.modulemap, tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp, tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.swift, tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.cpp, tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.swift, tests/projects/swift/bidirectional_cxx_interop_lib/xmake.lua, tests/projects/swift/bidirectional_cxx_interop_lib/test.lua
Adds comprehensive test project demonstrating C++ calling Swift and Swift calling C++ via extern "C" functions; includes C header, module map, C++ and Swift implementations, executable entry points, and build configuration with three XMake targets (fibonacci, cxx_interop_lib, swift_interop_lib).
Swift-C++ Interop Test Projects (Unidirectional)
tests/projects/swift/cxx_interop/lib/fibonacci/fibonacci.swift, tests/projects/swift/cxx_interop/src/fibonacci.cpp, tests/projects/swift/cxx_interop/xmake.lua, tests/projects/swift/cxx_interop/test.lua
Adds C++-to-Swift interop test project with public Swift Fibonacci function, C++ main calling the interop header, binary build target with module naming, and platform-specific test gate.
Swift-C++ Interop Test Projects (Library Variant)
tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift, tests/projects/swift/cxx_interop_lib/src/fibonacci.cpp, tests/projects/swift/cxx_interop_lib/xmake.lua, tests/projects/swift/cxx_interop_lib/test.lua
Adds library-oriented Swift-C++ interop test with shared Fibonacci implementation, C++ consumer, two XMake targets (fibonacci library and cxx_interop_lib binary), and macOS-specific test execution.
XMake Compiler and Toolchain Core
xmake/core/tool/compiler.lua, xmake/core/tool/toolchain.lua
Adds compiler:languageflags(lang) method for language-specific flag retrieval; extends toolchain descriptions to include Swift static library archiver (scar).
Swift Language Configuration
xmake/languages/swift/xmake.lua
Renames static target kind from "ar" to "scar" and associated flags from "arflags" to "scarflags"; adds scar menu entry for Swift static archiver configuration.
Swift Compiler Flag Checking
xmake/modules/core/tools/swiftc/has_flags.lua
Modifies error handling in flag validation to treat non-"unknown argument" errors as successful runs, enabling broader compatibility checking.
Swift Build Rules
xmake/rules/swift/xmake.lua
Introduces new swift.interop public rule for C++/Objective-C interop with header generation; enhances swift.build rule to apply C++ interoperability flags, parse-as-library mode, and forced module naming; updates swift rule dependencies to include interop, runtime utilities, and linker rules.
LLVM Toolchain Swift Support
xmake/toolchains/llvm/xmake.lua
Adds Swift toolsets (sc, scsh, scar, scld) wired to Swift compilers; replaces macOS-only Xcode handling with unified multi-platform block for macOS, iphoneos, tvos, watchos, xros; introduces dynamic Xcode sysroot resolution with platform-specific lazy loading; extends target flags for Swift-related configurations.
Swift Toolchain Updates
xmake/toolchains/swift/xmake.lua
Adds scar toolset declaration and reorders toolset definitions; updates on_load to conditionally compute xcode_sysroot for macOS and load platform-specific Xcode configuration.
Xcode Platform Loaders (Consolidated)
xmake/toolchains/xcode/load_iphoneos.lua, xmake/toolchains/xcode/load_appletvos.lua, xmake/toolchains/xcode/load_applexros.lua, xmake/toolchains/xcode/load_watchos.lua
Simplifies platform-specific configuration by delegating to shared load_platform function, removing previous manual arch, sdk, simulator, and flag initialization for each platform.
Xcode macOS Loader
xmake/toolchains/xcode/load_macosx.lua
Substantially refactors macOS toolchain setup with early architecture/sysroot initialization, unified target flag computation, consolidated flag handling for C/C++, Objective-C++, assembly, and Swift, and Catalyst/macabi-specific path injections; introduces potential runtime issue with undefined variable reference.
Xcode Toolchain Declarations
xmake/toolchains/xcode/xmake.lua
Adds scar toolset alias mapped to Swift compiler (swiftc) for consistency with other Swift toolsets.

Sequence Diagram(s)

sequenceDiagram
    participant CppApp as C++ Application
    participant CppInterop as C++ Interop Header<br/>(fibonacci-Swift.h)
    participant SwiftFib as Swift Function<br/>(fibonacciSwift)
    participant CppFib as C++ Function<br/>(fibonacci_cpp)
    
    rect rgb(220, 240, 255)
        Note over CppApp,SwiftFib: Unidirectional: C++ calls Swift
        CppApp->>CppInterop: call SwiftFibonacci::fibonacciSwift(5)
        CppInterop->>SwiftFib: invoke Swift function
        SwiftFib-->>CppInterop: return CInt result
        CppInterop-->>CppApp: return value to C++
    end
    
    rect rgb(240, 220, 255)
        Note over CppFib,SwiftFib: Bidirectional: Swift calls C++
        SwiftFib->>CppFib: call fibonacci_cpp(x-1)<br/>via extern "C"
        CppFib->>SwiftFib: nested call<br/>SwiftFibonacci::fibonacciSwift(x-2)
        SwiftFib-->>CppFib: return result
        CppFib-->>SwiftFib: return computed value
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Swift interop rule logic (xmake/rules/swift/xmake.lua): Dense flag generation, header creation, and async job registration require careful validation.
  • Xcode platform loader refactoring (load_macosx.lua and consolidation pattern): Significant restructuring with potential logic errors (undefined variable plat referenced in conditional); verify sysroot resolution and flag application across platforms.
  • Toolchain architecture changes (LLVM, Swift, Xcode): Multiple new toolsets and sysroot resolution logic; cross-platform flag propagation must be verified.
  • Test project consistency: Ensure all three interop variants (bidirectional, unidirectional, library) compile and execute correctly with the new build rules.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat(swift) add swift to C++ and objective-C interop" accurately reflects the primary feature being introduced in the changeset. The main change is the addition of Swift interoperability with C++ and Objective-C, which is implemented through a new swift.interop rule, new target configuration values, toolchain updates, and comprehensive test projects demonstrating the functionality. The title is concise, specific enough to convey the main objective, and avoids vague terminology or unnecessary detail. While the title operates at a higher level of abstraction than naming the specific swift.interop rule, this is appropriate for a feature-level PR title that is meant to communicate the user-facing capability rather than internal implementation details.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a764f4 and 716bc9f.

📒 Files selected for processing (1)
  • xmake/rules/swift/xmake.lua (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
xmake/rules/swift/xmake.lua (5)
xmake/core/base/os.lua (3)
  • os.iorunv (1049-1074)
  • os.mkdir (664-682)
  • os.rm (566-600)
xmake/core/base/path.lua (1)
  • path.join (283-286)
xmake/modules/async/jobgraph.lua (1)
  • jobgraph:add (71-95)
xmake/core/base/table.lua (1)
  • table.join (93-106)
xmake/core/base/option.lua (1)
  • option.get (336-345)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: build (MINGW32, i686, /mingw32)
  • GitHub Check: build (macos-13, x86_64)
  • GitHub Check: build
  • GitHub Check: build (macos-13, x86_64)
  • GitHub Check: build (ubuntu-latest, x86_64)
  • GitHub Check: build (macos-14, arm64)
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build (windows-2025, x64)
  • GitHub Check: build (windows-2025, arm64)
  • GitHub Check: build
  • GitHub Check: build (windows-2022, x64)
  • GitHub Check: build (windows-2022, x86)
🔇 Additional comments (2)
xmake/rules/swift/xmake.lua (2)

180-201: LGTM! Swift build configuration logic is correct.

The configuration properly handles:

  • C++ interoperability mode flags
  • Library and cxxmain parsing modes
  • Module name enforcement
  • Special swift_frontend tool handling

204-221: LGTM! Swift rule dependencies are properly configured.

The rule correctly composes all necessary dependencies for Swift interoperability, including runtime handling, link inheritance, object merging, and linking.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

♻️ Duplicate comments (7)
tests/projects/swift/bidirectional_cxx_interop_lib/test.lua (1)

1-7: Duplicate of comment in tests/projects/swift/cxx_interop/test.lua.

This code duplication was already flagged in the review of tests/projects/swift/cxx_interop/test.lua.

tests/projects/swift/cxx_interop_lib/test.lua (1)

1-7: Duplicate of comment in tests/projects/swift/cxx_interop/test.lua.

This code duplication was already flagged in the review of tests/projects/swift/cxx_interop/test.lua.

tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.swift (1)

1-7: Duplicate of comment in tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift.

This code duplication was already flagged in the review of tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift.

tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.cpp (1)

4-7: Unused parameters in main function.

The parameters argc and argv are declared but never used.

Apply this diff:

-int main(int argc, char ** argv) {
+int main() {
   std::cout << SwiftFibonacci::fibonacciSwift(5) << std::endl;
   return 0;
 }
tests/projects/swift/cxx_interop_lib/src/fibonacci.cpp (1)

4-7: Unused parameters in main function.

The parameters argc and argv are unused.

Apply this diff:

-int main(int argc, char ** argv) {
+int main() {
   std::cout << SwiftFibonacci::fibonacciSwift(5) << std::endl;
   return 0;
 }
tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp (1)

7-7: Incorrect Fibonacci base case for x=0.

The base case returns 1 for both x=0 and x=1, but the standard Fibonacci sequence defines F(0) = 0 and F(1) = 1.

Apply this diff:

 extern "C" int fibonacci_cpp(int x) {
   std::cout << "x [cpp]: " << x << std::endl;
-  if (x <= 1) return 1;
+  if (x == 0) return 0;
+  if (x == 1) return 1;
   return SwiftFibonacci::fibonacciSwift(x - 1) + SwiftFibonacci::fibonacciSwift(x - 2);
 }
xmake/rules/swift/xmake.lua (1)

104-112: Guard sourcefiles in on_prepare_files loop.

sourcebatch.sourcefiles can be nil; wrap with or {} to avoid ipairs(nil) error. (Duplicate of earlier feedback.)

-        local sourcefiles = sourcebatch.sourcefiles
+        local sourcefiles = sourcebatch.sourcefiles or {}
🧹 Nitpick comments (10)
tests/projects/swift/cxx_interop/test.lua (1)

1-7: Extract duplicated test logic into a shared helper.

This exact test function is duplicated in three files:

  • tests/projects/swift/cxx_interop/test.lua
  • tests/projects/swift/bidirectional_cxx_interop_lib/test.lua
  • tests/projects/swift/cxx_interop_lib/test.lua

Consider extracting this platform-checking logic into a shared test utility module to reduce duplication and improve maintainability.

tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift (1)

1-7: Consider extracting shared Fibonacci implementation.

This Fibonacci implementation is duplicated in tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.swift. While acceptable for test code, extracting it into a shared module would improve maintainability.

Note: The exponential time complexity O(2^n) is acceptable for these small test inputs but would be inefficient for larger values.

tests/projects/swift/cxx_interop/src/fibonacci.cpp (2)

4-7: Unused parameters in main function.

The parameters argc and argv are declared but never used in this test program.

Apply this diff to remove unused parameters:

-int main(int argc, char ** argv) {
+int main() {
   std::cout << SwiftFibonacci::fibonacciSwift(5) << std::endl;
   return 0;
 }

1-7: Code duplication across test projects.

This test file is duplicated in three separate test directories:

  • tests/projects/swift/cxx_interop/src/fibonacci.cpp
  • tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.cpp
  • tests/projects/swift/cxx_interop_lib/src/fibonacci.cpp

Consider extracting common test logic into a shared utility or template to reduce maintenance burden.

tests/projects/swift/cxx_interop/lib/fibonacci/fibonacci.swift (1)

1-7: Consider memoization for better performance.

The naive recursive implementation has O(2^n) time complexity. While acceptable for demo/test purposes with small inputs, consider adding memoization if this code is used as a reference for users.

xmake/rules/swift/xmake.lua (1)

45-47: Optionally disable rule early to shrink jobgraph.

When no public Swift sources are found, disable the rule to avoid adding empty jobs.

-        if not enabled then
-            return
-        end
+        if not enabled then
+            target:rule_enable("swift.interop", false)
+            return
+        end

Based on past review comments.

xmake/toolchains/xcode/load_macosx.lua (4)

48-50: Unconditional “-lz” may be unnecessary and surprising.

Forcing zlib linkage globally can cause unwanted deps or link failures on targets that don’t use zlib.

Drop “-lz” here and let targets opt-in:

-    toolchain:add('ldflags', '-arch', arch, targetflag, '-isysroot', xcode_sysroot, '-lz')
-    toolchain:add('shflags', '-arch', arch, targetflag, '-isysroot', xcode_sysroot, '-lz')
+    toolchain:add('ldflags',  '-arch', arch, targetflag, '-isysroot', xcode_sysroot)
+    toolchain:add('shflags',  '-arch', arch, targetflag, '-isysroot', xcode_sysroot)

55-55: Don’t enable ARC globally by default.

Forcing -fobjc-arc can break projects that intentionally use MRC or mixed code. Prefer making this opt-in via project config.

-    toolchain:add('mxflags', '-fobjc-arc')
+    -- Let projects opt-in: add_mxflags("-fobjc-arc") in xmake.lua if desired

28-31: Avoid bare assert for simulator; raise a helpful error or ignore.

assert(not simulator) aborts without context. If this loader is selected incorrectly, guide the user.

-    assert(not simulator)
+    if simulator then
+        raise("macosx toolchain cannot target the simulator; use the iPhone/tvOS/watchOS simulator toolchain instead")
+    end

24-24: xcode_sdkver is read but unused.

Either use it to default target_minver (when not set) or remove the variable.

-    local xcode_sdkver = toolchain:config('xcode_sdkver') or get_config("xcode_sdkver")
+    -- local xcode_sdkver = toolchain:config('xcode_sdkver') or get_config("xcode_sdkver")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 954944d and 5104ea6.

📒 Files selected for processing (30)
  • tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/fibonacci.h (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/module.modulemap (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.swift (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.cpp (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.swift (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/test.lua (1 hunks)
  • tests/projects/swift/bidirectional_cxx_interop_lib/xmake.lua (1 hunks)
  • tests/projects/swift/cxx_interop/lib/fibonacci/fibonacci.swift (1 hunks)
  • tests/projects/swift/cxx_interop/src/fibonacci.cpp (1 hunks)
  • tests/projects/swift/cxx_interop/test.lua (1 hunks)
  • tests/projects/swift/cxx_interop/xmake.lua (1 hunks)
  • tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift (1 hunks)
  • tests/projects/swift/cxx_interop_lib/src/fibonacci.cpp (1 hunks)
  • tests/projects/swift/cxx_interop_lib/test.lua (1 hunks)
  • tests/projects/swift/cxx_interop_lib/xmake.lua (1 hunks)
  • xmake/core/tool/compiler.lua (1 hunks)
  • xmake/core/tool/toolchain.lua (1 hunks)
  • xmake/languages/swift/xmake.lua (2 hunks)
  • xmake/modules/core/tools/swiftc/has_flags.lua (1 hunks)
  • xmake/rules/swift/xmake.lua (2 hunks)
  • xmake/toolchains/llvm/xmake.lua (2 hunks)
  • xmake/toolchains/swift/xmake.lua (1 hunks)
  • xmake/toolchains/xcode/load_appletvos.lua (1 hunks)
  • xmake/toolchains/xcode/load_applexros.lua (1 hunks)
  • xmake/toolchains/xcode/load_iphoneos.lua (1 hunks)
  • xmake/toolchains/xcode/load_macosx.lua (1 hunks)
  • xmake/toolchains/xcode/load_platform.lua (1 hunks)
  • xmake/toolchains/xcode/load_watchos.lua (1 hunks)
  • xmake/toolchains/xcode/xmake.lua (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
tests/projects/swift/cxx_interop_lib/test.lua (1)
xmake/core/base/os.lua (1)
  • os.host (1138-1140)
tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/fibonacci.h (1)
tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp (2)
  • fibonacci_cpp (5-9)
  • fibonacci_cpp (5-5)
tests/projects/swift/cxx_interop/test.lua (1)
xmake/core/base/os.lua (1)
  • os.host (1138-1140)
xmake/toolchains/swift/xmake.lua (1)
xmake/core/base/path.lua (1)
  • path.join (283-286)
xmake/rules/swift/xmake.lua (5)
xmake/core/base/os.lua (3)
  • os.iorunv (1049-1074)
  • os.mkdir (664-682)
  • os.rm (566-600)
xmake/core/base/path.lua (1)
  • path.join (283-286)
xmake/modules/async/jobgraph.lua (1)
  • jobgraph:add (71-95)
xmake/core/base/table.lua (1)
  • table.join (93-106)
xmake/core/base/option.lua (1)
  • option.get (336-345)
tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.cpp (1)
tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.swift (1)
  • fibonacciSwift (1-7)
xmake/toolchains/llvm/xmake.lua (1)
xmake/core/base/path.lua (1)
  • path.join (283-286)
tests/projects/swift/bidirectional_cxx_interop_lib/test.lua (1)
xmake/core/base/os.lua (1)
  • os.host (1138-1140)
tests/projects/swift/cxx_interop_lib/src/fibonacci.cpp (2)
tests/projects/swift/cxx_interop/lib/fibonacci/fibonacci.swift (1)
  • fibonacciSwift (1-7)
tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift (1)
  • fibonacciSwift (1-7)
xmake/toolchains/xcode/load_macosx.lua (1)
xmake/core/base/path.lua (1)
  • path.join (283-286)
tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp (1)
tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.swift (1)
  • fibonacciSwift (1-7)
tests/projects/swift/cxx_interop/src/fibonacci.cpp (2)
tests/projects/swift/cxx_interop/lib/fibonacci/fibonacci.swift (1)
  • fibonacciSwift (1-7)
tests/projects/swift/cxx_interop_lib/lib/fibonacci/fibonacci.swift (1)
  • fibonacciSwift (1-7)
tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.swift (1)
tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp (2)
  • fibonacci_cpp (5-9)
  • fibonacci_cpp (5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: build (windows-2022, x86)
  • GitHub Check: build (windows-2025, x86)
  • GitHub Check: build (windows-2025, x64)
  • GitHub Check: build (windows-2022, x86)
  • GitHub Check: build (windows-2022, x64)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (20)
tests/projects/swift/cxx_interop/xmake.lua (1)

1-9: LGTM!

The Swift-C++ interop configuration is well-structured. The settings properly enable bidirectional interop by marking Swift files as public, specifying the module name, interop type, header name, and the cxxmain flag to prevent symbol conflicts.

tests/projects/swift/bidirectional_cxx_interop_lib/src/fibonacci.swift (1)

1-3: LGTM!

This test code correctly demonstrates Swift calling a C++ function through the interop bridge.

tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/fibonacci.h (1)

1-6: LGTM!

The header properly declares the C-compatible interface with include guards and extern "C" linkage for interop.

tests/projects/swift/bidirectional_cxx_interop_lib/include/fibonacci/module.modulemap (1)

1-3: LGTM!

The module map correctly declares the Fibonacci module and exports the fibonacci.h header for C++/Swift interop.

tests/projects/swift/bidirectional_cxx_interop_lib/lib/fibonacci.cpp (1)

5-9: Verify interop with corrected Swift base case.

Once the base case is corrected in the Swift implementation (fibonacci.swift), ensure this C++ function correctly delegates to the updated Swift logic for consistent results across the bidirectional interop.

tests/projects/swift/cxx_interop_lib/xmake.lua (1)

1-12: LGTM!

The build configuration correctly establishes Swift-C++ interop with appropriate target dependencies, module naming, and language settings.

tests/projects/swift/bidirectional_cxx_interop_lib/xmake.lua (1)

1-23: LGTM!

The bidirectional interop configuration correctly establishes:

  • A shared fibonacci target with both Swift and C++ sources
  • Public Swift compiler flags for modulemap discovery
  • Separate binary targets for C++ and Swift consumers
  • Appropriate dependency relationships

The setup demonstrates a comprehensive Swift-C++ bidirectional interop workflow.

xmake/core/tool/compiler.lua (1)

366-371: LGTM! Clean delegation to the underlying tool.

The new languageflags method follows the established pattern of delegating to the underlying tool via _tool(). The implementation is straightforward and the documentation is consistent with the existing style in this file.

xmake/core/tool/toolchain.lua (1)

445-445: LGTM! Consistent toolkind description addition.

The new "scar" (Swift static library archiver) description follows the established pattern and is properly positioned in the descriptions table.

xmake/toolchains/xcode/xmake.lua (1)

54-54: LGTM! Consistent with existing Swift toolset declarations.

The new scar toolset correctly points to the Swift compiler (swiftc), mirroring the pattern used for other Swift toolsets (sc, scld, scsh).

xmake/languages/swift/xmake.lua (2)

25-26: LGTM! Appropriate language-specific toolkind separation.

Renaming the Swift static library toolkind from "ar" to "scar" appropriately distinguishes Swift-specific archiving from C/C++ archiving, allowing for Swift-specific flag handling.


108-108: LGTM! Menu entry consistent with toolkind change.

The new menu entry for the Swift Static Library Archiver aligns with the scar toolkind introduced in this file.

xmake/toolchains/xcode/load_applexros.lua (1)

21-25: LGTM! Clean refactoring to centralize platform loading.

Delegating to load_platform consolidates platform-specific configuration logic and reduces code duplication. This pattern is consistent with similar refactoring in other Xcode platform loaders (iphoneos, appletvos, watchos).

xmake/toolchains/swift/xmake.lua (2)

31-32: LGTM! Consistent scar toolset addition.

The new scar (Swift static library archiver) toolset follows the pattern of other Swift toolsets and aligns with the broader scar integration across toolchains.


36-47: LGTM! Proper macOS SDK configuration with platform delegation.

The conditional macOS logic correctly constructs the Xcode SDK path and delegates to the platform-specific loader, aligning with the refactoring pattern used in other Xcode toolchain loaders.

xmake/toolchains/xcode/load_watchos.lua (1)

21-25: Refactoring correctly addresses scarflags for watchOS.

Verification confirms the refactored load_platform implementation properly handles scarflags with both -target and -sdk for watchOS. In fact, the refactoring fixes a bug in the original code: the previous load_watchos.lua incorrectly used "-target %s-apple-ios%s" (iOS platform triple) instead of watchOS. The new implementation correctly generates "-target arm64-apple-watchos..." by using the plat parameter. The scarflags configuration at line 57 of load_platform.lua includes all required elements: -sdk, -target (via targetflag), -emit-library, and -static.

xmake/modules/core/tools/swiftc/has_flags.lua (1)

76-79: Acknowledge valid concern about error suppression logic, but unable to confirm the issue is wrong without swiftc installed.

The code at lines 76-79 does invert the normal success/failure semantics: it treats all errors except "unknown argument" as success. Your concern is justified—this broad suppression could mask legitimate compilation failures.

However, I cannot test swiftc directly in the sandbox environment to understand what specific error patterns it produces. The logic appears intentional (committed as a recent fix: ddcda7d7), but without access to the original PR discussion or swiftc's actual error output, I cannot definitively confirm whether:

  1. swiftc emits benign errors to stderr even during successful compilation
  2. The empty test file is expected to fail compilation for reasons unrelated to the flag
  3. This is an actual bug that went unnoticed

The code is production-ready and swift_frontend/has_flags.lua inherits the same logic, suggesting deliberate design rather than oversight.

xmake/toolchains/xcode/load_appletvos.lua (1)

21-25: Delegation looks good.

Simple handoff to load_platform(toolchain, "tvos") keeps behavior centralized. No issues.

xmake/toolchains/xcode/load_iphoneos.lua (1)

21-25: LGTM: centralized iOS loader.

Consistent with the new shared platform loader; no issues spotted.

xmake/toolchains/xcode/load_macosx.lua (1)

66-90: Catalyst iOSSupport paths: solid guard and path joins. LGTM.

If you want extra safety, consider verifying these subpaths exist for the active SDK before adding them (optional).

Comment on lines +84 to +95
local languages = target:get("languages")
for _, language in ipairs(languages) do
if language:startswith("c++")
or language:startswith("cxx")
or language:startswith("gnu++")
or language:startswith("gnuxx") then
-- c++26 currently prevent compilation of swift modules
local v = compinst:languageflags(language:gsub("26", "23"):gsub("latest", "23"))
if v then return v end
end
end
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Nil-guard languages when deriving C++ standard.

target:get("languages") can be nil. Add a quick guard.

-            local languages = target:get("languages")
-            for _, language in ipairs(languages) do
+            local languages = target:get("languages")
+            if not languages then return end
+            for _, language in ipairs(languages) do
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
local languages = target:get("languages")
for _, language in ipairs(languages) do
if language:startswith("c++")
or language:startswith("cxx")
or language:startswith("gnu++")
or language:startswith("gnuxx") then
-- c++26 currently prevent compilation of swift modules
local v = compinst:languageflags(language:gsub("26", "23"):gsub("latest", "23"))
if v then return v end
end
end
end
local languages = target:get("languages")
if not languages then return end
for _, language in ipairs(languages) do
if language:startswith("c++")
or language:startswith("cxx")
or language:startswith("gnu++")
or language:startswith("gnuxx") then
-- c++26 currently prevent compilation of swift modules
local v = compinst:languageflags(language:gsub("26", "23"):gsub("latest", "23"))
if v then return v end
end
end
end
🤖 Prompt for AI Agents
In xmake/rules/swift/xmake.lua around lines 84 to 95, target:get("languages")
can be nil which will cause an error when iterating; add a nil-guard immediately
after fetching languages (e.g., if not languages then return end) so the
function exits safely when no languages are defined before the for-loop that
derives the C++ standard.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
xmake/rules/swift/xmake.lua (1)

79-92: Add nil-guard for languages.

target:get("languages") can return nil, causing ipairs(nil) on line 82 to raise an error.

Apply this diff to guard against nil:

         local function _get_target_cppversion()
             local compinst = target:compiler("cxx")
             local languages = target:get("languages")
+            if not languages then return end
             for _, language in ipairs(languages) do
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5104ea6 and 4a764f4.

📒 Files selected for processing (1)
  • xmake/rules/swift/xmake.lua (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
xmake/rules/swift/xmake.lua (5)
xmake/core/base/os.lua (3)
  • os.iorunv (1049-1074)
  • os.mkdir (664-682)
  • os.rm (566-600)
xmake/core/base/path.lua (1)
  • path.join (283-286)
xmake/modules/async/jobgraph.lua (1)
  • jobgraph:add (71-95)
xmake/core/base/table.lua (1)
  • table.join (93-106)
xmake/core/base/option.lua (1)
  • option.get (336-345)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: build (windows-2025, x86)
  • GitHub Check: build (macos-13, x86_64)
  • GitHub Check: build (windows-2025, x86)
  • GitHub Check: build (windows-2025, arm64)
  • GitHub Check: build (macos-13, x86_64)
  • GitHub Check: build (windows-2025, x64)
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build (MINGW32, i686, /mingw32)
  • GitHub Check: build (macos-14, arm64)
🔇 Additional comments (2)
xmake/rules/swift/xmake.lua (2)

181-190: LGTM! Interop configuration is correctly applied.

The logic properly detects C++ interop mode, adds appropriate flags (-cxx-interoperability-mode=default, -parse-as-library), and forces the module name. The implementation is sound.


206-221: LGTM! Dependencies correctly declared.

The swift rule now properly depends on swift.interop, runtime utilities, link inheritance, and linker rules. This ensures correct build order and capability integration.

@Arthapz Arthapz force-pushed the add-swift-cxxinterop branch from 4a764f4 to 716bc9f Compare October 25, 2025 17:21
)
end

local compinst = import("core.tool.compiler").load("sc")
Copy link
Member

@waruqi waruqi Oct 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do not use local compinst = target:compiler("sc") and compinst:compflags()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because i don't know why but

                    local compinst = import("core.tool.compiler").load("sc")
                    local compinst2 = target:compiler("sc")
                    print(compinst:program())
                    print(compinst2:program())

give me

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend
/usr/local/Cellar/llvm/21.1.4/bin/clang++

-- c++26 currently prevent compilation of swift modules
local v = compinst:languageflags(language:gsub("26", "23"):gsub("latest", "23"))
if v then return v end
import("core.cache.localcache")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this module is unused.

@waruqi waruqi added this to the v3.0.5 milestone Oct 27, 2025
@waruqi waruqi merged commit 961a7f0 into xmake-io:dev Oct 28, 2025
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants