LoginSignup
7
2

コンパイル用shell scriptを記述する。
ここではCERT Cの例題を編纂(compile)・実行する方法を検討する。shell scriptのデバッグは苦手。なるべく簡単な機能だけ使う。

最終的にはmakeを作るかもしれない。makeのデバッグはもっと苦手。全部が完成したら作成予定。

引数に関する考察

1コンパイル対象ファイル
1.1 C用 .cを付加
1.2 c++用 .cppを付加

2 複数ファイルのコンパイル
2.1 2つファイル用
2.2 3つファイル用

3 コンパイルオプションの指定
ファイル名の後に、コンパイルオプションを記述

4 実行時のオプションの記述
最後の引数は実行時に用いる

まずは、下記に掲載するプログラム用。

CERT C入門(1) Rule 01. Preprocessor (PRE)
https://qiita.com/kaizen_nagoya/items/8d2cb4158ed53d5a0a28

C言語の断片を、できれば実行結果で何か出力する処理を入れる。
 コンパイルに意味があるかどうかを確かめる。
  (意味のない処理がどういう記述であってもどうでもいい。)
 副作用の有無を確かめるには出力するのが一番。
  (出力しようとしなければ副作用が生じないこともある。)
 実行結果に違いがあるかどうかを確かめる。
  (コンパイラによって違うがあるような出力を試す。)

これまでに類似の作業は、「C Puzzle Book」「国際規格C、C++」「MISRA C/MISRA C++」で行ってきた。

C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9

