技術討論區 > 程式討論版

如何將 c++ 原始碼變成 shell script 執行 ^__^

頁: (1/1)

Yamaka:

好久以前試過一次,不過沒試出來,今天再拿出來玩,終於弄出來了XD

目標是這樣:編寫好 c/c++ 程式碼之後,不手動跑 make 或是 gcc/g++ 編譯,
而是直接改原始碼的權限為可執行,然後就.....直接執行這個檔,例如:


--- 代碼: ---$ cat ex045.cc

#include <iostream>
 
int main(int argc, char **argv) {
  std::cout << "Hello, World!!\n"
            << argc << "\n" << argv[1] << " " << argv[2]
            << std::endl;
  return 0;
}
--- 程式碼結尾 ---


--- 引用 ---$ chmod +x ex045.cc
$ time ./ex045.cc 123 abc
Hello, World!!
3
123 abc

real   0m0.365s
user   0m0.304s
sys   0m0.048s
--- 引用結尾 ---


沒錯,就是要能夠直接跑 ./ex045.cc,不是編譯後的 ./ex045
中間測試過程就略過不提了,直接貼結果出來


--- 代碼: ---$ cat ex045.cc

//bin/true;CCE=$0;CCE="${CCE##*/}";CCE="/tmp/cc/${CCE%%.*}";[ ! -d "/tmp/cc" ]&&mkdir /tmp/cc/;if [ ! -f ${CCE} ] || [ `date -r $0 +%s` -gt `date -r ${CCE} +%s` ]; then /usr/bin/env clang++ -O3 -std=c++14 -o ${CCE} $0;fi; ${CCE} $@;exit
#include <iostream>
 
int main(int argc, char **argv) {
  std::cout << "Hello, World!!\n"
            << argc << "\n" << argv[1] << " " << argv[2]
            << std::endl;
  return 0;
}

--- 程式碼結尾 ---

跟其他 shell script 一樣,第一行對 c++ 來說是是註解
但卻是一串 bash 指令,這些指令會判斷原始碼與執行檔的檔案時間
必要的話就啟動編譯器編譯進行編譯,執行檔則丟到 /tmp/cc
最後再執行 /tmp/cc 資料夾裡的執行檔
這行最後面的『 exit 』指令是必要的
少了這行,bash 會一直往下讀取指令並執行...

第一次執行會先進行編譯,如果程式碼未修改過
之後再執行就不會編譯(直到 reboot)


--- 引用 ---$ time ./ex045.cc 123 abc
Hello, World!!
3
123 abc

real   0m0.365s
user   0m0.304s
sys   0m0.048s
$ time ./ex045.cc 123 abc
Hello, World!!
3
123 abc

real   0m0.022s
user   0m0.008s
sys   0m0.008s
--- 引用結尾 ---




Yamaka:

鞗改了一下,我把那一大串指令改寫成 .sh 檔放在 /usr/local/bin


--- 代碼: ---$ cat /usr/local/bin/cce.sh
#!/bin/bash
CCE=$1
CCE="${CCE##*/}"
CCE="/tmp/cc/${CCE%%.*}"
[ ! -d "/tmp/cc" ] && mkdir /tmp/cc/
if [ ! -f ${CCE} ] || [ `date -r $1 +%s` -gt `date -r ${CCE} +%s` ]; then
  /usr/bin/env clang++ -O3 -std=c++14 -o ${CCE} $1
fi
shift
#echo ${CCE}
${CCE} $@
--- 程式碼結尾 ---

$ sudo chmod +x /usr/local/bin/cce.sh

c++ 第一行就可以簡潔一點


--- 代碼: ---$ cat ex045.cc
//usr/local/bin/cce.sh $0 $@;exit
#include <iostream>
 
int main(int argc, char **argv) {
  std::cout << "Hello, World!!\n"
            << argc << "\n" << argv[1] << " " << argv[2]
            << std::endl;
  return 0;
}
--- 程式碼結尾 ---

執行效果一樣 ^^

$ time ./ex045.cc 123 abc
Hello, World!!
3
123 abc

real   0m0.026s
user   0m0.008s
sys   0m0.012s




dark:

這是什麼觀念與技術 ?

照貼試了一下

/usr/bin/env: clang++: 沒有此一檔案或目錄



Yamaka:

簡單來說,就是用 shell script 寫的簡易版的 make

檢查 c++ 程式檔對應的執行檔是否存在
並且比對程式檔與執行檔的時間
如果程式檔比較新就重新編譯
然後執行編譯後的執行檔

clang++ 是我用的 c++ 編譯器

dark:

原來如此 ... 了解了


clang++ -O3 -std=c++14 -o ${CCE} $1
改為自己習慣編譯的方式即可



頁: (1/1)

前往完整版本