Skip to content

A library with the identifier 'ios-arm64_x86_64-simulator' already exists. #348

Closed

Description

@shirakaba

I'm running the following cmake-rn invocation with cmake-rn@0.6.3:

npx cmake-rn \
  --source ./NativeScript \
  --build /Users/jamie/Documents/git/napi-ios/dist/intermediates \
  --out packages/ios/build/RelWithDebInfo \
  -D TARGET_ENGINE=none \
  --triplet arm64-apple-ios-sim \
  --triplet x86_64-apple-ios-sim \
  --triplet arm64-apple-ios \
  --triplet 'arm64;x86_64-apple-darwin'

It raises the following error:

A library with the identifier 'ios-arm64_x86_64-simulator' already exists.

I notice a relevant guard in react-native-node-api's apple.ts file, but it's not helping:

// Delete any existing xcframework to prevent the error:
// - A library with the identifier 'macos-arm64' already exists.
// Ideally, it would only be necessary to delete the specific platform+arch, to allow selectively building from source.
fs.rmSync(outputPath, { recursive: true, force: true });

For a reproduction, I'll describe how to get set up with https://github.com/NativeScript/napi-ios/tree/jb/cmake-rn. This branch is my very belated (sorry!) effort to review your much-appreciated PR NativeScript/runtimes#22.

Reproduction steps:

# Clone the repo and check out my branch.
git clone git@github.com:NativeScript/napi-ios.git
git fetch origin
# At the time of filing this issue, I'm working on commit 8332775: "uninstall react-native-node-api from scripts".
git checkout jb/cmake-rn

# Install npm deps.
npm install

# Run the script that ultimately calls cmake-rn.
./build_all_react_native.sh

Running that command produces a lot of build logs, finally ending in this failure log:

--------------------------------------------------------------------------------
--- 08:01:37 --- Building NativeScript prebuilt for React Native Node-API (NativeScript.apple.node) 
--------------------------------------------------------------------------------

✔ Configured projects (apple: arm64-apple-ios-sim, x86_64-apple-ios-sim, arm64-apple-ios, arm64;x86_64-apple-darwin)
✔ Built projects
✖ Failed to assemble XCFramework (NativeScript): Running 'xcodebuild' failed (code = 70)
A library with the identifier 'ios-arm64_x86_64-simulator' already exists.

Looking into it, the failing command itself was:

xcodebuild \
  -create-xcframework \
  -framework \
  /Users/jamie/Documents/git/napi-ios/dist/intermediates/arm64-apple-ios-sim/out/Release/NativeScript.framework \
  -framework \
  /Users/jamie/Documents/git/napi-ios/dist/intermediates/x86_64-apple-ios-sim/out/Release/NativeScript.framework \
  -framework \
  /Users/jamie/Documents/git/napi-ios/dist/intermediates/arm64-apple-ios/out/Release/NativeScript.framework \
  -framework \
  /Users/jamie/Documents/git/napi-ios/dist/intermediates/arm64_x86_64-apple-darwin/out/Release/NativeScript.framework \
  -output \
  /Users/jamie/Documents/git/napi-ios/packages/ios/build/RelWithDebInfo/NativeScript.apple.node.xcframework

And here's all the local state just before it ran it. We can see it deleted /Users/jamie/Documents/git/napi-ios/packages/ios/build/RelWithDebInfo/NativeScript.apple.node.xcframework before attempting the command, but to no avail.

Image

And just before this command was run, the state of the repo was as follows:

