Bài đăng trên blog đó là khá không chính xác.
Theo như tôi biết thì những thay đổi về C ++ ABI đã được đưa ra với mọi bản phát hành chính của GCC (tức là những thay đổi có thành phần số phiên bản thứ nhất hoặc thứ hai khác nhau).
Không đúng. Các thay đổi C ++ ABI duy nhất được giới thiệu kể từ GCC 3.4 đã tương thích ngược, có nghĩa là C ++ ABI đã ổn định trong gần chín năm.
Để làm cho vấn đề tồi tệ hơn, hầu hết các bản phân phối Linux lớn đều sử dụng ảnh chụp nhanh GCC và / hoặc vá các phiên bản GCC của chúng, khiến bạn hầu như không thể biết chính xác phiên bản GCC nào mà bạn có thể xử lý khi phân phối tệp nhị phân.
Sự khác biệt giữa các phiên bản vá lỗi của bản phân phối của GCC là nhỏ và ABI không thay đổi, ví dụ như Fedora's 4.6.3 20120306 (Red Hat 4.6.3-2) ABI tương thích với các bản phát hành FSF 4.6.x ngược dòng và gần như chắc chắn với bất kỳ 4.6 nào. x từ bất kỳ bản phân phối nào khác.
Trên GNU / Linux, các thư viện thời gian chạy của GCC sử dụng lập phiên bản ký hiệu ELF để dễ dàng kiểm tra các phiên bản ký hiệu mà các đối tượng và thư viện cần và nếu bạn libstdc++.so
cung cấp các ký hiệu đó thì nó sẽ hoạt động, không thành vấn đề nếu đó là một phiên bản vá lỗi hơi khác từ một phiên bản khác của bản phân phối của bạn.
nhưng không có mã C ++ nào (hoặc bất kỳ mã nào sử dụng hỗ trợ thời gian chạy C ++) có thể được liên kết động nếu điều này hoạt động.
Điều này cũng không đúng.
Điều đó nói rằng, liên kết tĩnh đến libstdc++.a
là một lựa chọn cho bạn.
Lý do nó có thể không hoạt động nếu bạn tải động một thư viện (bằng cách sử dụng dlopen
) là các ký hiệu libstdc ++ mà nó phụ thuộc vào có thể không được ứng dụng của bạn cần khi bạn (tĩnh) liên kết nó, vì vậy những ký hiệu đó sẽ không có trong tệp thực thi của bạn. Điều đó có thể được giải quyết bằng cách liên kết động thư viện được chia sẻ với libstdc++.so
(dù sao cũng là điều nên làm nếu tùy thuộc vào nó.) Sự xen kẽ biểu tượng ELF có nghĩa là các biểu tượng có trong tệp thực thi của bạn sẽ được sử dụng bởi thư viện được chia sẻ, nhưng những người khác thì không hiện trong tệp thực thi của bạn sẽ được tìm thấy trong bất kỳ libstdc++.so
tệp nào liên kết đến. Nếu ứng dụng của bạn không sử dụng, dlopen
bạn không cần quan tâm đến điều đó.
Một tùy chọn khác (và tùy chọn tôi thích hơn) là triển khai phiên bản mới hơn libstdc++.so
cùng với ứng dụng của bạn và đảm bảo nó được tìm thấy trước hệ thống mặc định libstdc++.so
, điều này có thể được thực hiện bằng cách buộc trình liên kết động tìm đúng chỗ, hoặc sử dụng $LD_LIBRARY_PATH
biến môi trường khi chạy- thời gian hoặc bằng cách đặt một RPATH
trong tệp thực thi tại thời điểm liên kết. Tôi thích sử dụng hơn RPATH
vì nó không dựa vào môi trường được thiết lập chính xác để ứng dụng hoạt động. Nếu bạn liên kết ứng dụng của mình với '-Wl,-rpath,$ORIGIN'
(lưu ý các dấu nháy đơn để ngăn trình bao cố gắng mở rộng $ORIGIN
) thì tệp thực thi sẽ có một RPATH
trong số $ORIGIN
đó yêu cầu trình liên kết động tìm kiếm các thư viện được chia sẻ trong cùng thư mục với tệp thực thi. Nếu bạn đặt cái mới hơnlibstdc++.so
trong cùng thư mục với tệp thực thi, nó sẽ được tìm thấy tại thời điểm chạy, vấn đề đã được giải quyết. (Một tùy chọn khác là đưa tệp thực thi vào /some/path/bin/
và libstdc ++ mới hơn. Vì vậy, vào /some/path/lib/
và liên kết với '-Wl,-rpath,$ORIGIN/../lib'
hoặc bất kỳ vị trí cố định nào khác liên quan đến tệp thực thi và đặt RPATH liên quan đến $ORIGIN
)
-static-libstdc++
tùy chọn, bạn sẽ chỉ cần sử dụng-static