Ninja: mencampur jalur absolut Depfile dengan jalur relatif manifes merusak pembangunan kembali

Dibuat pada 24 Feb 2017  ·  70Komentar  ·  Sumber: ninja-build/ninja

Panduan ninja memperingatkan terhadap campuran seperti itu, tetapi telah menjadi batasan serius.

Masalahnya adalah orang ingin sistem build mereka memanggil kompiler dengan jalur absolut ke file sumber. Ini menghasilkan keluaran yang lebih baik untuk IDE untuk mencocokkan pesan kesalahan dan merujuk kembali ke file asli. Ini juga dapat memengaruhi jalur yang direkam dalam informasi debug. Namun, ini bertentangan dengan preferensi ninja untuk jalur relatif dalam manifes build.

Berikut adalah skrip yang menunjukkan masalahnya: ninja-bug.bash.txt

Komentar yang paling membantu

Saya benar-benar tidak berpikir solusinya harus "mengatasi ini di semua alat lainnya".

1924 mendemonstrasikan perbaikan kerja lengkap dengan pengujian, berdasarkan pendekatan ninja_workdir . Generator yang menggunakan ini dapat menyelesaikan semua masalah di atas.

Semua 70 komentar

Cc: @nico @chaoren

Selama di CMake, ada diskusi yang relevan di edisi 16675 , edisi 13894 , dan MR 520 .

Sebagai solusinya, Anda dapat mengatur direktori keluaran objek secara eksplisit, bahkan "." atau "..", tetapi jalur absolut juga berfungsi.
ninjatst.bash.txt

@zlolik IIUC Anda menyarankan untuk menempatkan jalur absolut di node grafik manifes build ( build.ninja ). Tentu saja itu berfungsi (dan itulah yang dilakukan CMake dalam build di luar sumber), tetapi maksud saya di sini adalah bahwa Ninja tidak menganjurkan penggunaan jalur absolut, namun IDE mengharuskannya dalam output.

Secara hipotetis juga mungkin bahwa kompiler yang diberikan -c foo.c dapat menghasilkan jalur absolut di Depfile. Jika itu terjadi maka Ninja tidak akan mengenali ketergantungan karena masalah yang sama dilaporkan di sini.

Memperbaiki ini akan mengharuskan Ninja untuk dapat mengenali kapan jalur relatif dan jalur absolut adalah file yang sama dan hanya memiliki satu simpul grafik secara internal, bukan dua. Melakukan ini hanya untuk pemrosesan depfile mungkin sudah cukup, karena masuk akal untuk meminta generator build.ninja untuk memberi nama jalur secara konsisten dalam manifes build.

@bradking Pertama-tama, saya setuju dengan Anda bahwa kami memiliki masalah dengan ninja dan saya hanya menyarankan solusi.
Saya pikir ada 3 masalah terkait:

  1. Logika dengan input jalur absolut/relatif, detail lebih lanjut di #1152 .
  2. Logika untuk memaksa keluaran jalur absolut/relatif. Masalah dengan kompiler - satu-satunya cara untuk mengatakan kepada kompiler bahwa Anda ingin memiliki jalur absolut dalam output adalah menggunakan jalur absolut di baris perintah. Bukan masalah ninja tapi milik kita.
  3. Logika untuk mengurai jalur absolut/relatif Depfile. masalah ini.

Saya menggunakan 2 solusi:

  1. Gunakan awalan $p dan $o di jalur generator build.ninja untuk menyelesaikan 2 masalah pertama. Dalam kasus saya $p dan $o tidak mutlak tetapi relatif dari direktori saat ini di mana generator build.ninja dijalankan.
  2. Gunakan beberapa skrip untuk mengonversi Depfile ke jalur yang kompatibel dengan ninja. Beberapa kompiler bahkan memerlukan panggilan terpisah untuk menghasilkan Depfile. Tapi tidak ada masalah path yang mutlak while.

Untuk referensi, saya telah memulai utas di milis ninja-build dengan solusi yang diusulkan.

Masalah terkait lainnya tentang informasi debug dan cakupan: menggunakan perintah dengan jalur relatif juga membuat file informasi debug dengan jalur relatif. Masalahnya adalah file debug biasanya ditempatkan di sebelah file objek, bukan file sumber, jadi jalur relatif di sana merujuk pada file yang tidak ada.

Ada pembaruan tentang ini? Belum ada tanggapan di utas milis ...

Halo semuanya,

Secara hipotetis juga mungkin bahwa kompiler yang diberikan -c foo.c dapat menghasilkan jalur absolut di Depfile.

File ketergantungan IAR v8 hanya berisi jalur absolut.

Kami mengalami masalah ini saat melakukan build di luar sumber dengan CMake/Ninja/IAR: File yang dihasilkan yang berakhir di direktori biner CMake adalah relatif dalam manifes Ninja, output deps oleh IAR adalah mutlak.

Bagi saya, ini jelas merupakan masalah Ninja: Seharusnya tidak memiliki dua node untuk file yang sama, apa pun yang terjadi.

Saya sudah membaca saran @bradking , tetapi saya tidak begitu mengerti bagian tentang tautan simbolik dan mengapa getcwd() tidak dapat digunakan. Maukah Anda menguraikannya?

