Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swift-nioがビルドできない #75

Closed
omochi opened this issue Jul 21, 2023 · 7 comments
Closed

swift-nioがビルドできない #75

omochi opened this issue Jul 21, 2023 · 7 comments

Comments

@omochi
Copy link
Collaborator

omochi commented Jul 21, 2023

依存先パッケージとして https://github.com/apple/swift-nio の一つだけを持つプロジェクトを作成し、
prepareコマンドを実行したところ、下記のエラーが出て失敗しました。

⚠️ Execution was terminated:
Build description signature: 255c1b48e1cedfd0c497911cc284d885

Build description path: /Users/omochi/work/sp/App/.build/scipio/DerivedData/Intermediates.noindex/XCBuildData/255c1b48e1cedfd0c497911cc284d885.xcbuilddata

Building targets in dependency order
Undefined symbols for architecture x86_64:
  "_swift_release_n", referenced from:
      __sa_release_n in _AtomicsShims.o

Undefined symbols for architecture arm64:
  "_swift_release_n", referenced from:
      __sa_release_n in _AtomicsShims.o

  "_swift_retain_n", referenced from:
      __sa_retain_n in _AtomicsShims.o

  "_swift_retain_n", referenced from:
      __sa_retain_n in _AtomicsShims.o

ld: symbol(s) not found for architecture x86_64

Undefined symbol: _swift_release_n
Undefined symbol: _swift_retain_n
ld: symbol(s) not found for architecture arm64

Undefined symbol: _swift_release_n
Undefined symbol: _swift_retain_n
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Linker command failed with exit code 1 (use -v to see invocation)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Linker command failed with exit code 1 (use -v to see invocation)

swift-nio の依存先である swift-atomics パッケージに含まれる、
_AtomicsShims ターゲットのビルドに失敗しているようです。

このターゲットでは、 extern参照したSwiftランタイム関数である、
swift_retain_n を呼び出そうとしていますが、ビルド時にリンクできていないようです。

根本のパッケージの定義を以下に掲載します。

// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "App",
    platforms: [.macOS(.v13)],
    dependencies: [
        .package(url: "https://github.com/apple/swift-nio", from: "2.56.0")
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .executableTarget(
            name: "App",
            dependencies: [
                .product(name: "NIO", package: "swift-nio")
            ]
        ),
    ]
)

余談ですが、 https://github.com/unsignedapps/swift-create-xcframework で、
swift-nioパッケージを対象に実行したところ、
全く同じビルドエラーが生じました。

@giginet
Copy link
Owner

giginet commented Jul 21, 2023

おそらくここに書いてあることと同じで、libSwiftCore.dylibがダイナミックリンクできていません
apple/swift-atomics#8 (comment)

swift-nioに関しては、現状Static Library化することでビルドしています。
また、swift-nioはLibrary Evolutionもサポートしていないので、 --disable-library-evolution オプションも必要になります。

scipio create /path/to/swift-nio --static --disable-library-evolution -c release

integration testに含まれているので参考にしてみてください。

frameworkType: .static,
enableLibraryEvolution: false

@giginet
Copy link
Owner

giginet commented Jul 21, 2023

swift-create-xcframework は内部的に generate-xcodeproj を使っていて、これはSwift 5.8から削除されています。
(swift-create-xcframeworkは5.7以前のSwiftPMに依存している)

@omochi
Copy link
Collaborator Author

omochi commented Jul 22, 2023

ありがとうございます。

create は下記のようなエラーになってしまいました。

コマンド

create --platforms macOS --disable-library-evolution --static /Users/omochi/github/apple/swift-nio

結果

🔁 Resolving Dependencies...
📦 Building NIOHTTP1 for macOS
🚀 Combining into XCFramework...
Something went wrong during building
Please execute with --verbose option.
Execution was terminated:
“NIOHTTP1.framework” couldn’t be copied to “macos-arm64_x86_64” because an item with the same name already exists.


Error: Execution was terminated:
“NIOHTTP1.framework” couldn’t be copied to “macos-arm64_x86_64” because an item with the same name already exists.


Program ended with exit code: 1

念のため swift-nio/.build を削除してから実行しましたがダメでした。


integration testを参考に、
NIO product を利用するプロジェクトを作って prepare コマンドを使ったところ、
こちらはうまくビルドすることができました。


