I have found some details about using pthreads4w but could not find a complete example. What steps must be made in detail to install PThreads4W?
CodePudding user response:
Here is how I put things together. The goal is to have pthread available as system library on Microsoft Windows so I can just #include <pthread.h>
to my source code to use its functions.
The main issue is that the compiler/linker can find all parts of the library which are the header file pthread.h
, the linkable library pthread.lib
and its executable part pthread.dll
. It will look at predefined directories. For the header file it will look at the environment variable INCLUDE
or will use settings in environment variable CL
. INCLUDE
is only used by the buildsystem nmake. Builds with Visual Studio does ignore it. Settings in CL
is used by the compiler so it works on both buildsystems and we will use that. For pthread.lib
the compiler looks at the environment variable LIB
and the executable program searches for the needed pthread.dll
using the Path
environment variable.
I use the PowerShell. First we have to download and install pthreads4w from GitHub. It uses cmake
and can only be compiled with nmake
so we have to use the Generator 'NMake Makefiles'.
PS> git clone https://github.com/jwinarske/pthreads4w.git
PS> cd pthreads4w
PS> cmake -S . -B build -G 'NMake Makefiles' -D BUILD_TESTING=OFF -D CMAKE_BUILD_TYPE=Debug
PS> cmake --build build --config Debug --target install
--- snip ---
Install the project...
-- Install configuration: "Debug"
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/bin/pthreadVCE3d.dll
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/lib/pthreadVCE3d.lib
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/bin/pthreadVSE3d.dll
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/lib/pthreadVSE3d.lib
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/bin/pthreadVC3d.dll
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/lib/pthreadVC3d.lib
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/lib/libpthreadVCE3d.lib
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/lib/libpthreadVSE3d.lib
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/lib/libpthreadVC3d.lib
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/include/_ptw32.h
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/include/pthread.h
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/include/sched.h
-- Installing: C:/Users/ingo/devel/pthreads4w/PTHREADS-BUILT/x86_64/Debug/include/semaphore.h
That's where you find all headers, libs and dlls. Or something clearer:
.\PTHREADS-BUILT\
└── x86_64
└── Debug
├── bin
│ ├── pthreadVC3d.dll
│ ├── pthreadVCE3d.dll
│ └── pthreadVSE3d.dll
├── include
│ ├── _ptw32.h
│ ├── pthread.h
│ ├── sched.h
│ └── semaphore.h
└── lib
├── libpthreadVC3d.lib
├── libpthreadVCE3d.lib
├── libpthreadVSE3d.lib
├── pthreadVC3d.lib
├── pthreadVCE3d.lib
└── pthreadVSE3d.lib
There are some more libraries using exeptions but we only use the default and recommended shared version pthreadVC3d. For details about this naming look at the README of the project.
Now we provide the generic library name pthread.lib
with a symlink and set the environment variables.
PS> cd PTHREADS-BUILT\x86_64\Debug\lib\
PS> new-item -itemtype symboliclink -path . -name pthread.lib -value pthreadVC3d.lib
PS> $env:CL = "/I C:\Users\ingo\devel\pthreads4w\PTHREADS-BUILT\x86_64\Debug\include"
PS> $env:LIB = ";C:\Users\ingo\devel\pthreads4w\PTHREADS-BUILT\x86_64\Debug\lib"
PS> $env:Path = ";C:\Users\ingo\devel\pthreads4w\PTHREADS-BUILT\x86_64\Debug\bin"
Don't forget the plus sign and the starting semi colon. For testing it I use this simple program:
PS> type .\simple_pthread.cpp
#include <pthread.h>
#include <iostream>
namespace // no name, i.e. anonymous for file scope
// this is the C way for decorator STATIC
{
void* start_routine(void*) {
std::cout << "-- Hello from POSIX Thread" << std::endl;
return 0; // calls pthread_exit()
}
} // namespace
int main() {
pthread_t thread;
int rc;
void* retval;
std::cout << "-- starting POSIX Thread" << std::endl;
rc = pthread_create(&thread, NULL, &start_routine, NULL);
if (rc != 0) {
std::cerr << "Error! unable to create thread, rc=" << rc << std::endl;
exit(1);
}
rc = pthread_join(thread, &retval);
if (rc != 0) {
std::cerr << "Error! Unable to join thread with rc=" << rc << std::endl;
exit(1);
}
if (retval != NULL) {
std::cerr << "Error! Thread failed with retval=" << retval << std::endl;
exit(1);
}
return 0;
}
Now use it (where ever you have it stored):
PS> cl /EHsc .\simple_pthread.cpp pthread.lib
PS> .\simple_pthread.exe
-- starting POSIX Thread
-- Hello from POSIX Thread