Saya tidak begitu mengerti bagian tentang tautan simbolik dan mengapa getcwd() tidak dapat digunakan

@sebknzl masalahnya adalah bahwa jalur absolut yang ditulis ke build.ninja oleh generator mungkin berisi tautan simbolis yang sengaja tidak diselesaikan karena satu dan lain alasan. getcwd() biasanya mengembalikan jalur dengan symlink yang diselesaikan. Jika Ninja menafsirkan jalur relatif dalam manifes build atau depfile relatif terhadap getcwd() maka jalur absolut yang dibuatnya mungkin tidak cocok dengan apa yang digunakan generator manifes build dan kita masih akan berakhir dengan dua node.

ninja_workdir yang saya usulkan di utas yang Anda tautkan pada dasarnya memberi tahu Ninja apa yang digunakan generator sebagai basis untuk jalur relatif. Dalam praktiknya realpath(ninja_workdir) == realpath(getcwd()) harus selalu benar, tetapi itu tidak berarti ninja_workdir == getcwd() . Alternatif lain adalah bagi Ninja untuk realpath semuanya sebelum membuat node, tetapi itu berarti $in tidak akan diperluas ke apa yang dimaksudkan oleh generator.

@jhasse silakan lihat masalah ini dan proposal saya untuk mengatasinya.

Mengapa tidak menghasilkan _build.ninja_ dengan jalur absolut yang dikendalikan oleh CMAKE_NINJA_GENERATOR_OPTION_ ?

yaitu seperti ini, yang berfungsi:

Claus-MBP:build clausklein$ cat build.ninja 

# project dir
p = /Users/clausklein/Downloads
# object dir
o = /Users/clausklein/Downloads/.ninjatst.build

rule cp
  command = cp $in $out

rule cc
  depfile = $out.d
  deps = gcc
  command = cc -I$o -c $in -o $out -MD -MT $out -MF $out.d

# All absolute paths works
build all: phony $o/foo.o

# All absolute paths works
build $o/foo.h: cp $p/foo.h.in
  IN = $p/foo.h.in

# All absolute paths works
build $o/foo.o: cc $p/foo.c || $o/foo.h
  IN = "$p/foo.c"

default all

Claus-MBP:build clausklein$ 

dihasilkan dengan ninjatst.bash.txt

@ClausKlein kami mencoba mengajar CMake untuk menggunakan jalur absolut. Lihat diskusi yang saya tautkan di https://github.com/ninja-build/ninja/issues/1251#issuecomment -282322776. Saya lebih suka tidak menambahkan opsi yang mengatakan "lakukan sesuatu dengan cara berbeda yang memperbaiki beberapa kasus dan merusak yang lain".

Kami sangat membutuhkan fitur Ninja dalam proposal yang saya tautkan di https://github.com/ninja-build/ninja/issues/1251#issuecomment -487618865 untuk memperbaikinya dengan benar.

Baiklah

Kemudian apakah perbaikan ini untuk sistem mesonbuild juga tersedia ;-)

Am 12.03.2020 um 12:56 schrieb Brad King [email protected] :

@ClausKlein https://github.com/ClausKlein kami memang mencoba mengajar CMake untuk menggunakan jalur absolut. Lihat diskusi yang saya tautkan di #1251 (komentar) https://github.com/ninja-build/ninja/issues/1251#issuecomment-282322776 . Saya lebih suka tidak menambahkan opsi yang mengatakan "lakukan sesuatu dengan cara berbeda yang memperbaiki beberapa kasus dan merusak yang lain".

Kami sangat membutuhkan fitur Ninja dalam proposal yang saya tautkan di #1251 (komentar) https://github.com/ninja-build/ninja/issues/1251#issuecomment-487618865 untuk memperbaikinya dengan benar.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub https://github.com/ninja-build/ninja/issues/1251#issuecomment-598146822 , atau berhenti berlangganan https://github.com/notifications/unsubscribe-auth/AAN7QWWEDHMDA45DQVPLOUDRHDEVDANCNFSM4DBNL .

Katakanlah Ninja akan menggunakan ninja_workdir untuk mencocokkan informasi depfile dan kami memiliki situasi di mana ninja_workdir != getcwd() karena symlink. Bagaimana jika kompiler sekarang mencetak jalur absolut dengan menggunakan getcwd() ?

Kompiler tidak boleh menggunakan getcwd() untuk apa pun kecuali hal-hal itu diteruskan sebagai jalur relatif, dalam hal ini generator sistem pembangunan mungkin perlu bertanggung jawab.

Atau kita dapat mempertimbangkan untuk mencoba menormalkan wrt ninja_workdir dan getcwd() .

Nah, kompiler juga tidak boleh mengembalikan jalur absolut di Depfile saat diberikan jalur relatif ;)

@ClausKlein kami mencoba mengajar CMake untuk menggunakan jalur absolut. Lihat diskusi yang saya tautkan di #1251 (komentar). Saya lebih suka tidak menambahkan opsi yang mengatakan "lakukan sesuatu dengan cara berbeda yang memperbaiki beberapa kasus dan merusak yang lain".

Apa yang sebenarnya rusak ketika Anda menggunakan jalur absolut seperti yang disarankan oleh @ClausKlein?

