2009-02-04 50 views
6

Bất cứ ai có thể giải thích cách biên dịch hoạt động?Quá trình biên dịch

tôi dường như không thể tìm ra biên soạn các công trình như thế nào ..

Để cụ thể hơn, đây là một ví dụ .. Tôi đang cố gắng để viết một số mã trong MSVC++ 6 để tải một trạng thái Lua ..

tôi đã đã:

  • thiết lập các thư mục bổ sung cho thư viện và bao gồm tập tin vào thư mục bên phải
  • sử dụng extern "C" (vì Lua là C chỉ hoặc vì vậy tôi nghe)
  • .210
  • include'd các tập tin tiêu đề đúng

Nhưng tôi vẫn nhận được một số lỗi trong MSVC++ 6 về biểu tượng bên ngoài chưa được giải quyết (đối với các chức năng Lua mà tôi sử dụng). Khi tôi muốn biết cách giải quyết vấn đề này và tiếp tục, tôi nghĩ sẽ tốt hơn nếu tôi hiểu các quy trình cơ bản liên quan, vì vậy bất cứ ai cũng có thể viết một lời giải thích hay cho điều này? Những gì tôi đang tìm cách để biết là quá trình này .. Nó có thể trông như thế này:

Bước 1:

  • Input: Mã Nguồn (s)
  • Quy trình: Phân tích (có lẽ thêm chi tiết ở đây)
  • Output: bất cứ điều gì là đầu ra ở đây ..

Bước 2:

  • Đầu vào: Bất cứ điều gì là đầu ra từ bước 1, cộng với có thể bất cứ điều gì khác là cần thiết (thư viện? DLL? .vì thế? .lib?)
  • Process: bất cứ điều gì được thực hiện với đầu vào
  • Output: bất cứ điều gì là đầu ra

và vân vân ..

Cảm ơn ..

lẽ điều này sẽ giải thích những gì những biểu tượng là, những gì chính xác "liên kết" là, những gì "đối tượng" mã hoặc bất cứ điều gì là ..

Cảm ơn .. Xin lỗi vì đã là một noob ..

P.S. Điều này không phải là ngôn ngữ cụ thể .. Nhưng vui lòng thể hiện nó bằng ngôn ngữ bạn cảm thấy thoải mái nhất .. :)

EDIT: Vì vậy, dù sao, tôi đã có thể giải quyết các lỗi, nó chỉ ra rằng tôi phải tự thêm tệp .lib vào dự án; chỉ cần chỉ định thư mục thư viện (nơi .lib cư trú) trong cài đặt IDE hoặc cài đặt dự án không hoạt động ..

Tuy nhiên, câu trả lời dưới đây đã giúp tôi hiểu rõ hơn về quy trình. Rất cám ơn! .. Nếu bất cứ ai vẫn muốn viết một hướng dẫn kỹ lưỡng, hãy làm ..:)

EDIT: Chỉ để tham khảo thêm, tôi thấy hai bài viết của một tác giả (Mike Diehl) để giải thích điều này khá tốt .. :) Examining the Compilation Process: Part 1 Examining the Compilation Process: Part 2

+0

http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html Tôi thấy điều này ở đâu đó, bằng cách nào đó giải thích nó ở một mức độ nào đó .. – krebstar

Trả lời

10

Từ nguồn đến thực thi nói chung là một quá trình hai giai đoạn cho C và các ngôn ngữ liên quan, mặc dù IDE có thể trình bày điều này như là một quá trình duy nhất.

1/Bạn mã nguồn của bạn và chạy nó thông qua trình biên dịch. Trình biên dịch ở giai đoạn này cần nguồn của bạn và các tệp tiêu đề của các nội dung khác mà bạn sẽ liên kết với (xem bên dưới).

Biên dịch bao gồm chuyển tệp nguồn của bạn thành tệp đối tượng. Các tệp đối tượng có mã được biên dịch của bạn và đủ thông tin để biết những thứ khác mà họ cần, nhưng không phải là nơi để tìm những thứ khác (ví dụ: thư viện LUA).