[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de

MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9

Cコンパイル

cert0.sh
cc pre01n.c
./a.out

実行可能に

$ chmod +x cert0.sh

+xで実行権を付与。数字を打つより間違いが少ない。

初心者向けシェルスクリプトの基本コマンドの紹介
https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337

実行

$ ./cert0.sh
$ 3 3

コンパイルして実行する

引数

引数を渡す

cert1.sh
cc $1
./a.out

引数渡し実行

$ cert1 pre1n.c
$ 3 3

複数のコンパイラを使う

cert1.sh
cc $1
./a.out
gcc-6 $1
./a.out

課題、2つ目のコンパイルを失敗すると、1つ目をまた実行してしまう。誤解する可能性あり。

$ cert1 pre1n.c
$ 3 3
$ 3 3

実行結果を削除する

cert1.sh
cc $1
./a.out
rm a.out
gcc-6 $1
./a.out
rm a.out

事前の実行結果を削除

1つ目のコンパイルを失敗した場合、何かの結果を実行してしまう。

cert1.sh
rm a.out
cc $1
./a.out
rm a.out
gcc-6 $1
./a.out
rm a.out

実行ファイルを残す

cert2.sh
cc $1.c -o $1l
./$1l
gcc-6 $1.c -o $1g
./$1g

".c"の入力を省略できるようにした。

すごくスッキリした。

実行すると

$ cert2 pre1n
$ 3 3
$ 3 3

どちらがどちらの実行結果が間違えるといけない。

処理内容表示

cert2.sh
echo "clang/llvm $1.c"
cc $1.c -o $1l
./$1l
gcc-6 $1.c -o $1g
./$1g

実行して見ると

$ cert2 pre1n
clang/llvm pre32n.c
3 3
gcc-6 pre32n.c
3 3

1日目のシェルスクリプト作りはこの辺まで。
のつもりでいたら、certc側で、第二引数を渡す必要があるプログラムがあり、書き換え。コンパイルエラー時には実行しないように追記。

certc3.sh
#!/bin/sh
echo "$ clang $1.c"
cc $1.c -o $1l
if [  -e $1l ]; then
./$1l $2
fi
echo "\r"
echo "$ gcc-6 $1.c"
gcc-6 $1.c -o $1g
if [  -e $1g ]; then
./$1g $2
fi

gcc-7対応

clg7.sh
#!/bin/sh
echo "$ clang $1.cpp"
cc $1.c -o $1l -I.
if [  -e $1l ]; then
./$1l $2
fi
echo "\r"
echo "$ gcc-7 $1.cpp"
gcc-7 $1.c -o $1g -I.
if [  -e $1g ]; then
./$1g $2
fi

gcc-7対応コンパイル対象が2つある場合

clg72.sh
#!/bin/sh
echo "$ clang $1.c"
cc $1.c $2.c -o $1l -I.
if [  -e $1l ]; then
./$1l $3
fi
echo "\r"
echo "$ gcc-7 $1.c"
gcc-7 $1.c $2.c -o $1g -I.
if [  -e $1l ]; then
./$1l $3
fi

gcc-7対応コンパイル対象が3つある場合

clg73.sh
#!/bin/sh
echo "$ clang $1.c"
cc $1.c $2.c $3.c -o $1l -I.
if [  -e $1l ]; then
./$1l $4
fi
echo "\r"
echo "$ gcc-7 $1.c"
gcc-7 $1.c $2.c $3.c -o $1g -I.
if [  -e $1g ]; then
./$1g $4
fi

C++用作成

certcpp.sh
#!/bin/sh
echo "$ clang++ $1.cpp"
clang++ $1.cpp -o $1l
if [  -e $1l ]; then
./$1l $2
fi
echo "\r"
echo "$ g++-6 $1.cpp"
g++-6 $1.cpp -o $1g
if [  -e $1g ]; then
./$1g $2
fi

g++-7対応

cppgl.sh
#!/bin/sh
echo "$ clang++ $1.cpp"
clang++ $1.cpp  -o $1l
if [  -e $1l ]; then
./$1l $2
fi
echo "\r"
echo "$ g++-7 $1.cpp"
g++-7 $1.cpp -o $1g
if [  -e $1g ]; then
./$1g $2
fi

-std=c++17 追記

cppgl17.sh
#!/bin/sh
echo "$ clang++ $1.cpp"
clang++ $1.cpp  -std=c++17  -o $1l
if [  -e $1l ]; then
./$1l $2
fi
echo "\r"
echo "$ g++-7 $1.cpp"
g++-7 $1.cpp -std=c++17  -o $1g
if [  -e $1g ]; then
./$1g $2
fi

-Wallをつけた。一通りコンパイルしてみた。改良点を探すために-Wallの警告を順次確認。

cppwa17.sh
#!/bin/sh
echo "$ clang++ $1.cpp -std=c++17 -Wall"
clang++ $1.cpp -std=c++17 -Wall -o $1l
if [  -e $1l ]; then
./$1l $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++17  -Wall" 
g++-7 $1.cpp  -std=c++17 -Wall -o $1g
if [  -e $1g ]; then
./$1g $2
fi

-trigraph用にコンパイルオプションを記述できるようにした版(c++2011用)

cppwa11.sh
#!/bin/sh
echo " usege ./cppwa11.sh prog option msg"
echo "$ clang++ $1.cpp $2 -std=c++11 -Wall"
clang++ $1.cpp -std=c++11 $2  -Wall -o $1l
if [  -e $1l ]; then
./$1l $3
fi
echo "\r"
echo "$ g++-7 $1.cpp $2 -std=c++11  -Wall" 
g++-7 $1.cpp  -std=c++11 $2 -Wall -o $1g
if [  -e $1g ]; then
./$1g $3
fi

C++N4910用に -std=C++2b 版作成

clgc.sh
#!/bin/sh
if [  -e $1l ]; then
rm $1l
fi
if [  -e $1g ]; then
rm $1g
fi
echo "$ clang++ $1.cpp -std=03 -o $1l -I. -Wall" 
clang++ $1.cpp -std=c++03 -o $1l -I. -Wall
if [  -e $1l ]; then
./$1l 
fi
if [  -e $1l ]; then
rm $1l
fi
echo "$ clang++ $1.cpp -std=2b -o $1l -I. -Wall"
clang++ $1.cpp -std=c++2b -o $1l -I. -Wall
if [  -e $1l ]; then
./$1l
fi
echo "\r"
echo "$ g++ $1.cpp -std=03 -o $1g -I. -Wall"
g++ $1.cpp -std=c++03 -o $1g -I. -Wall
if [ -e $1g ]; then
./$1g
fi
if [ -e $1g ]; then
rm $1g
fi
echo "\r"
echo "$ g++ $1.cpp -std=2b -o $1g -I. -Wall"
g++ $1.cpp -std=c++2b -o $1g -I. -Wall
if [ -e $1g ]; then
./$1g 
fi

利用方法

./cppwa11 cpp2011-2-4 -trigraph
cppall.sh
#!/bin/sh
echo "$ clang++ $1.cpp -std=c++03 -Wall"
clang++ $1.cpp -std=c++03 -Wall -o $1l03
if [  -e $1l03 ]; then
./$1l03 $2
fi
echo "$ clang++ $1.cpp -std=c++11 -Wall"
clang++ $1.cpp -std=c++11 -Wall -o $1l11
if [  -e $1l11 ]; then
./$1l11 $2
fi
echo "$ clang++ $1.cpp -std=c++17 -Wall"
clang++ $1.cpp -std=c++17 -Wall -o $1l17
if [  -e $1l17 ]; then
./$1l17 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++03  -Wall"
g++-7 $1.cpp  -std=c++03 -Wall -o $1g03
if [  -e $1g03 ]; then
./$1g03 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++11  -Wall"
g++-7 $1.cpp  -std=c++11 -Wall -o $1g11
if [  -e $1g11 ]; then
./$1g11 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++17  -Wall" 
g++-7 $1.cpp  -std=c++17 -Wall -o $1g17
if [  -e $1g17 ]; then
./$1g17 $2
fi

docker用に追記

cppall.sh
#!/bin/sh
echo "$ clang++ $1.cpp -std=c++03 -Wall"
clang++ $1.cpp -std=c++03 -lc++ -I/usr/local/include/c++/7.3.0 -I/usr/local/include/c++/7.3.0/x86_64-linux-gnu -Wall -o $1l03
if [  -e $1l03 ]; then
	./$1l03 $2
fi
echo "$ clang++ $1.cpp -lc++ -std=c++11  -Wall"
clang++ $1.cpp -std=c++11 -lc++ -I/usr/local/include/c++/7.3.0 -I/usr/local/include/c++/7.3.0/x86_64-linux-gnu -Wall -o $1l11
if [  -e $1l11 ]; then
	./$1l11 $2
fi
echo "$ clang++ $1.cpp -lc++ -std=c++17  -Wall"
clang++ $1.cpp -std=c++17 -lc++ -I/usr/local/include/c++/7.3.0 -I/usr/local/include/c++/7.3.0/x86_64-linux-gnu -Wall -o $1l17
if [  -e $1l17 ]; then
	./$1l17 $2
fi
echo "\r"
echo "$ g++ $1.cpp -std=c++03  -Wall"
g++ $1.cpp  -std=c++03 -Wall -o $1g03
if [  -e $1g03 ]; then
	./$1g03 $2
fi
echo "\r"
echo "$ g++ $1.cpp -std=c++11  -Wall"
g++ $1.cpp  -std=c++11 -Wall -o $1g11
if [  -e $1g11 ]; then
	./$1g11 $2
fi
echo "\r"
echo "$ g++ $1.cpp -std=c++17  -Wall" 
g++ $1.cpp  -std=c++17 -Wall -o $1g17
if [  -e $1g17 ]; then
	./$1g17 $2
fi

-std=c++14を追加した版

cppall.sh
#!/bin/sh
echo "$ clang++ $1.cpp -std=c++03 -Wall"
clang++ $1.cpp -std=c++03 -I=. -Wall -o $1l03
if [  -e $1l03 ]; then
./$1l03 $2
fi
echo "$ clang++ $1.cpp -std=c++11 -Wall"
clang++ $1.cpp -std=c++11 -I=. -Wall -o $1l11
if [  -e $1l11 ]; then
./$1l11 $2
fi
echo "$ clang++ $1.cpp -std=c++14 -Wall"
clang++ $1.cpp -std=c++14 -I=. -Wall -o $1l14
if [  -e $1l14 ]; then
./$1l14 $2
fi
echo "$ clang++ $1.cpp -std=c++17 -Wall"
clang++ $1.cpp -std=c++17 -I=. -Wall -o $1l17
if [  -e $1l17 ]; then
./$1l17 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++03  -Wall"
g++-7 $1.cpp  -std=c++03 -I=. -Wall -o $1g03
if [  -e $1g03 ]; then
./$1g03 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++11  -Wall"
g++-7 $1.cpp  -std=c++11 -I=. -Wall -o $1g11
if [  -e $1g11 ]; then
./$1g11 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++14  -Wall"
g++-7 $1.cpp  -std=c++14 -I=. -Wall -o $1g14
if [  -e $1g14 ]; then
./$1g14 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++17  -Wall" 
g++-7 $1.cpp  -std=c++17 -I=. -Wall -o $1g17
if [  -e $1g17 ]; then
./$1g17 $2
fi

C++N4741はclang++ -std=c++2a

のc1.shでコンパイルエラーを確認。
cpla.shで2つのコンパイラの合計5つのオプション

c1.sh
#!/bin/sh
echo "$ clang++ $1.cpp  -std=c++2a -Wall"
clang++ $1.cpp -std=c++2a -I=. -Wall -o $1l2a
if [  -e $1l2a ]; then
./$1l2a $2
rm $1l2a
fi

コンパイル対象が2つの場合

c2.sh
#!/bin/sh
echo "$ clang++ $1.cpp $2.cpp -std=c++2a -Wall"
clang++ $1.cpp $2.cpp -std=c++2a -I=. -Wall -o $1l2a
if [  -e $1l2a ]; then
./$1l2a $3
rm $1l2a
fi
c3.sh
#!/bin/sh
echo "$ clang++ $1.cpp $2.cpp $3.cpp -std=c++2a -Wall"
clang++ $1.cpp $2.cpp $3.cpp -std=c++2a -I=. -Wall -o $1l2a
if [  -e $1l2a ]; then
./$1l2a $4
rm $1l2a
fi

2種類のコンパイラ、合計5種類のスイッチ

spla.sh
#!/bin/sh
echo "$ clang++ $1.cpp -std=c++03 -Wall"
clang++ $1.cpp -std=c++03 -I=. -Wall -o $1l03
if [  -e $1l03 ]; then
./$1l03 $2
fi
echo "$ clang++ $1.cpp -std=c++17 -Wall"
clang++ $1.cpp -std=c++17 -I=. -Wall -o $1l17
if [  -e $1l17 ]; then
./$1l17 $2
fi
echo "$ clang++ $1.cpp -std=c++2a -Wall"
clang++ $1.cpp -std=c++2a -I=. -Wall -o $1l2a
if [  -e $1l2a ]; then
./$1l2a $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++03  -Wall"
g++-7 $1.cpp  -std=c++03 -I=. -Wall -o $1g03
if [  -e $1g03 ]; then
./$1g03 $2
fi
echo "\r"
echo "$ g++-7 $1.cpp -std=c++17  -Wall" 
g++-7 $1.cpp  -std=c++17 -I=. -Wall -o $1g17
if [  -e $1g17 ]; then
./$1g17 $2
fi
cpla2.sh
#!/bin/sh
echo "$ clang++ $1.cpp $2.cpp -std=c++03 -Wall"
clang++ $1.cpp $2.cpp -std=c++03 -I=. -Wall -o $1l03
if [  -e $1l03 ]; then
./$1l03 $3
fi
echo "$ clang++ $1.cpp $2.cpp -std=c++17 -Wall"
clang++ $1.cpp $2.cpp -std=c++17 -I=. -Wall -o $1l17
if [  -e $1l17 ]; then
./$1l17 $3
fi
echo "$ clang++ $1.cpp $2.cpp -std=c++2a -Wall"
clang++ $1.cpp $2.cpp -std=c++2a -I=. -Wall -o $1l2a
if [  -e $1l2a ]; then
./$1l2a $3
fi
echo "\r"
echo "$ g++-7 $1.cpp $2.cpp -std=c++03  -Wall"
g++-7 $1.cpp  $2.cpp -std=c++03 -I=. -Wall -o $1g03
if [  -e $1g03 ]; then
./$1g03 $3
fi
echo "\r"
echo "$ g++-7 $1.cpp $2.cpp -std=c++17  -Wall" 
g++-7 $1.cpp $2.cpp -std=c++17 -I=. -Wall -o $1g17
if [  -e $1g17 ]; then
./$1g17 $3
fi
cpla3.sh
#!/bin/sh
echo "$ clang++ $1.cpp $2.cpp $3.cpp -std=c++03 -Wall"
clang++ $1.cpp $2.cpp $3.cpp -std=c++03 -I=. -Wall -o $1l03
if [  -e $1l03 ]; then
./$1l03 $4
fi
echo "$ clang++ $1.cpp $2.cpp $3.cpp -std=c++17 -Wall"
clang++ $1.cpp $2.cpp $3.cpp -std=c++17 -I=. -Wall -o $1l17
if [  -e $1l17 ]; then
./$1l17 $4
fi
echo "$ clang++ $1.cpp $2.cpp $3.cpp -std=c++2a -Wall"
clang++ $1.cpp $2.cpp $3.cpp -std=c++2a -I=. -Wall -o $1l2a
if [  -e $1l2a ]; then
./$1l2a $4
fi
echo "\r"
echo "$ g++-7 $1.cpp $2.cpp $3.cpp -std=c++03  -Wall"
g++-7 $1.cpp  $2.cpp $3.cpp -std=c++03 -I=. -Wall -o $1g03
if [  -e $1g03 ]; then
./$1g03 $4
fi
echo "\r"
echo "$ g++-7 $1.cpp $2.cpp $3.cpp -std=c++17  -Wall" 
g++-7 $1.cpp $2.cpp $3.cpp -std=c++17 -I=. -Wall -o $1g17
if [  -e $1g17 ]; then
./$1g17 $4
fi

整形台本

a.sh
#!/bin/bash
astyle -s2 -c -N < $1.cpp > $1s2.cpp
cat $1s2.cpp

参考資料

CERT CPP入門(1) Rule 01. Declarations and Initialization (DCL)
https://qiita.com/kaizen_nagoya/items/61b3c431756fe8e6af3e

Linux初心者のシェルスクリプト入門
https://qiita.com/lrf141/items/6c01d2f7afff79cd7286

ShellScriptでよく使う表現
https://qiita.com/rotocuir/items/986e8ee732730606622b

文書履歴

ver. 0.10 初版 20180320
ver. 0.11 第二引数渡し 20180321
ver. 0.12 C++版追記 20180322
ver. 0.13 gcc-7対応追記 20180407
ver. 0.14 echo "\r"、prompt表記 echo "$"追記。20180407
ver. 0.15 コンパイル対象ファイル2つ版、3つ版 20180407
ver. 0.16 "-I."追記。カレントディレクトリのヘッダファイルを<>include可能に 20180407
ver. 0.17 g++-7対応 20180408
ver. 0.18 コンパイルエラー時に実行しない設定追記。
"if [ -e x ]; then" "x" "fi"
ver. 0.19 -std=c++17 版 20180415
ver. 0.20 -Wallをつけた。20180423
ver. 0.21 # -trigraph用にコンパイルオプションを記述できるようにした版(c++2011用)20180424
ver. 0.22 -std=c++03, -std=c++11, -std=c++17の3種類でコンパイルする記述追記 20180424
ver. 0.23 N4606 Annex C(informative) Compatibility のため-std=c++14を追加した版を追記 20180503
ver. 0.24 N4741 でclang++ -std=c++2aだけ使うスクリプトと、2aを含めた5種類のスクリプトのファイルが1つ、2つ、3つ版 20180507
ver. 0.30 整形台本追記 20180524
ver. 0.31 C++N4910用に -std=C++2b 版作成 追記 20220614
ver. 0.32 上記スクリプト加筆 20220722

最後までおよみいただきありがとうございました。

いいね 💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚 and follow me for your happy life.

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2