Jika kompiler diberikan jalur absolut, maka depfile yang dihasilkannya memiliki jalur absolut, dan jalur tersebut tidak direkonsiliasi dengan jalur relatif ke header dalam manifes build, misalnya untuk header yang dihasilkan. Lihat tautan ninja-bug.bash.txt di posting pertama saya di bagian atas masalah ini. Ini menunjukkan contoh langkah demi langkah tentang apa yang terjadi dan diekspresikan secara murni dalam istilah Ninja dan tanpa CMake.

Saya sudah membacanya, tetapi mengapa tidak menggunakan https://github.com/ninja-build/ninja/issues/1251#issuecomment -284533599? Hanya karena Ninja "menghalangi" jalan absolut? Jika demikian, ini tentang perubahan dokumentasi?

File build.ninja jauh lebih kecil tanpa mengulang jalur absolut di mana-mana, dan itu membuatnya lebih cepat. Mereka juga terlihat lebih bagus, lebih mudah untuk di-debug, dan lebih sesuai untuk penyelesaian tab dari nama target build di shell. IMO itu adalah rekomendasi yang bagus untuk dibuat oleh Ninja. Ninja hanya membutuhkan sedikit lebih banyak informasi untuk mendamaikan kasus ini, dan itulah yang saya usulkan.

@bradking jalur relatif mungkin tidak selalu pendek:

build jsoncpp@sha/src_lib_json_json_reader.cpp.o: cpp_COMPILER ../../../../../Users/clausklein/Workspace/cpp/jsoncpp/src/lib_json/json_reader.cpp
 DEPFILE = jsoncpp@sha/src_lib_json_json_reader.cpp.o.d
 ARGS = -Ijsoncpp<strong i="7">@sha</strong> -I. -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp/include -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp/dir1 -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp/dir2 -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++17 -O3

contoh saya https://github.com/ninja-build/ninja/issues/1251#issuecomment -597877775 terlihat lebih bagus!

Generator CMake memiliki aturan tentang tidak menggunakan ../ urutan yang meninggalkan pohon build. Dalam build yang sepenuhnya di luar sumber, kami menggunakan jalur absolut ke pohon sumber dan jalur relatif di dalam pohon build. Yang terakhir tidak pernah dimulai di ../ karena mereka berada di bawah pohon build.

Saya tahu, itu dibuat dengan _mesonbuild_ . ;-)

Tapi daripada, mengapa tidak menyangkal generasi menjadi pohon sumber?

Kita bisa memperdebatkan manfaat dari jalur relatif v. absolut selamanya. Ninja tidak boleh berpendapat tentang itu. Masalahnya di sini adalah kasus rekonsiliasi di mana keduanya digunakan dalam satu build. Generator sistem pembangunan tidak selalu dapat mengontrol apa yang akan dilakukan alat dengan jalur. Ninja harus mendukung jalur absolut/relatif campuran ke file yang sama dan dapat melakukannya dengan pendekatan sederhana yang telah saya uraikan dalam proposal saya. Untuk kasus penggunaan yang memotivasi, perubahan diisolasi ke penguraian Depfile.

Ninja harus mendukung jalur absolut/relatif campuran ke file yang sama

Saya setuju!

Terima kasih atas semua penjelasannya, saya mulai mengerti.

Bagaimana jika Ninja akan (setelah menemukan jalur absolut di depfile) melakukan realpath baik cwd maupun jalur yang ditemukannya? Kemudian itu akan menghapus cwd realpathed dari depfile-path realpathed untuk mendapatkan jalur relatif agar cocok dengan header yang dihasilkan. Apakah itu akan berhasil?

getcwd() selalu merupakan jalur nyata sehingga langkah itu tidak diperlukan. Jika Ninja ingin realpath() jalur absolut yang disediakan depfile dan periksa awalan cwd yang bisa berfungsi. Namun, realpath() adalah syscall yang mungkin mahal sementara ninja_workdir yang saya usulkan dapat merekonsiliasi jalur murni di memori melalui pemrosesan string.

Pencampuran ke arah lain juga harus diizinkan: jalur absolut dalam manifes build tetapi jalur relatif di depfile. Saya tidak berpikir Ninja harus realpath() setiap jalur absolut saat mengurai build.ninja . Itu mungkin akan lambat.

Kita bisa menggunakan hasilnya untuk menentukan workdir. Misalnya:

getcwd(): /var/xyz/build
entri Depfile: /home/foo/build/bar.h
realpath(entri depfile): /var/xyz/build/bar.h
realpath relatif: bar.h
hapus itu dari entri Depfile: /home/foo/build -> ninja_workdir

Dengan cara ini kita hanya perlu memanggil realpath sekali.

Saya tidak berpikir bahwa menurunkan ninja_workdir secara otomatis dimungkinkan secara umum. Bagaimana kita tahu berapa banyak komponen logis dari jalur logis yang mengandung symlink asli yang sesuai dengan direktori kerja? Kami mungkin dapat melakukannya dengan mengambil satu komponen pada satu waktu hingga realpath-nya cocok dengan cwd, tetapi itu terasa hacky dan rawan kesalahan. Rasanya berisiko untuk mempercayai symlink pertama yang kebetulan terlihat seperti ini. Kami juga harus menjalankan realpath() di setiap jalur absolut yang kami temui sampai ada yang menyelesaikan dengan cara ini.

