Debian Packaging & Policy

Debian Packaging & Policy

본 포스트는 debian packaging과 policy(정책) 일부 대한 기본적인 지식을 소개하도록 함.

Introduction

Debian project 는 쉽게 말해 free OS 중 일종이고, 대표적인 예로 Ubutnu 가 debian 계열의 linux 배포판 중 하나이다.
개인적으로 내가 생각하는 Debian 의 가장 큰 장점은 package managing 이다.
Ubuntu를 써본 사람이라면 apt install XXXXX 이런 명령어를 필히 엄청 처 보았을 것이다.
여기서의 이 apt 가 debian 의 package manager 이고, 필요한 소프트웨어들을 아주 쉽게 설치/업그레이드/제거가 가능하다.
이번 주제는 이 pacakage 가 되겟다. 설명할 내용은 다음과 같다.

  • Debian Package는 어떤식으로 구성되고 동작하는가
  • Debian Package는 어떻게 만드는가
  • Debian Package가 지켜야할 것(Policy, 정책)은 어떤 것들이 있는가.
  • Debian Package의 유효성은 어떻게 검사하는가

여기서, 유효성 검사라 함은 sbuild 러는 tool을 통한 검사를 설명하고자 한다.
이것 말고도 다른 툴들이 있지만, 내가 안써봐서 모른다.
sbuild만 해도 충분히 어렵다.

Debian Package

Debian Package 는 기본적으로 .deb file라고 보면 된다.
dpkg 로 이러저러한 일들을 할 수 있는데, 일반적인 사용자 입장에서는 그냥 .deb file을 다운로드 받아서 압축을 풀고, 지정된 위치에 설치한다.
이게 apt install XXXX 했을때 일어나는 일이다.

서버

그렇다면 저 .deb 파일들은 어디서 가져오느냐.
ubuntu 기준으로는 /etc/apt/sources.list 파일에서 찾을 수 있다.
ubuntu의 package서버 주소가 서져 있을 것이다.
그 주소에 있는 패키지들을 받을 수 있고, 다른 서버를 추가하면 거기에 있는 또 다른 패키지들을 추가적으로 설치 할 수 있다.
주석으로 deb-src로 시작하는 내용이 있을텐데, 이는 "소스 패키지"를 가져올 수 있는 서버 이다.
이후 정책 파트에서 설명할 내용이지만, 쉽게 얘기해서 각 패키지의 소스 코드를 받을 수 있다.
이놈은 확장자가 deb 가 아닌 dsc 이다.

How to make DEB file

deb 파일을 만드는 방법은 여러가지이다.
기본적으로는 debian directory 생성 후에 control file에 필요한 내용을 적고, 설치될 파일 경로 지정해주고... 준비를 한다. 자세한 준비 과정은 debian poicy 세션, 문서를 참조하라.
그리고, dpkg -b 를 사용해서 만들면 deb file이 생성되는데, dpkg 명령어들로 설치, 삭제가 가능하다. 문제는 이렇게 manualy 작성한 deb 파일은 제대로 작동할리가 없다는 것.
왜냐하면, 패키지로 만들고자 하는 녀석의 dependancy들을 버전까지 상세히 알 수 없고, 미레에 버전이 올라갈때, 관리가 잘 안되기 마련이다.

내가 시도한 방법은 첫번째로, cpack이다. cmake로 이미 내 프로젝트가 빌드가 잘 되기 떄문에, 몇 가지만 추가하면 cpack으로 deb file 이 생성가능하다. 자동으로 debpendancy 또한 잡아준다.
그러나... 여전히 내가 만든 패키지가 어느 환경에서나 정상동작하는지 검증할 방법은 없다. 그래서, 알게 된 것이 sbuild 이다.
뒤에서 자세히 소개할 것인데, 우선 필요한 것은 deb file이 아니라 "소스 패키지" 이다. 소스로 부터 어느 환경에서나 빌드가 되는지 테스트하고, 그 이후에 deb 파일을 생성해준다.
Policy와 연관이 깊으니 policy를 먼저 간단히 보고 sbuild에 대해 소개하겠다.

Debian Policy

Debian Policy 문서를 링크타고 들어가서 한번 보시라. 너무 많다. 다 읽을수도 없고, 내 개인적인 생각으로는 꼭 다 지켜야 하는 것도 아니다.
우리에게 필요한 내용만 소개하고자 한다. (필요하지만 몰라서 소개 안하는 것도 있을 수 있다...)
앞서서, "소스 패키지" 없이 deb파일을 만드는 방법들을 소개했는데, 이렇게 만들어진 deb file들 만으로는 debian policy를 모두 지키지 못한 것이다.
Debian project 은 freeOS 답게, 모든 패키지 역시 오픈소스이고, 어느 시스템에서든지 빌드가 가능하고, 누구나 수정하고 재배포가 가능하기를 바란다.
이러한 상황을 가정하고 tool 들이 만들어져 있다. sbuild역시 마찬가지 이다.

