Java: ฉันจะรวบรวมโครงสร้างไดเร็กทอรีทั้งหมดของโค้ดได้อย่างไร


84

กรณีการใช้งานเป็นเรื่องง่าย ฉันได้รับซอร์สไฟล์ที่สร้างโดยใช้ Eclipse ดังนั้นจึงมีโครงสร้างไดเร็กทอรีแบบลึกซึ่งคลาส Java ใด ๆ สามารถอ้างถึงคลาส Java อื่นในโฟลเดอร์ลูกพี่น้องหรือพาเรนต์เดียวกัน

ฉันจะรวบรวมสิ่งทั้งหมดนี้จากเทอร์มินัลโดยใช้ javac ได้อย่างไร


ด้วยความอยากรู้อยากเห็นคุณใช้ระบบปฏิบัติการใด - Windows, Linux, Mac และอื่น ๆ สิ่งนี้สามารถช่วยตอบคำถามได้
Zach L

1
ฉันไม่ได้รวบรวม java ในบรรทัดคำสั่งในสองสามปี แต่ฉันคิดว่าถ้าคุณเพิ่งส่งไฟล์ที่มี main () ของคุณไปยัง javac มันจะค้นหาไฟล์อื่น ๆ ทั้งหมดที่จำเป็นในการคอมไพล์เนื่องจากการอ้างอิงทั้งหมดของคุณสามารถทำได้ ค้นพบโดยเริ่มจากไฟล์ที่มี main ()
Endophage

คำตอบ:


59

คุณต้องรู้ไดเรกทอรีทั้งหมดหรือสามารถใช้สัญลักษณ์แทน ..