.
├── dist
│   └── intermediates
│       ├── arm64-apple-ios
│       │   ├── CMakeCache.txt
│       │   ├── CMakeFiles
│       │   ├── CMakeScripts
│       │   ├── NativeScript.xcodeproj
│       │   ├── build
│       │   ├── cmake_install.cmake
│       │   └── out
│       ├── arm64-apple-ios-sim
│       │   ├── CMakeCache.txt
│       │   ├── CMakeFiles
│       │   ├── CMakeScripts
│       │   ├── NativeScript.xcodeproj
│       │   ├── build
│       │   ├── cmake_install.cmake
│       │   └── out
│       ├── arm64_x86_64-apple-darwin
│       │   ├── CMakeCache.txt
│       │   ├── CMakeFiles
│       │   ├── CMakeScripts
│       │   ├── NativeScript.xcodeproj
│       │   ├── build
│       │   ├── cmake_install.cmake
│       │   └── out
│       └── x86_64-apple-ios-sim
│           ├── CMakeCache.txt
│           ├── CMakeFiles
│           ├── CMakeScripts
│           ├── NativeScript.xcodeproj
│           ├── build
│           ├── cmake_install.cmake
│           └── out
├── metadata-generator
│   ├── dist
│   │   ├── arm64
│   │   │   └── bin
│   │   └── x86_64
│   │       └── bin
│   └── metadata
│       ├── metadata.ios-sim.arm64.h
│       ├── metadata.ios-sim.arm64.nsmd
│       ├── metadata.ios-sim.x86_64.h
│       ├── metadata.ios-sim.x86_64.nsmd
│       ├── metadata.ios.arm64.h
│       ├── metadata.ios.arm64.nsmd
│       ├── metadata.macos.arm64.h
│       ├── metadata.macos.arm64.nsmd
│       ├── metadata.macos.x86_64.h
│       ├── metadata.macos.x86_64.nsmd
│       ├── metadata.visionos-sim.arm64.nsmd
│       ├── metadata.visionos.arm64.nsmd
│       └── metadata.visionos.x86_64.nsmd
└── packages
    ├── ios
    │   └── build
    │       └── RelWithDebInfo # Currently empty
    ├── ios-sim                # Irrelevant (types-only)
    ├── macos
    │   ├── LICENSE
    │   ├── README.md
    │   ├── build
    │   │   └── RelWithDebInfo # Currently empty
    ├── objc                   # Irrelevant (uninvolved)
    ├── visionos               # Irrelevant (excluded)
    └── visionos-sim           # Irrelevant (types-only)

So there's no occurrence of ios-arm64_x86_64-simulator anywhere in the file tree. I'm wondering whether xcodebuild is actually generating it mid-run and tripping over its own output?

