Hi Tomohiro,

On Fri, 23 Jan 2026 12:28:51 +0000
kikairoya via Cygwin <[email protected]> wrote:
> 
> 2026年1月22日 17:20:03 (+09:00) で、Takashi Yano via Cygwin さんが書きました:
> 
> > >
> > > If you are planning to provide a package built with compiler-rt, 
> > > especially
> > > one that contains a DLL, I would say, "Please don't do that." It's very
> > > different if someone decides to build their own application with 
> > > compiler-rt
> > > and takes responsibility for doing so. Before providing such a package, 
> > > the
> > > implementation of native TLS in cygwin1.dll is needed, as well as an 
> > > update
> > > to the toolchains to use it (and, I guess, it is impossible to switch with
> > > keeping ABI). That changes the fundamental design of the distribution.
> > 
> > I attempted to build the entire compiler-rt (builtins) as a shared library,
> > similar to the suggestions in:
> > https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/emutls.c#L388-L389
> > , and could successfully solve the problem.
> > Could you please try 21.1.4-2 (Test)?
> > 
> 
> 
> I’m concerned this makes the situation worse than providing a static library. 
> I guess
> that the upstream has never built it as a shared library. Consequently, that 
> configuration
> appears to be largely untested.
> And then, what is the benefit of "specifying -rtlib=compiler-rt makes us 
> cyggcc_s.dll free but
> requires a dependency on cygclang_rt.builtins-21-x86_64.dll" ? Is there 
> another benefit?

I don't think I could get your point. The benefit of this test version is
solving the broken thread local variable reference between dlls and executable,
of course.

> Furthermore, if you really intend to provide a DLL linked with compiler-rt, 
> the
> DLL comes with limitations that are hard to notice.
> (If this is not what you are planning, please feel free to ignore this.)
> - Linking the DLL without -rtlib=compiler-rt breaks the EmuTLS functionality 
> silently. There is
>   no way to know that the linking needs compiler-rt except inspecting the DLL 
> with ldd or objdump.

Why? If -rtlib=compiler-rt is not specified, the program uses libgcc_s
which is a shared library. Therefore, emutls works as expected except
for a bug in libstdc++:
https://cygwin.com/pipermail/cygwin/2025-November/258943.html

> - GCC doesn't support -rtlib=compiler-rt. That effectively enforces the use 
> of clang.
> - A single module (EXE or DLL) can link against only one of the TLS 
> implementations, either the
>   one from libgcc_s or the one from compiler-rt. A TLS variable that relies 
> on the other
>   implementation would be broken (again, silently).

These are not related to the aproach whether compiler-rt provides shared
library or not, I think. Even if compiler-rt provides static library,
above two problems still exist.

> Of course that might not matter if EmuTLS is never used, however, I worry 
> about the
> assumptions that are not enforced or validators automatically would be broken 
> silently.
> 
> Therefore, my conclusion remains unchanged -- "Please don't do that."

I have uploaded compiler-rt 21.1.4-3 (Test), where the shared library
is used only for __emutls_get_address(), and programs that do not use
emutls will be linked with compiler-rt statically.

> Just to note, we're now focusing on compiler-rt because my original attention 
> is about
> EmuTLS, but the same discussion is applicable to libc++. A DLL that exports 
> C++ interfaces
> and linked to libc++ (if such a DLL were to be provided, would it be 
> cygLLVM-X.dll?) can't be
> linked together with another libstdc++-ed C++ library (e.g., boost).

No. cygLLVM-x.dll is a part of llvm package. The shared library in libc++
package is cygc++-1.dll. Anyway, I don't understand what is the problem
in that case.

$ clang++ -stdlib=libc++ -unwindlib=libunwind -rtlib=compiler-rt emutlstest.cc 
-o emudll.dll -DDLL=1 -shared && clang++ -stdlib=libstdc++ -unwindlib=libunwind 
-rtlib=compiler-rt emutlstest.cc -o emuexe.exe -DEXE=1 emudll.dll && 
./emuexe.exe
1 0xa00000538 0xa00000538
1 0xa000268a8 0xa000268a8
$ clang++ -stdlib=libstdc++ -unwindlib=libunwind -rtlib=compiler-rt 
emutlstest.cc -o emudll.dll -DDLL=1 -shared && clang++ -stdlib=libc++ 
-unwindlib=libunwind -rtlib=compiler-rt emutlstest.cc -o emuexe.exe -DEXE=1 
emudll.dll && ./emuexe.exe
1 0xa00000538 0xa00000538
1 0xa000109c8 0xa000109c8
$ clang++ -stdlib=libc++ -unwindlib=libgcc -rtlib=libgcc emutlstest.cc -o 
emudll.dll -DDLL=1 -shared && clang++ -stdlib=libstdc++ -unwindlib=libgcc 
-rtlib=libgcc emutlstest.cc -o emuexe.exe -DEXE=1 emudll.dll && ./emuexe.exe
1 0xa00000538 0xa00000538
1 0xa000269c8 0xa000269c8
$ clang++ -stdlib=libstdc++ -unwindlib=libgcc -rtlib=libgcc emutlstest.cc -o 
emudll.dll -DDLL=1 -shared && clang++ -stdlib=libc++ -unwindlib=libgcc 
-rtlib=libgcc emutlstest.cc -o emuexe.exe -DEXE=1 emudll.dll && ./emuexe.exe
1 0xa00000538 0xa00000538
1 0xa00010ae8 0xa00010ae8

Of course, the cases bellow do not work because executable and DLL
call different __emutls_get_address().

$ clang++ -stdlib=libc++ -unwindlib=libunwind -rtlib=compiler-rt emutlstest.cc 
-o emudll.dll -DDLL=1 -shared && clang++ -stdlib=libc++ -unwindlib=libgcc 
-rtlib=libgcc emutlstest.cc -o emuexe.exe -DEXE=1 emudll.dll && ./emuexe.exe
0 0xa00000538 0xa00000558
0 0xa00010ba8 0xa00010c58
$ clang++ -stdlib=libc++ -unwindlib=libgcc -rtlib=libgcc emutlstest.cc -o 
emudll.dll -DDLL=1 -shared && clang++ -stdlib=libc++ -unwindlib=libunwind 
-rtlib=compiler-rt emutlstest.cc -o emuexe.exe -DEXE=1 emudll.dll && 
./emuexe.exe
0 0xa00000538 0xa00000558
0 0xa00010b18 0xa00010c58


Furthermore, the following test case also works.

$ cat hello.cc
#include <iostream>
#ifdef DLL
void func()
{
        std::cout << "Hello(dll)" << std::endl;
}
#endif
#ifdef EXE
extern void func();
int main()
{
        std::cout << "Hello(main)" << std::endl;
        func();
        return 0;
}
#endif
$ clang++ -stdlib=libc++ -rtlib=compiler-rt -unwindlib=libunwind -DDLL hello.cc 
-shared -o hello.dll && clang++ -stdlib=libstdc++ -rtlib=libgcc 
-unwindlib=libgcc -DEXE hello.cc hello.dll -o hello.exe && ./hello.exe
Hello(main)
Hello(dll)
$ clang++ -stdlib=libstdc++ -rtlib=libgcc -unwindlib=libgcc -DDLL hello.cc 
-shared -o hello.dll && clang++ -stdlib=libc++ -rtlib=compiler-rt 
-unwindlib=libunwind -DEXE hello.cc hello.dll -o hello.exe && ./hello.exe
Hello(main)
Hello(dll)

-- 
Takashi Yano <[email protected]>

-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to