Tiêu đề được biên dịch trước với GCC


91

Có ai thành công khi nhận được các tiêu đề được biên dịch sẵn khi làm việc với GCC không? Tôi đã không gặp may trong những nỗ lực của mình và tôi chưa thấy nhiều ví dụ điển hình về cách thiết lập nó. Tôi đã thử trên cygwin gcc 3.4.4 và sử dụng 4.0 trên Ubuntu.


Tôi đã thử nó và tôi đã có trường hợp sử dụng tối ưu cho các tiêu đề được biên dịch trước vì nguồn c của tôi là do trình biên dịch tạo ra và không phải do người dùng viết. Sun Studio và đặc biệt là Visual Studio đã cải thiện thời gian xây dựng rất nhiều. Trên gcc, nó thậm chí còn trở nên tồi tệ hơn khi không có tiêu đề được biên dịch trước. Điều này xảy ra với 3.4 không testet với 4.x nhưng tốc độ và gcc là loại trừ lẫn nhau.
Lothar

@Lothar mã là gì? Tôi thấy g ++ nhanh hơn khoảng 10 lần so với các trình biên dịch Visual Studio gần đây, trên một số mã được tạo khuôn mẫu nhiều.
con lợn

Tôi không sử dụng các mẫu trong mã C ++ của mình. Nó chỉ là xử lý ngoại lệ C + + phần mở rộng C ++ đẹp. Ngay cả bây giờ 6 năm sau câu hỏi này VS2010 nhanh hơn rất nhiều. Nhưng trong thời gian chờ đợi, tôi có 16 lõi để tôi có thể sống với nó.
Lothar

Câu trả lời:


58

Tôi chắc chắn đã thành công. Đầu tiên, tôi sử dụng mã sau:


#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;
}

Đây chỉ là một thế giới chào mừng từ Boost Xpressive (xem liên kết bên dưới). Đầu tiên, tôi đã biên dịch với -Htùy chọn trong gcc. Nó hiển thị một danh sách khổng lồ các tiêu đề mà nó đã sử dụng. Sau đó, tôi xem xét các cờ biên dịch mà IDE (mã :: khối) của tôi đang tạo và thấy một cái gì đó như thế này:

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

Vì vậy, tôi đã viết một lệnh để biên dịch tệp Xpressive.hpp với các cờ giống hệt nhau:

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

Tôi đã biên dịch lại mã gốc với -Hvà nhận được kết quả này:

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

Các ! nghĩa là trình biên dịch có thể sử dụng tiêu đề được biên dịch trước. Dấu x có nghĩa là nó không thể sử dụng nó. Sử dụng cờ trình biên dịch thích hợp là rất quan trọng. Tôi đã tháo -H và chạy một số bài kiểm tra tốc độ. Tiêu đề được biên dịch trước đã cải thiện từ 14 giây lên 11 giây. Không tệ nhưng không tuyệt vời.

Lưu ý: Đây là liên kết đến ví dụ: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Tôi không thể làm cho nó hoạt động trong bài đăng.

BTW: Tôi đang sử dụng g ++ sau

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3


20
Thêm -Winvalid-pch sẽ giúp bạn gỡ lỗi nếu và tại sao có điều gì sai trong việc sử dụng PCH.
lefticus

Các tiêu đề biên dịch sẵn "không tệ nhưng không tuyệt vời" rất hữu ích khi bạn có nhiều tiêu đề liên kết lại với nhau, vì vậy chúng sẽ giảm thời gian biên dịch trên dự án rất lớn sử dụng thư viện lớn hoặc nhiều thư viện.
jokoon

