Bug #7307
closedgcc -ansi vs. alloca (undefined reference to `alloca')
Description
Ruby 2.0.0からは CFLAGS に -ansi が(サポートがあれば)付くように
なりましたが、これにより、 gcc の builtin alloca に依存しており
libc に alloca(3) を持たない環境、具体的にはOpenBSD(およびおそら
くNetBSDの mips, powerpc, powerpc64, sparc, sparc64 等)で次のよう
なリンクエラーが発生します。
linking miniruby
addr2line.o(.text+0x9e7): In function follow_debuglink': /home/knu/src/ruby-trunk-vanilla/addr2line.c:424: warning: strcpy() is almost always misused, please use strlcpy() regerror.o(.text+0x499): In function
onig_vsnprintf_with_pattern':
/home/knu/src/ruby-trunk-vanilla/regerror.c:334: warning: strcat() is almost always misused, please use strlcat()
regerror.o(.text+0x55e):/home/knu/src/ruby-trunk-vanilla/regerror.c:197: warning: sprintf() is often misused, please use snprintf()
dmyencoding.o(.text+0x120e): In function set_encoding_const': /home/knu/src/ruby-trunk-vanilla/encoding.c:1535: undefined reference to
alloca'
bignum.o(.text+0xbfea): In function rb_str_to_inum': /home/knu/src/ruby-trunk-vanilla/bignum.c:791: undefined reference to
alloca'
object.o(.text+0x11c2): In function rb_str_to_dbl': /home/knu/src/ruby-trunk-vanilla/object.c:2565: undefined reference to
alloca'
parse.o(.text+0x1e24): In function parser_yyerror': /home/knu/src/ruby-trunk-vanilla/build.unknown.openbsd-amd64/parse.y:5221: undefined reference to
alloca'
parse.o(.text+0xb2c8): In function parser_tokadd_string': /home/knu/src/ruby-trunk-vanilla/build.unknown.openbsd-amd64/parse.y:6072: undefined reference to
alloca'
parse.o(.text+0xb2fb):/home/knu/src/ruby-trunk-vanilla/build.unknown.openbsd-amd64/parse.y:6085: more undefined references to `alloca' follow
collect2: ld returned 1 exit status
*** Error code 1
Stop in /home/knu/src/ruby-trunk-vanilla/build.unknown.openbsd-amd64 (line 180 of Makefile).
なぜ(configure は成功するのに)こけるかの説明は以下の通りです。
- autoconf の AC_FUNC_ALLOCA は次のようなコードによるテストに展開
されるので、 gcc を使う限りは alloca は __builtin_alloca に置き換
わるので configure は成功する
#ifdef GNUC
define alloca __builtin_alloca¶
#else
ifdef _MSC_VER¶
include <malloc.h>¶
define alloca _alloca¶
else¶
ifdef HAVE_ALLOCA_H¶
include <alloca.h>¶
else¶
ifdef _AIX¶
#pragma alloca
else¶
ifndef alloca /* predefined by HP cc +Olibcalls */¶
void *alloca (size_t);
endif¶
endif¶
endif¶
endif¶
#endif
-
gcc は -ansi を付けると alloca を提供しなくなる
(__builtin_alloca は常にある) -
ruby のソースツリーでは(マクロを通じて)広く alloca が使われて
いるが、上記1のような alloca のケア(置換)を行っているのは gc.c
や #include "eval_intern.h" しているもののみ -
しかし、基本的にすべてのファイルが -ansi 付きでビルドされるので、
addr2line.o, regerror.o, encoding.o 等々に alloca への参照が埋まっ
てしまい、 libc に alloca がない環境ではリンクエラーとなる
解決策は、 ruby/ruby.h の alloca 関連部を gc.c などにあるような
gcc 対応を含む完全なものにすることです。
下のパッチを適用し、以下の環境で make test が通りました。
- OpenBSD/amd64 5.2-RELEASE (GCC 4.2.1) - libc has no alloca
- FreeBSD/amd64 9.1-PRERELEASE (GCC 4.2.1)
- FreeBSD/amd64 9.1-PRERELEASE (clang 3.1)
- Mac OS X 10.8.2 (Apple clang 4.1)
問題なければコミットします。
Files
Updated by knu (Akinori MUSHA) about 12 years ago
- File alloca.diff alloca.diff added
バリデーションに捕まったのにアップロードファイルを再添付忘れました。
Updated by knu (Akinori MUSHA) about 12 years ago
- Category changed from core to build
Sorry, I could have sworn that I chose ruby-dev as Preferred language but after a form error that I didn't fill in ruby -v the field got somehow reset to the default value (ruby-core) and I resubmitted the form without noticing it...
Updated by kosaki (Motohiro KOSAKI) about 12 years ago
ちゃんと読めてませんが、 autoconf の AC_FUNC_ALLOCA のコードをそのままカット&ペーストで持ってきたという意味ならライセンス非互換なのでよくないのではないでしょうか。
gc.c のやつをruby.h に引っ越しただけという話ならすいません。
#そもそも -ansi を外してしまうという案を押したい。-ansi はピュアANSI Cという意味だけど、rubyはANSI外の様々なPOSIX関数を
使いまくってるので、どうにも本来の使い道でない感があります。たまたま動いているだけというか¶
Updated by knu (Akinori MUSHA) about 12 years ago
その通り、 gc.c にあったものを ruby/ruby.h に移動しただけです。
当該部分の内容はコメントを含めほぼ autoconf の吐くものと同一ですが、 configure スクリプト冒頭にもある通り、
生成された configure スクリプトはGPLの例外で、利用(改変、コピー、配布)にあたって制限はないはずです。
cf. http://www.gnu.org/licenses/autoconf-exception.html
-ansi を外すというのはできればそうしたいですね。
潜在バグのあぶり出しや移植性の低いコードの混入を防ぐような効果を期待しているのでしょうか。
Updated by knu (Akinori MUSHA) about 12 years ago
なお、現状ではビルドできないプラットフォームがあるので、 -ansi をどうするかというのとは別に、
早めに入れて救済を優先したいなと思っています。
Updated by shyouhei (Shyouhei Urabe) about 12 years ago
knu (Akinori MUSHA) wrote:
-ansi を外すというのはできればそうしたいですね。
潜在バグのあぶり出しや移植性の低いコードの混入を防ぐような効果を期待しているのでしょうか。
そうです。もとの動機に関しては下記をご参照ください。
http://qa.atmarkit.co.jp/q/2159
Updated by knu (Akinori MUSHA) about 12 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r37571.
Akinori, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
Fix build when gcc is used and the platform's libc lacks alloca().
-
include/ruby/ruby.h (alloca), eval_intern.h (alloca), gc.c
(alloca): Make alloca() globally available by moving the
ultimate ifdef's to ruby/ruby.h. Gcc hides its builtin alloca()
when compiling with -ansi, and linking thus fails on platforms
that lack their own alloca() implementation in libc, which
include OpenBSD and some ports of NetBSD. We use alloca()
everywhere including from within third party C extentions, so
alloca() must be made globally available. [Bug #7307] -
addr2line.c (alloca): Replace the alloca() part with the
ultimate ifdef's. [Bug #7307]
Updated by knu (Akinori MUSHA) about 12 years ago
shyouhei (Shyouhei Urabe) wrote:
knu (Akinori MUSHA) wrote:
-ansi を外すというのはできればそうしたいですね。
潜在バグのあぶり出しや移植性の低いコードの混入を防ぐような効果を期待しているのでしょうか。そうです。もとの動機に関しては下記をご参照ください。
http://qa.atmarkit.co.jp/q/2159
なるほど。せっかく今はコンパイルできているので、具体的に困るまではいいか。
なお、そういう用途では-pedanticも付けるのが定番だと思いますが、実効性のほどは分かりません。