2/Liên kết, giai đoạn tiếp theo, là kết hợp tất cả các tệp đối tượng của bạn với thư viện để tạo tệp thi hành. Tôi sẽ không bao gồm liên kết động ở đây vì điều đó sẽ làm phức tạp giải thích với ít lợi ích.

Bạn không chỉ cần chỉ định thư mục mà trình liên kết có thể tìm thấy mã khác, bạn cần chỉ định thư viện thực có chứa mã đó. Thực tế là bạn đang nhận được bên ngoài chưa được giải quyết chỉ ra rằng bạn đã không làm điều này.

Ví dụ, hãy xem xét mã C đơn giản hóa sau đây (xx.c) và lệnh.

#include <bob.h> 
int x = bob_fn(7); 

cc -c -o xx.obj xx.c 

Điều này biên dịch xx.c tệp thành xx.obj. bob.h chứa nguyên mẫu cho bob_fn() để quá trình biên dịch thành công. -c chỉ thị trình biên dịch tạo tệp đối tượng thay vì tệp thực thi và -o xx.obj đặt tên tệp đầu ra.

Nhưng thực tế đang cho bob_fn() không phải là trong file header nhưng trong /bob/libs/libbob.so, vì vậy để liên kết, bạn cần một cái gì đó như:

cc -o xx.exe xx.obj -L/bob/libs;/usr/lib -lbob 

Điều này tạo ra xx.exe từ xx.obj, sử dụng thư viện (tìm kiếm trong các đường dẫn đã cho) của biểu mẫu libbob.so (lib và .so được thêm vào bởi trình liên kết thường). Trong ví dụ này, -L đặt đường dẫn tìm kiếm cho thư viện. -l chỉ định thư viện để tìm cách đưa vào tệp thi hành nếu cần. Trình liên kết thường lấy "bob" và tìm tệp thư viện có liên quan đầu tiên trong đường dẫn tìm kiếm được chỉ định bởi -L.

Tệp thư viện thực sự là tập hợp các tệp đối tượng (loại tệp nén chứa nhiều tệp khác, nhưng không nhất thiết phải nén) - khi xuất hiện lần đầu tiên có liên quan của bên ngoài không xác định, tệp đối tượng được sao chép từ thư viện và được thêm vào tệp thực thi giống như tệp xx.obj của bạn. Điều này thường tiếp tục cho đến khi không có thêm bên ngoài chưa được giải quyết. Thư viện 'có liên quan' là sửa đổi văn bản "bob", nó có thể tìm kiếm libbob.a, libbob.dll, libbob.so, bob.a, bob.dll, bob.so và cứ tiếp tục như vậy. Sự liên quan được quyết định bởi chính mối liên kết và phải được ghi lại.

Cách hoạt động phụ thuộc vào trình liên kết nhưng điều này về cơ bản là nó.

1/Tất cả các tệp đối tượng của bạn chứa danh sách các phần tử bên ngoài chưa được giải quyết mà chúng cần phải giải quyết. Trình liên kết đặt tất cả các đối tượng này và sửa các liên kết giữa chúng (giải quyết càng nhiều phần bên ngoài càng tốt).

2/Sau đó, đối với mọi bên ngoài vẫn còn chưa được giải quyết, trình liên kết sẽ kết hợp các tệp thư viện tìm tệp đối tượng có thể đáp ứng liên kết. Nếu nó tìm thấy nó, nó kéo nó vào - điều này có thể dẫn đến các phần bên ngoài chưa được giải quyết thêm khi đối tượng được kéo vào có thể có danh sách các phần tử bên ngoài riêng của nó cần được thỏa mãn.

3/Lặp lại bước 2 cho đến khi không có thêm bên ngoài chưa được giải quyết hoặc không có khả năng giải quyết chúng từ danh sách thư viện (đây là nơi bạn phát triển, vì bạn chưa bao gồm tệp thư viện LUA).

Biến chứng mà tôi đã đề cập trước đó là liên kết động. Đó là nơi bạn liên kết với một nhánh của một thường trình (loại một điểm đánh dấu) chứ không phải là thường trình thực tế, mà sau này được giải quyết tại thời gian tải (khi bạn chạy tệp thực thi). Những thứ như các điều khiển chung của Windows nằm trong các tệp DLL này để chúng có thể thay đổi mà không cần phải liên kết lại các đối tượng vào một tệp thực thi mới.