Activity

  1. shirakaba commented on Feb 6, 2026

    @shirakaba
    CollaboratorAuthor

    Okay, changing it from individual slices to a universal binary seems to work:

    Shell script

      TRIPLETS=()
    - TRIPLETS+=("arm64-apple-ios-sim")
    - TRIPLETS+=("x86_64-apple-ios-sim")
    + TRIPLETS+=("arm64;x86_64-apple-ios-sim")
    
      TRIPLET_ARGS=()
      for triplet in "${TRIPLETS[@]}"; do
        TRIPLET_ARGS+=(--triplet "$triplet")
      done
      
      OUTPUT_DIR="packages/ios/build/$CONFIG_BUILD"
      npx cmake-rn --source ./NativeScript --build "$DIST/intermediates" --out "$OUTPUT_DIR" -D TARGET_ENGINE=$TARGET_ENGINE "${TRIPLET_ARGS[@]}"

    Resulting command

      npx cmake-rn \
        --source ./NativeScript \
        --build /Users/jamie/Documents/git/napi-ios/dist/intermediates \
        --out packages/ios/build/RelWithDebInfo \
        -D TARGET_ENGINE=none \
    -   --triplet arm64-apple-ios-sim \
    -   --triplet x86_64-apple-ios-sim \
    +   --triplet 'arm64;x86_64-apple-ios-sim' \
        --triplet arm64-apple-ios \
        --triplet 'arm64;x86_64-apple-darwin'

    Output logs

    - ✔ Configured projects (apple: arm64-apple-ios-sim, x86_64-apple-ios-sim, arm64-apple-ios, arm64;x86_64-apple-darwin)
    - ✔ Built projects
    - ✖ Failed to assemble XCFramework (NativeScript): Running 'xcodebuild' failed (code = 70)
    - A library with the identifier 'ios-arm64_x86_64-simulator' already exists.
    + ✔ Configured projects (apple: arm64;x86_64-apple-ios-sim, arm64-apple-ios, arm64;x86_64-apple-darwin)
    + ✔ Built projects
    + ✔ XCFramework (NativeScript) assembled into packages/macos/build/RelWithDebInfo/NativeScript.apple.node

    I'm surprised, still. I would've thought it'd be okay to build arm64 and x86_64 separately; it would seem strange for it to be mandatory to build as a universal binary.

    If we can anticipate this, I wonder whether this is something we ought to warn the user about.

  2. kraenhansen commented on Feb 7, 2026

    @kraenhansen
    Collaborator

    Hmm, yeah. I agree, this is not intuitive and ideally it should be supported 🤔

    I tried to reproduce this outside or your setup, which failed with a different error:

    npm install
    npm run bootstrap
    cd packages/node-addon-examples/examples/1-getting-started/1_hello_world/napi
    npx cmake-rn --triplet arm64-apple-ios-sim --triplet x86_64-apple-ios-sim
    

    This yields:

    ✔ Configured projects (apple: arm64-apple-ios-sim, x86_64-apple-ios-sim)
    ✔ Built projects
    ✖ Failed to assemble XCFramework (hello): Running 'xcodebuild' failed (code = 70)
    Both 'ios-arm64-simulator' and 'ios-x86_64-simulator' represent two equivalent library definitions.
    
    ERROR Running 'xcodebuild' failed (code = 70)
    

    Not the exact same issue, but very similar 🤔 I'm using cmake-rn v0.6.3 (from main) and Xcode 26.2 / Build version 17C52 (xcodebuild -version).

    I get the same error when I invoke xcodebuild to create an xcframework from the intermediary artefacts:

    xcodebuild -create-xcframework -framework build/arm64-apple-ios-sim/out/Release/hello.framework -framework build/x86_64-apple-ios-sim/out/Release/hello.framework -output ./delete-me.xcframework
    

    This yields:

    Both 'ios-arm64-simulator' and 'ios-x86_64-simulator' represent two equivalent library definitions.
    

    Looking at the plist in one of these frameworks provides a hint to what might be the root cause:

    <?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>BuildMachineOSBuild</key>
    	<string>25C56</string>
    	<key>CFBundleDevelopmentRegion</key>
    	<string>English</string>
    	<key>CFBundleExecutable</key>
    	<string>hello</string>
    	<key>CFBundleIdentifier</key>
    	<string>example-0.hello</string>
    	<key>CFBundleInfoDictionaryVersion</key>
    	<string>6.0</string>
    	<key>CFBundlePackageType</key>
    	<string>FMWK</string>
    	<key>CFBundleShortVersionString</key>
    	<string>1.0</string>
    	<key>CFBundleSignature</key>
    	<string>????</string>
    	<key>CFBundleSupportedPlatforms</key>
    	<array>
    		<string>iPhoneSimulator</string>
    	</array>
    	<key>CFBundleVersion</key>
    	<string>1.0</string>
    	<key>CSResourcesFileMapped</key>
    	<true/>
    	<key>DTCompiler</key>
    	<string>com.apple.compilers.llvm.clang.1_0</string>
    	<key>DTPlatformBuild</key>
    	<string>23C53</string>
    	<key>DTPlatformName</key>
    	<string>iphonesimulator</string>
    	<key>DTPlatformVersion</key>
    	<string>26.2</string>
    	<key>DTSDKBuild</key>
    	<string>23C53</string>
    	<key>DTSDKName</key>
    	<string>iphonesimulator26.2</string>
    	<key>DTXcode</key>
    	<string>2620</string>
    	<key>DTXcodeBuild</key>
    	<string>17C52</string>
    	<key>MinimumOSVersion</key>
    	<string>26.2</string>
    	<key>UIDeviceFamily</key>
    	<array>
    		<integer>1</integer>
    	</array>
    </dict>
    </plist>
    

    It looks to me more like a limitation of the framework metadata schema 🤔 I don't know of any way to declare the intended architecture to get the two single architecture frameworks to co-exist within the Xcframework ...

  3. kraenhansen commented on Feb 7, 2026

    @kraenhansen
    Collaborator

    One option would be to use lipo to combine the two single architecture slices into one 🤔 We're already doing that in Ferric.

    I'm wondering, is this mostly a case of:

    1. This was surprising, but the workaround of building a universal binary is fine if the error was better and pointed you in the right direction, or
    2. This should be fixed, to automatically lipo a universal binary when multiple architectures for the same library definition is being built.
  4. kraenhansen commented on Feb 7, 2026

    @kraenhansen
    Collaborator

    I've created a PR to get a better failure earlier: #350

  5. self-assigned this
    on Feb 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

CMake RNOur `cmake` wrapping CLIenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions