2012-01-31 10 views
23

Tôi đã đọc về đề xuất mô-đun C++ (latest draft) nhưng tôi không hiểu đầy đủ (những) vấn đề mà nó nhằm mục đích giải quyết.Mô-đun C++ và C++ ABI

Mục đích của nó là cho phép một mô-đun được xây dựng bởi một trình biên dịch sẽ được sử dụng bởi bất kỳ trình biên dịch nào khác (trên cùng một hệ điều hành/kiến ​​trúc)? Đó là, số tiền đề xuất để tiêu chuẩn hóa C++ ABI?

Nếu không, có đề xuất nào khác được coi là tiêu chuẩn hóa C++ ABI và cho phép trình biên dịch tương thích không?

Trả lời

31

Đầu trang được biên dịch trước (PCH) là các tệp đặc biệt mà một số trình biên dịch nhất định có thể tạo cho tệp .cpp. Chúng chính xác là gì: mã nguồn được biên dịch trước. Chúng là mã nguồn đã được cung cấp thông qua trình biên dịch và được xây dựng thành một định dạng phụ thuộc trình biên dịch.

PCH thường được sử dụng để tăng tốc biên dịch. Bạn đặt các tiêu đề thường được sử dụng trong PCH, sau đó chỉ bao gồm PCH. Khi bạn thực hiện #include trên PCH, trình biên dịch của bạn không thực sự thực hiện công việC#include thông thường. Thay vào đó, nó tải các biểu tượng được biên dịch trực tiếp này vào trình biên dịch. Không chạy bộ tiền xử lý C++. Không chạy trình biên dịch C++. Không # bao gồm một triệu tệp khác nhau. Một tệp được tải và các biểu tượng xuất hiện hoàn toàn trực tiếp trong không gian làm việc của trình biên dịch của bạn.

Tôi đề cập đến tất cả những điều đó bởi vì các mô-đun là PCH trong mẫu hoàn hảo hoàn hảo của chúng. PCH về cơ bản là một hack khổng lồ được xây dựng trên một hệ thống không cho phép các mô-đun thực tế. Mục đích của mô-đun là cuối cùng để có thể lấy một tập tin, tạo ra một tập tin mô-đun trình biên dịch cụ thể có chứa các biểu tượng, và sau đó một số tập tin khác tải mô-đun đó khi cần thiết. Các biểu tượng được biên dịch trước, do đó, một lần nữa, không cần phải # bao gồm một loạt các công cụ, chạy một trình biên dịch, vv Mã của bạn nói, import thing.foo, và nó xuất hiện.

Nhìn vào bất kỳ tiêu đề thư viện chuẩn có nguồn gốc STL nào. Lấy ví dụ <map>. Tỷ lệ cược là tốt mà tập tin này hoặc là khổng lồ hoặc có rất nhiều #inclusions của các tập tin khác mà làm cho tập tin kết quả khổng lồ. Đó là rất nhiều phân tích cú pháp C++ phải xảy ra. Nó phải xảy ra cho mỗi tệp .cpp có #include <map> trong đó. Mỗi khi bạn biên dịch một tệp nguồn, trình biên dịch phải biên dịch lại cùng một thứ. Kết thúc. Và kết thúc. Và hơn nữa.

Không <map> thay đổi giữa các bộ sưu tập? Không, nhưng trình biên dịch của bạn không thể biết điều đó. Vì vậy, nó phải tiếp tục biên dịch lại nó.Mỗi khi bạn chạm vào tệp .cpp, tệp phải biên dịch mọi tiêu đề mà tệp .cpp này bao gồm. Mặc dù bạn không chạm vào các tiêu đề hoặc tệp nguồn ảnh hưởng đến các tiêu đề đó.

Tệp PCH là một cách để giải quyết vấn đề này. Nhưng chúng bị hạn chế, bởi vì chúng chỉ là một hack. Bạn chỉ có thể bao gồm một tệp cho mỗi tệp .cpp, vì nó phải là tệp đầu tiên được bao gồm bởi tệp .cpp. Và vì chỉ có một PCH, nếu bạn làm điều gì đó thay đổi PCH (như thêm tiêu đề mới vào nó), bạn phải biên dịch lại mọi thứ trong PCH đó.

Mô-đun cơ bản không liên quan gì đến trình biên dịch chéo ABI (mặc dù có một trong số đó là tốt đẹp và các mô-đun sẽ giúp dễ xác định một mô-đun hơn). Mục đích cơ bản của họ là tăng tốc thời gian biên dịch.

+1

Mục đích cơ bản vượt ra ngoài chỉ tăng tốc thời gian biên dịch .....: D –

10

Mô-đun là những gì Java, C# và nhiều ngôn ngữ hiện đại khác cung cấp. Họ vô cùng giảm thời gian biên dịch đơn giản vì mã trong tiêu đề của ngày hôm nay không phải được phân tích lặp đi lặp lại, mỗi lần nó được bao gồm. Khi bạn nói #include <vector>, nội dung của <vector> sẽ được sao chép vào tệp hiện tại. #include thực sự không có gì khác ngoài việc sao chép và dán.

Trong thế giới mô-đun, bạn chỉ cần nói import std.vector; ví dụ và trình biên dịch tải bảng truy vấn/biểu tượng của mô-đun đó. Tệp mô-đun có định dạng giúp trình biên dịch dễ dàng phân tích cú pháp và sử dụng nó. Nó cũng chỉ được phân tích cú pháp sau khi, khi mô-đun được biên dịch. Sau đó, tệp mô-đun được tạo trình biên dịch chỉ được truy vấn cho thông tin cần thiết.

Vì các tệp mô-đun được tạo bởi trình biên dịch, chúng sẽ được gắn chặt chẽ với biểu diễn bên trong của trình biên dịch mã C++ và sẽ không thể di chuyển được (giống như các tệp .o/.so/.a hiện nay , vì tên mangling vv).

7

Mô-đun trong C++ phải là điều tốt hơn so với các giải pháp ngày nay, nghĩa là khi thư viện bao gồm tệp * .so và tệp * .h với API. Họ phải giải quyết những vấn đề mà ngày nay với # bao gồm, đó là:

  • đòi hỏi macroguards (macro mà ngăn chặn điều đó định nghĩa được cung cấp nhiều lần)
  • là đúng dựa trên văn bản (vì vậy họ có thể bị lừa và Trong các điều kiện bình thường, chúng được tái diễn lại, điều này cũng cho thấy cơ hội nhìn khác nhau trong đơn vị biên dịch khác nhau được liên kết với nhau)
  • không phân biệt giữa các thư viện phụ thuộc chỉ được sử dụng và bắt nguồn từ (đặc biệt là nếu tiêu đề cung cấp hàm nội tuyến mẫu)

Mặc dù những gì Xeo nói, các mô-đun không tồn tại trong Java hoặc C#. Trong thực tế, trong các ngôn ngữ "tải module" dựa trên đó "ok, ở đây bạn có CLASSPATH và tìm kiếm thông qua nó để tìm bất cứ điều gì mô-đun có thể cung cấp các biểu tượng mà các tập tin nguồn thực sự sử dụng". Khai báo "nhập khẩu" trong Java không có "yêu cầu mô-đun" chút nào - giống như "sử dụng" trong C++ ("nhập ns.ns2. *" Trong Java giống như "sử dụng không gian tên ns :: ns2" trong C++) . Tôi không nghĩ rằng một giải pháp như vậy có thể được sử dụng trong C + +. Gần đúng nhất tôi có thể tưởng tượng là các gói trong Vala hoặc các mô-đun trong Tcl (các phiên bản 8.5). Tôi tưởng tượng rằng các mô-đun C++ không thể thực hiện được trên nền tảng, cũng không được nạp động (yêu cầu một bộ nạp mô-đun động C++ chuyên dụng - không phải là không thể, nhưng ngày nay khó xác định). Họ chắc chắn sẽ phụ thuộc vào nền tảng và cũng có thể được cấu hình khi được yêu cầu. Tuy nhiên, một C++ ABI ổn định là thiết thực chỉ cần trong phạm vi của một hệ thống, giống như với C++ ABI bây giờ.