# Autolinking behavior of @\_implementationOnly with static linking

**URL:** <https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393>\
**Category:** Core Libraries\
**Tags:** foundation, question\
**Created:** [February 3, 2021, 3:34am UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393 "2021-02-03T03:34:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [February 3, 2021, 3:34am UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/1 "2021-02-03T03:34:20Z")

</div>

I want to confirm that I'm using @\_implementationOnly correctly with static library in autolinking aspect.

Currently, [Foundation](https://github.com/apple/swift-corelibs-foundation) imports CoreFoundation with @\_implementationOnly attribute other than Linux and Darwin platforms.

Modules imported with @\_implementationOnly are not added to swift1\_autolink\_entries to hide the dependencies, and they will be linked as private dependencies so that users don't need to link the private dependencies explicitly.

But the private linking only works on dynamic linking.

For example, Wasm toolchain uses static linking and CoreFoundation is imported with @\_implementationOnly from Foundation. The produced `libFoundation.a` doesn't have CoreFoundation contents, so the Foundation users need to link CoreFoundation and CoreFoundation's dependencies explicitly.

In this case, should we merge CoreFoundation and CoreFoundation's dependencies with libFoundation.a like below?

```swift
$ llvm-ar -M <<EOS
create libFoundation.a
addlib libFoundation.a
addlib libCoreFoundation.a
addlib libuuid.a
addlib libicui18n.a
save
end
EOS

```

---

<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:** [February 4, 2021, 11:56am UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/2 "2021-02-04T11:56:37Z")

</div>

Hi @millenomi @spevans, would you have a moment to take a look at this or redirect us to someone else who could help?

---

<div class="post-metadata">

**Author:** ![spevans](https://avatars.discourse-cdn.com/v4/letter/s/59ef9b/32.png) [@spevans](https://forums.swift.org/u/spevans)\
**Post date:** [February 4, 2021, 12:28pm UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/3 "2021-02-04T12:28:46Z")

</div>

I agree with you that for the static Foundation libraries `libFoundation.a`, `libFoundationNetworking.a` and `libFoundationXML.a` the dependencies should be linked in, even on Linux.

I have asked @compnerd (who is the expert on this) about this before and I think the issue maybe that CMake couldn't merge the libraries or there was no way to express it in `CMakeLists.txt` or something like that. Can you get it working in CMake?

Note, the `libicui18n.a` should probably be linked into `libswiftCore.a` on WASM as they are also used by the stdlib not just Foundation, along with the other ICU libraries.

I think there is still some more work to be done on making CoreFoundation private since its module is still shipped with the toolchain and `import CoreFoundation` still works, but this should actually go away in the future.

---

<div class="post-metadata">

**Author:** ![compnerd](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/compnerd/32/2165_2.png) [@compnerd](https://forums.swift.org/u/compnerd)\
**Post date:** [February 4, 2021, 6:40pm UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/4 "2021-02-04T18:40:34Z")

</div>

Merging CoreFoundation into Foundation is reasonable for static linking purposes.

Merging the ICU libraries into the single module IMO is not okay though. CoreFoundation and libuuid are part of the project, but merging in ICU like that is both problematic because it is a separate project and because you are not guaranteed that the data and the ICU libraries will match.

Also note that you should be able to work with non-LLVM librarians (e.g. MSVC's `lib` which does not support MRI scripts). So this would need to be done manually.

---

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [February 5, 2021, 2:03am UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/5 "2021-02-05T02:03:38Z")

</div>

> [@compnerd](#):
>
> Merging the ICU libraries into the single module IMO is not okay though. CoreFoundation and libuuid are part of the project, but merging in ICU like that is both problematic because it is a separate project and because you are not guaranteed that the data and the ICU libraries will match.

I agree with you. Then I think we need to add icui18n into autolink entries to avoid forcing users explicit linking. So is there a good way to add libicui18n.a into autolink entries from Swift? The only way I come up with is

1. Create a modulemap for icui18n:

```swift
module icui18n {
  link "icui18n"
}

```

1. Add import statement in Foundation

```swift
import icui18n

```

It's a little hacky, so I want to know if there is a simpler way.

> [@compnerd](#):
>
> Also note that you should be able to work with non-LLVM librarians (e.g. MSVC's `lib` which does not support MRI scripts). So this would need to be done manually.

Thanks for letting me know about the MSVC case. What do you think about changing CoreFoundation and libuuid to Object Libraries in CMake? I think it doesn't depend on archiver script and make it easy to express in CMake.

---

<div class="post-metadata">

**Author:** ![compnerd](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/compnerd/32/2165_2.png) [@compnerd](https://forums.swift.org/u/compnerd)\
**Post date:** [February 8, 2021, 5:13pm UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/6 "2021-02-08T17:13:24Z")

</div>

> [@kateinoigakukun](#):
>
> So is there a good way to add libicui18n.a into autolink entries from Swift?

I think that for static builds, we could inject an additional member which has the autolinked dependencies manually generated.

1. For ELF:  
we could use the `.swift_autolink_1` section (via a trivial bit of assembly)
2. For PE/COFF:  
we can inject a simple C file with `#pragma comment(lib, "icui18n.lib")`
3. For MachO:  
we do nothing; static linking is not supported on MachO

For shared libraries, this is not a problem.

This avoids the additional module map and header paths that need to be injected, and instead moves the complexity to the build system where an additional file needs to be added via `target_sources`.

> [@kateinoigakukun](#):
>
> What do you think about changing CoreFoundation and libuuid to Object Libraries in CMake? I think it doesn't depend on archiver script and make it easy to express in CMake.

I had originally tried to use object libraries, but there were some issues that I ran into (I unfortunately do not remember the details). One case that I am worried about though is static builds - if you convert them to static libraries, they will still not be merged and makes handling more difficult. Furthermore, I'm not sure what the behaviour is for cross-project linking (e.g. XCTest links against Foundation, which will use the object library CoreFoundation). Is there a reason that you are interested in the object library? Does `$<TARGET_OBJECTS:CoreFoundation>` not give you what you need? The libraries are already built as static, so we shouldn't have any concerns about statically linking the content (PE/COFF differentiates between static and shared libraries and the objects cannot be used outside of the library type intended).

---

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [February 9, 2021, 2:44am UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/7 "2021-02-09T02:44:38Z")

</div>

> [@compnerd](#):
>
> I think that for static builds, we could inject an additional member which has the autolinked dependencies manually generated.

Sorry, my sentence was misleading. I meant that I want to add `LINK_LIBRARY` entry in Foundation.swiftmodule for icui18n.

Even though we inject autolink\_entries section in object file of Foundation, the section won't be read by swift-autolink-extract, so it doesn't work well on ELF and other platforms using swift\_autolink mechanism, I think.

As far as I investigated, there is no way to add LINK\_LIBRARY entry to swiftmodule explicitly, so I'm planning to add an option to do that. What do you think about this approach?

e.g. `swiftc -emit-module -public-autolink-library icui18n`

> [@compnerd](#):
>
> Is there a reason that you are interested in the object library? Does `$<TARGET_OBJECTS:CoreFoundation>` not give you what you need?

Thanks! `$<TARGET_OBJECTS:CoreFoundation>` is exactly what I needed. It works very well!

---

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [February 12, 2021, 12:30pm UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/8 "2021-02-12T12:30:08Z")

</div>

> [@kateinoigakukun](#):
>
> As far as I investigated, there is no way to add LINK\_LIBRARY entry to swiftmodule explicitly, so I'm planning to add an option to do that. What do you think about this approach?
> 
> e.g. `swiftc -emit-module -public-autolink-library icui18n`

I sent a PR to add a new option `-public-autolink-library`.

> <https://github.com/apple/swift/pull/35936>
>
> Foundation imports CoreFoundation with \`@\_implementationOnly\`,
> so CoreFoundatio…n's modulemap won't be read, and the dependent libraries
> of CoreFoundation will not be automatically linked when using static
> linking.
> 
> For example, CoreFoundation depends on libicui18n and it's modulemap has
> \`link "icui18n"\` statement. If Foundation imports CoreFoundation with
> \`@\_implementationOnly\` as a private dependency, the toolchain doesn't have
> CoreFoundation's modulemap and Foundation's swiftmodule doesn't import
> CoreFoundation. So the swiftc can't know that libicui18n is required.
> 
> This new option will add LINK\_LIBRARY entry in swiftmodule to
> specify dependent libraries (in the example case, Foundation's
> swiftmodule should have LINK\_LIBRARY entry of libicui18n)
> 
> 
> See also: \[Autolinking behavior of @\_implementationOnly with static linking\](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393)
> 
> CC: @compnerd

---

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [April 27, 2021, 11:01am UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/9 "2021-04-27T11:01:46Z")

</div>

5.4 toolchain was shipped with this issue, so `import FoundationNetworking` with -static-stdlib is now broken on Linux 😢

> <https://github.com/apple/swift-corelibs-foundation/issues/3226>
>
> | | |
> |------------------|-----------------|…
> |Previous ID | SR-14536 |
> |Radar | rdar://problem/77224218 |
> |Original Reporter | @kateinoigakukun |
> |Type | Bug |
> |Status | Resolved |
> |Resolution | Done |
>         
> \<details\>
> \<summary\>Environment\</summary\>
> 
> Ubuntu 20.04.2 LTS  
> Swift version 5.4 (swift-5.4-RELEASE)  
> Target: x86\_64-unknown-linux-gnu
> 
> 
> \</details\>
> 
> \<details\>
> \<summary\>Additional Detail from JIRA\</summary\>
> 
> | | |
> |------------------|-----------------|
> |Votes | 1 |
> |Component/s | Compiler, Foundation |
> |Labels | Bug |
> |Assignee | @kateinoigakukun |
> |Priority | Medium |
> 
>    
> 
> md5: 7e7c7781d9c433972e4118e0fd2fd9dc
> 
> \</details\>
> 
> 
> 
> 
> 
> \*\*Issue Description:\*\*
> 
> 
> \`\`\` swift
> import FoundationNetworking
> \_ = URLSession.shared
> \`\`\`
> 
> This code couldn't be built with -static-stdlib due to linking failure on Linux.
> 
> This issue was introduced by the use of @\\\_implementationOnly in swift-corelibs-foundation. FoundationNetworking shipped with Swift 5.4 imports CFURLSessionInterface with @\\\_implementationOnly, then FoundationNetworking.swiftmodule doesn't have a dependency declaration of CFURLSessionInterface. So "import FoundationNetworking" doesn't tell the driver to link CFURLSessionInterface and CFURLSessionInterface dependent libraries.
> 
> Here is my forum post about this issue several month ago.  
> \[Autolinking behavior of @\\\_implementationOnly with static linking\](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/7)
> 
> Here is the command line log.
> 
> \`\`\` java
> $ swiftc -static-stdlib main.swift -v
> /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/bin/swift-frontend -frontend -c -primary-file main.swift -target x86\_64-unknown-linux-gnu -disable-objc-interop -module-name main -o /tmp/main-980558.o -use-static-resource-dir
> /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/bin/swift-autolink-extract /tmp/main-980558.o -o /tmp/main-9e4f94.autolink
> /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/bin/clang -fuse-ld=gold -pie /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/lib/swift/linux/x86\_64/swiftrt.o /tmp/main-980558.o -Xlinker --start-group @/tmp/main-9e4f94.autolink -Xlinker --end-group -L /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/lib/swift\_static/linux @/home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/lib/swift\_static/linux/static-stdlib-args.lnk --target=x86\_64-unknown-linux-gnu -v -o main
> clang version 10.0.0 (git@github.com:apple/llvm-project.git 159d0efd5633014e890836a4227fb867b491eb6b)
> Target: x86\_64-unknown-linux-gnu
> Thread model: posix
> InstalledDir: /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/bin
> Found candidate GCC installation: /usr/lib/gcc/x86\_64-linux-gnu/9
> Selected GCC installation: /usr/lib/gcc/x86\_64-linux-gnu/9
> Candidate multilib: .;@m64
> Selected multilib: .;@m64
> "/usr/bin/ld.gold" -pie -z relro --hash-style=gnu --eh-frame-hdr -m elf\_x86\_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main /usr/lib/gcc/x86\_64-linux-gnu/9/../../../x86\_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86\_64-linux-gnu/9/../../../x86\_64-linux-gnu/crti.o /usr/lib/gcc/x86\_64-linux-gnu/9/crtbeginS.o -L/home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/lib/swift\_static/linux -L/usr/lib/gcc/x86\_64-linux-gnu/9 -L/usr/lib/gcc/x86\_64-linux-gnu/9/../../../x86\_64-linux-gnu -L/usr/lib/gcc/x86\_64-linux-gnu/9/../../../../lib64 -L/lib/x86\_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86\_64-linux-gnu -L/usr/lib/../lib64 -L/usr/lib/x86\_64-linux-gnu/../../lib64 -L/usr/lib/gcc/x86\_64-linux-gnu/9/../../.. -L/home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/bin/../lib -L/lib -L/usr/lib /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/lib/swift/linux/x86\_64/swiftrt.o /tmp/main-980558.o --start-group -lFoundationNetworking -lswift\_Concurrency -lswiftCore -lFoundation -lswiftGlibc -lm -lpthread -lutil -ldl -lswiftDispatch -ldispatch -lBlocksRuntime -lDispatchStubs -lCoreFoundation -luuid -lswiftSwiftOnoneSupport --end-group -ldl -lpthread -lswiftCore -licui18nswift -licuucswift -licudataswift -lstdc++ -lm -export-dynamic --exclude-libs ALL -lgcc --as-needed -lgcc\_s --no-as-needed -lc -lgcc --as-needed -lgcc\_s --no-as-needed /usr/lib/gcc/x86\_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86\_64-linux-gnu/9/../../../x86\_64-linux-gnu/crtn.o
> /home/katei/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2021-04-24-a/usr/lib/swift\_static/linux/libFoundationNetworking.a(MultiHandle.swift.o):MultiHandle.swift.o:function $s20FoundationNetworking10URLSessionC12\_MultiHandleC03rawE0Svvpfi: error: undefined reference to 'CFURLSessionMultiHandleInit'
> ... // and many undefined reference errors for CoreFoundation symbols
> \`\`\`
> 
> For now, we can link correctly with extra "-lCFURLSessionInterface -lcurl" options.

---

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [April 27, 2021, 2:54pm UTC](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393/10 "2021-04-27T14:54:55Z")

</div>

I sent a patch to address this issue 💉

[https://github.com/apple/swift-corelibs-foundation/pull/2996](https://github.com/apple/swift-corelibs-foundation/pull/2996)
