21 Apple Silicon Mac で GLSC をコンパイルする

(しばらく工事中)

訴え: Apple Silicon Mac で GLSC が (Xcode に含まれる cc で) コンパイルできない。どうしたらいいですか?


あれ、またダメになったのか?ということで紆余曲折が始まった。


同僚の先生からの訴えだったのだけど、雑談しているうちに、 自分で解答を発見された (さすがだ)。 というわけで、最初にその解答を紹介。
オリジナルを make するならば次でOK
curl -O  http://www602.math.ryukoku.ac.jp/~nakano/software/math/glsc-3.5.a.tar.Z
tar xzf glsc-3.5.a.tar.Z
cd glsc-3.5.a
MakefileCC = ccCC=cc -Wno-error=implicit-function-declaration -Wno-error=implicit-int に書き換える。
make
これでライブラリィが出来上がる。test/ctests, test/ctestd は動く。
sudo make install

以下、理由を説明する。


基本的には 「GLSC についてまとめておく (2021年版)」 に書いてあることだと思われる。そのときは Xcode の cc (LLVM/clang) で暗黙の関数宣言が禁止されたのだけど (これは確実)、 型名を書かないと int とみなすのも禁止されたみたい (これはいつからそうなったのか良く分からない)。

とにかく、Apple が提供する Xcode の cc では、GLSC が無修正ではコンパイルできなくなった。

私自身についていうと、 自分が管理する Mac には MacPorts で色々なパッケージを導入している関係で、 GCC がインストールされている (/opt/local/bin/gcc)。 この場合、macOS の Xcode の cc の仕様変更にはあまり影響を受けない。 Makefile を変えなくても、gcc が自動的に発見されて (この辺、GLSC は凝ってますね)、 それを用いて make が進められて成功する。

以前 (2020年末頃) やったときは、Xcode の cc でもコンパイルできるように、 GLSC のソース・プログラム中の関数宣言をみなプロトタイプ宣言にしてしまった。 それで GCC でなくても、Xcode の cc でコンパイルできるようになった(はず)。
以前の解 (今回は動かず)
rm -rf sagyou
mkdir sagyou
cd sagyou
curl -O  http://www602.math.ryukoku.ac.jp/~nakano/software/math/glsc-3.5.a.tar.Z
curl -O  http://nalab.mind.meiji.ac.jp/~mk/daishin/glsc-3.5+a.patch
curl -O  http://nalab.mind.meiji.ac.jp/~mk/program/graphics/glsc-3.5+mk.patch20201229
tar xzf glsc-3.5.a.tar.Z
cd glsc-3.5.a
patch -p1 < ../glsc-3.5+a.patch
patch -p1 < ../glsc-3.5+mk.patch20201229

ところが今回は、こうしても引っかかった。 Apple Siliconn Mac では、 使える C コンパイラーが見つからないということで、 CC=true となっている Makefile が生成されてしまう (当然コンパイルできない)。 (もしかすると、2020年暮れに上の変更で動くようになったというのは私の勘違いで、 実は gcc が使われていたのだろうか?? 今となっては古い macOS の Mac が身の回りにないので確認できない。)

今回、相談を持ちかけた先生が見つけた -Wno-error=implicit-intを Makefile に書いてから make すると確かに通る。
Makefileの該当部分
#
#       Commands
#
CC            = cc -Wno-error=implicit-int
CDEBUGFLAGS   = -O -g
CFLAGS        =

あるいは cnofig/Configure スクリプトをちょっといじると通る。
config/Configure の該当部分
if ( echo "main () { }" >$CFILE; $cc -o $AOUT $CFILE ) \
(何もしない C プログラムを作って、それがコンパイルできるかどうかチェックしている) を
config/Configure の該当部分をこんなふうに修正
if ( echo "int main () { }" >$CFILE; $cc -o $AOUT $CFILE ) \
に変更する (main() の前に int を足しただけ)。 これで Xcode の cc が “ちゃんと働く” と判定されて、パスするようだ。

GLSC 自体は今さら修正されないだろう。Mac 以外のことを考えると、 -Wno-error=implicit-int とするよりは、 config/Configure を直す方が筋が良いだろう (そう直して問題が起こるケースはまずないはずだ)。

というわけで、config/Configure を直すパッチを作った。

以下は、オリジナルの GLSC に、上山先生のパッチを当てて、 それから私のパッチ (どうでも良い(桂田研内々の) 機能拡張以外に、 関数宣言をプロトタイプ宣言にするのと、 Configure が Xcode の cc でも動くようにするパッチを含む) を当てて make する手順。

