2014-12-09 13 views
8

Tôi có chương trình Qt Linux. Tôi muốn nó ưu tiên sử dụng các thư viện Qt (động) trong thư mục thực thi nếu chúng tồn tại, nếu không hãy sử dụng các thư viện Qt của hệ thống. RPATH để giải cứu.Đặt thứ tự RPATH trong QMake

tôi thêm dòng này vào qmake 's tập tin .pro:

QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN\'' 

và nhìn vào thực thi kết quả với readelf tôi thấy:

0x000000000000000f (RPATH)    Library rpath: [$ORIGIN:/usr/local/Trolltech/Qt-5.2.0/lib] 
0x000000000000001d (RUNPATH)   Library runpath: [$ORIGIN:/usr/local/Trolltech/Qt-5.2.0/lib] 

Có vẻ đúng, nhưng ldd cho biết họ đang sử dụng phiên bản hệ thống:

libQt5Core.so.5 => /usr/local/Trolltech/Qt-5.2.0/lib/libQt5Core.so.5 (0x00007f2d2fe09000) 

Nếu tôi tự sửa qmake của kết quả Makefile để hoán đổi thứ tự của hai rpaths, vì vậy $ ORIGIN đưa ra sau khi usr/local/..., tôi nhận được hành vi đúng /:

0x000000000000000f (RPATH)    Library rpath: [/usr/local/Trolltech/Qt-5.2.0/lib:$ORIGIN] 
0x000000000000001d (RUNPATH)   Library runpath: [/usr/local/Trolltech/Qt-5.2.0/lib:$ORIGIN] 

libQt5Core.so.5 => ./libQt5Core.so.5 (0x00007fb92aba9000) 

Vấn đề của tôi là với cách qmake tạo biến LFLAGS cuối cùng. Tôi không thể hiểu làm thế nào để làm cho nó đưa thêm của tôi ($ ORIGIN) sau khi thư viện hệ thống. Bất kỳ ý tưởng?

+0

Tại sao bạn muốn sử dụng thư viện địa phương trên thư viện hệ thống? Trong một kịch bản triển khai thông thường, nơi bạn gửi thư viện với hệ nhị phân, bạn chỉ có địa phương hoặc hệ thống trên địa phương. –

+0

Tôi sẽ không làm điều này cho một sản phẩm sản xuất, nhưng nó rất hữu ích để gỡ lỗi, nơi thư viện địa phương có một số đầu ra chẩn đoán thêm (ví dụ). Tôi nhận ra tôi chỉ có thể sử dụng một cái gì đó dọc theo dòng LD_LIBRARY_PATH trong một kịch bản wrapper, nhưng tôi scurried xuống lỗ thỏ QMAke/RPATH này, và bây giờ tôi tò mò về làm thế nào để làm cho QMake làm những gì tôi muốn ... –

Trả lời

0

Tôi đang đoán một chút về những gì đang xảy ra, nhưng nó dựa trên việc biết một số hành vi kỳ lạ của ld.

kiểm tra sự hiện diện của biến số LD_LIBRARY_PATH sẽ có hiệu lực trước khi xử lý biến RUNPATH. Do có sự hiện diện của cả hai kiểu RPATHRUNPATH, quy tắc LD_LIBRARY_PATH có hiệu lực, do đó nếu được đặt thì hãy bỏ đặt nó.

Thứ hai, tôi chưa bao giờ mong đợi để xem:

libQt5Core.so.5 => ./libQt5Core.so.5 (0x00007fb92aba9000) 

trong đầu ra của ldd, tôi sẽ luôn luôn nhìn thấy sự mở rộng của $ORIGIN vào thư mục của nhị phân (? Có lẽ bạn rút ngắn nó), vì vậy tôi đã có thể mong đợi:

libQt5Core.so.5 => /path/to/bin/./libQt5Core.so.5 (0x00007fb92aba9000) 

có nghĩa là nó có vẻ giống như việc mở rộng LD_LIBRARY_PATH.:/usr/local/Trolltech/Qt-5.2.0/lib, mà với tôi có vẻ như bạn đã ghi đè môi trường xảy ra.