Generator buildsystem tahu persis jalur logis apa ke direktori kerja yang digunakannya saat membuat jalur absolut dalam pernyataan build dan baris perintah di build.ninja . Oleh karena itu, ini adalah sumber informasi yang paling dapat diandalkan untuk jalur workdir. Kami hanya perlu cara untuk mengomunikasikan informasi ini ke Ninja, oleh karena itu ninja_workdir yang saya usulkan mengikat.

Saya tidak yakin saya mengerti, maaf. Bisakah Anda memberi contoh di mana logika deteksi saya tidak berfungsi?

Itu bisa rusak jika generator buildsystem menempatkan symlink di dalam build tree (menunjuk ke tempat lain di build tree atau di luar sama sekali):

getcwd(): /var/xyz/build
entri Depfile: /home/foo/build/subdir-link/bar.h
realpath(entri depfile): /var/xyz/build/subdir-real/bar.h
realpath relatif: subdir-real/bar.h
hapus itu dari entri Depfile: ???

CMake tidak melakukan ini tetapi secara umum generator buildsystem bisa.

Bahkan jika kami bersedia mengatakan bahwa tidak didukung, deteksi masih dapat menghadapi:

getcwd(): /var/xyz/build
1000 entri Depfile: /home/foo/ext-lib/bar{1,2,...}.h
1000 realpath(entri depfile): /var/xyz/ext-lib/bar{1,2,...}.h
1000 realpath relatif: tidak ada di bawah cwd

Sekarang bayangkan itu muncul di 1000 sumber 'depfiles dan tidak pernah ada hit. Itu adalah 1 juta panggilan realpath() tanpa kecocokan untuk heuristik ini. Dan itu berulang setiap kali sumber dibangun kembali dan depfile-nya diurai ulang.

symlink di dalam build tree -> ya, kami tidak dapat benar-benar mendukungnya, itu akan menghasilkan semua jenis masalah lain (tanpa realpath-ing di semua tempat).

Contoh kedua terdengar agak artifisial. Biasanya Depfile dimulai dengan dependensi lokal, bukan dengan header sistem.

Jika itu benar-benar menjadi masalah kinerja, kita dapat men-cache workdir di .ninja_deps ?

Dalam build out-of-source, sangat sedikit entri depfile yang bahkan akan mengarah ke pohon build. Ini akan menjadi sangat umum:

getcwd(): /var/xyz/build
1000 entri depfile: /home/foo/project-source/bar{1,2,...}.h
1000 realpath(entri depfile): /var/xyz/project-source/bar{1,2,...}.h
1000 realpath relatif: tidak ada di bawah cwd

Ninja harus memanggil realpath() pada semua itu untuk berjaga-jaga, atau mempertahankan semacam tabel hasil untuk menghindari syscalls yang sebenarnya. Ia tidak dapat mengetahui sebelumnya kapan ia akan menemukan jalur symlink yang memutuskan ke cwd, dan bahkan tidak tahu apakah ia akan menemukannya.

Mengingat bahwa pencampuran jalur absolut dan realtif di depfile saat ini tidak berfungsi, saya tidak melihat bagaimana itu akan menjadi "sangat umum"??

depfile dari formulir dalam contoh saya sudah sangat umum bahkan ketika tidak menggunakan symlink atau jalur campuran. Saya memilikinya di sebagian besar pohon bangunan saya. Ninja tidak dapat mengetahui sebelumnya apakah heuristik diperlukan sehingga ia harus memblokir syscalls realpath() untuk berjaga-jaga.

Mungkin saya salah memahami contoh Anda. Apakah maksud Anda satu depfile dengan 3000 entri atau apakah 3 contoh terpisah itu untuk depfile dengan masing-masing 1000 entri?

Maksud saya 1000 entri depfile tersebar di sejumlah depfile. Bisa jadi satu. Bisa jadi banyak. Mungkin ada 10.000 entri di seluruh proyek. Jalur mereka dapat menunjuk ke mana saja di sistem file dan mungkin atau mungkin tidak pernah benar-benar mengarah ke pohon build.

Bisakah Anda memberikan contoh CMakeLists.txt yang menghasilkan campuran jalur seperti itu (tidak harus 1000, masing-masing hanya satu)?

Sulit untuk ditampilkan dalam file CMakeLists.txt karena CMake saat ini berhati-hati untuk menghindari pencampuran jalur dalam banyak kasus. Namun, ada masalah di pelacak masalah CMake tentang masalah yang tidak dapat diperbaiki tanpa Ninja memperbaikinya terlebih dahulu. Lihat misalnya CMake Issue 13894 . Pengguna ingin dapat memberikan jalur absolut ke kompiler bahkan untuk sumber (dan mungkin menyertakan direktori) di pohon build, atau saat melakukan build in-source. Ini berfungsi baik dengan generator Makefile CMake. Jika kita melakukannya dengan Ninja maka depfiles kembali dengan jalur absolut dan mereka tidak cocok dengan jalur relatif di build.ninja . Mungkin kita bisa beralih ke jalur absolut untuk semuanya, tetapi seperti yang dibahas di atas di sini, kita tidak perlu melakukan itu.