私は今後はこうする
rm -rf sagyou
mkdir sagyou
cd sagyou
curl -O  http://www602.math.ryukoku.ac.jp/~nakano/software/math/glsc-3.5.a.tar.Z
curl -O  https://m-katsurada.sakura.ne.jp/daishin/glsc-3.5+a.patch
curl -O  https://m-katsurada.sakura.ne.jp/program/graphics/glsc-3.5+mk.patch20240718
tar xzf glsc-3.5.a.tar.Z
cd glsc-3.5.a
patch -p1 < ../glsc-3.5+a.patch
patch -p1 < ../glsc-3.5+mk.patch20240718
こうしてから make すればライブラリィとテスト・プログラムができる。 続いて sudo make install すれば良い。


相変わらず Apple Silicon Mac で、 GLSC の Fortran 向けライブラリィが動かないのはなおっていない。 動かしたい Fortran プログラムがないから、作業する動機が見つからない。

GCC の gcc と gfortran の間での文字列渡しの問題ならば、 どこかに解説があるはずだから、GCC に限れば解決できそうに思うのだけど。 あ、最近の Fortran にはインターフェイスの規格が入っているんだったっけ。

(2024/7/20) そうだ、ChatGPT にきいてみよう。コンパイルできないプログラムを出して来て、 それに対して「こんなエラーが出る」と二度ほど返して、 コンパイルできるプログラム例が入手できた。
main.f90
module c_interface
  use iso_c_binding, only: c_char, c_int
  implicit none
  interface
    subroutine print_string(str) bind(C, name="print_string")
      import :: c_char
      character(kind=c_char), intent(in) :: str(*)
    end subroutine print_string
  end interface
end module c_interface

program main
  use c_interface
  implicit none
  character(len=4, kind=c_char) :: fortran_string

  ! Null-terminated string required for C
  fortran_string = 'ABC'//char(0)
  call print_string(fortran_string)
end program main
#include <stdio.h>

void print_string(const char *str) {
    printf("Received string: %s\n", str);
}
こうしてコンパイル実行
gfortran -c main.f90
gcc -c print_string.c
gfortran main.o print_string.o -o main_program
./main_program

なるほど。 これは Fortran 側でそれなりの準備をするということだな。 GLSC に組み込むにはどうすればいいかな。 GLSC は、Cの関数の側で世話を焼く設計になっている (Fortan から呼ぶとこんなふうになっているはずなので、それをキャッチするにはこうする、 というコードを書く)。 GLSC のライブラリィに Fortran で書いた関数のオブジェクトを入れるのかな。


(2024/8/3追記) まだ解決しないうちに書くと鬼に笑われそうだけど。

Fortran が動かない原因が何となく分かったようが気がする。 元々 g_sformat() あたりで問題が生じていることは分かっていたのだが、 原因が判明しなかった。 GLSC は、 多くのシステムですんなりコンパイルできるように非常に凝ったことをしている。 システムの差異を自動的に吸収するように作られていて、 それが30年近くうまく行っていたようなのだけれど、 それにほころびが生じたみたいだ。 今回の -Wno-error=implicit-int なんて、まさにそういうことだよね。

GLSC が作られた当初は、パソコンで動かすというよりは、 UNIX マシン (ワークステーションとかメインフレームとか)が対象であった。 本当に色々なシステムがあって、ソフトウェアの移植は日常的に大きな問題だった。 私も出回っているソフトを自分が使っているシステムで動かすために、 奮闘した記憶が残っている。 GLSC は、そういう趨勢の中で簡単にインストールできるように (使うのは主に数学屋さんでコンピューターのプロというわけじゃないものね)、 相当に頑張ったソフトウェアだった、すごいなあ、と思っている。

でも、今はシステムの違いと言っても、大したことはない。 Windows, Linux, Mac に収斂していて、 使っているコンパイラーも LLVM か GCC くらいと考えて良いだろう (Windows もWSLがあって、 こういうのをするときは Linux とみなして良くなったから、 というのが大きいかな。 結局、Linux と Mac だけということになるのかな)。

もしも今 GLSC を作るならば、ずいぶんすっきりした設計になりそうな気がする。

そこで考えたのだけれど、 全体を改変する気はないけれど、 g_sformat() についてだけでも、 対象システムを絞ることにして、自分で一から書き直してみる。 いわゆる varargs というやつで、自分で使ったことがなかったのだけれど、 何度もソースプログラムを読んでいるうちに、自分でもできそうに思えてきた。

学期末のゴタゴタが終わったらやってみよう。

桂田 祐史