+0

Đó là sản lượng nguyên văn từ ldd, không rút ngắn tham gia. LD_LIBRARY_PATH không được đặt trong bất kỳ ví dụ nào trong số này. –

+0

Bạn có * bất kỳ biến môi trường 'LD_' nào được đặt không? bạn có nhận được cùng một hành vi với 'env -i ldd '? Những gì distro Linux bạn đang sử dụng (cố gắng để kiểm tra lỗi)? – Petesh

1

Theo như nghiên cứu của tôi có thể nói, bạn chỉ có thể thêm RPATH vào đầu danh sách với QMake.

Nhưng nếu bạn sử dụng Linux và có thể cài đặt chrpath, bạn có thể hack theo cách đó.

Thêm khối này ở phần cuối của tập tin .pro bạn

# Add spacing since chrpath cannot expand RPATH length 
QMAKE_RPATHDIR = \ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY1\ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY2\ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY3\ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY4 
QMAKE_POST_LINK += 'chrpath -r \'/my/qt/installation:\$$ORIGIN\' $$OUT_PWD/mybinaryname;' 
+0

Không hoàn toàn là giải pháp tôi đã dự đoán, nhưng một hack tuyệt vời không kém! –

+0

Có thể sử dụng 'patchelf --set-rpath' thay vì' chrpath -r'. Có vẻ như nó cũng không có vấn đề gì khi mở rộng rpath, vì vậy không cần phải xóa QMAKE_RPATHDIR. – user362515

8

Bạn có thể thêm dòng sau vào bạn.tập tin pro để buộc các mối liên kết động để tìm trong các thư mục tương tự như ứng dụng Qt của bạn trong thời gian chạy trong Linux:

unix:{ 
    # suppress the default RPATH if you wish 
    QMAKE_LFLAGS_RPATH= 
    # add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded 
    QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\'" 
} 

Nếu bạn muốn nó để tìm trong một thư mục con của con đường thực thi, bạn có thể sử dụng:

QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN/libs\'" 

Lưu ý rằng bạn nên có các tệp .so có cùng tên chính xác trong thư mục ứng dụng của bạn. Ví dụ: bạn nên sao chép libQt5Core.so.5.2.0 vào thư mục ứng dụng của mình với tên libQt5Core.so.5. Bây giờ ldd hiển thị thư mục của ứng dụng.

Bạn cũng có thể có libQt5Core.so.5.2.0 và liên kết đến tên đó bằng tên libQt5Core.so.5 trong thư mục ứng dụng.

+0

Điều này rất gần. Đặt 'QMAKE_FLAGS_RPATH =' để chặn mặc định là khóa. Sau đó, tôi có thể làm: 'QMAKE_FLAGS + =" -Wl, -rpath, \ '/ usr/local/Trolltech/Qt-5.2.0/libs \' -Wl, -rpath, \ '\ $$ ORIGIN \' "' để có được các phần tử phù hợp trong RPATH theo đúng thứ tự. Có lẽ một số biến chứa đường dẫn hệ thống tôi có thể sử dụng, nhưng tôi không thể tìm thấy nó ... –

0

qmake sẽ luôn gắn QMAKE_RPATHDIR với QT_INSTALL_LIBS nội bộ theo quy định tại $(QT_DIR)/mkspecs/features/qt.prf file:

170: relative_qt_rpath:!isEmpty(QMAKE_REL_RPATH_BASE):contains(INSTALLS, target):\ 
173:  QMAKE_RPATHDIR += $$relative_path($$[QT_INSTALL_LIBS], $$qtRelativeRPathBase()) 
175:  QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev] 
179:!isEmpty(QMAKE_LFLAGS_RPATHLINK):!contains(QT_CONFIG, static) { 
189: QMAKE_RPATHLINKDIR *= $$unique(rpaths) 

Vì vậy, để tránh ứng dụng của bạn bằng cách sử dụng thư viện QTtừ đường dẫn hệ thống, nhận xét ra các dòng trên đó gắn QMAKE_RPATHDIR và thêm QMAKE_RPATHDIR=$ORIGIN vào tệp .pro của bạn.

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