Mungkin Anda dapat mencoba ini untuk tes https://github.com/ClausKlein/build-performance/commit/8013836486e3a459474eb374f6c3da5e20983443

Masalah yang ditampilkan di sini didasarkan pada https://github.com/ninja-build/ninja/issues/1251#issue -210080507
Ini menghasilkan target sebanyak yang Anda inginkan. yaitu 2 subduers masing-masing dengan 2 file sumber:

PWD=/Users/clausklein/Workspace/build-performance/build

rule cp
  command = cp $in $out

rule cc
  depfile = $out.d
  deps = gcc
  command = gcc -c -I$PWD $IN -o $out $FLAGS -MMD -MT $out -MF $out.d

rule link
  command = gcc -o $out $in $LINK_PATH $LINK_LIBRARIES

build foo: phony foo.h
build foo.h: cp foo.h.in

build bin/main0.o: cc /Users/clausklein/Workspace/build-performance/build/subdir0/main.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir0/main.c
build /Users/clausklein/Workspace/build-performance/build/subdir0/file0.o: cc /Users/clausklein/Workspace/build-performance/build/subdir0/file0.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir0/file0.c

build bin/main1.o: cc /Users/clausklein/Workspace/build-performance/build/subdir1/main.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir1/main.c
build /Users/clausklein/Workspace/build-performance/build/subdir1/file0.o: cc /Users/clausklein/Workspace/build-performance/build/subdir1/file0.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir1/file0.c

build bin/main0: link bin/main0.o /Users/clausklein/Workspace/build-performance/build/subdir0/file0.o 
build bin/main1: link bin/main1.o /Users/clausklein/Workspace/build-performance/build/subdir1/file0.o 

build all: phony foo bin/main0 bin/main1 
default all

Ini berfungsi baik dengan generator Makefile CMake.

Bagaimana cara Make menangani masalah symlink?

Bagaimana cara Make menangani masalah symlink?

Generator Makefile saat ini tidak menggunakan depfiles dan melakukan pemindaian perkiraannya sendiri. Itu kemungkinan akan diperbarui sebagai bagian dari menambahkan dukungan modul C++20 ke generator Makefile, di mana interpretasi jalur Depfile harus direkonsiliasi dengan cara yang sama seperti yang diusulkan di sini.

Salah satu pilihan adalah untuk melewati ninja_workdir untuk saat ini dan setidaknya mengajari Ninja untuk mendamaikan jalur campuran dengan asumsi bahwa getcwd() adalah yang teratas. Dengan begitu setidaknya jalur campuran akan berfungsi dalam kasus umum tanpa symlink. Kemudian ninja_workdir dapat ditambahkan untuk mendukung kasus yang lebih kompleks nantinya.

Tolong seseorang memperbaiki ini. Aku sangat kesal karena ini.

Saya menggunakan ARM-GCC dengan CMake dan VSCode. Ketika saya menggunakan build in-source, jalurnya relatif terhadap direktori "build" (bukan direktori root), yang menyebabkan VSCode tidak lagi dapat menyelesaikan jalur, yang berarti, Anda tidak bisa hanya mengklik path di jendela baris perintah, sebagai gantinya, Anda harus mencari sendiri setiap file. Ketika saya menggunakan build out-of-tree CMake, itu merusak "IntelliSense" dari Eclipse dan membuat masalah dengan subproyek CMake. Solusi saya untuk saat ini adalah menggunakan MakeFiles, karena menggunakan Path absolut per default. Tapi Ninja lebih baik, menghasilkan file yang lebih mudah dibaca (rules.ninja...) dan output build pada baris perintah lebih baik. Make memiliki masalah dengan peringatan keluaran pada baris perintah dalam konteks multithreaded, berarti, beberapa peringatan disisipkan. Yang menyebabkan saya membangun satu utas, yang sekali lagi, sangat menjengkelkan.

Tolong seseorang memperbaiki ini. Aku sangat kesal karena ini.

Saya menggunakan ARM-GCC dengan CMake dan VSCode. Saat saya menggunakan build dalam sumber, jalurnya relatif terhadap direktori "build" ...

Ada solusi: pilih direktori build di luar pohon sumber! yaitu _$TMPDIR/..._

Terima kasih ClausKlein, tetapi solusinya adalah pembuatan di luar sumber, tetapi saya memerlukan file di dalam pohon saya, karena direferensikan oleh skrip lain. Ini juga merupakan persyaratan build non-standar.

Solusi saya untuk saat ini adalah, ubah CMake menjadi selalu menggunakan jalur absolut. Saya tidak mengerti mengapa tidak ada opsi untuk ini. Namun, jika orang lain membutuhkan ini, ini adalah patch dari CMake v3.18.1:

@@ -241,7 +241,7 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
   // Add include directory flags.
   std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
     includes, this->GeneratorTarget, language,
-    language == "RC", // full include paths for RC needed by cmcldeps
+    true, // full include paths for RC needed by cmcldeps
     false, config);
   if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
     std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
