2014-12-04 23 views
10

Tôi đang gặp sự cố khi liên kết với thư viện Haskell mà chúng tôi đã viết. Nó đi sai trên Ubuntu, nhưng không phải trên Arch Linux. Các lỗi trên Ubuntu chúng tôi nhận được là điều này:Haskell liên kết với thư viện động trên Ubuntu

/usr/bin/ld: warning: libHSdeepseq-1.3.0.0-ghc7.4.1.so, needed by /usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so, not found (try using -rpath or -rpath-link) /usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so: undefined reference to 'deepseqzm1zi3zi0zi0_ControlziDeepSeq_zdfNFDataArrayzuzdcrnf1_info'

Vấn đề này dường như được gây ra bởi thực tế là libHScontainers-0.4.2.1-ghc7.4.1.so được liên kết không đúng như người ta có thể nhìn thấy bằng cách đầu ra của ldd: ldd /usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so linux-vdso.so.1 => (0x00007fffe95a2000) libHSdeepseq-1.3.0.0-ghc7.4.1.so => not found libHSbase-4.5.0.0-ghc7.4.1.so => not found libHSghc-prim-0.2.0.0-ghc7.4.1.so => not found libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f89a5a59000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f89a569a000) /lib64/ld-linux-x86-64.so.2 (0x00007f89a5fd8000)

Rõ ràng không thể tìm thấy thư viện phụ thuộc. Chúng được cài đặt. Tuy nhiên nếu tôi làm như vậy trên Arch: ldd /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/libHSdeepseq-1.3.0.2-ghc7.8.3.so linux-vdso.so.1 (0x00007fff09dfe000) libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007fb8d3e96000) libm.so.6 => /usr/lib/libm.so.6 (0x00007fb8d3b91000) librt.so.1 => /usr/lib/librt.so.1 (0x00007fb8d3988000) libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fb8d3784000) libffi.so.6 => /usr/lib/libffi.so.6 (0x00007fb8d357b000) libHSarray-0.5.0.0-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../array-0.5.0.0/libHSarray-0.5.0.0-ghc7.8.3.so (0x00007fb8d32e1000) libHSbase-4.7.0.1-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../base-4.7.0.1/libHSbase-4.7.0.1-ghc7.8.3.so (0x00007fb8d2967000) libHSinteger-gmp-0.5.1.0-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../integer-gmp-0.5.1.0/libHSinteger-gmp-0.5.1.0-ghc7.8.3.so (0x00007fb8d274c000) libHSghc-prim-0.3.1.0-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../ghc-prim-0.3.1.0/libHSghc-prim-0.3.1.0-ghc7.8.3.so (0x00007fb8d24cf000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fb8d212c000) libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fb8d1f10000) /usr/lib64/ld-linux-x86-64.so.2 (0x00007fb8d435f000)

Các thư viện được tìm thấy.

Như được đề xuất, tôi có thể giải quyết vấn đề này trên Ubuntu bằng cách sử dụng -rpath trong ứng dụng mà chúng tôi cố gắng liên kết với thư viện Haskell. Nhưng điều này có nghĩa là chúng ta phải làm điều này cho mỗi gói Haskell có vẻ như sai với tôi. Chúng tôi cũng có thể sửa lỗi này bằng cách thêm một dòng vào /etc/ld.so.conf.d/ghc.conf. Nhưng điều này cũng phải được thực hiện cho mọi gói và không thân thiện với người dùng.

Một vài câu hỏi tôi có:

  • cách chính xác để khắc phục điều này là gì?
  • Tại sao các gói trong số ghc-dynamic được liên kết không chính xác?
  • Tại sao người liên kết có thể tìm thấy libHScontainers-0.4.2.1-ghc7.4.1.so nhưng không phải là libHSdeepseq-1.3.0.0-ghc7.4.1.so?
+0

Bạn đã cài đặt một số thư viện ghc qua 'apt-get' và các thư viện khác thông qua 'cabal install' chưa? – Zeta

+0

Không, tôi chỉ cài đặt ghc-dynamic. Không có gói nào được cài đặt với cài đặt cabal. – meijuh

Trả lời

1

tôi rất nghi ngờ rằng điều này là bởi vì các thư viện Haskell cài đặt bởi GHC có những vị trí phụ thuộc của họ (các RPATH lĩnh vực tiêu đề ELF của họ, bạn có thể xác minh bằng readelf -d) xác định theo $ORIGIN. Khi thư viện X phụ thuộc vào thư viện Y, thư viện X thể chỉ ra rằng thư viện Y nên được tìm thấy trong một vị trí tương đối so với vị trí của mình bằng cách sử dụng $ORIGIN. Điều này được hỗ trợ bởi trình liên kết động, nhưng không được liên kết tĩnh hỗ trợ.

(Tôi đang suy đoán đây :) thư viện của bạn sẽ xác định vị trí của trực tiếp phụ thuộc của nó (trong trường hợp của bạn, tôi đoán, điều này bao gồm containers) về riêng của mình RPATH, mà không phải là về của $ORIGIN. Đây là lý do tại sao các mối liên kết có thể tìm thấy những người, nhưng không phụ thuộc transitive của nó (một lần nữa, tôi đoán, điều này bao gồm deepseq trong trường hợp của bạn).

Vậy tại sao sự khác biệt giữa Arch Linux và Ubuntu? (Điều tra thêm.) Điều này là do không giống như trên Arch Linux, liên kết của Ubunbu sử dụng --as-needed theo mặc định. Bạn thấy đấy, ghc sẽ liên kết thư viện của bạn với tất cả phụ thuộc của nó (bao gồm cả những người chuyển đổi), nhưng sau đó trình liên kết sẽ bỏ qua một số phụ thuộc đó vì nó không trực tiếp phụ thuộc vào chúng. Bạn có thể xác minh điều này bằng cách liên kết lại với --no-as-needed.

Lưu ý rằng các lỗi này bởi các trình liên kết tĩnh thực sự không phải là lỗi, nhưng cảnh báo: nó cố gắng giải quyết các biểu tượng, nhưng không thể; nhưng trình liên kết động sẽ vẫn có thể. Vì vậy, bạn có thể hướng dẫn các mối liên kết để bỏ qua những lỗi này (--unresolved-symbols=ignore-all) và tất cả nên được tốt.

Tôi đã chiến đấu với việc thêm hỗ trợ rõ ràng vào Cabal để tạo thư viện Haskell để sử dụng trong các chương trình C và tìm thấy cùng một vấn đề. Xem https://github.com/haskell/cabal/pull/2540#issuecomment-95984067 để biết chi tiết.

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