-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
doc/Threads: avoid dependency('threads')
with MinGW + Win32 threading
#13124
base: master
Are you sure you want to change the base?
Conversation
On MinGW, dependency('threads') assumes the caller wants POSIX thread primitives instead of Win32 primitives. This makes sense because the latter doesn't require any additional action, while the former needs a winpthreads dependency. However, some libraries use Win32 threading on Windows but add dependency('threads') anyway, which is undesirable in a build that wants to avoid shipping winpthreads. Recommend skipping dependency('threads') on Windows if POSIX threading is not needed.
This is a somewhat obscure footgun. MinGW GCC can be compiled with either a It seems worth writing down though. I've ended up PRing three different dependencies to fix this issue for my use case, and it'd be nice to have some canonical upstream docs. |
I would much rather just fix 'threads' do the the right thing, including being able to say that you want win32 threads instead of pthreads. I had a patch at one point to be able to query whether the threads you got was pthreads compatible or win32 threads compatible, but it got bikeshedded to death |
But is it even knowable? If you can have both win threads and posix ones in the compiler toolchain then you need to be able to say something like |
yeah, or The only places i can think of where you can run into issues is with I suspect @lazka either has a better idea of what kind of pain we'd be taking on by trying to fix this, or know someone who does. |
To back up a bit, a program will acquire a winpthreads dependency for one/both of two reasons, which are otherwise orthogonal:
For case 1, Meson could provide a way to detect the thread model (but can't know whether the program actually uses thread intrinsics), but that seems out of scope: while the person invoking Meson might want to avoid the winpthreads dep, the program itself is unlikely to care in any way. For case 2, the program knows which threading API it wants, and should specify it. Querying afterward doesn't make sense: "Meson, please pick an arbitrary thread API, and then I'll decide whether I like it" isn't the usual UX. Rather than adding special syntax as @dcbaker proposes, maybe we should define two new |
I'd like to avoid having to do things like: if host_machine.system() in ['linux', 'freebsd', 'openbsd', 'netbsd', ...]
threads = dependency('threads-posix')
else
threads = dependency('threads-win32')
endif In c++ especially it's common to not care, you're going to use I know of at least one other case where the project provides it's own level of abstraction, and does it through #define tricks that have to be special cased in weird ways for mingw |
I was thinking more like thread_dep = dependency('threads-win32', required: false)
if not thread_dep.found()
thread_dep = dependency('threads-posix')
endif and of course, only for programs that support both thread APIs.
Ah, good point. I don't think it's possible to implement that generically though, without knowing something about the underlying implementation. For example, if the MinGW
Yup. The projects that support both Win32 and pthreads are the ones I'm especially trying to improve here. |
And I want to do this without degrading the current situation where |
That's kinda the situation now, though. I copypasted For projects sophisticated enough to support multiple threading APIs, I think four legible lines of dependency checks are not unreasonable. The other projects will use whatever threading API they use, and those would just have If there's strong opposition to deprecating
As I laid out above, this isn't actually possible without knowing what threading API the application intends to use. |
Can you elaborate on this? Thread local variables aren't really implemented with either of them, as far as I know; with GCC they're implemented with "emulated TLS". I tested the output of extern __thread int var;
int get(void) {
return var;
} And it's identical between As far as I know, the choice between the thread models does not affect code generation in any way, it just changes which backend implementation is used in libgcc and libstdc++.
There's a recent change on this front, though - since GCC 13,
As noted, I don't think Also - for mingw toolchains with Clang, there's no similar big global switch for "thread model". |
Ah, yeah, good catch. So under
Nice, that's really good news! The additional info about thread models is helpful, thanks. For clarity, I had mentioned the
If the application was developed for Linux, |
Our conclusion (with @mstorsjo) is probably that |
To be clear, |
Yes, it's only a suggestion. I think it should not be confused with
Notably, |
I'm not opposed to having a way to specify that you want additional support beyond the basics of C++ Threads or C11 threads, like full pthreads. My preference would be to extend the I'm not sure how to proceed with actual implementation changes those. |
I was lead here while trying to figure out which threading API(s) But on the risk of derailing this documentation PR further into off-topic territory: The discussion about ideal Having just one dep to enable whatever threading API without knowing which doesn't make much sense to me as implementation code will differ depending on the chosen API. EIther the returned dep object needs to indicate what API was selected, or for consistency with older version, keep only looking for pthread if no flavour arg was passed. has_threads = false
foreach thread_flavour : ['iso', 'win32', 'pthread', 'solaris']
tdep = dependency('thread', flavour: thread_flavour, required: false)
if tdep.found()
deps += tdep
has_threads = true
conf.set('CONFIG_THREADS', 1)
conf.set('CONFIG_THREADS_@1@'.format(thread_flavour.to_upper()), 1)
break
endif
endforeach |
msys2's clang64 environment errors out due to undefined symbols with pthread. The non-clang environments are fine as gcc implicitly links pthread. mesonbuild/meson#13124 (comment) Signed-off-by: Christopher Degawa <ccom@randomderp.com>
msys2's clang64 environment errors out due to undefined symbols with pthread. The non-clang environments are fine as gcc implicitly links pthread. mesonbuild/meson#13124 (comment) Signed-off-by: Christopher Degawa <ccom@randomderp.com>
On MinGW,
dependency('threads')
assumes the caller wants POSIX thread primitives instead of Win32 primitives. This makes sense because the latter doesn't require any additional action, while the former needs a winpthreads dependency. However, some libraries use Win32 threading on Windows but adddependency('threads')
anyway, which is undesirable in a build that wants to avoid shipping winpthreads. Recommend skippingdependency('threads')
on Windows if POSIX threading is not needed.