@@ -1133,8 +1133,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
   const std::string& fileConfig, bool firstForConfig)
 {
   std::string const language = source->GetLanguage();
-  std::string const sourceFileName =
-    language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source);
+  std::string const sourceFileName = source->GetFullPath();
   std::string const objectDir = this->ConvertToNinjaPath(
     cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
              this->GetGlobalGenerator()->ConfigDirectory(config)));

Perhatian , ada tambalan untuk cmake, tetapi lihat https://github.com/ninja-build/ninja/issues/1251

Kami membutuhkan tambalan untuk Ninja!

Dalam komentar terakhir saya, saya menunjukkan tambalan untuk CMake untuk menggunakan jalur absolut alih-alih jalur relatif. Ternyata ini adalah ide yang buruk, karena merusak dependensi header CMake kustom dengan Ninja (misalnya file header yang dihasilkan bergantung pada file .json). Kira masalah ini berasal dari masalah ini di sini, yang saya terlalu bodoh untuk mengerti.

Jika seseorang tertarik, saya sekarang menggunakan Ninja dengan jalur relatif. Saya telah membuat ekstensi untuk VSCode agar dapat mengklik jalur relatif di dalam terminal terintegrasi. perpanjangan

@GrandChris Hebat! Adakah peluang untuk membuatnya berfungsi di tab Output juga?

@weliveindetail Jangan ragu untuk membuat masalah baru di https://github.com/GrandChris/TerminalRelativePath/issues dan jelaskan kasus penggunaan Anda secara detail. Tetapi tab keluaran di VSCode berperilaku berbeda dengan terminal terintegrasi dan saya tidak berpikir ada api untuk memperluas perilaku dalam hal ini.

Ok terima kasih. Akhirnya, jalur relatif yang dapat diklik mungkin harus diselesaikan dalam VSCode atau ekstensi CMake. Akan ping di sisi mereka.

Untuk referensi, ini muncul lagi di CMake Issue 21865 . Ini adalah contoh lain dari kasus di mana tidak mudah (mungkin?) untuk membuat dependensi yang ditemukan depfile menggunakan representasi jalur yang sama persis dengan build.ninja .

1917 menambahkan pengikatan ninja_workdir yang diusulkan di atas sebagai fitur yang berguna sendiri. Setelah digabungkan, saya dapat menindaklanjuti dengan perbaikan untuk masalah ini.

@jhasse Saya ingin menemukan solusi yang dapat diterima untuk memperbaiki hulu ini. ninja_workdir memecahkan masalah. Saya telah memperdebatkan kasus saya di atas. Apa alternatif lain yang Anda sarankan?

Seperti yang telah Anda tunjukkan masalahnya (mencampur jalur absolut depfile dengan jalur relatif manifes merusak pembangunan kembali) adalah dengan desain. Saya pikir kita harus membuat masalah yang lebih spesifik, karena kita telah menyentuh beberapa masalah dalam diskusi (misalnya menghubungkan direktori build).

Untuk dua kasus penggunaan dalam komentar awal, alternatif saya adalah:

Ini menghasilkan keluaran yang lebih baik untuk IDE untuk mencocokkan pesan kesalahan dan merujuk kembali ke file asli.

Perbaiki IDE, atau berikan /FC atau -fabs-path-diagnostics ke kompiler.

Ini juga dapat memengaruhi jalur yang direkam dalam informasi debug.

Ini juga harus diperbaiki oleh kompiler. Saya akan menyarankan untuk melihat -fdebug-prefix-map , tetapi saya tidak yakin apa masalahnya sebenarnya.

Berikut adalah skrip yang menunjukkan masalah: ninja-bug.bash.txt

Tidak juga, itu menunjukkan perilaku Ninja saat ini. Dua masalah

  1. "IDE saya tidak dapat mencocokkan keluaran kompiler dengan file yang benar"
  2. "Saya membutuhkan jalur absolut dalam informasi debug"

perlu penjelasan lebih lanjut. Kalau tidak, ini terlihat seperti masalah XY bagi saya (X menjadi "mencampur jalur absolut dan relatif" dan Y menjadi 1. atau 2.).

Saya benar-benar tidak berpikir solusinya harus "mengatasi ini di semua alat lainnya".

1924 mendemonstrasikan perbaikan kerja lengkap dengan pengujian, berdasarkan pendekatan ninja_workdir . Generator yang menggunakan ini dapat menyelesaikan semua masalah di atas.

Saya juga tidak, karena saya tidak melihatnya sebagai solusi.

Ini BUKAN opsi gcc GNU!

Am 05.03.2021 um 16:58 schrieb Jan Niklas Hasse [email protected] :

Perbaiki IDE, atau berikan /FC https://docs.microsoft.com/de-de/cpp/build/reference/fc-full-path-of-source-code-file-in-diagnostics atau -fabs- path-diagnostics https://reviews.llvm.org/D23816 ke kompiler.

Ini juga dapat memengaruhi jalur yang direkam dalam informasi debug.

Berikut adalah skrip yang menunjukkan masalah: ninja-bug.bash.txt

Tidak juga, itu menunjukkan perilaku Ninja saat ini.

Posting saya yang Anda kutip mengakui bahwa saat ini perilaku yang didokumentasikan.
Tujuan dari masalah ini adalah untuk mempertanyakan desain dengan
mendemonstrasikan kelas kasus penggunaan yang tidak dilayaninya.