+0

Wow điều này là tốt .. Tôi chấp nhận điều này như là câu trả lời .. :) BTW, bạn có thể giải thích thêm một chút về cú pháp bạn đã sử dụng không? những gì hiện -lbob đứng trong lệnh thứ hai? – krebstar

+0

Xong, mặc dù các lệnh tôi đã đề cập là các lệnh kiểu UNIX. Nó được thực hiện khác nhau trong IDE MSVC, nơi bạn đặt đường dẫn thư viện và tên thư viện trong hộp thoại cấu hình dự án. – paxdiablo

+0

Không có vấn đề gì, bạn đã khá hữu ích :) Một điều cuối cùng .. Vì vậy, trong môi trường MSVC, các tệp .lib là các thư viện tĩnh phải được bao gồm trong dự án và các tệp .dll là các thư viện động được tải thông qua Lệnh LoadLibrary hoặc tương tự? Đó có phải là sự khác biệt duy nhất giữa hai người không? – krebstar

1

Bạn phải đi vào thiết lập dự án và thêm một thư mục mà bạn có thư viện LUA * .lib ở đâu đó trên tab "linker". Thiết lập được gọi là "bao gồm cả thư viện" hoặc một cái gì đó, xin lỗi tôi không thể nhìn nó lên.

Lý do bạn nhận được "biểu tượng bên ngoài chưa được giải quyết" là do việc biên dịch trong C++ hoạt động theo hai giai đoạn. Đầu tiên, mã được biên dịch, mỗi tệp .cpp trong tệp .obj của chính nó, sau đó "trình liên kết" bắt đầu và nối tất cả các tệp .obj đó vào tệp .exe. File .lib chỉ là một tập tin .obj được gộp lại với nhau để làm cho việc phân phối các thư viện trở nên đơn giản hơn một chút. Vì vậy, bằng cách thêm tất cả "#include" và khai báo extern bạn đã nói với trình biên dịch rằng một nơi nào đó nó sẽ có thể tìm mã với những chữ ký nhưng linker không thể tìm thấy mã đó bởi vì nó không biết nơi những tập tin .lib với thực tế mã được đặt.

Đảm bảo bạn đã đọc REDME của thư viện, thường họ có giải thích khá chi tiết về những gì bạn phải làm để đưa mã vào trong mã của bạn.

+0

Tôi đã thử điều đó nhưng nó không hoạt động . Tôi sẽ đi chải lại tập tin readme một lần nữa .. – krebstar

+0

Thư mục không đủ - bạn cũng cần chỉ định tệp thư viện. – paxdiablo

5

Bước 1 - trình biên dịch:

  • Input: Mã Nguồn tập tin [s]
  • Quy trình: Phân tích mã nguồn và dịch thành mã máy
  • Output: Object file [s], trong đó bao gồm [ s] của:
    • Tên biểu tượng được xác định trong đối tượng này và tệp đối tượng này "xuất"
    • Mã máy được liên kết với ea Biểu tượng ch được định nghĩa trong tệp đối tượng này
    • Tên của các ký hiệu không được xác định trong tệp đối tượng này, nhưng phần mềm trong tệp đối tượng này phụ thuộc và phần mềm đó phải được liên kết sau đó, tức là tên của tệp đối tượng này " nhập khẩu"

bước 2 - Kết nối:

  • Input:
    • Object file [s] từ bước 1
    • Thư viện của các đối tượng khác (ví dụ:từ O/S và phần mềm khác)
  • Process:
    • Đối với mỗi đối tượng mà bạn muốn liên kết
    • Lấy danh sách các biểu tượng mà điều này đối tượng nhập khẩu
    • Tìm các biểu tượng này trong khác thư viện
    • Liên kết các thư viện tương ứng với các tệp đối tượng của bạn
  • Đầu ra: một tệp thực thi, bao gồm mã máy từ tất cả các đối tượng của bạn, cộng với các đối tượng từ các thư viện được nhập (liên kết) đến các đối tượng của bạn.
