酷!學園

技術討論區 => 程式討論版 => 主題作者是: Yamaka 於 2015-09-08 14:21

主題: 如何將 c++ 原始碼變成 shell script 執行 ^__^
作者: Yamaka2015-09-08 14:21
好久以前試過一次,不過沒試出來,今天再拿出來玩,終於弄出來了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


主題: Re: 如何將 c++ 原始碼變成 shell script 執行 ^__^
作者: Yamaka2015-09-08 14:37
鞗改了一下,我把那一大串指令改寫成 .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


主題: Re: 如何將 c++ 原始碼變成 shell script 執行 ^__^
作者: dark2016-10-11 01:28
這是什麼觀念與技術 ?

照貼試了一下

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

主題: Re: 如何將 c++ 原始碼變成 shell script 執行 ^__^
作者: Yamaka2016-10-11 13:14
簡單來說,就是用 shell script 寫的簡易版的 make

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

clang++ 是我用的 c++ 編譯器
主題: Re: 如何將 c++ 原始碼變成 shell script 執行 ^__^
作者: dark2016-10-11 16:13
原來如此 ... 了解了


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