Kedua hal tersebut ... (1) ... (2) ... perlu penjelasan lebih lanjut.

Itu hanya dua contoh masalah yang dibuat lebih mudah untuk diselesaikan dengan
melewati jalur absolut ke perkakas. Jalur absolut bukannya tidak masuk akal
hanya karena solusi lain tersedia dalam contoh spesifik seperti itu
masalah (menggunakan fitur khusus dari perkakas yang tersedia dari beberapa vendor).
Jalur absolut membantu memecahkan sebagian besar masalah ini tanpa pembaruan
ke ekosistem lainnya. Seperti yang saya posting sebelumnya :

Kita bisa memperdebatkan manfaat dari jalur relatif v. absolut selamanya. Ninja harus
tidak boleh berpendapat tentang itu. Masalahnya di sini adalah mendamaikan kasus-kasus di mana
keduanya digunakan dalam satu build. Generator buildsystem tidak bisa selalu
mengontrol apa yang akan dilakukan alat dengan jalur.

Dalam sistem pembangunan dunia nyata yang kompleks, mungkin ada sejumlah lapisan yang berubah-ubah
skrip, pembungkus, alat, dll., (dari semua jenis vendor) antara
jalur yang ditulis dalam build.ninja oleh pembuat file build dan jalur sebenarnya
ditemui oleh Ninja di Depfile. Terkadang file yang diberikan dapat direferensikan oleh
depfile dari alat yang tidak secara langsung diberikan jalur dari build.ninja .
Agar Depfiles bekerja di bawah desain Ninja saat ini, seluruh perkakas
stack harus diberi tahu dengan tepat bagaimana generator build.ninja memilih untuk mengekspresikan
jalur tersebut pada pernyataan build, dan memiliki fitur yang mempertahankannya atau mengonversinya
mereka dengan cara yang sama. Hal ini tidak dapat ditundukkan secara umum.

Ninja dapat mengatasi masalah ini dengan sedikit perubahan desain: rekonsiliasi dan
jalur absolut dalam depfile dengan jalur relatif di build.ninja (dan sebaliknya
sebaliknya). Saya tidak meminta untuk merekonsiliasi jalur sewenang-wenang ke file yang sama, hanya untuk
kenali bahwa /path/to/some/file dalam depfile sama dengan some/file di
file build /path/to/build.ninja .

Ada preseden untuk pembaruan desain semacam itu. Ketika Ninja pertama kali dimulai, harapan
adalah bahwa jalur akan selalu ditemui oleh ninja dengan cara yang sama
representasi byte-untuk-byte yang ditulis oleh pembuat file build
build.ninja . Jalankan git blame -M -C -w -- src/util.cc dan lihat sejarahnya
dari CanonicalizePath untuk melihat serangkaian kasus yang ditemui di mana itu
filosofi desain harus santai. Ini adalah kelas lain dari kasus seperti itu.

Masalahnya saya tidak setuju

Ninja tidak boleh berpendapat tentang itu.

di tempat pertama.

Hal ini tidak dapat ditundukkan secara umum.

Jadi apa masalah spesifiknya? Maaf saya agak bingung.

Saya tidak setuju dengan "Ninja seharusnya tidak memiliki pendapat tentang itu" sejak awal....Jadi apa isu spesifiknya?

Ini bukan tentang satu masalah khusus, tetapi tentang seluruh kelas masalah yang jauh lebih mudah diselesaikan dengan jalur absolut. Seharusnya tidak masalah mengapa pengembang ingin meneruskan jalur absolut ke alat mereka, hanya saja mereka ingin menggunakan jalur absolut untuk alasan apa pun yang berlaku untuk kasus khusus mereka. Membangun sistem ada untuk melayani penggunanya, bukan untuk mendikte kebijakan. Ninja seharusnya menjadi bahasa rakitan untuk sistem build, namun tidak memiliki cara untuk mengekspresikan sistem build menggunakan jalur gaya campuran.

Kebijakan Ninja untuk perubahan upstream adalah bahwa masalah harus diselesaikan dengan pembuat file build, dan bukan upstream Ninja, jika masalah tersebut dapat diselesaikan tanpa kehilangan efisiensi . Dalam hal ini, satu-satunya cara untuk menyediakan ninja_workdir -gaya rekonsiliasi tujuan umum dari jalur depfile dari pembuat file build adalah dengan menyuntikkan setelah setiap perintah yang menghasilkan depfile perintah tambahan untuk merevisi jalur di depfile agar sesuai file build sebelum ninja memuatnya. Perintah ekstra itu akan memiliki biaya runtime sendiri yang jauh di atas apa yang dilakukan #1924 (sejumlah kecil pencarian ekstra di dalam memori di dalam proses ninja ). Oleh karena itu, rekonsiliasi tujuan umum lebih efisien untuk disediakan di Ninja hulu, dan juga merupakan kandidat untuk dimasukkan.

