読者です 読者をやめる 読者になる 読者になる

いけむランド

はてダからやってきました

string table overflow が起きたため CMAKE_C_FLAGS から -g を取り除いた話

この記事は 第2のドワンゴ Advent Calendar 2016 - Qiita の 7 日目 (空いていたので飛び込んだのは 10 日目ですが) です。


プリプロセッサやテンプレートを駆使した C++ ヘッダを g++ でコンパイルする時でたまに発生する string table overflow さん...。

stackoverflow.com

-g がデバッグシンボルを残してるせいなのか、-g を取り除けば大丈夫らしいのだが、CMake のコンパイルフラグから -g を取り除くのにちょいと苦労した。

最初に CMakeLists.txt 内で

set(CMAKE_CXX_FLAGS "")

とか

set(ENV{CXXFLAGS} "")

で上書きしてみたものの全然消えてくれない。

cygport から呼び出していたので cmake.cygclass を見てみたら、そもそもコマンドラインオプションに直接渡してた。

	cmake -Wno-dev \
		${cmdir} \
		-DCMAKE_BINARY_DIR=. \
		-DCMAKE_BUILD_TYPE=${buildtype} \
		-DCMAKE_C_COMPILER=$(which ${CC}${exeext}) \
		-DCMAKE_C_FLAGS="${CFLAGS} ${CPPFLAGS}" \
		-DCMAKE_CXX_COMPILER=$(which ${CXX}${exeext}) \
		-DCMAKE_CXX_FLAGS="${CXXFLAGS} ${CPPFLAGS}" \
		-DCMAKE_Fortran_COMPILER=$(which ${FC}${exeext}) \
		-DCMAKE_Fortran_FLAGS="${FCFLAGS} ${CPPFLAGS}" \
		-DCMAKE_AR=$(which ${AR}${exeext}) \
		-DCMAKE_RANLIB=$(which ${RANLIB}${exeext}) \
		-DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" \
		-DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}" \
		-DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" \
		-DCMAKE_INSTALL_PREFIX=$(__host_prefix) \
		-DCMAKE_LEGACY_CYGWIN_WIN32=0 \
		${crossargs} \
		"${@}" \
		${CYGCMAKE_ARGS} \
		|| error "cmake failed"
cygport/cmake.cygclass at master · cygwinports/cygport · GitHub

なので cmake 呼び出し前に cygport の設定ファイルの方で

CXXFLAGS=""

のように無効化してみたがまだ消えない。

さらに cmake.cygclass をよく見ると

	if defined _CYGPORT_RESTRICT_debuginfo_
	then
		buildtype=Release
	else
		buildtype=RelWithDebInfo
	fi
cygport/cmake.cygclass at master · cygwinports/cygport · GitHub

とあって、CMake のデフォルト設定を見ると

$ cmake --system-information | grep CMAKE_CXX_FLAGS | grep -e '=='
CMAKE_CXX_FLAGS == ""
CMAKE_CXX_FLAGS_DEBUG == "-g"
CMAKE_CXX_FLAGS_MINSIZEREL == "-Os -DNDEBUG"
CMAKE_CXX_FLAGS_RELEASE == "-O3 -DNDEBUG"
CMAKE_CXX_FLAGS_RELWITHDEBINFO == "-O2 -g -DNDEBUG"

となっているので Release になるように

_CYGPORT_RESTRICT_debuginfo_=1 # cygport 内では RESTRICT="debuginfo" で同等の効果がある

することでようやく -g が消えた。


CMake を使う時は (CMake に限ったことではないですが) オプションと環境変数をきちんと確認しましょう。