懶人神器
更新
大家注意一下,由于在寫入MANIFEST的時候,Class-Path路徑給的是 ../lib
,即上級目錄的lib。 所以在對拍時如果手動移動了 jar包的位置,需要保證 lib/ 文件夾在存放jar包的上一級目錄下,否則在運行時會報錯 ClassNotFound
(也可以在源碼中直接修改jar包的輸出位置)
一種可能的文件樹如下:
├──src
│ ├─ Archer.jar
│ ├─ Berserker.jar
│ ├─ Caster.jar
| ├─ ....
| └─ Alterego.jar
├──lib
│ ├─ elevator-input-hw3-1.4-jar-with-dependencies.jar
│ └─ timable-output-1.1-raw-jar-with-dependencies.jar
└──your_pat.py
一鍵build:zip -> jar
由于每次互測都要經過重復的操作:
download -> unzip -> compile -> run
本著一懶到底的原則,以及想要進一步熟悉一下shell指令,寫了一個builder的腳本。
自己留著沒意思,就拿出來分享給大家了,慢慢享用。
同時要感謝一下 fmh,過程中幫我解決了許多問題,還有 lqq 以身試法幫我測試~
使用
- pre
- 將所有下載的zip壓縮包(java源文件)放入src文件夾中
- 將本次作業的兩個官方接口(外部jar包)放入lib文件夾中
- 在
2.
中,更改相應的lib文件的絕對路徑
- 保證最后文件目錄樹如下即可:
├──src
│ ├─ Archer.zip
│ ├─ Berserker.zip
│ ├─ Caster.zip
| ├─ ....
| └─ Alterego.zip
├──lib
│ ├─ elevator-input-hw3-1.4-jar-with-dependencies.jar
│ └─ timable-output-1.1-raw-jar-with-dependencies.jar
└──builder.sh
- run
- 運行
builder.sh
- 運行
然后就可以愉快地開始對拍啦
注意如果有player上交的src文件有多個main入口,有可能會出錯。(但同樣的,如果上交文件包含有多個入口,官方評測可能也過不了,這也是為什么rules中規定只能有一個入口)
實現思路
1. 解壓縮并將lib中的外部包導入相應目錄內
easy
2. 將src文件夾下的java編譯為class文件
- 編譯輸出路徑為
player/out/
- 注意
lib
中的 -classpath 為絕對路徑
3. 將*.class打包成jar
- 難點(
坑點) 在于MANIFEST.mf
的寫入- 保證 Main-Class: 帶有相應的包路徑 ,如
elevator3.Main
- 保證 Class-Path: 為相對路徑
- 保證文件后有兩個空行。
- 保證 Main-Class: 帶有相應的包路徑 ,如
- 因此,為滿足上述需求:
- 由于.class為二進制文件,無法直接解析,但out文件夾下的.class文件結構與.java相同,故可以通過
grep
檢索.java
文件,得到Main類包路徑,再對得到的路徑進行標準格式化操作即可。 - 相對路徑:
.
表示當前路徑;..
表示上一目錄的路徑 需要有空行是真的坑,差點自閉···
- 由于.class為二進制文件,無法直接解析,但out文件夾下的.class文件結構與.java相同,故可以通過
源碼
#!/bin/bash# Pre-Condition:
# NOTHING# Attention:
# *.zip will be deleted# Procedure:
# 1. put all *.zip into the src/ folder
# 2. put the external .jar into lib/ folder
# 3. run './builder.sh'
# 4. the jar-files has been generated in the 'out' folder of the corresponding directory, enjoy!# file-tree is as follows:
# dir
# ├──src
# ├──lib
# └──builder.shcd src/
# 1. unzip and copy lib/ to src/
echo unzip start...ls *.zip > temp.txt
sed 's/.zip//g' temp.txt > names.txt # sed 's/src/dst/'
names=`cat names.txt` # attention# echo $names
for name in ${names[@]}
domkdir $nameunzip $name.zip -d $namecp -a ../lib $name
donerm *.txt
rm *.zip
echo unzip successfully...# 2. compile to class
echo complie start...prefix="javac -encoding utf-8 -d out/ @srcpath.txt "
lib="-classpath /C/Users/94831/Desktop/CourseCenter/OO/testShell/lib/elevator-input-hw3-1.4-jar-with-dependencies.jar:/C/Users/94831/Desktop/CourseCenter/OO/testShell/lib/timable-output-1.1-raw-jar-with-dependencies.jar "
command=${prefix}${lib}dirs=`ls`
echo $dirsfor dir in ${dirs[@]}
do# echo $dircd $dirmkdir outfind -name "*.java" > srcpath.txt$command# rm srcpath.txtcd ..
doneecho compile successfully...# 3. pack to jar
echo packing to jar...for dir in ${dirs[@]}
doecho $dircd $dir# write config information to MANIFEST.mfecho -n 'Main-Class: ' > MANIFEST.mfgrep -l "public static void main" . -r | sed s/\\.\\///g | sed s/src\\///g | sed s/\\.java//g | sed s/\\//./g >> MANIFEST.mfsed '2, $d' MANIFEST.mf | tee MANIFEST.mfecho 'Class-Path: ../lib/elevator-input-hw3-1.4-jar-with-dependencies.jar ../lib/timable-output-1.1-raw-jar-with-dependencies.jar' >> MANIFEST.mfecho >> MANIFEST.mfmv MANIFEST.mf outcd outfind -name "*.class" > classpath.txtjar cvfm $dir.jar MANIFEST.mf @classpath.txtcd .. # from outcd .. # from player_dir
doneecho pack successfully...