Opsi javac untuk mengkompilasi semua file java di bawah direktori yang diberikan secara rekursif

127

Saya menggunakan kompiler javac untuk mengkompilasi file java di proyek saya. File-file tersebut didistribusikan melalui beberapa paket seperti ini: com.vistas.util, com.vistas.converter, com.vistas.LineHelper, com.current.mdcontect.

Masing-masing paket ini memiliki beberapa file java. Saya menggunakan javac seperti ini:

javac com/vistas/util/*.java com/vistas/converter/*.java
      com.vistas.LineHelper/*.java com/current/mdcontect/*.java

(dalam satu baris)

Alih-alih memberikan begitu banyak jalur, bagaimana saya bisa meminta kompiler untuk mengkompilasi secara rekursif semua file java dari direktori com induk?

pengguna496934
sumber
2
Anda harus benar-benar melihat alat-alat seperti Ant atau Maven.
Laurent Pireyn
Posting SO ini mungkin berguna stackoverflow.com/questions/864630/…
Gopi

Jawaban:

220

Saya juga menyarankan menggunakan beberapa jenis alat build ( Ant atau Maven , Ant sudah disarankan dan lebih mudah untuk memulai dengan) atau IDE yang menangani kompilasi (Eclipse menggunakan kompilasi tambahan dengan strategi rekonsiliasi, dan Anda bahkan tidak perlu peduli untuk menekan tombol "Kompilasi" apa saja ).

Menggunakan Javac

Jika Anda perlu mencoba sesuatu untuk proyek yang lebih besar dan tidak memiliki alat build yang tepat di dekatnya, Anda selalu dapat menggunakan trik kecil yang javacmenawarkan: nama-nama class untuk dikompilasi dapat ditentukan dalam file. Anda hanya perlu memberikan nama file javacdengan @awalan.

Jika Anda dapat membuat daftar semua *.javafile di proyek Anda, mudah:

# Linux / MacOS
$ find -name "*.java" > sources.txt
$ javac @sources.txt

:: Windows
> dir /s /B *.java > sources.txt
> javac @sources.txt
  • Keuntungannya adalah solusi yang cepat dan mudah.
  • Kekurangannya adalah Anda harus membuat ulang sources.txtfile setiap kali Anda membuat sumber baru atau mengganti nama file yang sudah ada yang mudah dilupakan (sehingga cenderung rawan kesalahan) dan tugas yang melelahkan.

Menggunakan alat membangun

Dalam jangka panjang lebih baik menggunakan alat yang dirancang untuk membangun perangkat lunak.

Menggunakan Ant

Jika Anda membuat build.xmlfile sederhana yang menjelaskan cara membuat perangkat lunak:

<project default="compile">
    <target name="compile">
        <mkdir dir="bin"/>
        <javac srcdir="src" destdir="bin"/>
    </target>
</project>

Anda dapat mengkompilasi seluruh perangkat lunak dengan menjalankan perintah berikut:

$ ant
  • Keuntungannya adalah Anda menggunakan alat build standar yang mudah diperluas.
  • Kekurangannya adalah Anda harus mengunduh, mengatur, dan mempelajari alat tambahan. Perhatikan bahwa sebagian besar IDE (seperti NetBeans dan Eclipse) menawarkan dukungan besar untuk menulis file build sehingga Anda tidak perlu mengunduh apa pun dalam hal ini.

Menggunakan Maven

Maven tidak sepele untuk mengatur dan bekerja dengan, tetapi belajar itu membayar dengan baik. Berikut tutorial yang bagus untuk memulai proyek dalam 5 menit .

  • Keuntungan utama (bagi saya) adalah bahwa ia menangani dependensi juga, jadi Anda tidak perlu mengunduh file Jar lagi dan mengelolanya dengan tangan dan saya merasa lebih berguna untuk membangun, mengemas, dan menguji proyek yang lebih besar.
  • Kekurangannya adalah bahwa ia memiliki kurva belajar yang curam, dan jika plugin Maven suka menekan kesalahan :-) Hal lain adalah cukup banyak alat yang juga beroperasi dengan repositori Maven (seperti Sbt untuk Scala, Ivy untuk Ant, Graddle for Groovy) .

Menggunakan IDE

Sekarang apa yang bisa meningkatkan produktivitas pengembangan Anda. Ada beberapa alternatif open source (seperti Eclipse dan NetBeans , saya lebih suka yang sebelumnya) dan bahkan yang komersial (seperti IntelliJ ) yang cukup populer dan kuat.

Mereka dapat mengelola bangunan proyek di latar belakang sehingga Anda tidak harus berurusan dengan semua hal-hal baris perintah. Namun, selalu berguna jika Anda tahu apa yang sebenarnya terjadi di latar belakang sehingga Anda dapat memburu kesalahan sesekali seperti a ClassNotFoundException.

Satu catatan tambahan

Untuk proyek yang lebih besar, selalu disarankan untuk menggunakan IDE dan alat build. Yang pertama meningkatkan produktivitas Anda, sedangkan yang kedua memungkinkan untuk menggunakan IDE yang berbeda dengan proyek (misalnya, Maven dapat menghasilkan deskriptor proyek Eclipse dengan mvn eclipse:eclipseperintah sederhana ). Selain itu, memiliki proyek yang dapat diuji / dibangun dengan satu perintah baris mudah untuk diperkenalkan kepada kolega baru dan ke server integrasi berkelanjutan misalnya. Sepotong kue :-)

rlegendi
sumber
4
Saat menggunakan javac, akan lebih baik untuk menentukan direktori keluaran. find -name "*.java" > sources.txt && javac -d bin @sources.txt. Kalau tidak * file .class disimpan ke direktori di mana sumbernya.
Maksim Dmitriev
1
Sepenuhnya benar. Meskipun menurut saya, jika seseorang baru saja mulai bermain-main javac, konsep CLASSPATH, cara menjalankan kode java, cara menangani paket, yang seharusnya menjadi folder root untuk menjalankan, dll. Biasanya tidak jelas. Jadi saya menghilangkan dir output. Bagaimanapun, terima kasih atas sarannya!
rlegendi
6
Untuk pengguna mac yang menemukan ini, findperintahnya adalah: find . -name "*.java" > sources.txt(perhatikan .)
MrDuk
@ MrDuk Apa yang menambahkan "." melakukan? Apakah itu untuk mencari di dalam direktori saat ini?
Brady Sheehan
@ BradySheehan akan mulai mencari dari jalur yang diberikan. "." berarti mulai dari kamus saat ini. Perhatikan bahwa Anda harus menentukan path untuk find (di OS X)
Kris
39
find . -name "*.java" -print | xargs javac 

Agak brutal, tetapi bekerja seperti neraka. (Gunakan hanya pada program kecil, sama sekali tidak efisien)

Matthieu Riegler
sumber
1
Jika Anda menggunakan ini pertimbangkan find ... -print0dan xargs -0 ...bukannya untuk tidak merusak spasi dalam nama file
sapht
29

Jika shell Anda mendukungnya, apakah sesuatu seperti ini berfungsi?

javac com/**/*.java 