간단한 예를 보자. grep 처럼 많이 쓰는 tool 역시 패키지 형태로 제공되고, 소스 또한 받을 수 있다.
apt source를 이용하면 source package 를 받을 수 있고, 직접 고쳐서 다시 재배포가 가능하다. 물론 debian 서버 관리자가 안받아줘서 debian 공식 서버에는 못 올리겠지만... 어떻게든 배포를 하려면 가능은 하다.

이 외에도 지켜야 할 것들이 생각보다 많다. 예를 들면, debian package들은 모드 debian directory를 가지고 있어야하고, 그 안에 여러 파일들이 있어야하는데, changelog 같은 변경사항을 기록하는 파일도 필수적으로 있어야한다. control 파일도 있어야하는데, 여기에도 maintainer 와 같은 사람 정보도 꼭 있어야하고, 패키지가 될 root directory이름은 NAME-X.X.X 와 같은 형식으로 버전이 명시 되어 있어야만한다.

또 중요한 것은 이미 build 가 된 binary 파일이 있으면 안된다. 특정 시스템에서 정상동작 하지 않을 수 있기 때문. 모든 것들은 source code로 부터 빌드되어야 한다.

게다가, apt (또는 그 외 시스템엥서 쓰이는 패키지매니저)를 써본사람들은 잘 알 겠지만, 패키지들은 개발용 여부에 따라 (주로 header 파일의 포함여부) 패키지가 분리된다.
freetype library 를 예로 들면, libfreetype / libfreetype-dev 이렇게. dev 버전은 develope 버전으로 헤더가 같이 설치된다. freetype라이브러리를 사용한 프로그램을 개발할 수 있다.
실행되는 시스템에 따라 (32bit/64bit 혹은 arm 과 같은 다른 architecture), 다른 형태의 패키지도 존재한다.

자세한 내용들은 debian policy 공식 문서를 참조하시고, 우리에겐 구세주와 같은 sbuild 가 이런 것들을 모두 검사해줄 것이다. 그렇다면, 최소한으로 꼭 지켜야 할 것들을 알려줄 것이고, 고놈들을 지키는 것부터 시작해보면 된다.

sbuild

Debian 배포판을 선택해서 sandbox를 만들고 테스트 하는 툴이다. 소스 패키지가 input 이 되고, 생성된 sandbox 환경에서 소스 패키지를 빌드하면서 테스트를 한다. 결과물은 빌드가 완료된 deb 파일과 테스팅 결과 및 데비안 정책 검사 결과 이다.
실제 실행시키는 과정을 통해 하나하나 설명하겠다.

환경설정

  • 나는 main machine 으로 64bit fedora 27을 사용하고 있었기 때문에, 여기서 먼저 시도해 보았다. debian 계열이 아니라 그런지 실패.
  • Gnome Boxes VM 을 이용해서, Ubuntu 17.10 (artful)을 설치하고 시도하였다. 역시 실패.
  • VM 이 아닌 Native로 Ubuntu 17.10 (artful) 64bit을 설치하고 시도하니 드디어 sbuild를 끝까지 실행할 수 있었다.

실패한 내용들은 굳이 설명할 필요 없을 것 같아서 생략함. 그저 삽질일 뿐.

실행

sbuild를 위해서는 debian source package 가 필요하다.

우선 프로젝트 이름을 debian 형식에 맞게 변경하자.
가상의 프로젝트 이름을 testp 라고 해보겟다.
mv testp testp-0.0.1
버전은 테스트용이기 때문에, 0.0.1 로 지정하였다.
버전에 관한 내용은 따로 뒤에서 설명하겠다.

그 이후에 tarball을 생성해 주어야 한다.
tar -cvzf testp-0.0.1.tar.gz testp-0.0.1
그럼 우리 프로젝트의 root directory와 같은 레벨에 압축된 파일이 생성된다.

이제 debmake를 실행하면 기본적으로 필요한 내용들이 생성된다.
orig tarball symlink 및 debian directory가 생성된다.
debian directory 안에는 changelog, control 등의 파일이 생성되고 내용도 저절로 적혀있다.
우리가 가장 관심있는 control 파일에는, 빌드를 위한 dependancy 와, 실행을 위한 dependancy가 나눠서 적혀있다.
알아서 소스를 보고 debmake가 찾아주는데, 경험살 잘 찾아주지는 않는다.
개인적으로 테스트 해 볼때, build는 하지 않는 참고용 code가 포함되어 있었는데, 여기를 뒤져서 필요없는 내용까지 추가되어있었다.
정작 필요한 내용들은 없어서 sbuild가 실패 했었다. 이럴 떄는 손으로 control 파일에 내용을 적어주어야 한다.

