[ 懶人神器 ] —— OO一鍵build:.zip -> .jar

懶人神器


更新

你們注意一下,因爲在寫入MANIFEST的時候,Class-Path路徑給的是 ../lib ,即上級目錄的lib。 因此在對拍時若是手動移動了 jar包的位置,須要保證 lib/ 文件夾在存放jar包的上一級目錄下,不然在運行時會報錯 ClassNotFoundjava

(也能夠在源碼中直接修改jar包的輸出位置)git

一種可能的文件樹以下:github

├──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
因爲每次互測都要通過重複的操做:shell

download -> unzip -> compile -> runbash

本着一懶到底的原則,以及想要進一步熟悉一下shell指令,寫了一個builder的腳本。測試

本身留着沒意思,就拿出來分享給你們了,慢慢享用。ui

同時要感謝一下 fmh,過程當中幫我解決了許多問題,還有 lqq 以身試法幫我測試~spa

使用

  • 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
  • 而後就能夠愉快地開始對拍啦code

  • 注意若是有player上交的src文件有多個main入口,有可能會出錯。(但一樣的,若是上交文件包含有多個入口,官方評測可能也過不了,這也是爲何rules中規定只能有一個入口)orm

實現思路

1. 解壓縮並將lib中的外部包導入相應目錄內

easy

2. 將src文件夾下的java編譯爲class文件

  • 編譯輸出路徑爲player/out/
  • 注意 lib中的 -classpath 爲絕對路徑

3. 將*.class打包成jar

  • 難點(坑點) 在於MANIFEST.mf 的寫入
    1. 保證 Main-Class: 帶有相應的包路徑 ,如 elevator3.Main
    2. 保證 Class-Path: 爲相對路徑
    3. 保證文件後有兩個空行。
  • 所以,爲知足上述需求:
    • 因爲.class爲二進制文件,沒法直接解析,但out文件夾下的.class文件結構與.java相同,故能夠經過grep檢索.java文件,獲得Main類包路徑,再對獲得的路徑進行標準格式化操做便可。
    • 相對路徑: .表示當前路徑;..表示上一目錄的路徑
    • 須要有空行是真的坑,差點自閉···

源碼

#!/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.sh

cd 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[@]}
do
    mkdir $name
    unzip $name.zip -d $name
    cp -a ../lib $name
done

rm *.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 $dirs

for dir in ${dirs[@]}
do
    # echo $dir
    cd $dir
    mkdir out
    find -name "*.java" > srcpath.txt
    $command
    # rm srcpath.txt
    cd ..
done

echo compile successfully...


# 3. pack to jar
echo packing to jar...

for dir in ${dirs[@]}
do
    echo $dir
    cd $dir
    # write config information to MANIFEST.mf
    echo -n 'Main-Class: ' > MANIFEST.mf
    grep -l "public static void main" . -r | sed s/\\.\\///g | sed s/src\\///g | sed s/\\.java//g | sed s/\\//./g >> MANIFEST.mf
    sed '2, $d' MANIFEST.mf | tee MANIFEST.mf
    echo 'Class-Path: ../lib/elevator-input-hw3-1.4-jar-with-dependencies.jar ../lib/timable-output-1.1-raw-jar-with-dependencies.jar' >> MANIFEST.mf
    echo >> MANIFEST.mf
    mv MANIFEST.mf out

    cd out
    find -name "*.class" > classpath.txt
    jar cvfm $dir.jar MANIFEST.mf @classpath.txt
    cd ..   # from out
    cd ..   # from player_dir
done

echo pack successfully...

若有問題,歡迎留言交流!

相關文章
相關標籤/搜索