I set Eclipse (Actually Xilinx SDK but based on Eclipse), and g++4.9.2, to compile a project which uses standalone ASIO and I used -std=c++11 in the Properties -> C/C++ Build -> Settings -> Tool Settings -> Other flags so it can compile using all C++11 features.
I also set ASIO_HAS_STD_THREAD, ASIO_STANDALONE
and so on in C/C++ General Symbols, and I expect that the ASIO header will use std::thread
instead of pthread
. However, I still see Error from make:
undefined reference to pthread_create,
..asio-1.10.6\include\asio\detail\impl\posix_thread.ipp
and posix_tss_ptr.hpp
so the problem is, since I am using C++11, and specified ASIO_HAS_STD_THREAD
but not ASIO_HAS_PTHREADS
, the posix_thread.ipp
should not be even included (through posix_thread.hpp), according to thread.hpp in ASIO:
#if !defined(ASIO_HAS_THREADS)
# include "asio/detail/null_thread.hpp"
#elif defined(ASIO_WINDOWS)
# if defined(UNDER_CE)
# include "asio/detail/wince_thread.hpp"
# else
# include "asio/detail/win_thread.hpp"
# endif
#elif defined(ASIO_HAS_PTHREADS)
# include "asio/detail/posix_thread.hpp"
#elif defined(ASIO_HAS_STD_THREAD)
# include "asio/detail/std_thread.hpp"
#else
# error Only Windows, POSIX and std::thread are supported!
#endif
Contrary to most people believe, C++11 doesn't need the -pthread
and I have tried to compile a simple project without -pthread
in Eclipse. However, you can correct me if I am wrong. When I put -pthread
in the linker option, it does compile, however I felt I don't want the pthread if not necessary.
When I search the posix_tss_ptr.hpp, I found also in Makefile.am. I wonder whether this affect the error?
So what is the cause of the problem? If not the above two suspect? I hope the solution can be still using pure C++11 way, not to use pthread if my reasoning is correct.
I found that ASIO_HAS_PTHREADS is defined not by me and that's why ASIO uses POSIX threads somewhere and the linker then needs the option -pthread. Then I traced down to the asio/detail/signal_blocker.hpp by using #error directive. There are only two places that it is defined and they are in ASIO config.hpp
# if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
# define ASIO_HAS_PTHREADS 1
# elif defined(_POSIX_THREADS)
# define ASIO_HAS_PTHREADS 1
ASIO still replies on POSIX THREADS or Windows for signal_blocker.hpp shown below. That's why ASIO still needs pthread.
#if !defined(ASIO_HAS_THREADS) || defined(ASIO_WINDOWS) \
|| defined(ASIO_WINDOWS_RUNTIME) \
|| defined(__CYGWIN__) || defined(__SYMBIAN32__)
typedef null_signal_blocker signal_blocker;
#elif defined(ASIO_HAS_PTHREADS)
typedef posix_signal_blocker signal_blocker;
#endif
And _PTHREADS is defined from the gnu cross compiler (arm-xilinx-linux-gnueabi) include files such as features.h, posix_opt.h, and etc. I am not going to track down which truly defined the macro, but ASIO is the source which uses _POSIX_THREADS and so the linker option -pthread should be there.
Again, non ASIO C++11 thread doesn't need -pthread for g++ 4.9.2 but standalone ASIO needs it. The following code is built correctly without -pthread in g++4.9.2 (Xilinx SDK which is based on Eclipse):
#include <thread>
void test() {
for(int i=0;i<100;i++);
}
int main()
{
std::thread thread1(test);
thread1.join();
return 0;
}
The fact that a program is written in C++11 has no bearing on with whether or
not it needs to be linked with the pthread
library. It needs to link that
library if it requires Posix threads.
C++11 provides the std::thread
class and each conforming compiler's standard
library must implement the functionality of that class using some native
threads API hosted by the target system. GCC implements it using pthreads
,
so you cannot any build a program that creates std::thread
objects with
GCC unless you link it with -pthread
. This fact is unconnected with asio
.
LATER
I actually built a program without pthread using std::std just using -std=c++11
I think you are mistaken and confused by the fact that some Windows ports of GCC
link libpthread
by default. E.g. if your example program is in thread.cpp
I
can successfully build it in Windows with TDM-GCC 4.9.2 so:
>g++ -std=c++11 -o test_thread thread.cpp
But if you build it in verbose mode:
>g++ -v -std=c++11 -o test_thread thread.cpp
you can see that a great many library options are passed to the linker
behind the scenes, in particular -lpthread
:
>g++ -v -std=c++11 -o test_thread thread.cpp 2>&1 | grep -Po 'pass-through=-lpthread' -
pass-through=-lpthread
And on Linux you will not link libpthread
unless you ask:
$ g++ -std=c++11 -o test_thread thread.cpp
/tmp/ccpyEles.o: In function `std::thread::thread<void (&)()>(void (&)())':
thread.cpp:(.text._ZNSt6threadC2IRFvvEJEEEOT_DpOT0_[_ZNSt6threadC5IRFvvEJEEEOT_DpOT0_]+0x7d): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status