月別アーカイブ: 2019年2月

mingw クロスコンパイル時に windres エラーが出るときの解決法

OpenCV のクロスコンパイルをしているときに、windres が見つからないというエラーが出た。普通、クロスコンパイルする際に、GCC や G++ (GXX) の設定はするが、リソースコンパイラというものも設定しなければいけなかったようで、そこにはまってしまった。結構エラーで困っている人は多いようなので、書いてみる。

CMAKE の設定として書いているが、他の環境でも役立つはずである。

どうやら

  1. -DCMAKE_SYSTEM_NAME=Windows
  2. -DENABLE_PRECOMPILED_HEADERS:BOOL=OFF
  3. -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc-7.3-posix -DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++-posix -DCMAKE_RC_COMPILER=i686-w64-mingw32-windres

の3つくらいをやっておけばよいようだ。最後のうち、RC_COMPILER の設定は、よく考えればアタリマエではあるはずなのだが、なかなか気づけなかった。VC++ とか使ったことがないし…。
2つ目は、エラーが出なければ入れなくても良いと思う。

私が実際に投げたコマンドは以下である

cmake -DENABLE_PRECOMPILED_HEADERS:BOOL=OFF -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++-posix -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc-7.3-posix -DCMAKE_RC_COMPILER=i686-w64-mingw32-windres -D CMAKE_BUILD_TYPE:STRING=RELEASE -D BUILD_SHARED_LIBS:BOOL=ON -D CMAKE_CXX_FLAGS:STRING="-pipe -O2 -std=gnu++14 -Wa,-mbig-obj" -D CPU_DISPATCH:STRING="SSE4_1;SSE4_2;" -D WITH_ITT:BOOL=OFF -D WITH_IPP:BOOL=OFF -D WITH_OPENMP:BOOL=ON -D WITH_OPENGL:BOOL=ON -D ENABLE_FAST_MATH:BOOL=ON -D BUILD_PERF_TESTS:BOOL=OFF -D BUILD_TESTS:BOOL=OFF -D BUILD_EXAMPLES:BOOL=OFF -D CMAKE_INSTALL_PREFIX:PATH=/home/tako/progs/opencv-3.4.5_install_mingw32/ -D OPENCV_EXTRA_MODULES_PATH:PATH=/home/tako/progs/opencv_contrib-3.4.5/modules/ -DOPENCV_ENABLE_NONFREE:BOOL=ON -DENABLE_PRECOMPILED_HEADERS:BOOL=OFF -G Ninja ../opencv-3.4.5/
ninja -v -j3 install

ninja は早かった。ninja が不要な人は -G Ninja を外せばよい。

cygwinでcmakeを利用したwindowsアプリケーションのビルド に

# クロスコンパイルのターゲットのシステム名
SET(CMAKE_SYSTEM_NAME Windows)

# クロスコンパイラ等の設定
SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)

#Cフラグの設定
#ビルドタイプに共通の設定
set(CMAKE_C_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
#Debugビルドに利用する設定
set(CMAKE_C_FLAGS_DEBUG "-g3 -gdwarf-2")
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -gdwarf-2")

# ビルド環境(cygwin)での、ターゲット用の環境の場所
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)

# cmakeのFIND_XXX() コマンドのデフォルト設定
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

ときちんと書いてあったので、これを見て助けられた。数時間意味が分からず彷徨ってしまった。感謝したい。

Instruction

Give cmake options:

  1. -DCMAKE_SYSTEM_NAME=Windows
  2. -DENABLE_PRECOMPILED_HEADERS:BOOL=OFF
  3. -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc-7.3-posix -DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++-posix -DCMAKE_RC_COMPILER=i686-w64-mingw32-windres

Don’t forget to set CMAKE_RC_COMPILER when you encounter windres errors. 2. may be deletable.

DNS の設定がうまくいかず、戻るような現象について考察する

私も間違っているかもしれませんので、変なところがあれば指摘して頂きたい。

権威サーバへの問い合わせ

