2012-04-22 29 views
7

liên quan đến đường dẫn sau Với: http://www.archlinux.org/news/libpnglibtiff-rebuilds-move-from-testing/Tại sao tôi nên biên dịch lại toàn bộ chương trình chỉ để cập nhật thư viện?

Có thể ai đó giải thích cho tôi lý do tại sao một chương trình cần được xây dựng lại sau khi một trong những thư viện của nó đã được cập nhật?

Điều đó có ý nghĩa gì khi tệp "chính" không bị thay đổi?

+0

Rất tương tự như http://stackoverflow.com/a/10269818/841108 –

Trả lời

13

Nếu chữ ký của các hàm liên quan không thay đổi, thì "xây dựng lại" chương trình có nghĩa là các tệp đối tượng phải được liên kết lại. Bạn không cần phải biên dịch lại lại.

API là hợp đồng mô tả giao diện cho các chức năng công khai trong thư viện. Khi trình biên dịch tạo ra mã, nó cần biết loại biến nào để truyền cho từng hàm, và theo thứ tự nào. Nó cũng cần phải biết kiểu trả về, vì vậy nó biết kích thước và định dạng của dữ liệu sẽ được trả về từ hàm đó. Khi mã của bạn được biên dịch, địa chỉ của một hàm thư viện có thể được biểu diễn là "bắt đầu của thư viện, cộng với 140 byte". Trình biên dịch không biết địa chỉ tuyệt đối, vì vậy nó chỉ đơn giản chỉ định một offset từ đầu của thư viện.

Nhưng trong phạm vi thư viện, nội dung (có nghĩa là, việc triển khai) của các chức năng có thể thay đổi. Khi điều đó xảy ra, độ dài của mã có thể thay đổi, do đó địa chỉ của các hàm có thể thay đổi. Đó là công việc của trình liên kết để hiểu nơi các điểm vào của mỗi chức năng cư trú, và điền vào các địa chỉ đó vào mã đối tượng để tạo ra tệp thực thi.

Mặt khác, nếu cấu trúc dữ liệu trong thư viện đã thay đổi và thư viện yêu cầu người gọi để quản lý bộ nhớ (một thực tế xấu, nhưng tiếc là phổ biến), sau đó bạn sẽ cần phải biên dịch lại mã để nó có thể giải thích cho những thay đổi. Ví dụ: nếu mã của bạn sử dụng malloc(sizeof(dataStructure)) để cấp phát bộ nhớ cho cấu trúc dữ liệu thư viện được tăng gấp đôi về kích thước, bạn cần phải biên dịch lại mã của mình vì sizeof(dataStructure) sẽ có giá trị lớn hơn.

+0

Nói cách khác, bạn đang nói rằng liên kết lại chỉ cần thiết khi các chức năng của thư viện được cập nhật. Tuy nhiên, trong thực tế, chúng tôi không xây dựng lại thường xuyên Thư viện có liên kết tĩnh hay động không? – kstratis

+1

Thư viện có được liên kết tĩnh hay động không ? Thư viện động được nạp vào thời gian chạy, trong khi các thư viện tĩnh được liên kết vào tệp thực thi vì nó được xây dựng. –

+0

Tôi đã xóa bình luận trước đó của mình và tôi đang viết lại câu hỏi của mình: Đối với những gì bạn nói trong đoạn 3 về các địa chỉ hàm: Giả sử chúng ta có một thư viện với 2 hàm; . Bây giờ tất cả được biên dịch và chạy tốt. Theo gợi ý của bạn nếu tôi đặt một câu lệnh in đơn giản bên trong phương thức đầu tiên thì tôi có phải 'liên kết lại' chương trình của tôi với thư viện vì độ dài mã mới không? Nếu không, hãy giải thích trong trường hợp xây dựng lại trường hợp nào là phù hợp. – kstratis

5

Có hai loại khả năng tương thích: API và ABI.

Tính tương thích API là về các chức năng và cấu trúc dữ liệu mà các chương trình khác có thể dựa vào. Ví dụ, nếu phiên bản 0.1 của libfoo định nghĩa một hàm API gọi là "hello_world()", và phiên bản 0.2 loại bỏ nó, bất kỳ chương trình nào dựa vào "hello_world()" cần cập nhật để làm việc với phiên bản libfoo mới.

Khả năng tương thích ABI là về các giả định về cách các hàm và đặc biệt, cấu trúc dữ liệu được thể hiện trong các tệp nhị phân. Nếu ví dụ libfoo 0,1 cũng xác định cấu trúc dữ liệu recipe với hai trường: "hướng dẫn" và "thành phần" và libfoo 0,2 giới thiệu "phép đo" trước trường "thành phần" thì chương trình dựa trên công thức nấu ăn libfoo 0,1 phải được biên dịch lại vì "hướng dẫn" và các trường "thành phần" có thể sẽ ở các vị trí khác nhau trong phiên bản 0.2 của tệp nhị phân libfoo.so.

+0

Bạn có thể cung cấp ví dụ sau khi cập nhật mà tôi không cần phải xây dựng lại 'chương trình của tôi' không? – kstratis

+0

Giả sử bạn có tính toán mã một giá trị từ chuỗi mã fibonacci thông qua hàm 'int fib (int index)'. Giả sử trong libfoo 0,1 hàm giải quyết vấn đề này đệ quy (ví dụ: 'fib (n) = fib (n-1) + fib (n-2)') và trong libfoo 0.2 các tác giả nhận ra có một giải pháp dạng khép kín và áp dụng nó cho tốc độ tăng tốc và giảm sử dụng bộ nhớ chính. Hành vi của hàm này là "có chức năng" giống hệt nhau. Chữ ký và vị trí của hàm vẫn giữ nguyên. Vì vậy, không cần phải biên dịch lại. – user268396

+0

Tôi đang bối rối ở đây ... @Adam Liss ngụ ý khác! Xin vui lòng đọc bình luận của tôi dưới bài viết của mình. – kstratis

0

"thư viện" là gì?

nếu "thư viện" là chỉ nhị phân (ví dụ: thư viện được liên kết động aka ".dll", ".dylib" hoặc ".so"; hoặc thư viện được liên kết tĩnh aka ".lib" hoặc ".a ") thì không cần biên dịch lại, liên kết lại phải đủ (và thậm chí có thể tránh được trong một số trường hợp đặc biệt)

otoh, thư viện thường không chỉ chứa đối tượng nhị phân - ví dụ như tiêu đề- các tệp có thể bao gồm một số logic trong dòng (hoặc macro) nếu vậy, việc liên kết lại không đủ, và bạn có thể phải biên dịch lại để sử dụng phiên bản mới nhất của thư viện libs

+0

Còn thư viện liên kết tĩnh thì sao? –

+0

@ adam-liss: tốt, với các thư viện được liên kết tĩnh, nhị phân của bạn là khép kín (đối với thư viện), vì vậy nếu bạn không quan tâm đến các sửa lỗi/... trong phiên bản mới của thư viện bạn don ' t phải biên dịch lại/relink. nếu bạn muốn bất kỳ tính năng/sửa lỗi mới nào từ thư viện có hiệu lực trong ứng dụng của bạn, nguyên tắc tương tự sẽ áp dụng: nếu những gì được nhìn thấy trong các thay đổi của tệp tiêu đề (API công khai + một số macro/nội tuyến), bạn phải biên dịch lại; nếu chỉ thực hiện các thay đổi của thư viện, nó là đủ để liên kết lại –

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