2021年12月3日金曜日

最小の makefile を作りたい(改訂版)

小さいCプログラムのための makefile を作りたい、という話。
 

カレントディレクトリに main.c という簡単な C プログラムがあったとき、これをコンパイルして main という実行ファイルを作ることを考えます。 まあ cc main.c -o main で終わり、なので、

てことになるわけですが、やれここでコンパイル時にデバッグフラグだの、数学関数をリンクするだの言い始めると途端にオプションが増えます。

そんなときによく使われるのが makefile に書かれる変数なのですが、これもまた雑に調べるとオプションを指定する環境変数がごちゃごちゃしていて分かりにくい。 特に LDFLAGS と LDLIBS の扱いで混乱してしまい、困ってしまいました。 リンクするライブラリ(-lmなど)はソースファイルの後に書かなければいけないのですが、 LDFLAGSに書けばいいよみたいな資料が若干見当たり、その通りに書くとコンパイルできない(リンクに失敗する)という…

こんなとき役に立つのが make のデフォルトルールの表示です。 Linux の make (GNU make) には オプション -p があるので、
であることが分かります。一方、FreeBSDのmake (BSD make) はオプションと挙動が違いまして、 となります。このデバッグ出力は標準エラー出力に吐き出されますので注意してください。

いずれにせよ、
  • LDFLAGSはソースファイルより前に付く
  • LDLIBSはソースファイルより後に付く
  • .c ルールはソースファイル foo.c から実行ファイル foo を作る、というルールなので、program: foo.c などとだけ makefile に書いてもルールに合致しないので何も起こらない
ことが分かりますから、
  • LDFLAGS にはライブラリの所在を表すパス(-L オプション)などを書く
  • LDLIBS にはリンクしたいライブラリの実体なり -l オプションなりを書く
という使い方であることに気づくわけです。

オブジェクトファイル .o を作る場合はどうなるのか? については、ルールの表示から探してみて、CFLAGS の付けかたについて考えてみるとよいでしょう。例えば、プログラム中で自作関数などが呼び出された回数や処理時間を計測するプロファイラ gprof を用いる場合は、コンパイラとして gcc を想定し、コンパイル時とリンク時の両方に -pg オプションが必要なので、たとえば
という書き方になります。main()があるソースコードのファイル名は拡張子をつけずに実行ファイル名とお揃いにしておく(prog.c に main()を書くなら実行ファイル名は prog とする)というのがポイントです。 これは、make -pで表示される暗黙のルールから、以下の二つが適用されて、main という実行ファイルが作られる、ということから確認できます。
(FreeBSDでは cc が clang の時に -pg オプションを付けると、正しく動作しない実行ファイルが出来て困ったので、念のため書き添えておきます。 )

gmake には .c.out ルールが標準で備わっていません。さらに、実行ファイルを作成するルールについても、よく見ると となっており、実行ファイルに .exe とか .out をつけるようにはなっていません。実行ファイルのファイル名と、ソースコードなどのファイル名が異なるもの(sample という実行ファイルを main.c から作る、みたいな)だと途端にうまくいかなくなるわけです。また、この様子だと分割コンパイルを行う場合も、暗黙のルールには頼りにくいように見えます。

上記の点を踏まえ、さらに分割コンパイルを行うときのMakefile は、たとえば以下のようになろうかと思います。 main()関数を持つ main.c, 他の関数を持つ sub.c, sub.c が持つグローバル変数や関数プロトタイプの情報を他の関数に伝えるための sub.h から、 実行ファイル prog を作る例です。

EXEC が実行ファイル名をあらわす変数ですが、これが prog ではなく main なら、OBJS から EXEC を作る部分の LINK.o のルールは、main.o から main を作る暗黙のルールが適用となるため、不要となるでしょう。さらに、 main.o や sub.o の作成については暗黙のルールを適用できそうな気がします。これらのことを大胆に(ヘッダファイルの依存関係を省略するなどして)反映させると、上のMakefileは下のように若干短縮出来ます。
rm -fの後ろにアスタリスクを含めるのはうっかりミスで全てのファイルを消し飛ばすくらいのハイリスクなのでやめておいたほうがいいと思いますし、ソースコードの依存関係が分かりにくいので、しっかり書いたほうがよいでしょう。

2020年8月23日日曜日

wsl2のubuntuを使うときのメモ

※ apt-get upgrade を実行すると、多くのエラーが発生するのはなぜですか。
という内容を見ていたのですが、これは以下のサイトの説明が参考になります。

で、Docker版Ubuntuではこのへんの設定がきちんと行われているようで、ほかにaptなどの高速化やキャッシュファイルの削除などを行う設定が入っているようでした。

wsl2でもやったらいいんじゃないかな、というメモでした。

2020年7月22日水曜日

google ドライブでファイルを一括ダウンロード出来ない?(2020年春以降)

google ドライブで複数のファイルを一括ダウンロードしようとしても、圧縮されたzipファイルがいつまでたってもダウンロード出来ないぞ?? と思っていたのですが……

複数のファイルのダウンロードを行うと、これらのファイルはzipファイルに圧縮されます。右下のほうにファイルの圧縮に関する情報が表示されますが、圧縮されたファイルがダウンロードされる準備が整った頃に……


こんなダイアログが表示されませんか?

そしてこの『このサイトを離れますか?』(行った変更が保存されない可能性があります。)[このページを離れる][キャンセル]というダイアログで、「このページを離れたらファイルのダウンロードが出来ないのではないか?」と思って[キャンセル]を押してませんか?

それが罠です。

ここでは[このページを離れる]を押すのが正解です。それを押すと、用意されたzipファイルのダウンロードが開始されます。

いや分かるかそんなん!?