Header yang telah dikompilasi dengan GCC

91

Adakah yang berhasil mendapatkan header yang dikompilasi sebelumnya yang bekerja dengan GCC? Saya tidak beruntung dalam upaya saya dan saya belum melihat banyak contoh bagus tentang cara menyiapkannya. Saya sudah mencoba cygwin gcc 3.4.4 dan menggunakan 4.0 di Ubuntu.

Lee Baldwin
sumber
Saya mencobanya dan saya memiliki kasus penggunaan yang optimal untuk header yang telah dikompilasi karena sumber c saya adalah compiler yang dihasilkan dan bukan ditulis oleh pengguna. Sun Studio dan khususnya Visual Studio banyak meningkatkan waktu pembuatan. Pada gcc, keadaan menjadi lebih buruk daripada tanpa header yang telah dikompilasi sebelumnya. Ini dengan 3.4 belum testet dengan 4.x tetapi kecepatan dan gcc sama-sama eksklusif.
Lothar
@Lothar apa kodenya? Saya menemukan g ++ sekitar 10x lebih cepat daripada kompiler Visual Studio baru-baru ini, pada beberapa kode yang sangat template.
babi
Saya tidak menggunakan template dalam kode C ++ saya. Ini hanya penanganan pengecualian C + + ekstensi C ++ yang bagus. Bahkan sekarang 6 tahun setelah pertanyaan ini, VS2010 adalah jauh lebih cepat. Tapi saat ini saya punya 16 core jadi saya bisa hidup dengannya.
Lothar

Jawaban:

59

Saya pasti sukses. Pertama, saya menggunakan kode berikut:


#include <boost/xpressive/xpressive.hpp>
#include <iostream>

using namespace std;
using namespace boost::xpressive;

//A simple regex test
int main()
{
    std::string hello( "hello world!" );

    sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
    smatch what;

    if( regex_match( hello, what, rex ) )
    {
        std::cout << what[0] << '\n'; // whole match
        std::cout << what[1] << '\n'; // first capture
        std::cout << what[2] << '\n'; // second capture
    }
    return 0;
}

Ini hanyalah hello world dari Boost Xpressive (lihat link di bawah). Pertama, saya mengkompilasi dengan -Hopsi di gcc. Itu menunjukkan daftar besar header yang digunakannya. Kemudian, saya melihat bendera kompilasi yang diproduksi oleh IDE (code :: blocks) saya dan melihat sesuatu seperti ini:

g++ -Wall -fexceptions -g -c main.cpp -o obj/Debug/main.o

Jadi saya menulis perintah untuk mengompilasi file Xpressive.hpp dengan flag yang sama persis:

sudo g++ -Wall -fexceptions -g /usr/local/include/boost/xpressive/xpressive.hpp

Saya mengkompilasi kode asli lagi dengan -Hdan mendapatkan keluaran ini:

g ++ -Wall -fexceptions -H -g -c main.cpp -o obj / Debug / main.o
! /usr/local/include/boost/xpressive/xpressive.hpp.gch
main.cpp
. /usr/include/c++/4.4/iostream
.. /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++config.h
.. /usr/include/c++/4.4/ostream
.. /usr/include/c++/4.4/istream
main.cpp

The! berarti kompilator dapat menggunakan header yang telah dikompilasi sebelumnya. Tanda x berarti tidak dapat menggunakannya. Menggunakan flag compiler yang tepat sangatlah penting. Saya melepas -H dan menjalankan beberapa tes kecepatan. Header yang telah dikompilasi mengalami peningkatan dari 14 detik menjadi 11 detik. Tidak buruk tapi tidak bagus.

Catatan: Berikut tautan ke contoh: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Saya tidak bisa membuatnya berfungsi di pos.