Bahkan jika Anda menggunakan jalur absolut untuk semuanya, daripada mencampur jalur absolut dan relatif, ada masalah ergonomis yang mengganggu. Jika pengguna meminta ninja untuk membuat ulang file keluaran tertentu daripada target palsu, misalnya ninja out/my_executable atau ninja out/foo/bar.o , mereka harus ingat untuk melewati jalur absolut, atau ninja akan gagal dengan kesalahan "target tidak dikenal" yang membingungkan. Masalah sebaliknya juga ada: pengguna mungkin meminta ninja untuk membangun kembali jalur absolut saat file build.ninja menggunakan jalur relatif.

Dalam satu alat generator Ninja yang saya pertahankan, saya mengatasi ini dengan meminta setiap pernyataan build menyertakan jalur relatif dan jalur absolutnya yang sesuai sebagai output. Ini berfungsi, tetapi itu benar-benar terasa seperti peretasan untuk mengatasi batasan di Ninja. (Sunting: Juga, jika build.ninja hanya menggunakan jalur relatif dan dengan demikian masih dapat bekerja setelah dipindahkan ke jalur absolut yang berbeda, menambahkan alias jalur absolut akan merusak kemampuan itu.)

Memang, ini bukan masalah yang persis sama dengan depfiles, tetapi ini menyarankan Ninja harus lebih menyadari kesetaraan jalur absolut vs. relatif secara umum.

@comex Terima kasih, itu masalah yang valid. Bisakah Anda membuka masalah baru untuk itu?

Seharusnya tidak masalah mengapa pengembang ingin melewati jalur absolut ke alat mereka [...]

saya tidak setuju.

Dalam kasus ini, satu-satunya cara untuk menyediakan ninja_workdir -gaya rekonsiliasi tujuan umum dari jalur depfile [...]

Mengapa Anda membutuhkan rekonsiliasi ninja_workdir -style sejak awal?

Mengapa Anda membutuhkan rekonsiliasi gaya ninja_workdir sejak awal?

Hal ini memungkinkan pengembang untuk menggunakan jalur relatif di build.ninja sambil tetap menangani jalur absolut yang dihasilkan dalam depfile dengan alat yang tidak mereka kendalikan. Jika tidak, mereka mungkin terpaksa menggunakan jalur absolut di build.ninja untuk mengakomodasi perkakas tersebut dalam kombinasi dengan batasan desain ninja. Proposal saya tidak mencegah penggunaan jalur relatif. Ini memungkinkan lebih banyak penggunaan dari mereka.

Saya telah membuka #1925 untuk menerapkan rekonsiliasi yang sama seperti #1924, tetapi tanpa ikatan ninja_workdir . Itu memisahkan keputusan untuk merekonsiliasi jalur depfile dari keputusan untuk mendukung jalur workdir logis dengan tautan simbolik.

[...] jalur absolut yang dihasilkan di Depfiles dengan perkakas yang tidak mereka kendalikan.

Apakah ada contoh untuk perkakas seperti itu?

Kami tidak mungkin memprediksi perilaku semua perkakas yang digunakan oleh semua orang di dunia. Bahkan untuk perkakas yang kami kendalikan, kami telah membahas beberapa kasus di atas yang mudah diselesaikan dengan jalur absolut, tetapi memerlukan opsi khusus alat dan banyak perhatian untuk diselesaikan dengan jalur relatif. CMake lebih memilih jalur absolut dalam beberapa kasus untuk alasan yang sama. Saya memiliki beberapa laporan bug tentang generator Ninja yang tidak melakukan itu sementara semua generator lain melakukannya. Saya telah beberapa kali menghabiskan berjam-jam melacak masalah dependensi hanya untuk menemukan bahwa itu adalah contoh lain dari jalur depfile yang tidak direkonsiliasi dengan jalur manifes build. Alat tersebut memberikan informasi yang dibutuhkan Ninja untuk menangkap dependensi, tetapi Ninja mengabaikannya.

Posisi Anda muncul sebagai pendapat bahwa jalur relatif secara universal lebih baik. Orang lain memiliki pendapat berbeda bahwa jalur absolut lebih baik dalam beberapa kasus. Saya tidak berpikir itu adalah tempat alat pembangunan untuk menginjili jalur relatif.

Proposal saya menambahkan sedikit infrastruktur ke Ninja. Apa itu sakit? Tidak memilikinya mengeksternalisasi biaya yang jauh lebih besar.

Ya benar sekali!

Dan dengan jalur absolut, cmake mampu menghilangkan kompiler duplikat include paths .
Ini mengurangi waktu pembuatan lagi.

Am 09.03.2021 um 19:20 schrieb Brad King [email protected] :

Saya tidak berpikir itu adalah tempat alat pembangunan untuk menginjili jalur relatif.

Saya mengatur masalah CMake mengenai masalah yang kami hadapi dengan file cpp yang dihasilkan oleh kompiler Cepat Qt dan dan mengaktifkan unity build. Penyelidikan lokal saya menunjukkan bahwa ninja sejauh ini merupakan sistem pembangunan tercepat, tetapi dalam konstelasi ini tidak dapat diandalkan. Sekarang saya menghadapi masalah bagaimana saya dapat menemukan solusi atau membenarkan peningkatan waktu pembuatan.

CMake baru saja mengalami masalah dengan dependensi melingkar yang, hingga saat ini, ditutupi oleh masalah Ninja ini. Jika masalah ini telah diperbaiki, kami akan menemukan masalah CMake lebih cepat.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat