2014년 1월 6일 월요일

우분투에서 SRPM(Source RPM) 수정하기

0. RPM, Source RPM

RPM은 다들 알다시피 Redhat Package Manager의 약자로, 자신이 만든 소프트웨어를 배포하기 편리한 하나의 패키지로 만드는데 사용되는 시스템이며, 그렇게 만들어진 패키지를 rpm 또는 rpm 파일이라 한다.
독점 소프트웨어에서는 배포하는 패키지라면 빌드 완료된 바이너리로만 구성되어 있는 경우가 대부분이지만, 오픈소스 소프트웨어에서는 배포 패키지가 꼭 바이너리여야 할 이유가 없다. 패키징만 잘 되어 있어 주고 받기 편하고 사용자가 어느 시스템을 사용하든 그 소프트웨어를 쉽게 설치할 수 있으면 땡이다.
그리고, 어떤 면에서는 빌드가 끝난 바이너리보다 소스코드로 배포하는게 더 나은 경우가 존재한다.
따라서, RPM은 빌드가 끝난 바이너리를 패키징해서 만들수도, 소스코드를 담고 빌드 방법을 함께 담아서 패키지로 만들 수도 있다.
각각을 Binary RPM, Source RPM 이라고 부르기도 한다.

1. RPM을 수정해야 하는 경우

많은 사용자가 쉽게 사용할 수 있도록 배포자는 혼신의 노력을 기울여 패키지를 만들었겠지만, 실제 패키지를 사용해보면 문제가 발생하는 경우가 많다.
문제를 발견해서 수정해 원저자에게 패치를 보내주는게 오픈소스 소프트웨어의 좋은 경우겠지만, 때로는 원저자가 더이상 해당 프로젝트에 관심을 잃은 경우가 있고, 또는 당장의 빠른 수정이 필요한 경우가 있다.
SRPM의 경우는 특히나 소스코드를 볼 수 있으므로 자신이 수정해서 당장의 문제를 해결하는 것이 가능하다.

본 글에서는 우분투 환경에서 patch를 만들어 srpm을 수정하는 방법을 기술한다.
테스트한 환경은 우분투 13.04 64bit server판이었다.

target.src.rpm 이라는 이름의 srpm을 수정한다고 가정한다.

2. 필요 패키지 설치

먼저 시스템에 rpm 패키지가 설치되어 있지 않다면 다음 명령으로 rpm 패키지를 설치한다. rpm은 레드햇 계열의 패키지 포맷이지만 데비안 계열인 우분투에서도 rpm 패키지를 이용해 사용할 수 있다.

$ sudo apt-get install rpm

해당 패키지는 rpm을 단계별로 설치할 수 있는 rpm과, 새로이 RPM 파일을 만들 수 있는 rpmbuild다른 명령을 제공한다. 이 글에선 rpm을 이용해 코드를 풀고, 이 코드를 수정 후, 수정된 내용으로 rpmbuild를 이용해 새로인 SRPM을 만드는 식으로 수정된 SRPM을 얻을 것이다.

3. SRPM 풀기

rpm 을 이용해 srpm을 단계별로 설치할 수 있으며, 이 단계는 간략히 소스코드를 꺼내고, 빌드하고, 설치하고, 하는 단계로 이루어진다. 따라서 꺼내는 단계까지만 설치를 진행하면 우리가 보고 싶은 소스코드를 볼 수 있다. 아래 명령을 통해 소스코드를 꺼내는 단계까지만 진행할 수 있으며, 소스코드를 위치시킬 경로는 _topdir로 설정할 수 있다. 아래 명령의 /path/to/extract 는 자신이 편한 디렉토리 경로로 대체하자.

$ rpm --define ‘_topdir /path/to/extract’ -i target.src.rpm

이제 /path/to/extract에 가보면 SPECS와 SOURCE 디렉토리가 있고, 각 디렉토리 아래에는 각각 spec 파일과 압축되거나 한 형태의 소스코드가 있다.
하지만 아직 소스코드는 압축된 상태이다. 그냥 압축 해제 프로그램으로 압축을 풀지 말고, 다음의 과정을 진행하자.


4. 빌드 준비