質問させてください。

typeの選択の挙動について

swiftpmはmac向けで普通にビルドすると、type指定のないtarget達(そしてほとんどはtype指定がない)は、
すべてstatic libraryとしてビルドされ、
最後のexecutableにすべてリンクされます。

なので、scipioのデフォルトの挙動はそれと同じであろうかと思ったのですが、そうではなく、
デフォルトではそれぞれのtargetはdynamic libraryとしてビルドしようとするのでしょうか?

また、もし --static 指定している状況で、
パッケージ定義側で明示的に type: .dynamic 指定されたproductがあった場合、
これはどちらになるのでしょうか?

dynamic libraryのビルド挙動について

試しにswift-atomicsのパッケージ定義を下記のように変更し、
$ swift build によってdynamic libraryとしてビルドさせたところ、
成功して libAtomics.dylib が得られました。

@@ -30,6 +30,7 @@ let package = Package(
   products: [
     .library(
       name: "Atomics",
+      type: .dynamic,
       targets: ["Atomics"]),
   ],
   targets: [

つまり、 swift-atomics にdynamic libraryとしてビルドできない問題があるのではなく、
scipioの生成するxcodebuild向けのdynamic libraryの構成が、
swift buildの挙動と異なっているという問題があるのだと思います。

これは今後修正の予定はありますか?
そうだったら、僕も調べてみるつもりです。


generate-xcodeprojも同様に動かなくなっていたんですね。

@kateinoigakukun
Copy link

kateinoigakukun commented Jul 25, 2023

swift buildはproductに対してのみリンクし、それ以外のターゲットの成果物は生のオブジェクトファイルとswiftmoduleのまま扱うのに対し、Scipioの生成するPIFはターゲットごとにframeworkを作ろうとするところに不一致があると思います。

なのでScipio側でなんとかする場合、product対してのみdynamic frameworkを許容し、それ以外のターゲットは全てstatic framework(もしくは可能ならアーカイブなしのframework)を作るようにPIFModifierを変更するのが良さそうです。ちょっとやってみます。

@omochi
Copy link
Collaborator Author

omochi commented Jul 26, 2023

下記のように swift-atomics_AtomicsShims ターゲットを直接product化して、
CLIからビルドしようとしたところ、同様のエラーが発生しました。

    .library(
        name: "_AtomicsShims",
        type: .dynamic,
        targets: ["_AtomicsShims"]
    )
$ swift build --product _AtomicsShims
Building for debugging...
ld: Undefined symbols:
  _swift_release_n, referenced from:
      __sa_release_n in _AtomicsShims.c.o
  _swift_retain_n, referenced from:
      __sa_retain_n in _AtomicsShims.c.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[0/1] Linking lib_AtomicsShims.dylib

なるほど確かに、
_AtomicsShims ターゲットは、dylibとしてビルドできないが、
別のdylibにリンクすることはできるようですね。

@giginet
Copy link
Owner

giginet commented Jul 27, 2023

@kateinoigakukun さんの言うとおり、targetとproductの扱いに不備があることは認識しています。

SwiftNIOはStaticビルド時のみうまく行くことを確認して、Dynamicだとうまくリンクできない例を確認しています。

@omochi
Copy link
Collaborator Author

omochi commented Jul 27, 2023

@kateinoigakukun に詳しく教えてもらいました。

_AtomicShimslibSwiftCore に依存しているのに、それが宣言されていないことが本質的な問題なようです。
ただ、libAtomic.dylib を構成する場合など、
リンク対象ターゲットに (Atomics などの) Swiftターゲットがある場合は、
リンカーがswiftcのドライバになり、
リンク対象に libSwiftCore が追加されるから、
_AtomicShims が正しくリンクできるそうです。

よって _AtomicShims 単体でシンボル解決できないのは、swift-nio 側の宣言・実装の問題
(またはSwiftPMの表現能力?) ということのようです。

productでないtargetはstatic libraryとしてビルドするのが良さそうですが、
それは本質的にはこのissueと関係ない改善です。

--static でビルドする限り問題なさそうだし、
dynamicが無理なのはこういう事なので、
本件はcloseします。
ありがとうございました。

@omochi omochi closed this as completed Jul 27, 2023
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

No branches or pull requests

3 participants