【C言語】MinGWでマルチスレッドプログラムのコンパイルができなかった話


戦車の話が一切出てこない暇人戦車長です。

今回はWindows環境でのC言語プログラム作成でこけた話です。

Windows10環境にMinGWを導入してまともなソースコードが書けている状態からスタートです。

この解決法で問題が起きても僕は一切責任を負いませんので自己責任でお願いします。

 

 

コンパイル通らん

「-lpthread」をつけてgccしたのにエラーが・・・

 f:id:bakuhatuma:20200616201553p:plain

Makefileでは

$gcc -o ファイル名 ソースファイル名 -lpthread

的なことしてます。

エラーコードは

"fatal error: pthread.h: No such file or directory
#include <pthread.h>
^
compilation terminated.
make: *** [XX.o] Error 1"

つまり「ライブラリpthread.hが見つからん」ってことですね。

 

ヘッダファイル等の手動導入

ないなら手動で入れるしかないじゃないということでgithub

sourceforge.net

にアクセスして、

libpthread-2.8.0-3-mingw32-dll-2.tar.lzma

pthreads-w32-2.8.0-3-mingw32-dev.tar.lzma

をDL。

MinGWとかコマンドプロンプトとかで

$lzma -d ファイル名

を実行して二つともを解凍一回目。

 できた二つのファイル↓を

f:id:bakuhatuma:20200616202554p:plain

WinRARとかで解凍2回目。

するとこの二つのフォルダ―ができる

f:id:bakuhatuma:20200616202727p:plain

この中身の「bin」「lib」「include」をフォルダごとMinGW直下↓にコピーすればOK。

f:id:bakuhatuma:20200616202934p:plain

それでもエラーは吐かれ続ける

「ヘッダファイル突っ込んだしコンパイル通るやろ」と思ってコンパイルしたら

 

f:id:bakuhatuma:20200616203511p:plain

 

$ make all gcc -c XX.c
In file included from c:\mingw\include\pthread.h:288:0,
from XX.c:5:
c:\mingw\include\sched.h:152:47: error: unknown type name 'pid_t'
PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
^~~~~
c:\mingw\include\sched.h:154:47: error: unknown type name 'pid_t'
PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
^~~~~
In file included from XX.c:5:0:
c:\mingw\include\pthread.h:307:8: error: redefinition of 'struct timespec'
struct timespec {
^~~~~~~~
In file included from c:\mingw\include\pthread.h:218:0,
from XX.c:5:
c:\mingw\include\time.h:115:8: note: originally defined here
struct timespec
^~~~~~~~
make: *** [XX.o] Error 1

 

エラーだよコンチクショウ!!!

エラーコードを見ると

① sched.hでのerror: unknown type name 'pid_t'

② pthread.h&time.hでのerror: redefinition of 'struct timespec'・originally defined here(競合)

の二つかなぁと見れる

 

インクルードガードやらを追記

①の方はtype nameを宣言?してやれば解決しそうってことで覗くと

sched.h

f:id:bakuhatuma:20200616204151p:plain

おろ?

宣言されてるやん。

if文で弾かれたかな???って当たりを付けて

sched.h

f:id:bakuhatuma:20200616204340p:plain

#endifの後(126行目)に

typedef int pid_t;

を追記。

良くはないだろうけどまぁ行けるっしょって感じで。

 

②は・・・

競合かなぁ

"struct timespec"っていう関数が重複して宣言されてるって感じ。

インクルードガードは???

まさか・・・

pthread.h

f:id:bakuhatuma:20200616204814p:plain

oh.....

time.hが先に読まれた場合の記述がない

time.hの方には

f:id:bakuhatuma:20200616205438p:plain

#if defined __need_struct_timespec && ! __struct_timespec_defined

がありますね。

なので、pthread.h→time.hの順に読まれてたらセーフだったのかも。

pthread.hにインクルードガードを追記しましょう

f:id:bakuhatuma:20200616205748p:plain

timespec関数を定義する部分を挟むように

#ifndef _TIME_H

#endif

を追記。

コンパイル通してみると

f:id:bakuhatuma:20200616211405p:plain

無事通りました。

これが正しいやり方なのかわかりませんが無事に通ってよかったです。

ホントめんどくさかった・・・。