다음은 포팅 과정에서 만나게 될 흔한 주의점의 목록입니다. 여러분의 포트를 이 목록에 대해 검사해 보아야 하지만, 다른 사람이 보낸 것도 PR 데이터베이스에서 검사해 볼 수 있습니다. 여러분이 검사한 포트에 대한 의견은 버그 리포트와 일반적인 의견에서 설명한 대로 보내세요. PR 데이터베이스의 포트를 검사하는 것은 우리가 그 포트를 빨리 등록할 수 있도록 하고, 여러분이 어떻게 하고 있는지 안다는 것을 증명해 줍니다.
바이너리를 작게 만드세요. 원본 소스가 이미 바이너리 스트립
(역주: `strip'명령으로 심볼 테이블이나 기타 실행에 필요하지
않는 정보를 삭제하는 일)을 한다면, 됐습니다. 그렇지 않다면
post-install 규칙에 직접 하는 방법을 추가해야 합니다.
여기 예를 보세요:
post-install:
strip ${PREFIX}/bin/xdl
file 명령을 설치된 실행 파일에 사용해서
바이너리가 스트립되었는지 아닌지를 알아볼 수 있습니다.
그 명령이 `not stripped(스트립 안 되었음)'이라고 하지 않는다면,
스트립 된 것입니다.
bsd.port.mk에서 제공하는 매크로를 사용하여
여러분의 *-install 타겟에서 올바른 모드와 소유자를 설정하도록
확인하세요. 이것들은 다음과 같습니다:
${INSTALL_PROGRAM}은
바이너리 실행 파일을 설치하는 명령입니다.${INSTALL_SCRIPT}는
실행 가능한 스크립트를 설치하는 명령입니다.${INSTALL_DATA}는
공유할 수 있는 자료를 설치하는 명령입니다.${INSTALL_MAN}은
매뉴얼 페이지와 다른 문서를 설치하는 명령입니다
(아무것도 압축하지 않습니다).이들은 기본적으로 적절한 인수를 지정한 install
명령입니다. 아래 예제에서 사용 방법을 보세요.
변경해야 하거나 동작하는 UNIX의 버전에 따른 조건부 컴파일을 해야 하는 코드를 만날 수 있습니다. 조건부 컴파일때문에 코드를 변경해야 한다면, 변경사항을 되도록이면 일반화하여 FreeBSD 1.x시스템으로 하위 포팅을 하거나 CSRG의 4.4BSD, BSD/386, 386BSD, NetBSD, OpenBSD와 같은 다른 BSD시스템으로 크로스 포팅할 수 있도록 해야 합니다.
4.3BSD/Reno (1990)와 BSD코드의 새 버전을 판별하는 권장 방법은
<sys/param.h>에 정의된 `BSD' 매크로를
사용하는 것입니다. 다행히도 이 파일은 이미 C코드안에 포함되는 경우가
많습니다. 그렇지 않다면 다음 코드를:
#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif
.c 파일 안의 적당한 곳에 추가하세요. 이들을 심볼로 정의하는
모든 시스템은 sys/param.h을 갖고 있다고 믿습니다. 그렇지 않은 시스템을
알고 있다면, 알려 주세요. FreeBSD 포트 메일링 리스트
<freebsd-ports@FreeBSD.ORG>에 전자우편을 보내 주시기 바랍니다.
다른 방법은 GNU Autoconf스타일의 해결방법을 따르는 것입니다:
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
이 방법에서는 Makefile의 CFLAGS에
-DHAVE_SYS_PARAM_H를 추가하는 것을 꼭 기억해야
합니다.
일단 <sys/param.h>을 포함하였다면, 다음과 같이 사용합니다:
#if (defined(BSD) && (BSD >= 199103))
위 코드는 컴파일되는 코드가 4.3 Net2 코드기반이나 그 이상인지 탐지합니다(FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1과 그 아래).
#if (defined(BSD) && (BSD >= 199306))
를 사용해서 컴파일되는 코드가 4.4 코드 기반이나 그 이상인지 탐지하세요( FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 이상).
BSD 매크로의 값은 4.4BSD-Lite2 코드 기반에서는 199506입니다. 이는 정보 제공의 목적으로만 사용됩니다. 이 값은 4.4-Lite에만 기반을 둔 FreeBSD 버전과 4.4-Lite2의 변경사항을 포함하는 FreeBSD 버전 간의 비교에 사용되어서는 안됩니다. 대신에 __FreeBSD__ 매크로를 사용해야 합니다.
드물게는 다음과 같이 사용합니다:
__FreeBSD__ 는 모든 버전의 FreeBSD에서 정의되어
있습니다. FreeBSD에만 영향을 주는 변경을 하고 있다면 이것을
사용하세요. sys_errlist[] 와 strerror()를
사용할 것인지에 대한 포팅 문제는 버클리주의지 FreeBSD에서의
변경사항이 아닙니다.
__FreeBSD__가 2로 정의되어
있습니다. 이전 버전에서는 1입니다. 나중 버전도 각각의
주 버전 번호에 맞도록 올라갈 것입니다.
BSD 매크로를 사용하는 것입니다. 실제적으로
FreeBSD에만 해당하는 변경이 있었다면(`ld'를 사용할 때의
특별한 공유 라이브러리 옵션과 같은) FreeBSD 2.x와 그 이상
시스템을 탐지하기 위해 __FreeBSD__와 `#if __FreeBSD__ >
1'를 사용하는 것이 좋습니다.
2.0-RELEASE이후의 FreeBSD시스템을 자세히 알아내고 싶다면
다음을 사용하세요:
#if __FreeBSD__ >= 2
#include <osreldate.h>
# if __FreeBSD_version >= 199504
/* 2.0.5+ 릴리즈에 특정한 코드는 여기에 */
# endif
#endif
__FreeBSD_version 값:
2.0-RELEASE: 199411
2.1-current's: 199501, 199503
2.0.5-RELEASE: 199504
2.2-current(2.1 이전): 199508
2.1.0-RELEASE: 199511
2.2-current(2.1.5 이전): 199512
2.1.5-RELEASE: 199607
2.2-current(2.1.6 이전): 199608
2.1.6-RELEASE: 199612
2.1.7-RELEASE: 199612
2.2-RELEASE: 220000
2.2.1-RELEASE: 220000 (예, 변경 없습니다)
2.2-STABLE (2.2.1-RELEASE 이후): 220000 (예, 그래도 변경 없습니다)
2.2-STABLE (texinfo-3.9 이후): 221001
2.2-STABLE (top 이후): 221002
2.2.2-RELEASE: 222000
2.2-STABLE (2.2.2-RELEASE 이후): 222001
2.2.5-RELEASE: 225000
2.2-STABLE (2.2.5-RELEASE 이후): 225001
2.2-STABLE (ldconfig -R 통합 이후): 225002
2.2.6-RELEASE: 226000
2.2.7-RELEASE: 227000
2.2-STABLE (2.2.7-RELEASE 이후): 227001
2.2-STABLE (semctl(2) 변경 이후): 227002
3.0-current (mount(2) 변경 이전): 300000
3.0-current (mount(2) 변경 이후): 300001
3.0-current (semctl(2) 변경 이후): 300002
3.0-current (ioctl 인수 변경 이후): 300003
3.0-current (ELF변환 이후): 300004
3.0-RELEASE: 300005
3.0-current (3.0-RELEASE 이후): 300006
(2.2-STABLE은 종종 2.2.[567]-RELEASE이후에도 자신을
2.2.5-STABLE이라고 나타내는 것에 주의하세요)
이 형태는 연도 다음에 월을 나타내는 것이었지만 2.2 부터
시작하는 조금 더 간단한 주/부 시스템의 시작에 맞추어
바꾸었습니다. 이는 여러가지 가지에서의 병렬 개발에서는 실제
릴리즈 날짜로 단순하게 릴리즈를 판별하기에는 불가능하기
때문입니다.
(지금 포트를 만들고 있다면 이전 -current에 대해서는 걱정하지
않아도 됩니다. 이것들은 단순히 참조하라고 나열해 놓은
것입니다).
이미 만들어진 수백가지 포트에서 __FreeBSD__를 사용해야만 하는
경우는 단지 한두가지일 뿐입니다. 이전에 포트를 잘못 만들어서 잘못된
곳에서 이를 사용했다는 사실 때문에 여러분도 그래야 한다는 것을
의미하지는 않습니다
이 소프트웨어에
표준 메뉴얼 페이지와 info 페이지 이외에 사용자에게 유용하리라
생각하는 문서가 있다면, ${PREFIX}/share/doc
아래에 설치하세요. 이전 것들 처럼 post-install 타겟에서
할 수 있습니다.
포트를 위해 새 디렉토리를 만드세요. 디렉토리 이름은
포트가 무엇인지를 반영해야 합니다. 이는 보통
${PKGNAME}에서 버전 부를 뺀 것입니다.
그러나 사용자가 동시에 포트의 여러 버전을 필요로 할 것이라
생각되면 전체 ${PKGNAME}을 사용할 수 있습니다.
문서의 설치를 사용자가 /etc/make.conf에서 막을 수
있도록 NOPORTDOCS 변수에 따르도록 하세요. 다음
예를 보세요:
post-install:
.if !defined(NOPORTDOCS)
${MKDIR} ${PREFIX}/share/doc/xv
${INSTALL_MAN} ${WRKSRC}/docs/xvdocs.ps ${PREFIX}/share/doc/xv
.endif
pkg/PLIST에 추가하는 것을 잊지 마세요!
(여기에선 NOPORTDOCS에 대해 걱정하지 마세요.
현재로서는 패키지가 /etc/make.conf에서 변수를 읽도록
하는 방법이 없습니다.)
또한, pkg/MESSAGE 파일을 사용해서 설치 후에
메시지를 표시하도록 할 수 있습니다.
자세한 것은
pkg/MESSAGE 사용
을 보세요.
포트가 /usr/ports/distfiles를 난잡하게 만들도록 하지
마세요. 포트가 많은 파일을 얻어와야 하거나, 다른 포트와 충돌할 만한
이름을 가진 파일을 얻어와야 한다면(예: `Makefile'),
${DIST_SUBDIR}을 포트의 이름
(버전 번호를 제외한 ${PKGNAME}면 됩니다)으로
지정하세요. 이것은 ${DISTDIR}을 기본값인
/usr/ports/distfiles에서
/usr/ports/distfiles/${DIST_SUBDIR}로 바꾸며,
결과적으로 여러분의 포트에서 필요한 모든 것을 그 부디렉토리에
넣도록 합니다.
또한 ftp.freebsd.org의 백업 마스터 사이트의 같은 이름으로
된 부디렉토리도 살펴봅니다.
(${DISTDIR}을 명시적으로 Makefile에 지정하면
그렇게 되지 않으므로, ${DIST_SUBDIR}을 꼭 쓰세요)
이것은 Makefile에서 정의한 ${MASTER_SITES}에는
영향을 미치지 않는다는 것에 주의하세요.
RCS 문자열을 패치에 넣지 마세요. CVS는 파일을 포트 트리에
넣을 때 그 부분을 망가뜨릴 것이며, 나중에 다시 꺼낼 때
다르게 나와서 패치가 실패할 것입니다. RCS 문자열은
달러 기호 (`$')로 둘러쌓여 있으며,
보통 `$Id'나 `$RCS'로
시작합니다.
패치를 만들기 위해 diff의 재귀 (`-r')옵션을
쓰는 것은 좋습니다만, 패치의 결과가 불필요한 쓰레기를 만들어내지
않는지 확인해 주세요. 특히, 두 백업 파일 사이, 포트가 Imake나
GNU configure 등을 사용할 때의 Makefile 사이의 diff는 불필요하며
지워야 합니다.
configure.in을 고쳐서 configure를 재생성하기 위해
autoconf를 실행해야 한다면, configure의 diff를 얻지 마세요
(종종 수천라인이 되기도 합니다!). USE_AUTOCONF=yes를 지정하고
configure.in의 diff를 얻으세요.
또한 파일을 지워야 할 때에는 패치의 일부에서보다는
post-extract 타겟에서 할 수 있습니다. 일단 diff의 결과에
만족한다면, 패치 파일당 하나의 소스 파일이 되도록 나눠 주세요.
포트의 설치가 ${PREFIX}에 상대적이도록 하세요.
(이 변수의 값은 ${LOCALBASE} (기본값은
/usr/local)이며, ${USE_X_PREFIX}
이나 ${USE_IMAKE}이 지정되어 있으면,
${X11BASE}입니다(기본값 /usr/X11R6).)
`/usr/local'이나 `/usr/X11R6'이 소스의
어디에서도 하드코딩되지 않도록 해야 포트가 더 유연해지고
다른 사이트의 필요에도 맞게 할 수 있습니다.
imake를 사용하는 X 포트에서는, 자동적으로 됩니다.
그렇지 않으면, 포트의 여러가지 스크립트/Makefile에서
`/usr/local'이 나오는 부분을
(imake를 사용하지 않는 X 포트들은 `/usr/X11R6')
`${PREFIX}'로 단순히 바꾸기만 하면 됩니다.
이 변수들은 컴파일과 설치 과정의 모든 단계에서 자동적으로
아래로 전달됩니다.
포트가 정말 USE_X_PREFIX을 필요로 하지 않는다면
지정하지 마세요
(예. X 라이브러리를 링크하거나 ${X11BASE}의
파일을 참조할 필요가 있는 경우).
${PREFIX}변수는 Makefile이나 사용자의 환경에서
재설정될 수 있습니다. 그러나, 개별 포트가 이 변수를 명시적으로
Makefile에서 지정하는 것은 정말 권장하지 않습니다.
또한, 명시적인 경로명이 아닌 위에서 언급한 변수를 사용하여
다른 포트의 프로그램/파일을 참조하세요. 예를 들면,
포트가 less의 전체 경로명을 얻기 위해
PAGER 매크로를 필요로 한다면, 다음 컴파일러 플래그를
사용하세요:
-DPAGER=\"${PREFIX}/bin/less\"
이나
X 포트인 경우
-DPAGER=\"/usr/local/bin/less\"대신
-DPAGER=\"${LOCALBASE}/bin/less\"
이 방법은 시스템 관리자가 `/usr/local' 트리를 다른 곳으로 옮겼을 경우에도 동작할 기회를 더 줄 것입니다.
포트가 ${PREFIX}의 올바른 부디렉토리에
설치하도록 하세요. 어떤 포트는 모든 것을 다 묶어서
포트의 이름으로 된 부디레게토리에 모든 것을 넣습니다만,
이것은 잘못된 것입니다. 또한 여러 포트는 바이너리,
헤더 파일, 매뉴얼 페이지를 제외한 모든 것을
`lib' 부디렉토리에 넣습니다만, 이는 BSD 패러다임에는
잘 맞지 않습니다. 많은 파일은 다음 위치로 옮겨야 합니다:
`etc' (셋업/설정 파일),
`libexec' (내부적으로 시작하는 실행 파일),
`sbin' (수퍼유저/관리자용 실행 파일),
`info' (info 브라우저의 문서),
`share' (아키텍처 독립적인 파일).
자세한 것은 hier(7)을 보세요, /usr에 적용되는
법칙은 대부분 /usr/local에 적용됩니다.
예외는 USENET `news'를 다루는 포트입니다. 이들 관련 파일의
설치는 ${PREFIX}/news을 사용합니다.
삭제할 때 포트가 스스로를 깨끗이 하도록 하세요.
이는 포트가 특별히 만들어낸 모든 디렉토리에 대해
@dirrm 행을 추가하는 것으로 충분합니다.
부모 디렉토리를 지우기 위해서는 부디렉토리를 먼저 지워야 한다는
사실을 주의하세요. 다음과 같습니다:
:
lib/X11/oneko/pixmaps/cat.xpm
lib/X11/oneko/sounds/cat.au
:
@dirrm lib/X11/oneko/pixmaps
@dirrm lib/X11/oneko/sounds
@dirrm lib/X11/oneko
그러나, 종종 @dirrm은 다른 포트가 같은 부디렉토리를
공유하는 관계로 오류가 날 수 있습니다. 경고 없이
빈 디렉토리만을 지우기 위해서 @unexec에서 rmdir을
부를 수 있습니다:
:
@unexec rmdir %D/share/doc/gimp 2>/dev/null || true
이는 오류 메시지를 지우지도 않고 다른 포트가
${PREFIX}/share/doc/gimp에 어떤 파일을 설치해서
비어 있지 않아도 pkg_delete가 비정상적으로 종료하지
않도록 합니다.
포트가 설치 시스템에 특정 사용자를 필요로 한다면,
pkg/INSTALL 스크립트가 pw를 불러 자동적으로
생성하도록 하세요. net/cvsup-mirror의 예를 보세요.
여러분의 포트는 바이너리 패키지를 설치할 때 컴파일될때와 같은
사용자/그룹 ID 번호를 사용한다면, 50에서 99사이의 빈 UID를
선택하고 아래에 등록하세요. japanese/Wnn의 예를 보세요.
시스템이나 다른 포트에서 이미 그 UID를 사용하지 않는지 확인하세요. 다음은 50에서 99 사이의 현재 UID 목록입니다.
majordom:*:54:54:Majordomo Pseudo User:/usr/local/majordomo:/nonexistent
cyrus:*:60:60:the cyrus mail server:/nonexistent:/nonexistent
gnats:*:61:1:GNATS database owner:/usr/local/share/gnats/gnats-db:/bin/sh
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
xten:*:67:67:X-10 daemon:/usr/local/xten:/nonexistent
pop:*:68:6:Post Office Owner (popper):/nonexistent:/nonexistent
wnn:*:69:7:Wnn:/nonexistent:/nonexistent
ifmail:*:70:66:Ifmail user:/nonexistent:/nonexistent
pgsql:*:70:70:PostgreSQL pseudo-user:/usr/local/pgsql:/bin/sh
ircd:*:72:72:IRCd hybrid:/nonexistent:/nonexistent
alias:*:81:81:QMail user:/var/qmail/alias:/nonexistent
qmaill:*:83:81:QMail user:/var/qmail:/nonexistent
qmaild:*:82:81:QMail user:/var/qmail:/nonexistent
qmailq:*:85:82:QMail user:/var/qmail:/nonexistent
qmails:*:87:82:QMail user:/var/qmail:/nonexistent
qmailp:*:84:81:QMail user:/var/qmail:/nonexistent
qmailr:*:86:82:QMail user:/var/qmail:/nonexistent
msql:*:87:87:mSQL-2 pseudo-user:/var/db/msqldb:/bin/sh
이 범위에서 새 UID나 GID를 예약하는 포트(또는 업그레이드)를 보낼 때에는 우리에게 알려주세요. 그렇게 해야 예약된 ID의 목록을 최신의 것으로 유지할 수 있습니다.
Makefile은 간단하고 합리적으로 작업해야 합니다.
줄수를 줄일수 있거나 더 읽기 쉽게 할 수 있다면, 그렇게 하세요.
그런 예제에는 쉘 `if' 구조 대신 make의 `.if'
구조를 사용한다거나, ${EXTRACT*}를 다시 정의할
수 있다면 do-extract를 재정의하지 않는다던가,
`CONFIGURE_ARGS += --prefix=${PREFIX}'대신
$GNU_CONFIGURE를 사용하는 등의 방법이 있습니다.
포트는 반드시 지정된 ${CFLAGS}변수를 존중해야
합니다(역주: CFLAGS를 별도로 지정하지 마세요).
그렇지 않다면, `NO_PACKAGE=ignores cflags'를
Makefile에 추가하세요.
${PREFIX}/etc에 설정 파일을 두어야 한다면,
pkg/PLIST에 적지 말고 설치하지 마세요.
그렇지 않으면 사용자가 주의깊게 편집한 파일을 pkg_delete
가 지우고 새 설치 파일로 덮어쓰게 될 것입니다.
대신, 예제 파일을 접두사를 붙여 설치하고
(`<파일명>.sample'이면 됩니다)
사용자가 소프트웨어를 동작시키기 전에 파일을 복사하고 편집해야
한다는 점을 알려주는
메시지를 표시해야 합니다.
포트를 내거나 소스에 반영할 때 portlint로 포트를 검사하세요.
코드의 다음 릴리즈에 포함할 수 있도록 원저자/관리자에게 적용할 수 있는 변경 사항/패치를 보내세요. 이는 다음 릴리즈에서 여러분의 작업을 더 편하게 해 줄 뿐입니다.
pkg/DESCR, pkg/COMMENT, pkg/PLIST
는 각각 두번 이상 검사해야 합니다.
포트를 다시 볼 때 더 좋은 생각이 떠오른다면, 그렇게 하세요.
우리 시스템에 GNU General Public License의 복수의 복사본을
두지 마세요(역주: COPYRIGHT파일을 설치하거나 pkg/DESCR에
GNU GPL을 쓰지 마세요).
법적 문제를 이야기할때에는 주의를 기울이세요! 우리가 불법적으로 소프트웨어를 배포하지 못하도록 하세요!
우리에게 물어보기 전에 기존의 예제와
bsd.port.mk 파일을 살펴보세요!
;)
문제가 있으면 우리에게 물어보세요! 그냥 맨땅에 해딩하지
마시고요! :)