Jika shell Anda tidak mendukung **, maka mungkin

javac com/*/*/*.java

berfungsi (untuk semua paket dengan 3 komponen - beradaptasi dengan lebih atau kurang).

dokter hewan
sumber
Saya telah mencoba untuk menggunakan ini di command prompt pada windows 10. Dapatkah seseorang mengkonfirmasi jika ia bekerja pada windows 10 atau jika saya salah melakukannya
Dan
26

Dalam kasus biasa di mana Anda ingin mengkompilasi seluruh proyek Anda, Anda bisa menyediakan javac dengan kelas utama Anda dan membiarkannya mengkompilasi semua dependensi yang diperlukan:

javac -sourcepath . path/to/Main.java

orang aneh
sumber
Metode yang sangat sederhana, tidak bergantung pada file tambahan
linquize
Ini adalah yang terbaik dan paling sederhana untuk orang-orang yang tidak punya banyak waktu untuk belajar Semut (seperti saya)
Hamza Abbad
Sayangnya itu malas. Jika Anda tidak menyentuh Main.java, yang mungkin tidak akan Anda lakukan setelah membuat file kedua, tidak ada lagi yang dapat dikompilasi.
Tom Hawtin - tackline
Tidak bekerja dengan baik di sini. Beberapa dependensi tidak dikompilasi ulang meskipun sedang diubah. @ TomHawtin-tackline Saya mencoba menyentuh sebelumnya pada utama tetapi tidak ada. Mungkin sentuhan pada semua diperlukan. Agak canggung.
mmm
4

javac -cp "jar_path/*" $(find . -name '*.java')

(Saya lebih suka tidak menggunakan xargs karena dapat membaginya dan menjalankan javac beberapa kali, masing-masing dengan subset file java, beberapa di antaranya mungkin mengimpor yang lain yang tidak ditentukan pada baris perintah javac yang sama)

Jika Anda memiliki titik masuk App.java, cara freaker dengan -sourcepath adalah yang terbaik. Itu mengkompilasi setiap file java lain yang dibutuhkan, mengikuti dependensi impor. misalnya:

javac -cp "jar_path/*" -sourcepath src/ src/com/companyname/modulename/App.java

Anda juga dapat menentukan target kelas-berkas dir: -d target/.

Curtis Yallop
sumber
3

Saya menyarankan Anda untuk belajar menggunakan semut , yang sangat cocok untuk tugas ini dan sangat mudah dipahami dan didokumentasikan dengan baik.

Anda hanya perlu mendefinisikan target seperti ini di file build.xml:

<target name="compile">
    <javac srcdir="your/source/directory"
           destdir="your/output/directory"
           classpath="xyz.jar" />
</target>
JB Nizet
sumber
2

Saya hanya menggunakan make dengan makefile sederhana yang terlihat seperti ini:

JAVAC = javac -Xlint:unchecked
sources = $(shell find . -type f -name '*.java')
classes = $(sources:.java=.class)

all : $(classes)

clean :
        rm -f $(classes)

%.class : %.java
        $(JAVAC) $<

Ini mengkompilasi sumber satu per satu dan hanya mengkompilasi ulang jika perlu.

Edward Doolittle
sumber
1

perintah javac tidak mengikuti proses kompilasi rekursif, jadi Anda harus menentukan setiap direktori saat menjalankan perintah, atau memberikan file teks dengan direktori yang ingin Anda sertakan:

javac -classpath "${CLASSPATH}" @java_sources.txt
gvalenncia
sumber
0

Saya telah menggunakan ini dalam proyek Xcode JNI untuk secara rekursif membangun kelas pengujian saya:

find ${PROJECT_DIR} -name "*.java" -print | xargs javac -g -classpath ${BUILT_PRODUCTS_DIR} -d ${BUILT_PRODUCTS_DIR}
bishopthom
sumber