BTW: Saya menggunakan g ++ berikut

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Pengguna1
sumber
20
Menambahkan -Winvalid-pch akan membantu Anda men-debug jika dan mengapa terjadi kesalahan dalam penggunaan PCH.
lefticus
Header prakompilasi "not bad but not great" berguna jika Anda memiliki banyak header yang saling ditautkan, sehingga akan mengurangi waktu kompilasi pada project yang sangat besar yang menggunakan library besar atau banyak library.
jokoon
4
"tidak buruk tapi tidak hebat": menggunakan gcc 4.4.7, 136 file .cpp ukuran total 35,5 Mb, 148 .h file ukuran total 5,5 Mb, file .gch 48 Mb, Debug build membutuhkan 2'20 "(vs 2 '14 "non-pch), -O2 build yang dioptimalkan membutuhkan waktu 4'30" (vs 5'33 "non-pch) Efeknya diharapkan mendekati build debug, tetapi itu hanya build yang dioptimalkan yang mendapatkan keuntungan dari prakompilasi .... Tidak yakin kenapa. Prekompilasi jauh lebih dramatis di Windows!
Andreas Vergison
1
(lanjutan) File output pch / non-pch yang sesuai memiliki ukuran byte yang persis sama, itu bagus. Pengaturan waktu di atas tampaknya berbeda saat mengulang build, misalnya -O2 non-pch bervariasi antara 3'45 "dan 5'33", jadi ini bukan ilmu pasti, mungkin karena dijalankan di VMware. Bagaimanapun, gcc pch tidak terlihat bermanfaat sama sekali dalam kasus saya. Bandingkan dengan basis kode yang sama pada Windows VS2012 (x64, kompilasi ulir tunggal): debug 46 "pch, 2'50" non-pch, rilis 2'13 "pch, 5'02" non-pch. Dan tentu saja lebih cepat lagi saat mengaktifkan multi-prosesor ...
Andreas Vergison
@AndreasVergison - Sudahkah Anda mencoba menggunakan -Winvalid-pchuntuk memastikan bahwa tajuk yang dikompilasi sebelumnya digunakan dengan benar? Kami melihat peningkatan besar menggunakan pch untuk debug build kami, jadi saya ingin tahu apakah ada masalah dengan penyiapan Anda.
Josh Kelley
52

Pertama, lihat dokumentasi di sini .

Anda mengkompilasi header seperti file lainnya tetapi Anda meletakkan output di dalam file dengan akhiran .gch.

Jadi misalnya jika Anda mengkompilasi stdafx.h Anda akan memiliki header yang telah dikompilasi yang akan secara otomatis dicari dipanggil stdafx.h.gchkapan saja Anda menyertakanstdafx.h

Contoh:

stdafx.h:

#include <string>
#include <stdio.h>

a.cpp:

#include "stdafx.h"
int main(int argc, char**argv)
{
  std::string s = "Hi";
  return 0;
}

Kemudian kompilasi sebagai:

> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out

Kompilasi Anda akan berfungsi meskipun Anda menghapus stdafx.h setelah langkah 1.

Brian R. Bondy
sumber
8

The -xspecifier untuk C ++ dikompilasi header adalah -x c++-header, tidak -x c++. Contoh penggunaan PCH berikut.

pch.h:

// Put your common include files here: Boost, STL as well as your project's headers.

main.cpp:

#include "pch.h"
// Use the PCH here.

Hasilkan PCH seperti ini:

$ g++ -x c++-header -o pch.h.gch -c pch.h

The pch.h.gchharus dalam direktori yang sama seperti pch.hagar dapat digunakan, jadi pastikan bahwa Anda menjalankan perintah di atas dari direktori mana pch.hadalah.

psaghelyi.dll
sumber
3
Ini seharusnya -c pch.h, bukan -c pch.cpp?
MM
7

Saya telah berhasil mendapatkan header yang telah dikompilasi yang bekerja di bawah gcc sekali di masa lalu, dan saya ingat mengalami masalah saat itu juga. Hal yang perlu diingat adalah bahwa gcc akan mengabaikan file (header.h.gch atau serupa) jika kondisi tertentu tidak terpenuhi, daftarnya dapat ditemukan di halaman dokumentasi header yang dikompilasi gcc .

Umumnya, yang paling aman adalah membuat sistem build Anda mengompilasi file .gch sebagai langkah pertama, dengan opsi baris perintah yang sama dan dapat dieksekusi seperti sumber Anda lainnya. Ini memastikan file tersebut mutakhir dan tidak ada perbedaan halus.

Mungkin juga ide bagus untuk membuatnya bekerja dengan contoh yang dibuat-buat terlebih dahulu, hanya untuk menghilangkan kemungkinan bahwa masalah Anda spesifik untuk kode sumber dalam proyek Anda.

Paul
sumber
7

Panggil gcc dengan cara yang sama seperti Anda memanggilnya untuk file sumber Anda tetapi dengan file header.

misalnya

g++ $(CPPFLAGS) test.h

ini menghasilkan file bernama test.h.gch

Setiap kali gcc mencari test.h, gcc mencari test.h.gch terlebih dahulu dan jika menemukannya, ia akan menggunakannya secara otomatis.

Informasi lebih lanjut dapat ditemukan di bawah GCC Precompiled Headers

simon
sumber
Saya menggunakan gcc 3.4 dan baris g ++ stdafx.h tidak akan dikompilasi, Anda mendapatkan kesalahan "g ++: kompilasi file header diminta", tetapi ini akan dikompilasi, meskipun tidak yakin apakah itu yang saya inginkan: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB
1

Pastikan untuk -include your_header.h

Beginilah cara saya menyusun dan menggunakan bits/stdc++.hkoleksi.

Kode

#include <bits/stdc++.h>

Kemudian saya menemukan lib dengan mengkompilasi file saya dengan -H dan melihat output

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

dimana saya melihat

. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h

Jadi saya membuat direktori baru bitsdi dalam direktori saat ini dan menyalin stdc++.hdari sana.

Lalu aku lari

g++ bits/stdc++.h -O3 -std=c++14  -pthread

yang dihasilkan bits/stdc++.gch

Biasanya saya mengumpulkan kode saya melalui

g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable

, tapi saya harus memodifikasinya menjadi

g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable

karena hanya memutuskan untuk .gchmengajukan, bukan .hdengan -include bits/stdc++.h Itu adalah kunci bagi saya. Hal lain yang perlu diingat adalah Anda harus mengkompilasi *.hfile header dengan parameter yang hampir sama dengan yang Anda kompilasi *.cpp. Ketika saya tidak menyertakan -O3atau -pthreadmengabaikan *.gchheader yang telah dikompilasi sebelumnya.

Untuk memeriksa apakah semuanya benar Anda dapat mengukur perbedaan waktu dengan membandingkan hasil

time g++ sol.cpp ...

atau lari

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

lagi dan cari jalur header dan jika Anda sekarang mendapatkan !sebelum jalur perpustakaan, misalnya

! ./bits/stdc++.h.gch
....
Íhor Mé
sumber