On Sun, 25 Jan 2026 12:04:39 +0000 kikairoya via Cygwin <[email protected]> wrote: > > Hello Takashi, > > > To be clear, I'm not asking you to fix the TLS functionality of compiler-rt; > I'm > just asking you to not package a DLL built with -rtlib=compiler-rt (and also > -stdlib=libc++). > > Such a library implicitly enforces the use of specific compiler options, > making > it incompatible with other libraries, even if compiler-rt is provided as a > shared library.
Ok. Are you talking about a specific package, or is this meant as a general statement? > 2026年1月24日 18:29:52 (+09:00) で、Takashi Yano via Cygwin さんが書きました: > > > > > > > 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. > > > > That doesn't explain the benefit of using compiler-rt instead of libgcc. > The availability itself of the option to select a runtime (i.e., the existence > of the compiler-rt package -- thanks for your effort!) is indeed a benefit for > programmers, but not for other packages or users, including programmers who > want > to use the other package as a library. Ah, I got it. Providing alternative itself is a some kind of benefit. And also the program built with compiler-rt (and libunwind) will be free from external DLLs except in the case where the emutls is used (as far as using 21.1.4-3 that returns to static linking in most cases). > Regarding building a package with -rtlib=compiler-rt, either verification that > the problem does not affect programmers in practice or a clear justification > is > needed, since there is at least one downside. > To verify that a package built with -rtlib=compiler-rt doesn't cause a problem > with the TLS, it would be enough to check that if no module (not only DLLs; > EXEs > also can export symbols) in the package exports a symbol beginning with > __emutls_. However, I believe this kind of check should be automated for *all* > packages by default, regardless of who maintains it or whether the package > uses > compiler-rt; otherwise, the check will easily be overlooked. Of course, the > checker must always pass for a module which is linked to libgcc_s. Do you assume the check would be implemented in cygport? > > > 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 > > As you confirmed below, importing a TLS variable from a DLL that built with > -rtlib=compiler-rt requires end-programmers to also use the same flag for it > to > work correctly. Therefore, a DLL built with comipler-rt can't work with > another > DLL that exports a TLS variable. I agree. > > > - 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. > > > > Yes, I explained that building compiler-rt as a shared library doesn't solve > the > problem. If you meant "the problem" is the incomatibility between compiler-rt and libgcc_s, you are right. However, at least, it solves the problem that the program using emutls across the executable and DLL does not work as expected, which occured even using only compiler-rt. > > > 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. > > > > I don't understand how the split runtime solves the problem. Ditto. Depends on what "the problem" means. > > > 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. > > > > It seems you're saying "No" to something what I didn't claim. > I'm worried that you might build the next version of the llvm package (or > other > library packages you maintain) with -stdlib=libc++ and > -rtlib=compiler-rt. That's all I'm asking with "Please don't do that." > Consider to the case of someone is developing an LLVM plugin helped with > Boost. Both of the LLVM headers and the Boost headers include standard C++ > libraries. If the llvm package were built with libc++, how would they specify > the -stdlib flag to compile a .cpp file that includes both of LLVM and Boost > headers? I’ve eventually come to understand your concern. I have no plant to build llvm package with libc++/compiler-rt/linunwind. But, I'm planning to provide clangd https://cygwin.com/pipermail/cygwin-apps/2026-January/044769.html which using libc++ as follows, $ ldd /usr/bin/clangd ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7fff41180000) KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7fff40ab0000) KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7fff3e650000) cygc++-1.dll => /usr/bin/cygc++-1.dll (0x46a270000) cygwin1.dll => /usr/bin/cygwin1.dll (0x7fff202e0000) cygz.dll => /usr/bin/cygz.dll (0x394930000) cygzstd-1.dll => /usr/bin/cygzstd-1.dll (0x394760000) cygunwind-1.dll => /usr/bin/cygunwind-1.dll (0x5cafa0000) because libstdc++ with libgcc_s has a problem: https://cygwin.com/pipermail/cygwin/2025-November/258943.html This package does not provide libraries neither static nor DLL. Do you think this also has a risk you concern? Thanks for the test cases below. The problem in all cases is that the instance created by libstdc++/libc++ is manipulated with libc++/libstdc++. Is this supposed to happen when using boost, for example? > There are examples of how fail with "A DLL that exports C++ interfaces" below. > > A case that fails to link: > $ cat vec.cc > > #include <vector> > void f(std::vector<int> *x); > #ifdef DLL > void f(std::vector<int> *x) {}; > #endif > #ifdef EXE > int main() { f(nullptr); } > #endif .... > A case that causes a runtime error or broken silently: > > #include <string> > std::string g(); > #ifdef DLL > std::string g() { return "abc"; } > #endif > #ifdef EXE > #include <stdio.h> > int main() { printf("%zu\n", g().length()); } > #endif .... > $ cat exc.cc > void e(); > #ifdef DLL > void e() { throw 3; } > #endif > #ifdef EXE > #include <stdio.h> > int main() { > try { > puts("try"); > e(); > } catch (int a) { > printf("catch %d\n", a); > } catch (...) { > puts("catch other"); > } > puts("finish"); > } > #endif .... > A case that looks slightly more practical: > $ cat deq.cc > > #include <deque> > class some_state { > std::deque<int> state; > public: > void modify_state(int x); > bool verify_state() const; > }; > #ifdef DLL > void some_state::modify_state(int x) { state.push_back(x); } > bool some_state::verify_state() const { > int x = 0; > for (auto i: state) x += i; > return x > 0; > } > #endif > #ifdef EXE > #include <stdio.h> > int main() { > some_state s; > s.modify_state(3); > printf("%d\n", s.verify_state()); > } > #endif -- 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