javac dir1/*.java dir2/*.java dir3/dir4/*.java dir3/dir5/*.java dir6/*src/*.java

2
ฉันคิดว่า: เพียงแสดงรายการไฟล์. java ทั้งหมดหลัง javac โดยใช้ชื่อหรือสัญลักษณ์แทน
euphoria83

54
หรือแค่ใช้javac $(find . -name "*.java").
Georg Schölly


41

หากสิ่งที่คุณต้องการทำคือเรียกใช้คลาสหลักของคุณ (โดยไม่ต้องคอมไพล์.javaไฟล์ที่คลาสหลักไม่ได้ขึ้นอยู่กับ) คุณสามารถทำสิ่งต่อไปนี้:

cd <root-package-directory>
javac <complete-path-to-main-class>

หรือ

javac -cp <root-package-directory> <complete-path-to-main-class>

javac จะแก้ไขการอ้างอิงทั้งหมดโดยอัตโนมัติและรวบรวมการอ้างอิงทั้งหมดด้วย


5
นี่เป็นวิธีการทำงานที่ง่ายที่สุด ทำไมคนถึงไม่ชอบ?
Alphaaa

12
อาจเป็นเพราะความเรียบง่ายไม่สนใจข้อเท็จจริงที่ว่างานคอมไพล์จำนวนมากสำหรับไลบรารีหรือรหัสสนับสนุนจะไม่มีวิธีการหลักที่เชื่อมโยงกับการอ้างอิงที่จำเป็นทั้งหมด เป็นคำตอบที่ดี แต่ไม่ใช่คำตอบที่ฉันเคยใช้ใน framework / public codebase
Ajax

4
IMHO กรอบงานหรือโครงการสาธารณะอื่น ๆ ควรใช้การจัดการงานสร้างบางประเภท การรวบรวมแบบนี้เหมาะสมกับโครงการส่วนตัวขนาดเล็กเท่านั้น
svenwltr

@Ajax แต่ถ้าเป็นเช่นนั้นคุณสามารถใช้-sourcepath .ตัวเลือกแล้วตั้งชื่อไฟล์หลักเพื่อให้ได้ผลเช่นเดียวกัน
coderatchet

1
ใครบอกว่ามีหลัก? ใครบอกว่าไม่มีสี่ไฟ? ทุกคลาสที่คุณต้องการในผลลัพธ์ของคุณอ้างอิงโดย main (และไม่ใช้ META-INF / services หรือเทคนิคการโหลดบริการอื่น ๆ ) หากสิ่งที่คุณทำคือการทดสอบหลักวิธีนี้ก็ใช้ได้อย่างไรก็ตามมันล้มเหลวในการจัดการกับงาน "คอมไพล์ไฟล์ java ทั้งหมดในไดเร็กทอรีที่กำหนด" ระบบการสร้างที่เหมาะสมคือ # 1 เครื่องมือ cli เช่นfind . -type f -name "*.java" | xargs javac เป็นหมายเลข 2 และวิธีนี้ก็ต่อเมื่อมีจุดเริ่มต้นของวิธีการหลักเดียวที่ครอบคลุมทั้งแอป
Ajax

12

ฉันจะรับคำแนะนำของจอนและใช้ Ant เพราะนี่เป็นงานที่ค่อนข้างซับซ้อน

อย่างไรก็ตามหากคุณตั้งใจที่จะรับมันทั้งหมดในบรรทัดเดียวใน Terminal บน Linux คุณสามารถใช้คำสั่งfind แต่ผมไม่แนะนำนี้ได้ทั้งหมดเนื่องจากมีการรับประกันว่าการพูด, Foo.java จะถูกรวบรวมหลังจาก Bar.java ไม่มีแม้การใช้งานFoo Barตัวอย่างจะเป็น:

find . -type f -name "*.java" -exec javac {} \;

หากคลาสทั้งหมดของคุณยังไม่ได้รับการคอมไพล์หากมีสายรัดหลักหรือคลาสไดรเวอร์ (โดยทั่วไปคือคลาสที่มีเมธอดหลักของคุณ) การรวบรวมคลาสหลักนั้นทีละคลาสควรรวบรวมโปรเจ็กต์ส่วนใหญ่แม้ว่าจะอยู่ในโฟลเดอร์ที่ต่างกันก็ตาม Javac จะพยายามอย่างสุดความสามารถเพื่อแก้ไขปัญหาการพึ่งพา


1
บน windows สามารถใช้ได้find_gnu . -type f -name "*.java" | xargs javacเมื่อ find.exe เวอร์ชัน gnu ถูกเปลี่ยนชื่อเป็น find_gnu.exe ฉันได้รับ gnu find.exe จาก msysgit
n611x007

หรือใน Windows batch แท้: for /f "usebackq" %f in (``dir /s /b *.java``) do javac %f(ใช้ back-quotes ครั้งเดียวdir /s /bแต่ฉันหาวิธีจัดรูปแบบไม่ถูกต้อง)
Matthieu

ฉันคิดว่าfindวิธีแก้ปัญหาเป็นปัญหาเพราะมันรวบรวม java แต่ละคลาสแยกกันทำให้ช้ามาก
AlikElzin-kilaka

12

ต่อไปนี้เป็นวิธีที่ฉันพบ:

1) สร้างรายการไฟล์ที่มีพา ธ สัมพัทธ์ในไฟล์ (พูดว่า FilesList.txt) ดังนี้ (เว้นวรรคคั่นหรือคั่นบรรทัด):

foo/AccessTestInterface.java
foo/goo/AccessTestInterfaceImpl.java

2) ใช้คำสั่ง:

javac @FilesList.txt -d classes

สิ่งนี้จะรวบรวมไฟล์ทั้งหมดและวางไฟล์คลาสไว้ในไดเร็กทอรีคลาส

วิธีง่ายๆในการสร้าง FilesList.txt คือไปที่ไดเรกทอรีรากต้นทางของคุณ

dir *.java /s /b > FilesList.txt

แต่จะเติมพา ธ สัมบูรณ์ การใช้โปรแกรมแก้ไขข้อความ "Replace All" พา ธ ไปยังไดเร็กทอรีต้นทาง (รวม \ ในตอนท้าย) ด้วย "" (เช่นสตริงว่าง) และบันทึก


นี่เป็นวิธีที่ "ดั้งเดิม" มากกว่าเนื่องจาก javac รองรับไฟล์ "batch"
lovespring

วิธีการ "dir * .java / s / b> FilesList.txt" จะไม่ทำงานหากเส้นทางมีช่องว่าง javac จะบ่นเกี่ยวกับ FilesList.txt
aderesh

10

คำตอบที่มีอยู่แล้วดูเหมือนจะเกี่ยวข้องกับตัวไฟล์ * .java เท่านั้นและไม่ใช่วิธีการง่ายๆกับไฟล์ไลบรารีที่อาจจำเป็นสำหรับการสร้าง

สถานการณ์บรรทัดเดียวที่ดีซึ่งรับไฟล์ * .java ทั้งหมดแบบวนซ้ำรวมถึงไฟล์ * .jar ที่จำเป็นสำหรับการสร้างคือ:

javac -cp ".:lib/*" -d bin $(find ./src/* | grep .java)

ที่นี่ไฟล์ bin เป็นปลายทางของไฟล์คลาส lib (และอาจเป็นไดเร็กทอรีการทำงานปัจจุบัน) มีไฟล์ไลบรารีและไฟล์ java ทั้งหมดในไดเร็กทอรี src และด้านล่างจะถูกคอมไพล์


ฉันมีปัญหาในการรวบรวมซอร์สโค้ดไคลเอนต์ที่สร้างโดย swagger
Eenvincible

9

คุณต้องใช้บางอย่างเช่น Ant เพื่อทำสิ่งนี้ตามลำดับชั้น:

http://ant.apache.org/manual/Tasks/javac.html

คุณจะต้องสร้างสคริปต์การสร้างโดยมีเป้าหมายที่เรียกว่าคอมไพล์ซึ่งประกอบด้วยสิ่งต่อไปนี้

<javac sourcepath="" srcdir="${src}"
         destdir="${build}" >
    <include name="**/*.java"/>