+0

ChrisW, bạn có biết chính xác người liên kết tìm thấy các biểu tượng trong các thư viện khác không? Liệu nó chỉ tìm kiếm thông qua một tập tin lib được chỉ định, hoặc nó có thể được thực hiện để quét một thư mục và thử tất cả các tập tin lib? Thanks .. – krebstar

+0

Bạn cung cấp cho nó một danh sách rõ ràng các tên tập tin lib (và danh sách các thư mục mà các tập tin lib cụ thể có thể tìm thấy): vì vậy bạn cần xác định/biết tên của các tập tin lib chứa các ký hiệu mà nguồn của bạn phụ thuộc. – ChrisW

+0

Google tìm thấy cho tôi một chương trình mẫu sử dụng Lua: http://www.codeproject.com/KB/library/lua.aspx ... theo mẫu này, tên tệp của tệp thư viện lua là "lua.lib" . – ChrisW

3

Hai bước chính là biên dịch và liên kết.

Biên soạn sẽ lấy các đơn vị biên dịch đơn (các tệp đơn giản là nguồn, với tất cả các tiêu đề mà chúng bao gồm) và tạo các tệp đối tượng. Bây giờ, trong các tệp đối tượng đó, có rất nhiều hàm (và các công cụ khác, như dữ liệu tĩnh) được xác định tại các địa điểm (địa chỉ) cụ thể. Trong bước tiếp theo, liên kết, một chút thông tin bổ sung về các chức năng này cũng cần thiết: tên của chúng. Vì vậy, chúng cũng được lưu trữ. Một tệp đối tượng có thể tham chiếu đến hàm (vì nó muốn gọi chúng khi mã được chạy) thực sự nằm trong các tệp đối tượng khác, nhưng vì chúng ta đang xử lý một tệp đối tượng ở đây, chỉ tham chiếu biểu tượng ('tên' của chúng) những hàm khác được lưu trữ trong tệp đối tượng.

Tiếp theo là liên kết (hãy hạn chế bản thân để liên kết tĩnh tại đây). Liên kết là nơi các tệp đối tượng đã được tạo trong bước đầu tiên (trực tiếp hoặc sau khi chúng được đưa vào nhau thành tệp .lib) được lấy cùng nhau và một tệp thực thi được tạo. Trong bước liên kết, tất cả các tham chiếu tượng trưng từ một tệp đối tượng hoặc một tệp khác được giải quyết (nếu chúng có thể), bằng cách tra cứu tên trong đối tượng chính xác, tìm địa chỉ của hàm và đặt địa chỉ trong đúng vị trí.

Bây giờ, để giải thích điều gì đó về 'C "extern' điều bạn cần:

C không có chức năng quá tải. Một hàm luôn được nhận biết bằng tên của nó. Vì vậy, khi bạn biên dịch mã dưới dạng mã C, chỉ tên thật của hàm được lưu trữ trong tệp đối tượng.

C++, tuy nhiên, có điều gì đó gọi là 'quá tải hàm/phương thức'. Điều này có nghĩa rằng tên của một hàm không còn đủ để xác định nó. Trình biên dịch C++ do đó tạo ra 'tên' cho các hàm bao gồm các nguyên mẫu của hàm (vì tên cộng với nguyên mẫu sẽ nhận dạng duy nhất một hàm). Điều này được gọi là 'mangling tên'.

Đặc tả 'bên ngoài' C '' là cần thiết khi bạn muốn sử dụng thư viện đã được biên dịch dưới dạng mã 'C' (ví dụ, các nhị phân Lua biên dịch trước) từ dự án C++.

Đối với vấn đề chính xác của bạn: nếu nó vẫn không hoạt động, những gợi ý này có thể giúp: * có các nhị phân Lua được biên dịch cùng phiên bản VC++ không? * bạn có thể đơn giản biên dịch Lua cho mình, hoặc trong giải pháp VC của bạn, hoặc là một dự án riêng biệt với mã C++? * bạn có chắc chắn rằng bạn có tất cả những điều "bên ngoài" C "" đúng không?

Các vấn đề liên quan