spec 파일은 빌드 준비 / 실행 / 정리 등의 과정을 Makefile처럼 정리해 뒀고, 보통 prepare 과정을 통해 SOURCE 디렉토리 아래 소스코드를 BUILD 디렉토리 아래로 옮기고, 소스코드가 압축되어 있다면 압축을 푸는 식으로 빌드 준비를 한다. 다음의 커맨드로 이를 행한다.

$ cd /path/to/extract/SPECS
$ rpmbuild --define ‘_topdir /path/to/extract’ -bp target.spec


target.spec은 SPECS 디렉토리 아래 존재하는 spec 확장명의 파일명을 입력한다.

5. 코드 수정 & 패치 작성

이제 코드에 수정을 가하고 이를 바탕으로 패치를 만들어 SOURCE 디렉토리로 이동시켜야 한다. 오리지널 코드와 수정한 코드를 둘 다 가지고 있어야 그 차이로 변경내역을 나타내는 패치로 만들어야 하므로, 다음과 같이 오리지널 코드를 보존해 둔 상태로 코드를 수정한다.
명령어의 existing_dir은 실제 존재하는 소스코드 디렉토리의 이름으로 대체하자.

$ cd /path/to/extract/BUILD
$ cp -R ./existing_dir ./extracting_dir.orig


본인에게 편한 방법으로 /path/to/extract/BUILD/existing_dir 아래의 코드에 수정을 가하고 나서 다음 명령을 이용해 패치를 만들고 SOURCES 디렉토리 아래로 옮긴다. 역시 name_of_patch.patch는 본인이 원하는 패치 파일 이름으로 적당히 대체를.


$ diff -Npru existing_dir.orig/ existing_dir > name_of_patch.patch
$ mv name_of_patch.patch /path/to/extract/SOURCES/


6. srpm 설치 시 patch를 적용하도록 spec 파일 수정

이제 해당 srpm을 설치 시 앞의 과정에서 만든 패치를 적용하게 해야 한다. specs 파일을 수정하는 것으로 그렇게 할 수 있다.
Source 항목 아래 Patch0 라는 항목을 만들어 앞서 만든 name_of_patch.patch를 적어주고, %setup 아래 %patch0 -p1이라는 항목을 넣어 해당 patch를 사용함을 알린다.


예:
Source0: %{name}-%{version}-%{release}.tar.gz                                   
Patch0: for_ubuntu13.04_sjpark.patch                                            
Prefix: /usr                                                                    
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root                       
Requires(post): /sbin/ldconfig                                                  
Requires(postun): /sbin/ldconfig                                                
Conflicts: infinipath-libs                                                      
                                                                                
%package devel                                                                  
Summary: Development files for QLogic PSM                                       
Group: System Environment/Development                                           
Requires: %{name} = %{version}-%{release}                                       
Requires(post): /sbin/ldconfig                                                  
Requires(postun): /sbin/ldconfig                                                
Conflicts: infinipath-devel                                                     
                                                                                
%description                                                                    
The PSM Messaging API, or PSM API, is QLogic's low-level                        
user-level communications interface for the Truescale                           
family of products. PSM users are enabled with mechanisms                       
necessary to implement higher level communications                              
interfaces in parallel environments.                                            
                                                                                
%description devel                                                              
Development files for the libpsm_infinipath library                             
                                                                                
%prep                                                                           
%setup -q -n infinipath-psm-%{version}-%{release}                               
%patch0 -p1           

7. 수정된 RPM 빌드

이제 끝. 마지막으로 우리가 원하는 SRPM 또는 RPM을 얻기 위해 다음 명령을 날려준다.

$ rpmbuild --define '_topdir /path/to/extract' -ba target.spec


이제 RPMS 디렉토리 아래에 rpm이, SRPMS 디렉토리 아래에 srpm 파일이 존재할 것이다.


번외: 현 디렉토리의 모든 SRPM을 4번 단계까지 진행하는 코드

이상의 내용을 바탕으로 python으로 간략히 현 디렉토리의 모든 SRPM을 4번 단계까지, 즉 코드를 볼 수 있는 수준까지 진행하는 스크립트를 짜봤다.
https://gist.github.com/sjp38/7095984


참고 자료:

댓글 없음:

댓글 쓰기