필요한 준비가 끝났으니, 소스 패키지를 생성할 차례.
dpkg-source -b testp-0.0.1
이제 .dsc 파일이 생성되었다.
여기서 dsc 의 format 을 default로 지정해 줄 텐데, 나는 quilt 3.0이었다.
이것 외에도 다른 format 들이 있는데, 뭐가 다른지는 잘 모르겠다.
아무거나 해도 되는 것 같아서 신경 안썼는데, 나중에 수정할때는 신경을 써야 하는 것 같다.
모든 소스 코드와 필요한 내용들이 준비가 되었으니, sbuild를 해 볼 수 있다.

sbuild 를 위해서는 테스팅할 sandbox를 생성해야 한다.
chroot를 이용해서 테스트해볼 환경을 구성할 수 있는데, debian의 distribution 버전과 architecture 를 선택하여 한번 만들면 여러번 재활용할 수 있다.
(따로 찾아보세염, 나중에 추가함)

생성한 환경들중에 테스트 해보고 싶은 dist와 arch 를 넣으면 테스트와 함께 필드가 된다.
sbuild -d testing testp-0.0.1.dsc (맞나? 확인해바야뎀)
주루루루륵 로그가 생기면서 내용을 확인을 할 수 있다.
여기서 testing 이란 debian의 test 용 배포버전인데, debian 이 알아서 버전을 올리면서 test 배포버전을 관리한다.

적어도 이 버전에서는 잘 동작함을 sbuild를 통해 확인할 수 있는 것이다!!
나는 내 프로젝트를 테스트해볼때 많은 문제들이 있었다.
build를 실패하면 terminal 에 로그가 찍히는데 그걸 보고 수정해 나가면 된다.
나는 다른 사람의 도움을 받아서 debian/control파일의 dependancy를 수정해서 build가 되게 하였다.
참고로, 내 컴퓨터에서랑 다른 분의 컴퓨터에서랑 로그가 달랐고, 그래서 삽질 꽤나 했는데, 아직도 왜 그런지는 잘 모르겠다.
로그는 터미널에도 찍히고, debug 옵션을 주면 더 자세하게 찍히고, sbuild를 실행한 곳에 XXX.build 라는 이름의 파일로도 저장된다.

build는 통과했지만 lintian은 실패했는데, lintian은 bug나 policy 위반을 검사해주는 것이라고 한다. 나는 정책위반을 좀 했는데, 이를 해결하려면 고민이 필요한 시점이다. 꼭 지켜야 하는지도 사실 잘 모르겠고.

어쨋든, 완전 깡통의 debian system에서 설치, 빌드는 완벽함을 보증 받은 상태라고 볼 수 있겠다.

참고

Versioning

버전은 여러가지 의미를 내포한다. 딱 보고 무슨의미인지 알 수 있으면 제일 좋다.
이런 것들을 위해서 여러 버저닝 정책들이 있는데, 통상적으로 debian 패키지에서 쓰는 버전을 보도록 하겠다.

형식은 A.B.C 이다. A는 major, B는 minor, C는 patch 버전이다.

  • major 버전은 주요 API들의 변화가 있을 수 있음을 암시한다. 하위호환성이 지원안될 수도 있다. python 이 대표적인 예. python2 와 python3는 사용 문법이 조금 다르다.
    또한, major버전이 0 이면 아직 정식 출시가 전임을 의미하고 어떠한 변화들도 있을 수 있다. 1 부터는 같은 major 버전에서 최소 하위호환성을 제공해야하고, API 문서등 사용법도 알려줄수 있어야 한다.
  • minor 버전은 의미있는 변화를 의미한다. 주요 업데이트.
  • patch 버전은 소소한 변화. 작은 버그 수정 같은 것.

이 외에도, package이름을 보면 버전처럼 보이는 숫자를 볼 수 있다.
예를 들면,
libfreetype6라는 패키지는 6 이 붙어서 버전이 6인거 같다. 하지만 정보를 조회하면 버전이 2.8.X 란다. 저 패키지 이름에 붙은 숫자는 여기서 말하는 버전이 아니며, 패키지 배포상의 숫자이다. 구분할 것.

또한 버전에는 뒤에 시스템이 붙을 수 있다. 2.8.2_ubuntu1 이런식으로. 뒤에는 주로 시스템에 따라 빌드가 다르게 되니 시스템을 쓰는 것 같은데, 자세히는 잘 모르겠다. dpkg 인가 sbuild인가가 알아서 붙여주긴 하더라.