</javac>

จากนั้นคุณจะสามารถรวบรวมไฟล์ทั้งหมดโดยเรียกใช้:

 ant compile

อีกวิธีหนึ่งคืออิมพอร์ตโปรเจ็กต์ของคุณไปยัง Eclipse และจะคอมไพล์ซอร์สไฟล์ทั้งหมดสำหรับโปรเจ็กต์นั้นโดยอัตโนมัติ


น่าเสียดายที่ต้องทำบนเซิร์ฟเวอร์ที่ไม่รองรับมด
euphoria83

2

มีวิธีดำเนินการโดยไม่ต้องใช้อักขระไปป์ซึ่งสะดวกหากคุณกำลังใช้กระบวนการจากภาษาโปรแกรมอื่นเพื่อทำสิ่งนี้:

find $JAVA_SRC_DIR -name '*.java' -exec javac -d $OUTPUT_DIR {} +

แม้ว่าคุณจะอยู่ใน Bash และ / หรือไม่รังเกียจที่จะใช้ไปป์คุณก็สามารถทำได้:

find $JAVA_SRC_DIR -name '*.java' | xargs javac -d $OUTPUT_DIR

2

วิธีแก้ปัญหาของ Windows: สมมติว่าไฟล์ทั้งหมดอยู่ในไดเร็กทอรีย่อย 'src' และคุณต้องการคอมไพล์เป็น 'bin'

for /r src %i in (*.java) do javac %i -sourcepath src -d bin

หาก src มีไฟล์. java อยู่ด้านล่างจะเร็วกว่า

javac src\\*.java -d bin

1
ใช้งานได้ แต่ superslow - javac ถูกเรียกด้วยไฟล์เดียวต่อการโทรเท่านั้นดังนั้นหากคุณมีจำนวนมาก ...
St.Shadow
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.