2011-12-27 35 views
12

Tôi cố gắng để liên kết một mô-đun C++ sử dụng GCC, về cơ bản như thế này:Thứ tự liên kết GCC đã thay đổi?

gcc -c hello.c 
g++ -c world.cpp 
gcc -ohello -lstdc++ hello.o world.o 

Lưu ý rằng tôi sử dụng -lstdc++ để liên kết các mô-đun ++ C trong, vì vậy mà tôi có thể sử dụng gcc thay vì g++. Vấn đề là tôi nhận được lỗi:

undefined reference to `operator new(unsigned long)' 

(Giả sử rằng world.cpp chứa ít nhất một cuộc gọi đến new.)

Lỗi này là cố định nếu tôi đặt -lstdc++ ở phần cuối của dòng linker , như thế này:

gcc -ohello hello.o world.o -lstdc++ 

Tôi biết rằng câu hỏi này đã được hỏi nhiều lần ở đây, nhưng tôi có một yêu cầu đặc biệt. Tôi không trực tiếp gọi GCC. Tôi đang sử dụng một hệ thống xây dựng cho một ngôn ngữ lập trình khác (Mercury) đang gọi GCC thay mặt tôi, và tôi không thể dễ dàng thay đổi cách gọi GCC (mặc dù tôi có thể chỉ định các thư viện bổ sung bằng biến môi trường LDFLAGS). Vì vậy, tôi có hai yêu cầu bổ sung:

  • tôi không thể sử dụng g++ liên kết (chỉ gcc) - đó là lý do tại sao tôi đang làm việc -lstdc++ trick ở trên chứ không phải chỉ đơn giản là liên kết với g++).
  • Tôi không nghĩ rằng mình có thể kiểm soát thứ tự của lệnh liên kết - Mercury sẽ đặt các tệp .o trên dòng lệnh sau bất kỳ thư viện nào.

Tôi hiểu lý do cơ bản tại sao đơn đặt hàng lại quan trọng, nhưng điều khiến tôi khó hiểu là tại sao số này lại bị ngắt? Tôi vừa cập nhật lên Ubuntu 11.10/GCC 4.6.1. Tôi đã biên dịch thành công chương trình này trong nhiều năm bằng cách sử dụng chính xác kỹ thuật trên (đặt -lstdc++ trước). Chỉ có bây giờ có lỗi này đi lên. Một chương trình không liên quan của tôi liên kết với OpenGL sử dụng -lgl và điều đó cũng đã phá vỡ khi tôi nâng cấp và tôi phải di chuyển -lgl đến cuối dòng lệnh. Tôi có lẽ sẽ khám phá ra rằng hàng chục chương trình của tôi không còn biên dịch nữa. Tại sao điều này lại thay đổi? Có cái gì đó sai với hệ thống mới của tôi hay là cách nó bây giờ? Lưu ý rằng đây là những thư viện được chia sẻ bình thường, không được liên kết tĩnh.

Tôi có thể làm gì để làm cho GCC quay trở lại theo cách cũ, khi thứ tự thư viện không quan trọng? Có cách nào khác tôi có thể thuyết phục GCC liên kết libstdc++ đúng cách mà không cần di chuyển nó sau các tệp .o trên dòng lệnh không?

Trả lời

12

Nếu Mercury đặt các tệp đối tượng sau thư viện, Mercury bị hỏng. Thư viện thuộc về các tệp đối tượng - luôn luôn. Đôi khi bạn có thể lấy đi thứ tự ngược lại, nhưng không đáng tin cậy. (Thư viện tĩnh phải đi sau khi các tệp đối tượng tham chiếu các ký hiệu trong thư viện tĩnh. Đôi khi, một trình liên kết sẽ lưu ý các ký hiệu được xác định bởi một thư viện được chia sẻ ngay cả khi không sử dụng ký hiệu nào; Nếu thư viện chia sẻ cung cấp ít nhất một biểu tượng.)

+3

Vì vậy, về cơ bản "hồi quy" này chỉ dành cho toàn bộ sự nghiệp phát triển của tôi, tôi đã dựa vào thực tế là "vô tình làm việc" và bây giờ nó đã ngừng hoạt động? Có vẻ như một thay đổi khá lớn - tôi đã đặt các thư viện trước các tệp đối tượng cho phần tốt hơn của một thập kỷ nay vì tôi không biết đây là vấn đề :(Cảm ơn lời khuyên.Có vẻ như vấn đề không phải là Mercury đặt các đối tượng sau thư viện, nhưng có nhiều phụ thuộc phức tạp hơn trong lệnh LDFLAGS của tôi. Tôi đang tiến bộ, vì vậy tôi sẽ cho bạn một dấu tích. Cảm ơn. – mgiuca

+1

Giả thuyết chưa được chứng minh: có thể đã có thay đổi trong 'ld' ảnh hưởng đến bạn. Mục tiêu có thể là tránh tải các thư viện được chia sẻ không sử dụng. Nếu bạn sử dụng các thư viện tĩnh, bạn chỉ nhận được những thứ bạn cần. Nó từng là trường hợp nếu bạn liệt kê một thư viện được chia sẻ trên đường liên kết, nó sẽ được tải trong thời gian chạy, ngay cả khi thư viện không cung cấp bất kỳ biểu tượng nào. Chỉ tải thư viện nếu nó đáp ứng ít nhất một biểu tượng có thể giảm thời gian khởi động cho chương trình. Nhưng nó cũng có nghĩa là nếu biểu tượng chỉ xuất sắc khi thư viện được quét là 'main()', thì thư viện sẽ không được tải. –

+0

Xem nhận xét về '--as-needed' cho phiên bản 2.20 của' ld' trong [NEWS] (http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/src/ld/NEWS? tập tin rev = 1.121 & content-type = text/plain & cvsroot = src & only_with_tag = binutils-binutils-2_22). Xem thêm [manual] (http://sourceware.org/binutils/docs-2.22/ld/Options.html#Options) và '--copy-dt-needed-entries' và' --no-copy- tùy chọn dt-needed-entries'. Giả thuyết _unproven trước đây ít nhất đã được chứng minh, tôi tin. –

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