프로그램을 컴파일 prog
하고 소스에서 빌드하고 /usr/local/ssl-1.0.2
. 0.9.8을 사용하는 이전 시스템에서는 큰 문제 없이 작동합니다. 1.0.1이 설치된 최신 시스템에서는 약간의 작업이 더 필요합니다. 이유가 궁금합니다.
1) Ubuntu 10.04, OpenSSL 0.9.8:
1.0.2에 대해 컴파일하고 링크하기 위해 따르는 단계는 다음과 같습니다.
$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto
=> 0.9.8 파일만 나오므로 1.0.2 파일 경로를 추가해보겠습니다...
$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto
=>
libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
libcrypto.so.0.9.8 (libc6, hwcap: 0x0008000000008000) => /lib/i686/cmov/libcrypto.so.0.9.8
libcrypto.so.0.9.8 (libc6, hwcap: 0x0004000000000000) => /lib/i586/libcrypto.so.0.9.8
libcrypto.so.0.9.8 (libc6, hwcap: 0x0002000000000000) => /lib/i486/libcrypto.so.0.9.8
libcrypto.so.0.9.8 (libc6) => /lib/libcrypto.so.0.9.8
libcrypto.so.0.9.8 (libc6) => /usr/lib/libcrypto.so.0.9.8
libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so
그래서 컴파일할 수 있습니다 prog
...
$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog
=>
libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0x0083b000)
... 그리고 1.0.2와 올바르게 연결되어 있습니다.
2) OpenSSL 1.0.1을 사용하는 Debian Wheezy에서:
같은 단계, 다른 결과.
$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto
=>
libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0
마찬가지로 1.0.2에 경로를 추가합니다...
$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto
=>
libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0
libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so
그럼 컴파일을 해보는데...
$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog
=>
libcrypto.so.1.0.0 => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0 (0xb7591000)
그러나 여기서는 1.0.2와 연결되지 않습니다. 컴파일 타임 라이브러리 경로는 정확하지만( 로 지정되지 -L
않으면 gcc
에서 사용된 일부 함수가 1.0.2에만 해당되므로 실패할 수 있음 prog
) 런타임 경로는 올바르지 않습니다.
3) Wheezy에서 작동시키는 방법
실행 여부에 관계없이 ldconfig /usr/local/ssl-1.0.2/lib
:
$ gcc -o prog ... -Wl,--rpath=/usr/local/ssl-1.0.2/lib -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog
=>
libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0xb7592000)
또는 export LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib
실행하기 전에 실행하세요 gcc
.
내가 알고 싶은 것
mr.spuratic의 제안에 따라 LD_DEBUG=libs ./prog
경로가 /etc/ld.so.cache
. 해당 파일을 열었고 .so가 조회되는 순서가 .so의 출력과 일치한다는 것을 알았습니다 ldconfig -p
.
실제 질문은 다음과 같습니다.
- 1.0.2 파일이 1)에서는 ldconfig 목록의 맨 위에 있지만 2)에서는 그렇지 않은 이유는 무엇입니까? 순수한 무작위성? 1.0.1과 1.0.2 파일의 접미사가 동일하여 혼란이 있습니까? ("1.0.0")
아니면 다르게 말하면,
- 3)에 추가된 플래그가 1)에 필요하지 않은 이유는 무엇입니까?
답변1
기본이 아닌 패키지에 대해 컴파일/링크할 때 주의해야 할 세 가지 사항이 있습니다.
- 헤더(보통
CFLAGS
) - 컴파일 타임 라이브러리 경로(일반적으로
LDFLAGS
) - 런타임 라이브러리 경로(rpath
LDFLAGS
,LD_RUN_PATH
또는 )LD_LIBRARY_PATH
을 통해ld.so.conf
당신은 그것이 무엇인지 말하지 않았기 prog
때문에 그 구성이 얼마나 잘 작동할지 알 수 없습니다(또는 그것이 autoconf를 사용한다면?). 처음 두 단계만 안정적으로 수행하는 많은 것을 보았습니다.
CFLAGS
링크 단계에서는 라이브러리 경로 순서가 관련됩니다. GNU 툴체인(gcc 및 binutils)을 사용한다고 가정하면 이전에 설정 configure
하거나 직접 설정하여 무슨 일이 일어나고 있는지 확인할 수 있습니다 Makefile
.
export CFLAGS="-Wl,-t"
그러면 -t
추적 옵션이 링커에 전달됩니다. make 중에 간결한 "CC" 및 "LD" 행만 출력되는 경우 make 명령에 V=1
또는 를 추가해야 할 수도 있습니다 .)VERBOSE=1
런타임 시 ld.so
신중하게 설정하여 시도하는 내용을 확인할 수 있습니다 LD_DEBUG
. 예:
LD_DEBUG=libs ./myprog
(또는 자세한 내용을 보려면 files
또는 값을 사용해 보세요)symbols
빌드 시 세 가지 매개변수를 모두 올바르게 지정하려면 다음을 수행할 수 있어야 합니다.
export CFLAGS="-I/usr/local/ssl-1.0.2/include"
export LDFLAGS="-L/usr/local/ssl-1.0.2/lib -R/usr/local/ssl-1.0.2/lib"
그런 다음 재구성/재컴파일하십시오.
--openssldir
더 일반적인 방법보다는 사용하고 있습니다 --prefix
(후자를 권장하며 make install_sw
기본 설치에서 제공하는 1000개 정도의 매뉴얼 페이지 및 심볼릭 링크가 필요하지 않은 경우에도 사용합니다). 이것이 문제의 일부일 수 있습니다. 어떤 이유로 표시되는 .so 라이브러리에는 ld.so
버전 접미사(예: )가 없는 것으로 알려져 있으므로 .so.1.0.2
적절한 " make install
"가 이를 설정해야 합니다( link-shared
main 의 대상을 통해 Makefile
).
이 옵션은 런타임 링커( )가 일반적으로 제공하는 -R
기본값에 의존할 필요가 없도록 특정 OpenSSL 라이브러리에 대한 실행 가능 출력에 RPATH를 포함하도록 링커에 지시합니다 . ld.so
다음을 사용하여 기존 바이너리를 수정할 수 있습니다.chrpath
대신에.
이는 내보내기와 거의 동일합니다 LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib
. RPATH 및 관련 RUNPATH에 대한 자세한 내용은 여기에서 확인할 수 있습니다.http://blog.tremily.us/posts/rpath/
최후의 수단으로 "shared" 없이 또는 "noshared"를 사용하여 OpenSSL을 구축할 수 있습니다. 이렇게 하면 이 문제가 없는 정적 라이브러리가 제공됩니다(그러나 ELF .so 내에서 사용하는 경우 PIC가 발생하는 등의 다른 문제가 있을 수 있습니다). /PIE 문제)
업데이트된 세부 정보에 따르면 문제는 1.0.1과 1.0.2beta가 모두 .so 버전 접미사(SONAME)를 1.0.0으로 설정했다는 것입니다. 0.9.8만 있는 첫 번째 시스템에서는 문제가 발생하지 않습니다. 두 번째 버전에서는 1.0.1과 1.0.2가 모두 1.0.0으로 버전이 지정되어 있으며 순서에 따라 "첫 번째 경기에서 승리합니다"입니다 ld.so.{conf,d}
. ld
컴파일 타임 링커는 ld.so
런타임 링커와 다른 프로그램이며 동작이 다를 수 있다는 점을 기억하십시오 (보시다시피 일반적으로 기호 오류 또는 더 심각한 결과를 초래함).
$ cd /usr/local/src/openssl/openssl/1.0.2beta1
$ readelf -a libssl.so | grep SONAME
0x0000000e (SONAME) Library soname: [libssl.so.1.0.0]
$ cat verchk.c
int main(int argc, char *argv[]) {
printf("build: %s\n",OPENSSL_VERSION_TEXT);
printf("run : %s\n",SSLeay_version(SSLEAY_VERSION));
return 0;
}
$ gcc -Wall -I/usr/local/src/openssl/openssl-1.0.2-beta1/include \
-Wl,-rpath /usr/local/src/openssl/openssl-1.0.2-beta1/ \
-o verchk /usr/local/src/openssl/openssl-1.0.2-beta1/libcrypto.so verchk.c
$ ./verchk
build: OpenSSL 1.0.2-beta1 24 Feb 2014
run : OpenSSL 1.0.2-beta1 24 Feb 2014
$ grep SHLIB_M...R= Makefile
SHLIB_MAJOR=1
SHLIB_MINOR=0.0
업데이트
OpenSSL-1.1에서는 API 수준이 일부 변경되었습니다. 위 코드는 v1.1 헤더 및 이전 라이브러리( undefined reference to `OpenSSL_version'
)로 컴파일되지 않습니다.
SSLeay_version()
이제 더 이상 사용되지 않으며 (에 따라 OPENSSL_API_COMPAT
) #define
적절한 API 함수에 -d 될 수 있습니다 OpenSSL_version()
.
답변2
내의 파일 중 하나에 새 lib의 경로가 있습니까 /etc/ld.so.conf.d
? 다음 실행:-
#ldconfig -v
캐시를 다시 작성합니다. 빠르면 인쇄된 긴 목록에서 새 라이브러리를 볼 수 있습니다(또는 또는 파이프로 파이프 grep
) less
.
경로가 이미 첫 번째 서버에는 있었지만 두 번째 서버에는 없었을 수도 있습니다.