まず、DNS には権威サーバと呼ばれるサーバと、キャッシュサーバと呼ばれるサーバがある。
ドメインの管理画面から設定をして、設定が書き出されるのは、権威サーバである。

例えば、www.example.com の権威サーバを調べに行きたければ、ルートサーバから辿る。

dig +norec NS www.example.com @a.root-servers.net.

とする。

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43407
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.example.com. IN NS

;; AUTHORITY SECTION:
com. 172800 IN NS e.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
...
;; ADDITIONAL SECTION:
e.gtld-servers.net. 172800 IN A 192.12.94.30
e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
b.gtld-servers.net. 172800 IN A 192.33.14.30
b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
...

のような応答があるはずだ。大事なのは、AUTHORITY SECTION だ。ここが、次に見に行く先のサーバを示している。サーバの IP アドレスは、ADDITIONAL SECTION に示されている。

dig +norec NS www.example.com @a.gtld-servers.net.

とすると

example.com. 172800 IN NS a.iana-servers.net.

と応答がある。

dig +norec NS www.example.com @a.iana-servers.net.

とすると

;; AUTHORITY SECTION:
example.com. 3600 IN SOA sns.dns.icann.org. noc.dns.icann.org. 2018112845 7200 3600 1209600 3600

なので、SOA レコードが返ってきた。これで、a.iana-servers.net. が責任をもったサーバであるということが分かる。以降は a.iana-servers.net. に問い合わせる。

dig +norec A www.example.com @a.iana-servers.net.

に対して

;; ANSWER SECTION:
www.example.com . 86400 IN A 93.184.216.34

より、www.example.com. の IP アドレスを得ることができた。

いちいち探すのはやってられない…キャッシュサーバ

いちいち、まず権威サーバを探し、次に、本来の問い合わせをする…のは面倒でやってられないので、この流れを代わりにしてくれるのがキャッシュサーバと思ってよい。

今まで出てきた 86400 というのは TTL と呼ばれ、「この秒数まではキャッシュしてよいよ」という数字である。この時間、キャッシュサーバは、同一の問い合わせに、覚えていた(キャッシュした)値を返してよい。逆に、今すぐに設定を書き換えても、86400秒は新しい設定を見てもらえない可能性があるということだ。

キャッシュサーバへの問い合わせ

+norec を外して

dig A www.example.com @8.8.8.8

8.8.8.8 を好きではない方には申し訳ないが…等としてみる。8.8.8.8 は公開キャッシュサーバである。

;; ANSWER SECTION:
www.example.com. 4676 IN A 93.184.216.34

と答えが返ってくる。TTL の値が違うのが分かるだろう。

キャッシュするのは誰?

では、一般的なクライアントがアクセスする際に、キャッシュをしてしまうのは誰かというと、
・使っている PC
・PC の問い合わせ先キャッシュサーバ
であると考えられる。使っている PC の、キャッシュ時間がいくらぐらいなのかは、少し調べたがわからなかった。(TTL 以下でキャッシュをクリアしても問題がないのである)

問い合わせ先は、DHCP で設定されることもある。結局 ISP のサーバとなることが多いだろう。

設定が戻ったりするのはなぜなのさ

基本的に、問い合わせ先のキャッシュ DNS サーバ…つまり優先 DNS サーバは1台なので、戻ることはなさそうな気がする。

ここからが面倒なのだが、「同一 IP で実は複数のマシンが世界のあちこちに存在する」ということが許されており、そのような場合は、複数のマシンで別のキャッシュ応答をする可能性がありそうだ。

dig の問い合わせ先を、そのキャッシュサーバの IP に設定して、問い合わせを繰り返して確認するのが、「今何が起きているか」を把握するための、1番の近道だと思われる。

権威サーバ側についても同じ問題(IP anycast や 負荷分散)は生じえるが、こちらは遅れがあまりないうちに同期されるように、ドメイン管理業者がマネジメントしているはずである。

なぜ「DNSの浸透」は問題視されるのか は良い記事なので、ぜひ目を通していただきたい。