最新のんでは,無問題ですか?

10万行くらいのCのソースがあります。10個くらいのディレクトリにソースは小分けにされています。ディレクトリそれぞれにMakefileがあり,libxxx.aを生成し,ルートディレクトリのMakefileがリンクする,よくあるパターンですな。コンパイラはポーティングされたgcc。

autoconfなんて使ってません。というかそんなにメジャーな環境ではないのです。

決定的な設計ミスと思われるのが,システム全体の階層化に失敗していることです。

つまり上下関係がはっきりしないので,ソース間の相互依存関係がスパゲッティになっています。プログラムのフローはスパゲッティになっていないのですが。

すると何がおこるか?

liba.a内のある関数は,libb.aに依存し,libb.aの別の関数はliba.aに依存する。

そんなことになります。すると,ちゃんと定義してある関数に対してリンカldが,undefined refereceエラーを吐きます。

このうちいくつかは,暗黙的宣言によるものですので,ヘッダにプロトタイプを書いたり,externで正しい関数プロトタイプを書けばおさまります。

しかし最後まで消えないものがあります。これはリンカのバグとは言いませんが,厄介な挙動です。

もちろん,複数の.aが相互依存を抱えている状況をなんとかするのが正しい対処だということはサルでも理解することが出来ます。

さて,数年前にかかれたMakefileにはこの問題への対症療法として,

$(CC) main.obj liba.a libb.a libc.a liba.a $(LDFLAGS)・・・

のように重複して書かれているのです。確認してみると,確かに記述順を変更することでリンカエラーが出たり出なかったりします。
# アーカイブファイルは-lで指定して欲しいと思うのは凝り固まった考え方ですかね。

ldの仕様においては,オブジェクトファイルやライブラリファイルの記述順はシンボル名の検索に影響を与えることは分かっています。しかしこんがらがった依存関係を解きほぐすことはそう簡単なことではありませんし,ディレクトリの構成やモジュールの切り分け方で解消できない場合もあります。そうなると破壊的対策が求められることになります。10万行のうち数万行が影響を受けるとして,流用の利点がどの程度損なわれるでしょうか。

とにかく何か関数を書いて,それを別のモジュールで参照した途端,微妙なバランスが崩れて大量のリンカエラーとなります。

あきらかな「臭いものにはフタ」的対策です。しかしこんなフタがあっては,開発は遅々として進みません。

ご安心下さい,フタを取っても大丈夫です。ldにはちゃんとオプションがあります。

GNU リンカ LD の使い方: Invocation
http://www.sra.co.jp/wingnut/ld/ld-ja_2.html

-( archives -)
–start-group archives –end-group
    archives はアーカイブファイルのリストを指定する. ファイル名そのものでも良いし, `-l’ オプションでも良い.

    指定されたアーカイブに対し, 新たな未定義参照がなくなるまで繰り返し検索が行なわれる. 普通, ひとつのアーカイブはコマンド行で指定された順に一回だけ検索が行なわれる. そのアーカイブ中のシンボルが, コマンド行上後ろに現れるアーカイブ中のオブジェクトが参照する未定義シンボルを解決するのに必要な場合は, リンカはその参照を解決できない. アーカイブをグループ化することで, 全ての参照が解決されるまでグループの全てのアーカイブが繰り返し検索される.このオプションを使うと性能が非常に落ちるので, 二個以上のアーカイブの間で循環的な参照があり, それが避けられない場合にだけ使うのがよいだろう.

性能が非常に落ちる」と書かれていますが,十万行規模でもリンクにかかる時間に体感差はほとんどありません。おそらくドキュメントが書かれたのが相当昔なのでしょう。

さて,同じソースをVCに食わせるとリンカエラーなんて出ません。リンカの挙動や仕様については,誰が決めているのでしょうか?コンパイラとともに標準化されていますか?

グーグル辺りが,「–start-group」などの検索語に反応してくれないのも困り物です。誰かが同じ問題につまずいても,ここにたどり着くことはきっとないでしょう。こんなオプションがあるくらいなのですから,同様の問題にひっかかる人は相当多数おられるはずですが,情報が見つかりません。このオプションが常識的過ぎて,知らなかった私がアホウなだけなんでしょうか?

とにかくこの問題の呼び方を提案しておきます。

LDにおけるシンボルの循環参照による未定義参照エラー問題およびその解消法

cyclic reference undefined reference linker error

これくらい書いておけば,引っかかってくれるかな?

補足:
-Wl,」についても頭に入れておくこと。『「–start-group」をつけても現象に変化が無い!!』と騒ぎ立てるのはやめていただきたい。