4
"không tệ nhưng không tuyệt vời": sử dụng tệp gcc 4.4.7, 136 .cpp tổng kích thước 35,5 Mb, tệp .h 148, tổng kích thước 5,5 Mb, tệp .gch là 48 Mb, bản dựng gỡ lỗi mất 2'20 "(so với 2 '14 "không pch), bản dựng được tối ưu hóa -O2 mất 4'30" (so với 5'33 "không pch) Hiệu ứng sẽ được mong đợi gần các bản dựng gỡ lỗi, nhưng đó chỉ là bản dựng được tối ưu hóa thu lợi nhuận từ biên dịch trước .... Không chắc chắn lý do tại sao. Biên dịch trước là cách ấn tượng hơn trên Windows!
Andreas Vergison

1
(tiếp) Các tệp đầu ra pch / không-pch tương ứng có kích thước byte chính xác cùng kích thước, điều đó tốt. Các thời gian trên dường như thay đổi khi lặp lại các bản dựng, ví dụ -O2 non-pch thay đổi trong khoảng từ 3'45 "đến 5'33", do đó, nó không phải là khoa học chính xác, có lẽ do chạy trong VMware. Dù sao thì, gcc pch trông không có lợi chút nào trong trường hợp của tôi. So sánh nó với cơ sở mã tương tự trên Windows VS2012 (x64, biên dịch luồng đơn): gỡ lỗi 46 "pch, 2'50" không pch, phát hành 2'13 "pch, 5'02" không pch. Và tất nhiên thậm chí nhanh hơn nhiều khi cho phép đa xử lý ...
Andreas Vergison

@AndreasVergison - Bạn đã thử sử dụng -Winvalid-pchđể đảm bảo rằng tiêu đề được biên dịch trước đang được sử dụng đúng cách chưa? Chúng tôi nhận thấy một cải tiến lớn khi sử dụng pch cho các bản dựng gỡ lỗi của chúng tôi, vì vậy, tôi tự hỏi liệu có vấn đề gì với thiết lập của bạn không.
Josh Kelley

52

Trước hết, hãy xem tài liệu tại đây .

Bạn biên dịch tiêu đề giống như bất kỳ tệp nào khác nhưng bạn đặt đầu ra bên trong tệp có hậu tố là .gch.

Vì vậy, ví dụ: nếu bạn biên dịch trước stdafx.h, bạn sẽ có một tiêu đề được biên dịch trước sẽ được tự động tìm kiếm stdafx.h.gchbất kỳ lúc nào bạn đưa vàostdafx.h

Thí dụ:

stdafx.h:

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

a.cpp:

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

Sau đó, biên dịch thành:

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

Quá trình biên dịch của bạn sẽ hoạt động ngay cả khi bạn xóa stdafx.h sau bước 1.


8

Thông số -xcho các tiêu đề được biên dịch trước C ++ -x c++-headerthì không -x c++. Ví dụ sử dụng PCH sau đây.

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.

Tạo PCH như sau:

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

Lệnh pch.h.gchphải nằm trong cùng thư mục với pch.hlệnh để được sử dụng, vì vậy hãy đảm bảo rằng bạn thực hiện lệnh trên từ thư mục ở đâu pch.h.


3
Điều này nên được -c pch.h, không -c pch.cpp?
MM

7

Tôi đã từng quản lý để có được các tiêu đề được biên dịch trước hoạt động dưới gcc một lần trong quá khứ và tôi nhớ lại khi đó tôi cũng gặp sự cố. Điều cần nhớ là gcc sẽ bỏ qua tệp (header.h.gch hoặc tương tự) nếu một số điều kiện nhất định không được đáp ứng, bạn có thể tìm thấy danh sách trong số đó trên trang tài liệu tiêu đề được biên dịch trước của gcc .

Nói chung, cách an toàn nhất là để hệ thống xây dựng của bạn biên dịch tệp .gch ở bước đầu tiên, với các tùy chọn dòng lệnh tương tự và có thể thực thi được như phần còn lại của nguồn. Điều này đảm bảo tệp được cập nhật và không có sự khác biệt nhỏ.

Trước tiên, có lẽ cũng nên làm cho nó hoạt động với một ví dụ có sẵn, chỉ để loại bỏ khả năng các vấn đề của bạn là cụ thể đối với mã nguồn trong dự án của bạn.


7

Gọi gcc giống như cách bạn gọi nó cho tệp nguồn của mình nhưng với tệp tiêu đề.

ví dụ

g++ $(CPPFLAGS) test.h

điều này tạo ra một tệp có tên test.h.gch

Mỗi khi gcc tìm kiếm test.h, đầu tiên nó sẽ tìm test.h.gch và nếu tìm thấy nó, nó sẽ tự động sử dụng.

Có thể tìm thấy thêm thông tin trong Tiêu đề được biên dịch trước của GCC


Tôi đang sử dụng gcc 3.4 và dòng g ++ stdafx.h sẽ không biên dịch, bạn gặp lỗi "g ++: biên dịch tệp tiêu đề được yêu cầu", nhưng điều này sẽ biên dịch, không chắc liệu đó có phải là những gì tôi muốn hay không: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB

1

Đảm bảo -include your_header.h

Đây là cách tôi biên dịch trước và sử dụng bits/stdc++.hbộ sưu tập.

#include <bits/stdc++.h>

Sau đó, tôi xác định vị trí lib bằng cách biên dịch tệp của tôi với -H và xem đầu ra

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

nơi tôi đã thấy

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

Vì vậy, tôi đã tạo một thư mục mới bitsbên trong thư mục hiện tại và sao chép stdc++.htừ đó.

Sau đó tôi chạy

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

cái nào tạo ra bits/stdc++.gch

Thông thường, tôi đã biên dịch mã của mình qua

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

, nhưng tôi đã phải sửa đổi điều đó thành

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

vì nó chỉ được giải quyết với .gchtệp thay vì .hvới -include bits/stdc++.h Đó là chìa khóa cho tôi. Một điều khác cần lưu ý là bạn phải biên dịch *.htệp tiêu đề với các tham số gần giống như khi bạn biên dịch *.cpp. Khi tôi không bao gồm -O3hoặc -pthreadnó bỏ qua *.gchtiêu đề được biên dịch trước.

Để kiểm tra xem mọi thứ có chính xác hay không, bạn có thể đo chênh lệch thời gian thông qua so sánh kết quả của

time g++ sol.cpp ...

hoặc chạy

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

một lần nữa và tìm kiếm các đường dẫn tiêu đề và nếu bây giờ bạn nhận được !trước đường dẫn thư viện, chẳng hạn

! ./bits/stdc++.h.gch
....
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.