CentOS 7(둘 다 64비트, 호스트 하나, 가상 머신 하나)에서 실행하기 위해 Ubuntu에서 바이너리를 컴파일하려고 합니다.
지금까지 모든 공유 라이브러리가 포함된 바이너리를 복사했습니다. 더 이상 라이브러리 누락 오류가 발생하지 않지만 멋진 ld SIGSEGV가 표시됩니다.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5d67681 in ?? ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64
(gdb) where
#0 0x00007ffff5d67681 in ?? ()
#1 0x00007fffffffe3f0 in ?? ()
#2 0x00007ffff7decdd4 in _dl_check_map_versions () from /lib64/ld-linux-x86-64.so.2
#3 0x00007ffff7de08a3 in dl_main () from /lib64/ld-linux-x86-64.so.2
#4 0x00007ffff7df2aee in _dl_sysdep_start () from /lib64/ld-linux-x86-64.so.2
#5 0x00007ffff7dde4a4 in _dl_start () from /lib64/ld-linux-x86-64.so.2
#6 0x00007ffff7dddb08 in _start () from /lib64/ld-linux-x86-64.so.2
#7 0x0000000000000001 in ?? ()
#8 0x00007fffffffe8bb in ?? ()
#9 0x0000000000000000 in ?? ()
소스 코드가 있지만 소스에서 빌드된 일부 라이브러리에 의존하고 centOS에서 시도했지만 g++ 버전이 오래되었고 c++11을 지원하지 않기 때문에 우분투에서 거의 컴파일하고 테스트할 수 없습니다. devtools 버전을 설치한 후 이제 다른 오류가 발생하지만 이는 다른 문제인 것 같습니다.
그렇다면 이 오류를 극복하기 위해 제가 할 수 있는 일은 없을까요? 결국 이렇게 될까요? Ubuntu에서 CentOS로 포팅하는 가장 쉬운 방법은 무엇입니까?
답변1
나는 이것을하지 않는 것이 좋습니다. 일반적으로 배포판의 패키지 작성 프로세스 중에 다양한 배포판에 대한 바이너리를 작성하는 것이 더 쉽습니다. CentOS에서는 rpmbuild
.
VM을 다루고 있으므로 CentOS 7 VM + 빌드 도구를 설정한 다음 거기서 패키지 빌드를 수행하는 것이 더 간단합니다.
소스 기반 배포판 사용자의 관찰
나는 일반적으로 다른 사람의 답변을 편집하는 경향을 따르지 않지만 사람들이 소스 기반 배포판의 차이점을 깨닫도록 도와줌으로써 느리지만 확실하게 여기에서 명성을 얻고 있습니다. 그 중 3가지 주요 배포판은 다음과 같습니다.
또한 바이너리 기반 배포판에는 두 가지 주요 배포판이 있습니다.
현재로서는 주요 하이브리드 배포판이 1개뿐입니다(소스 코드와 바이너리 간 교차).
Linux 사용자가 좋아하든 싫어하든 다른 모든 Linux 배포판은 이러한 6개 상위 버전 중 하나의 하위 버전입니다. 그렇게 말하고 다음 요점으로 넘어 갑시다.
소스 기반 배포판의 소프트웨어와 바이너리 배포판의 소프트웨어를 혼합하는 것은 불가능합니다.
이것을 안다는 것은 또한,수행 중인 작업을 알지 못하는 한 바이너리 배포판의 소스에서 개별 패키지를 컴파일하면 안 됩니다.. 이 규칙에는 예외가 있습니다.
- 필요한 패키지가 배포 저장소/트리/등에 존재하지 않습니다(이것이 OP가 질문한 이유입니다).
- 당신은 하나를 찾을 수 없습니다저장소/트리/등에 있는 필수 패키지의 최신 버전 - 항목 9 참조.
OP에 왜 문제가 있습니까?
기술적으로 말하면, 최종 패키지의 경우 패키지를 사용하는 것과 소스에서 빌드하는 것 사이에는 차이가 없습니다. 즉, 패키지를 성공적으로 빌드하고 작동한다면 누구도 그렇게 한다고 비난할 수 없습니다. 하지만 이렇게 할 때 하나의 바이너리 기반 배포판에서 애플리케이션을 구축하는 데 사용되는 도구는 다른 바이너리 배포판에서 사용할 수 있는 도구보다 높은 버전이라는 점을 기억해야 합니다. OP가 보고 있는 것은 이전 패키지와 새 패키지 간의 델타 또는 변경 사항입니다. 위에서 언급한 6개 운영 체제 중 하나이든 하위 운영 체제이든 각 운영 체제의 패키지 및 운영 체제 관리자가 해당 운영 체제에 대해 안정적인 것으로 표시될 패키지를 선택함으로써 증가 또는 변경이 발생합니다. 바이너리 릴리스용으로 패키지를 선택하면 대부분의 경우 다음 릴리스까지 고정됩니다.심각한 오류발견되었다.
반면 소스 기반 배포판에는 새 소스가 제공되는 즉시 프로젝트를 업데이트하여 즉시 버그를 수정할 수 있는 옵션이 있습니다.
이것이 OP에 문제가 있는 이유입니다.
Ubuntu의 출시 일정 및 업데이트 주기는 새 버전을 채택하도록 선택합니다.툴체인 빌드, CentOS가 이를 채택하기 전에. CentOS는 안정성을 기반으로 구축되었으므로 다음 릴리스까지 빌드 도구 체인이 업데이트되지 않을 수 있습니다.주요 버전. 그래서 OP에 문제가 발생했습니다.이와 유사, Ubuntu의 빌드 도구 체인은 C++11을 지원하는 반면 CentOS의 빌드 도구 체인은 모든 버전 불일치가 수정될 때까지 이를 지원하지 않으며 나중에 여러 패키지 관리자를 사용할 때 문제가 발생하기 때문입니다.
OP는 무엇을 해야 합니까?
- 패키지가 호스팅되는 시스템에서 사용할 수 있는 빌드 도구를 결정합니다. 이 경우에는 CentOS입니다. 여기 하나 있어요올바르게 설치하는 방법에 대한 페이지. 이전 링크의 목록에 따르면 이 컴파일러는 C++11을 지원합니다. 매우 숙련된 직감으로서, OP의 버전 불일치는
binutils
Binutils가libtool
glibc에 의존하고 libtool이 binutils에 의존하므로libtool
간접적으로 의존하는 경우 발생합니다.glibc
왜 모든 시스템의 거의 모든 패키지가 간접적으로 의존하는지 설명하지 않겠습니다glibc
. 그렇습니다. - 올바르게 설치된 빌드 도구 체인이 C++11을 지원하지 않는 경우 OP는 현재 직면한 문제를 완화하기 위해 C++98을 사용해야 합니다.
- 위의 1단계에서 빌드 도구 모음을 업데이트한 후 OP는 이제 CentOS VM에서 소스 코드를 컴파일하고 필요에 따라 수정/수정을 수행해야 합니다. OP에 패키지가 필요한 경우 이 게시물에서 알 수 있듯이 rpmbuild를 사용해야 합니다. 이는 패키지가 있는 VM의 기본 패키지 관리자이기 때문입니다. Yum은 패키지 관리자가 아닙니다. Yum은 종속성 파서입니다.
인용하다
답변2
OP 솔루션 및 결론
이전 답변을 바탕으로 이것이 제가 해결한 솔루션입니다.
1. 소스코드 복사
소스 코드를 가상 머신이나 다른 컴퓨터에 복사합니다. 나는 다음을 사용했습니다 :
scp -R /host/path/to/src/ user@remoteHost:/remote/build/path/
이는 자동차 여행과도 같으므로, 다른 컴퓨터에서 찾을 수 있는 공유 라이브러리와 기타 리소스를 제외하고 컴파일하는 데 필요한 모든 소스 코드를 포장하고 수집하세요.
2. 종속성 설치(라이브러리/빌드 도구)
VM을 기본 설치(centOS7분)로 복원하고 시행착오를 기반으로 내 앱을 빌드하기 위한 업데이트된 도구(yum search, install, try build 명령)
yum -y update
yum -y install boost-* #probably could have used only boost-devel
yum -y install glibc-utils
yum -y install gcc-c++
yum -y install git
yum -y install libtool
yum -y install zlib-devel
yum -y install ncurses-devel
yum -y install make
yum -y install cmake
yum -y install openssl-devel
yum -y install libssh2-devel
...
프로젝트가 운영 체제 저장소에서 사용할 수 없는 (최신) 라이브러리에 의존하는 경우 소스에서 설치하십시오.
예를 들어, c-ares와 업데이트된 mysql 클라이언트 라이브러리로 구축된 컬을 사용해야 합니다.
#mysqlclient
if [[ -z $(ldconfig -p | grep libmysqlclient) ]]
then
mkdir -p "${INSTALL_PREQ_PATH}/lib/mysql/";
cd "${INSTALL_PREQ_PATH}lib/mysql/"
wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
yum -y localinstall mysql-community-release-el7-5.noarch.rpm
sudo yum install mysql-community-client
sudo yum install mysql-community-devel
fi
#c-ares
if [[ -z $(ldconfig -p | grep libcares) ]]
then
mkdir -p "${INSTALL_PREQ_PATH}lib/libcares/"
cd "${INSTALL_PREQ_PATH}lib/libcares/"
git clone git://github.com/bagder/c-ares.git
cd c-ares
./buildconf
./configure
make
sudo make install
ldconfig
fi
#libcurl
if [[ -z $(ldconfig -p | grep libcares) ]]
then
mkdir -p "${INSTALL_PREQ_PATH}lib/libcurl/"
cd "${INSTALL_PREQ_PATH}lib/libcurl/"
wget http://curl.haxx.se/download/curl-7.39.0.tar.gz
tar -xvzf curl-7.39.0.tar.gz
cd curl-7.39.0
./configure --enable-ares --with-libidn --with-zlib --disable-ipv6
make
sudo make install
ldconfig
fi
관찰하다: 각 빌드에는 위 단계에 추가된 자체 종속성이 있습니다.
3. Foreach 종속성을 설치하고 작동하는지 확인하고 문제가 있는지 확인했습니다.
시스템에 라이브러리가 로드되어 있는지 확인하십시오.
ldconfig # update library cache
ldconfig -p | grep libcurl # check for library
제 경우에는 기본적으로 링크 빌더 검색 경로에 포함되지 않는 /usr/local/lib/ 폴더에 라이브러리가 설치되어 있었습니다. 이 문제를 해결하려면:
echo "/usr/local/lib/">/etc/ld.so.conf.d/local.conf #add lib search path
ldconfig #reload library cache
또한 공유 라이브러리를 사용하는 다른 프로그램이 여전히 작동하는지 확인하십시오. 내 경우에는 ssh와 ssl이 누락되어 컬 설치가 중단되었습니다. 다음을 수정하십시오.
rm /etc/ld.so.conf.d/local.conf #remove the new libs search path
ldconfig #reload
yum install openssl-devel #install ssl dependency
yum install libssh2-devel #install ssh dependency
cd "${INSTALL_PREQ_PATH}lib/libcurl/" #go to libcurl source path
./configure --enable-ares --with-libidn --with-zlib --disable-ipv6 --with-ssl --with-libssh2 # configure build with ssl and ssh
make #compile
sudo make install #install binary, libs and headers
echo "/usr/local/lib/">/etc/ld.so.conf.d/local.conf #add lib search path
ldconfig #reload library cache
4. 프로그램 구축
제 경우에는 우분투와 같은 컴파일러인 gcc-c++(g++)를 사용했습니다. 작동하지 않는 경우:
- 종속성이 누락되었는지 확인하고 경고 및 오류를 읽어보세요.
- 두 시스템의 컴파일러 버전을 확인하고, 코드 및 컴파일러 플래그에 대한 지원 차이를 확인하고, 인터넷을 사용하여 운영 체제에 맞게 컴파일러를 업데이트하는 방법을 찾으세요.
기타 참고사항:
- 다른 컴퓨터에 다시 시도하거나 (재)설치할 수 있도록 단계를 bash 스크립트에 기록하는 것이 좋습니다.
- 이는 생산 기계에 대한 좋은 제안이 아닙니다. 다른 곳에서 실험해 보십시오.
- 가상 머신을 사용하는 경우 스냅샷을 찍고, 그렇지 않으면 백업을 만들고 항상 실패에 대비하세요.
- 내 조언을 받아들이지 마십시오. 이것은 나에게 효과적이었습니다. 모든 사람에게 효과가 없을 수도 있고 다른 상황에서는 나쁜 선택이 될 수도 있습니다. 저는 전문가는 아니고 저같은 초보분들께 도움을 드리고자 글을 씁니다 :)