Perl 해킹 방법

Perl 해킹 방법 (perlhack)

Perl 개발이 어떻게 이루어지는지 설명하는 문서예요. Perl 5 Porters 이메일 리스트, Perl 저장소, 버그 트래커, 패치 작성 지침, 그리고 Perl 개발 철학에 대한 해설을 담고 있어요.

출처: perlhack - How to hack on Perl

개요 (DESCRIPTION)

이 문서는 Perl 개발이 어떻게 진행되는지 설명해요. Perl 5 Porters 이메일 리스트, Perl 저장소, Perl 버그 트래커, 패치 지침, 그리고 Perl 개발 철학에 대한 해설의 세부사항을 포함해요.

초고속 패치 가이드 (SUPER QUICK PATCH GUIDE)

pod 수정, 버그 테스트, 주석 수정 같은 단일의 작은 패치 하나만 제출하고 싶다면 아주 쉬워요! 방법은 이렇습니다:

  • 소스 저장소를 확인하세요

perl 소스는 git 저장소에 있어요. 다음 명령으로 저장소를 클론할 수 있어요:

% git clone https://github.com/Perl/perl5.git perl
% cd perl
  • 최신 조언을 따르는지 확인하세요

이 가이드의 조언이 최근에 갱신됐을 수 있으니, perl 소스에서 최신 버전을 직접 읽어보세요:

% perldoc pod/perlhack.pod
  • 변경을 위한 브랜치를 만드세요

변경을 커밋할 blead 기반 브랜치를 만드세요. 이 브랜치는 나중에 Perl 이슈 트래커로 보내는 데 사용돼요.

% git checkout -b mychange
  • 변경을 하세요

해킹, 해킹, 해킹. Perl은 능력이 다른 여러 운영체제, 다른 파일시스템 구성, 심지어 다른 문자 집합을 가진 여러 플랫폼에서 실행된다는 점을 명심하세요. perlhacktips가 이에 대한 조언을 줘요.

  • 변경을 테스트하세요

다음 명령으로 모든 테스트를 실행할 수 있어요:

% ./Configure -des -Dusedevel
% make test

테스트가 통과할 때까지 계속 해킹하세요.

  • 변경을 커밋하세요

작업을 커밋하면 변경이 여러분의 로컬 시스템에 저장돼요: 먼저 커밋할 항목 목록에 작업을 추가해야 해요. 변경한 파일의 모든 것을 포함하려면 이렇게 말할 수 있어요:

% git add file1 file2 ...

하지만 더 유연한 방법은 이렇게 하는 거예요:

% git add -i

그리고 프롬프트를 따라 원하는 것을 선택적으로 추가하세요. 이것은 진행하면서 무엇을 추가하는지 다시 확인할 수 있게 해줘요. 전부 추가되면:

% git commit

git은 변경을 설명하는 커밋 메시지를 입력할 편집기(기본 편집기 또는 여러분이 구성한 것)를 열 거예요. 끝나면 저장하고 종료하세요.

프로젝트의 원활한 기능을 위해, 지금뿐 아니라 미래에도, 좋은 커밋 메시지를 작성하는 것이 중요해요. 이 내용은 아래 "Commit message"에서 다뤄요.

  • Perl 기여자 목록에 이름을 추가하세요

Perl에 기여한 모든 사람의 목록과 Git 커밋 기록을 유지해요. 기본은 perl 배포판의 일부인 AUTHORS 파일에 이름과 이메일 주소를 공개적으로 나열하며 우리의 감사를 보여주는 것이에요. 하지만 어떤 사람들은 대신 익명으로 남기를 선택해요.

이미 기여했다면, 새 이메일 주소 같은 걸로 기록을 갱신하려는 게 아니라면 이 단계를 건너뛰어도 돼요. 다음을 실행해서 가능성을 보세요:

perldoc Porting/updateAUTHORS.pl

한 번도 기여한 적이 없다면 다음 중 하나를 실행하세요:

공개적으로 인정받고 싶다면:

perl Porting/updateAUTHORS.pl
  • 익명으로 남고 싶다면:
perl Porting/updateAUTHORS.pl --exclude-me

그런 다음 변경을 커밋하세요.

  • 변경을 GitHub에 제출하세요

다음 단계는 패치를 GitHub에 제출하는 거예요.

아직 하지 않았다면 perl5 저장소의 GitHub 포크를 만들고 원격(remote)으로 추가하세요. GitHub 문서(https://help.github.com/en/articles/working-with-forks)에 설명된 대로요.

% git remote add fork [email protected]:MyUser/perl5.git

자세한 내용은 "Connecting to GitHub with SSH"를 보세요.

git push에 HTTPS URL을 쓰고 싶다면 "Cloning with HTTPS URLs"를 보세요.

% git remote add fork https://github.com/MyUser/perl5.git

이제 작업을 제출할 준비가 됐어요. 이렇게 하려면 새 브랜치를 포크로 푸시하세요.

% git push -u fork mychange

마지막으로 GitHub 문서(https://help.github.com/en/articles/creating-a-pull-request-from-a-fork)에 설명된 대로 브랜치에서 blead로 Pull Request를 만드세요.

  • 감사합니다

포터들이 Perl을 더 좋게 만드는 데 써 준 시간에 감사드려요. 고마워요!

  • 다음에 (Next time)

다음에 패치를 만들고 싶을 때는 최신 perl의 원시(pristine) 상태에서 시작해야 해요. 보관하고 싶은 로컬 변경이나 추가 파일이 있는지 확인한 뒤 다음 명령을 실행하세요:

% git checkout blead
% git pull
% git reset --hard origin/blead
% git clean -dxf

버그 보고 (BUG REPORTING)

Perl의 버그를 보고하거나 기존 Perl 버그와 패치를 찾아보려면 GitHub 이슈 트래커(https://github.com/perl/perl5/issues)를 사용하세요.

버그 리포트를 제출하기 전에 perl5-porters 리스트의 아카이브(아래 참조)와/또는 버그 추적 시스템을 확인하세요. 종종 버그가 이미 보고되었을 거예요.

버그 추적 시스템에 로그인해 기존 버그 리포트에 댓글을 달 수 있어요. 기존 버그에 대한 추가 정보가 있다면 추가해 주세요. 포터들이 버그를 고치는 데 도움이 돼요.

PERL 5 PORTERS

perl5-porters (p5p) 메일링 리스트는 Perl 표준 배포판이 유지·개발되는 곳이에요. Perl을 유지하는 사람들을 "Perl 5 Porters", "p5p", 또는 그냥 "포터들(porters)"이라고도 불러요.

리스트의 검색 가능한 아카이브는 https://markmail.org/search/?q=perl5-porters 에 있어요. https://archive.develooper.com/[email protected]/ 에도 아카이브가 있어요.

perl-changes 메일링 리스트

perl5-changes 메일링 리스트는 perl 저장소의 유지·개발 브랜치에 제출되는 각 패치의 사본을 받아요. 구독과 아카이브 정보는 https://lists.perl.org/list/perl5-changes.html 을 보세요.

IRC의 #p5p

많은 포터들이 irc://irc.perl.org/#p5p 채널에도 활동해요. 자유롭게 채널에 가입해서 Perl 코어 해킹에 대해 질문하세요.

PERL 소스 얻기 (GETTING THE PERL SOURCE)

Perl의 모든 소스 코드는 github.com의 단일 Git 저장소에 중앙 저장돼요. 저장소에는 Perl 1 이후의 많은 Perl 개정과, 이전 버전 관리 시스템인 Perforce의 모든 개정이 들어 있어요.

git을 Perl 저장소와 함께 사용하는 방법의 훨씬 자세한 내용은 perlgit을 보세요.

Git을 통한 읽기 접근 (Read access via Git)

컴퓨터에 Git 사본이 필요해요. git 프로토콜을 사용해 저장소 사본을 가져올 수 있어요:

% git clone [email protected]:Perl/perl5.git perl

이것은 저장소를 클론하고 perl 디렉토리에 로컬 사본을 만들어요.

방화벽 이유로 git 프로토콜을 사용할 수 없으면 http로도 클론할 수 있어요:

% git clone https://github.com/Perl/perl5.git perl

웹을 통한 읽기 접근 (Read access via the web)

웹으로 저장소에 접근할 수 있어요. 이것은 트리를 탐색하고, 최근 커밋을 보고, 저장소 알림을 구독하고, 특정 커밋을 검색하는 등을 할 수 있게 해줘요. https://github.com/Perl/perl5 에서 접근할 수 있어요.

git을 통한 쓰기 접근 (Write access via git)

commit bit이 있다면 git 사용의 자세한 내용은 perlgit을 보세요.

Perl 패치 (PATCHING PERL)

단일의 작은 수정보다 더 광범위한 작업을 계획하고 있다면 아래 문서를 읽으시길 권해요. 이것은 작업에 집중하고 패치가 Perl 소스에 통합되기 쉽게 만드는 데 도움이 돼요.

패치 제출 (Submitting patches)

제출할 작은 패치가 있다면 GitHub Pull Request 워크플로로 제출해 주세요. p5p 리스트로 패치를 보낼 수도 있어요.

패치는 GitHub 또는 p5p 리스트에서 검토·논의돼요. 단순하고 논란 없는 패치는 보통 토론 없이 적용돼요. 패치가 적용되면 티켓이 갱신되고 이메일을 받게 돼요.

다른 경우에는 패치에 더 많은 작업이나 논의가 필요해요. 논의에 참여하고 패치를 옹호하시길 권해요. 때로 패치는 우연히 잊혀질 수 있어요. 한 달 동안 아무 조치가 없으면 p5p에 알림 이메일을 보내는 게 적절해요. Perl 5 개발자는 모두 자원봉사자라는 점을 기억하고 정중하게 행동하세요.

변경은 항상 "blead"라는 메인 개발 브랜치에 직접 적용돼요. 일부 패치는 유지 브랜치로 백포트될 수 있어요. 패치가 유지 브랜치에 적절하다고 생각하면(perlpolicy의 "MAINTENANCE BRANCHES" 참조), 제출할 때 그 이유를 설명해 주세요.

패치 수락 받기 (Getting your patch accepted)

코드 패치를 제출한다면 Perl 5 Porters가 패치를 수락하도록 도울 수 있는 몇 가지가 있어요.

패치 스타일 (Patch style)

GitHub Pull Request 워크플로를 사용하면 패치가 자동으로 적절한 형식으로 제공돼요. p5p 리스트에 검토용 패치를 제출하고 싶다면 적절하게 만드세요.

git으로 Perl 소스를 체크아웃했다면 git format-patch를 사용하면 Perl에 적합한 스타일의 패치가 만들어져요. format-patch 명령은 각 커밋마다 패치 파일 하나를 만들어요. 모든 커밋에 단일 패치를 보내는 걸 선호한다면 git diff를 사용할 수 있어요.

% git checkout blead
% git pull
% git diff blead my-branch-name

이것은 blead와 현재 브랜치의 차이에 기반한 패치를 만들어요. diff를 만들기 전에 blead가 최신인지 확인하는 것이 중요해요, 그래서 git pull을 먼저 호출해요.

가능하면 git을 사용하길 강력히 권해요. 여러분의 삶과 우리의 삶을 더 쉽게 만들 거예요.

하지만 git을 사용하지 않더라도 적절한 패치를 만들 수 있어요. 디핑할 깨끗한 Perl 소스 사본이 필요해요. 포터들은 통합 디프(unified diff)를 선호해요. GNU diff를 사용해 이런 디프를 만들 수 있어요:

% diff -Npurd perl.pristine perl.mine

Perl 사본에서 make realclean을 실행해 빌드 아티팩트를 제거하세요. 그렇지 않으면 혼란스러운 결과를 얻을 수 있어요.

커밋 메시지 (Commit message)

커밋 메시지는 커밋에 대해 이 질문들에 답해야 해요: "누가(Who)", "언제(When)", "무엇을(What)", "어디서(Where)", "왜(Why)", "어떻게(How)".

git은 자동으로 "누가"(여러분)와 "언제"(지금)를 넣으므로 일반적으로 걱정할 필요 없어요. 하지만 나머지 네 개에는 확실히 답해야 해요.

커밋 메시지는 제목과 본문 두 부분이 있어요. 드물게, 제목이 변경을 적절히 설명하면 본문을 생략할 수 있어요. 그런 경우 git 단축키로 커밋을 만들 수 있어요:

% git commit -m'perlhack: Fix spelling error'

이것은 git이 편집기를 여는 것을 방지해 키 입력을 절약해 줘요.

이 경우 제목은 "무엇"(철자 오류)과 "어디서"(pod/perlhacktips.pod)에 답해요. "왜"는 생략하는데, 이런 오류는 항상 고쳐야 할 나쁜 것이라는 프로젝트 정책을 올바르게 가정하기 때문이에요. "어떻게"도 생략하는데, 이 경우 답이 명백하기 때문이에요.

제목은 아주 중요해요. 먼 미래까지 반복해서 읽힐 거예요; 본문보다 훨씬 자주요. 지금 제목을 만들 때 인색하는 것은 Perl의 미래 유지자들에게 부당한 일이에요.

그리고 제목은 이메일의 Subject: 줄처럼 약 50자 이하로 짧아야 해요. 일부 도구는 더 긴 제목을 거부하고, 일부는 50번째 문자쯤에서 표시를 자르기만 해요.

제목은 제한된 공간에서 충분한 정보를 전달해서 git log를 하는 사람이 커밋 메시지 본문이 현재 필요로 하는 것과 관련 있는지, 아니면 더 깊이 들어가지 않고 다음 커밋으로 건너뛸 수 있는지 즉시 결정할 수 있어야 해요.

즉 최소한 "무엇"과 "어디서"에 답하고, 여유가 있으면 "왜"의 힌트도 담아야 해요. "어떻게"는 일반적으로 메시지 본문으로 미룰 수 있어요.

"무엇"은 유용할 만큼 충분한 세부사항이 있어야 하지만, 무의미한 세부사항을 제공할 만큼 많지는 않아야 해요. 예를 들어 철자 오류를 고칠 때 사람들이 어떤 단어가 잘못 쓰였는지 알고 싶어할 가능성은 낮아요. 그 정보를 주는 것은 오히려 그들이 진짜 목적에 집중하는 것을 방해할 수 있어요. 직접 git log를 해보세요. 이 질문에 답하는 좋은 제목의 예가 대부분 있고, 가끔 더 많았으면 하는 생각이 드는 것도 있을 거예요.

"어디서"는 형태가 크게 다를 수 있어요. 어떤 경우에는 "regex"나 "mro"(메서드 해석 순서) 같은 하위 시스템을 가리킬 거예요. 어떤 경우에는 특정 함수를 가리켜요:

% git commit -m'Use getentropy() for seeding PRNG in Perl_seed()'

드물게는 파일을:

% git commit -m'embed.fnc: Add ptr asserts for refcounted functions'

때로는 모듈을:

% git commit -m'Devel::PPPort: Add support for utf8_to_uv'

그리고 드물게는 완전히 생략돼요:

% git commit -m'Add feature "class"'

간결함은 커밋 제목에서 유용해요. 50자 제한 때문만이 아니라, 불필요한 세부사항을 추가하지 않도록 편향시켜 미래에 git log를 훑는 사람들이 더 빨리 읽을 수 있게 하기 때문이에요. "어디서: 제목 나머지" 스타일은 "어디서" 답에 가장 적은 문자를 쓰는 경향이 있어 "무엇"에 더 많은 문자를 남겨요. 때로는 맞추기 위해 창의력을 발휘해야 할 때가 있어요. 예를 들어 위 예의 'Devel::'은 메시지가 문자 제한을 초과하면 생략할 수 있었어요. 제목을 더 간결하게 다시 쓰는 데 시간을 좀 써야 할 수도 있어요. 필요하면 약어도 허용돼요. 하지만 이것은 모국어가 영어가 아닌 사람들도 읽는다는 점을 명심하세요.

커밋 메시지 본문은 일반 영어로 세부사항을 채워요. 커밋이 실제로 머지되려면, 그 변경이 잠재적 피해를 능가할 만큼 바람직하다고 판단할 권한이 있는 사람을 설득해야 해요. 본문은 핵심 요점과 무관한 텍스트를 포함하지 않아야 해요.

이런 경우에는 일반적으로 설득이 필요 없고(따라서 제목 이상을 포함할 필요 없음):

% git commit -m'"Where": Add/clarify comments'
% git commit -m'"Where": Use more mnemonic variable name'
% git commit -m'"Where": Move ARGS_ASSERT to top of function'

(마지막 것은, 커밋을 머지할 수 있는 사람이라면 그런 매크로가 함수 최상단에 두는 것이 가장 좋고, 많은 매크로가 C99로의 이동으로 해제된 C89 컴파일러 제한으로 그렇게 하지 않았을 뿐이라는 것을 알기 때문이에요.)

커밋 메시지는 패치가 고치는 문제나 추가하는 새 기능에 대한 설명을 포함해야 해요.

일반적으로 커밋 메시지는 Perl 코어를 아는 프로그래머가 여러분이 무엇을 하려 했는지, 어떻게 하려 했는지, 그리고 왜 그 변경이 Perl에 중요한지 빠르게 이해하도록 도와야 해요.

  • 왜 (Why)

메시지 본문은 왜 만드는 변경이 중요한지 설명해야 해요. 누군가 6개월이나 6년 뒤에 여러분의 변경을 보면, 여러분의 의도가 명확해야 해요.

나중에 다른 코드 조각을 단순화할 의도로 기능을 폐기(deprecate)한다면, 그렇게 말하세요. 성능 문제를 고치거나 코어의 다른 부분을 지원하기 위해 새 기능을 추가한다면, 그것을 언급하세요.

  • 무엇 (What)

메시지 본문은 제목의 내용을 확대해 Perl 코어의 어떤 부분을 변경하는지, 그리고 패치가 무엇을 하길 기대하는지 설명해야 해요.

  • 어떻게 (How)

문서 변경, 새 테스트, 사소한 패치에는 필요하지 않지만, 변경이 어떻게 작동하는지 설명할 가치가 보통 있어요. 오늘 여러분에게 명확해도, 다음 달이나 다음 해의 포터에게는 명확하지 않을 수 있어요.

본문은 고려된 대안들보다 이 특정 구현을 선택한 이유를 설명하는 자리예요. 성능 향상을 주장한다면 여기에 뒷받침하는 벤치마크를 추가하는 것이 좋아요.

우리는 이제 GitHub을 사용하며, GitHub은 커밋 메시지에서 이런 형태의 문구를 검색해요:

m/Fixes\s+#(\d+)/

그것을 찾으면 매치된 숫자를 가져와 PR이 머지될 때 그 번호의 GitHub 이슈를 자동으로 닫아서 노력을 절약해줘요. (그 형태여야 한다는 것을 주의하세요. 대신:

Fixes GH #1234

라고 하면 #1234에는 아무 일도 일어나지 않아요.)

이것은 GitHub에서 이슈와 Pull Request를 교차 연결한다는 추가 혜택도 있어서, 하나에서 시작해 다른 하나를 찾고 어떤 논의가 있었는지 보기 쉬워요.

하지만 이것은 적절한 커밋 메시지의 대체물이 아니에요. 우리가 영원히 GitHub에 있지 않을 수도 있고, 그래서 이 정보를 복구하기 어려워질 수 있어요.

커밋 메시지도 코드의 주석 자리를 대체하려는 의도가 아니에요. 커밋 메시지는 만든 변경을 설명하고, 코드 주석은 코드의 현재 상태를 설명해야 해요.

방금 새 기능을 문서, 테스트, 잘 주석이 달린 코드와 함께 구현했다면 짧은 커밋 메시지로 충분할 때가 많아요. 하지만 파서나 렉서 깊숙이에서 단일 문자만 변경했다면, 미래의 독자가 무엇을 했고 왜 했는지 이해하도록 보장하려면 작은 소설을 써야 할 수도 있어요.

주석, 주석, 주석 (Comments, Comments, Comments)

코드에 적절히 주석을 다세요. 모든 줄에 주석을 다는 것은 불필요하지만, 연산자의 부작용을 이용하거나, 패치되는 함수 밖에서 느껴질 변경을 만들거나, 다른 사람이 혼란스러워할 수 있는 것은 문서화해야 해요. 오류를 범한다면, 주석을 너무 적게 다는 것보다 너무 많이 다는 쪽으로 하는 것이 낫습니다.

최고의 주석은 코드가 무엇을 하는지가 아니라 그렇게 하는지 설명해요.

스타일 (Style)

일반적으로, 패치하고 있는 코드의 특정 스타일을 따라주세요.

특히 Perl 소스를 패치할 때 다음과 같은 일반 지침을 따르세요:

  • 코드에는 4칸 들여쓰기, 중첩된 CPP #define에는 2칸 들여쓰기, 8칸 탭스톱.

  • 들여쓰기에 탭 문자 대신 공백을 사용하세요.

코드베이스는 들여쓰기에 탭과 공백이 혼합되어 있고, 우리는 공백만으로 옮겨가고 있어요. 패치하는 줄을 8칸 탭에서 공백으로 변환하면 이 마이그레이션에 도움이 돼요.

  • 79칼럼을 넘지 않도록 노력하세요

일반적으로 80칼럼 줄을 목표로 해요. 80칼럼을 지키는 것이 고문스러운 코드나 재작업으로 이어질 때는 더 길어도 괜찮아요. 80을 넘는 초과를 최소화하려고 하세요.

  • ANSI C 프로토타입

  • 언커들드 else(uncuddled elses)와 제어 구조 들여쓰기의 "K&R" 스타일

  • C++ 스타일(//) 주석 없음

  • 다시 방문해야 할 곳을 XXX로 표시하세요(그리고 자주 방문하세요!)

  • 조건이 여러 줄에 걸칠 때 열린 중괄호는 "if"와 정렬; 그 외에는 줄 끝에 있어야 함

  • 함수 정의에서 이름은 0열에서 시작(반환 값 타입은 이전 줄에)

  • 괄호가 따르는 키워드 뒤에는 공백 하나, 함수 이름과 괄호 사이에는 공백 없음

  • 조건문에서의 할당은 피하고, 불가피하면 추가 괄호 사용, 예: "if (a && (b = c)) ..."

  • "return foo;" — "return(foo);"보다

  • "if (!foo) ..." — "if (foo == FALSE) ..." 등보다

  • "register"로 변수를 선언하지 마세요. 현대 컴파일러에서는 역효과일 수 있고, Perl 소스가 정기적으로 컴파일되는 C++에서는 폐기되었어요.

  • XS 코드가 접근할 수 있는 헤더의 인라인 함수는 gcc의 -Wswitch-default(switch 문에 "default" 케이스가 없을 때마다 경고) 같은 흔히 쓰는 추가 컴파일 플래그로 경고 없이 컴파일될 수 있어야 해요. 이런 추가 플래그의 사용은 합법적인 C 코드의 잠재적 문제를 잡기 위한 것이고, Linux 배포자 같은 Perl 집계자(aggregators)가 자주 사용해요.

테스트 스위트 (Test suite)

패치가 (문서만 바꾸는 게 아니라) 코드를 바꾼다면, 고치는 버그를 보여주거나 추가하는 새 기능을 검증하는 하나 이상의 테스트 케이스도 포함해야 해요. 일반적으로 새 테스트 파일을 만들기보다 기존 테스트 파일을 갱신해야 해요.

테스트 스위트 추가물은 일반적으로 이 지침을 따르세요(Gurusamy Sarathy [email protected]의 제공):

  • 무엇을 테스트하는지 알라. 문서와 소스를 읽어라.

  • 성공보다 실패하는 경향.

  • 결과를 엄격하게 해석.

  • 무관한 기능을 사용(이상한 상호작용을 드러내기 위해).

  • 비표준 관용구 사용(그렇지 않으면 TIMTOWTDI를 테스트하지 않는 것).

  • 가능하면 하드코딩된 테스트 숫자를 피하라(t/op/tie.t의 EXPECTED/GOT가 훨씬 더 유지보수하기 쉽고 더 나은 실패 보고를 줌).

  • 테스트가 실패할 때 의미 있는 에러 메시지를 주라.

  • 테스트 대상이 아니면 qx//와 system()을 피하라. 사용한다면 모든 perl 플랫폼을 커버하는지 확인하라.

  • 만든 임시 파일을 unlink하라.

  • 예상치 못한 경고를 $SIG{WARN}로 에러로 승격하라.

  • 이미 설치된 것이 아니라 테스트되는 버전과 함께 제공되는 라이브러리와 모듈을 사용해야 한다.

  • 무엇을 테스트하는지 설명하는 주석을 코드에 추가하라.

  • '1..42' 문자열 갱신을 불필요하게 만들라. 또는 반드시 갱신하라.

  • 주어진 연산자, 라이브러리, 함수의 모든 동작을 테스트하라.

모든 선택적 인자를 테스트하라.

다양한 컨텍스트(불리언, 스칼라, 리스트, lvalue)에서 반환 값을 테스트하라.

전역과 어휘 변수를 모두 사용하라.

예외적이고 병리적인 경우를 잊지 마라.

코어 모듈 패치 (Patching a core module)

이것은 한 가지 추가 고려사항과 함께, 다른 것처럼 패치하는 것과 똑같아요.

소스 트리의 cpan/ 디렉토리에 있는 모듈은 Perl 코어 밖에서 유지돼요. 저자가 모듈을 갱신하면 갱신본이 그냥 코어에 복사돼요. 버그 보고와 패치 제출에 대한 자세한 내용은 그 모듈의 문서나 https://metacpan.org/ 의 목록을 보세요.

대부분의 경우 cpan/ 모듈에 대한 패치는 업스트림으로 보내야 하고 Perl 코어에 개별적으로 적용해서는 안 돼요. cpan/ 파일에 대한 패치가 업스트림 수정이 이루어져 CPAN에 릴리스되고 blead에 복사될 때까지 절대 기다릴 수 없다면, 로컬 수정이 이루어졌음을 표시하기 위해 Porting/Maintainers.pl 파일에 CUSTOMIZED 항목을 추가(또는 갱신)해야 해요. 자세한 내용은 Porting/Maintainers.pl을 보세요.

반대로 dist/ 디렉토리의 모듈은 코어에서 유지돼요.

perldelta 갱신 (Updating perldelta)

pod/perldelta.pod 항목이 타당할 만큼 중요한 변경에는, 실제 변경과 함께 delta 항목을 제출하면 포터들이 크게 감사할 거예요. 중요한 변경에는 다음이 포함되지만 이에 국한되지 않아요:

  • 코어 기능 추가, 폐기, 제거

  • 코어 또는 이중 생활(dual-life) 모듈 추가, 폐기, 제거, 업그레이드

  • 새 코어 테스트 추가

  • 코어의 보안 이슈와 사용자에게 보이는 버그 수정

  • perl 또는 C 수준에서 기존 코드를 깨뜨릴 수 있는 변경

  • 중요한 성능 향상

  • pod/ 디렉토리의 문서 추가, 제거, 또는 중요 변경

  • 중요한 플랫폼별 변경

perldelta 항목을 pod/perldelta.pod 안의 올바른 섹션에 추가했는지 확인하세요. 좋은 perldelta 항목 작성 방법에 대한 더 많은 정보는 Porting/how_to_write_a_perldelta.podStyle 섹션에서 볼 수 있어요.

좋은 패치의 조건 (What makes for a good patch?)

새 기능과 언어 확장은 논란이 될 수 있어요. 어떤 기능이 추가되는지 결정하는 특정 기준 집합은 없지만, 패치를 개발할 때 고려할 질문이 여기 있어요:

개념이 Perl의 일반적인 목표와 맞는가? (Does the concept match the general goals of Perl?)

우리의 목표는 다음을 포함하되 국한되지 않아요:

  • 빠르고, 단순하고, 유용하게 유지하라.

  • 기능/개념을 가능한 한 직교(orthogonal)하게 유지하라.

  • 임의의 한계 없음(플랫폼, 데이터 크기, 문화).

  • 어디에서나 Perl을 사용/패치/옹호하기에 열려 있고 흥미롭게 유지하라.

  • 새 기술을 동화시키거나, 그 기술로의 다리를 만들라.

구현은 어디에? (Where is the implementation?)

세상의 모든 말은 구현 없이는 쓸모없어요. 거의 모든 경우, 새 기능을 주장하는 사람들은 그것을 구현할 사람일 것으로 기대돼요. 새 기능을 코딩할 수 있는 포터들은 자신의 일정이 있고, 여러분의 (어쩌면 좋은) 아이디어를 구현할 수 없어요.

하위 호환성 (Backwards compatibility)

기존 Perl 프로그램을 깨는 것은 치명적인 죄예요. 새 경고는 논란이 될 수 있어요—어떤 사람은 경고를 내는 프로그램은 깨진 게 아니라고 하고, 어떤 사람은 깨진 것이라고 해요. 키워드 추가는 프로그램을 깨뜨릴 잠재력이 있고, 기존 토큰 시퀀스나 함수의 의미를 바꾸는 것은 프로그램을 깨뜨릴 수 있어요.

Perl 5 코어에는 featuredeprecate 모듈처럼 포터들이 하위 호환되지 않는 변경을 더 호환되게 만드는 데 도움이 되는 메커니즘이 포함돼 있어요. 적절할 때 이것들을 사용해 주세요.

대신 모듈이 될 수 있나? (Could it be a module instead?)

Perl 5에는 Perl 인터프리터를 계속 변경할 필요를 피하기 위한 확장 메커니즘, 모듈과 XS가 있어요. 함수를 내보내는 모듈을 쓸 수 있고, 그 함수에 내장 함수처럼 호출될 수 있도록 프로토타입을 줄 수 있으며, 정말 복잡한 것을 구현하고 싶다면 Perl 인터프리터의 런타임 데이터 구조를 건드리는 XS 코드를 쓸 수도 있어요.

가능할 때마다 새 기능은 코어에 고려되기 전에 CPAN 모듈에서 프로토타입 되어야 해요.

기능이 충분히 일반적인가? (Is the feature generic enough?)

이것은 제출자만 언어에 추가하기를 원하는 것인가, 아니면 널리 유용한가? 때로는 좁은 초점의 기능을 추가하는 대신, 포터들이 더 일반화된 기능을 누군가 구현할 때까지 기다리기로 결정할 수 있어요.

잠재적으로 새 버그를 도입하는가? (Does it potentially introduce new bugs?)

Perl 인터프리터의 큰 덩어리의 급진적 재작성은 새 버그를 도입할 잠재력이 있어요.

얼마나 큰가? (How big is it?)

변경이 작고 국소적일수록 더 좋아요. 마찬가지로, 작은 패치의 연속이 단일 큰 패치보다 크게 선호돼요.

다른 바람직한 기능을 배제하는가? (Does it preclude other desirable features?)

패치가 미래 개발의 길을 막으면 거부될 가능성이 높아요. 예를 들어 프로토타입에 진실되고 최종적인 해석을 두는 패치는, 아직 다뤄지지 않은 프로토타입의 미래 옵션이 있기 때문에 거부될 가능성이 높아요.

구현이 견고한가? (Is the implementation robust?)

좋은 패치(빡빡한 코드, 완전하고, 정확한)는 들어갈 가능성이 더 커요. 엉성하거나 부정확한 패치는 수정이 이루어질 때까지 보류되거나, 추가 통지 없이 완전히 버려질 수 있어요.

구현이 이식 가능할 만큼 일반적인가? (Is the implementation generic enough to be portable?)

최악의 패치는 시스템 특정 기능을 사용해요. 이식 불가능한 Perl 언어 추가가 수락될 가능성은 매우 낮아요.

구현이 테스트되었나? (Is the implementation tested?)

동작을 바꾸는 패치(버그 수정이나 새 기능 도입)는 모든 것이 예상대로 작동하는지 검증하는 회귀 테스트를 포함해야 해요.

원래 작성자가 제공한 테스트가 없으면, 미래에 perl을 변경하는 다른 사람이 패치가 구현하는 동작을 무의식적으로 깨뜨리지 않았는지 어떻게 확신할 수 있을까요? 그리고 테스트가 없으면 패치 작성자가 패치에 쏟은 고된 작업이 미래에 누군가에 의해 우연히 버려지지 않을 것이라고 어떻게 확신할 수 있을까요?

충분한 문서가 있나? (Is there enough documentation?)

문서 없는 패치는 아마 제대로 생각되지 않았거나 불완전해요. 문서 없이는 기능을 추가하거나 변경할 수 없으므로, 소스 코드뿐 아니라 적절한 pod 문서용 패치를 제출하는 것이 중요해요.

다른 방법이 있나? (Is there another way to do it?)

Larry가 말했어요: "Perl 슬로건이 There's More Than One Way to Do It이지만, 나는 어떤 것을 하는 10가지 방법을 만드는 데는 주저한다". 이것은 탐색하기 까다로운 휴리스틱이에요. 한 사람의 필수 추가가 다른 사람의 무의미한 cruft일 수 있으니까요.

너무 많은 작업을 만드는가? (Does it create too much work?)

커미터를 위한 작업, Perl 프로그래머를 위한 작업, 모듈 저자를 위한 작업, ... Perl은 쉬워야 해요.

말보다 패치 (Patches speak louder than words)

동작하는 코드는 항상 허황된 아이디어보다 선호돼요. 기능을 추가하는 패치는, 아무리 열렬히 주장된 기능 요청이라도, 무작위 기능 요청보다 언어에 포함될 가능성이 훨씬 높아요. 이것은 "유용할 것인가?"와 연결되는데, 누군가 패치를 만드는 데 시간을 썼다는 사실이 그 기능에 대한 강한 욕구를 보여주기 때문이에요.

테스트 (TESTING)

코어는 나머지 Perl과 같은 테스트 스타일, 즉 Test::Harness를 통한 간단한 "ok/not ok" 실행을 사용하지만, 몇 가지 특별한 고려사항이 있어요.

코어에서 테스트를 쓰는 방법은 세 가지가 있어요: Test::More, t/test.pl, 그리고 임시적인 print $test ? "ok 42\n" : "not ok 42\n". 어느 것을 사용할지는 작업하고 있는 테스트 스위트의 어느 부분인지에 달려 있어요. 이것은 높은 수준의 실패(예: Config.pm 깨짐)가 기본 기능 테스트를 실패하게 만드는 것을 방지하기 위한 조치예요.

t/test.pl 라이브러리는 Test::More의 일부 기능을 제공하지만 대부분의 모듈 로딩을 피하고 가능한 한 적은 코어 기능을 사용해요.

직접 테스트를 쓴다면 Test Anything Protocol을 사용하세요.

  • t/base, t/comp, t/opbasic

require가 작동하는지, 심지어 서브루틴이 작동하는지도 모르므로, 이 세 가지에는 임시 테스트를 사용하세요. 테스트되는 기능을 사용하지 않도록 조심스럽게 밟으세요. 예를 들어 t/opbasic의 테스트는 t/test.pl이 이미 작동이 입증되었다고 가정하는 기능을 테스트하므로 t/op보다 거기에 배치되었어요.

  • *t/*의 다른 모든 하위 디렉토리

이제 기본 require()와 서브루틴이 테스트되었으므로 t/test.pl 라이브러리를 사용할 수 있어요.

Config 같은 특정 라이브러리를 조건부로 사용할 수도 있지만, 거기 없으면 테스트를 우아하게 건너뛰도록 하세요.

  • t/ 아래에 없는 테스트 파일

이 범주는 dist, ext, lib 같은 디렉토리 아래의 .t 파일을 포함해요. 이제 Perl 코어가 테스트되었으므로 Test::More를 사용할 수 있고 이제 사용해야 해요. 테스트에서 코어 모듈의 전체 스위트를 사용할 수도 있어요. (cpan/ 아래의 .t 파일 변경은 위 "Patching a core module"에서 언급했듯이 그 모듈의 업스트림 유지자에게 제출해야 해요.)

"make test"라고 하면 Perl은 t/TEST 프로그램으로 테스트 스위트를 실행해요(Win32에서는 t/harness를 대신 사용). 모든 테스트는 테스트를 포함하는 디렉토리가 아닌 t/ 디렉토리에서 실행돼요. 이것은 lib/ 테스트에서 몇 가지 문제를 일으켜, 패치할 기회가 돼요.

크로스 플랫폼 문제에 대해 삼중으로 의식해야 해요. 보통 File::Spec을 사용하고, 절대적으로 필요할 때가 아니면 fork()system() 같은 것을 피하고, 주어진 문자가 특정 서수 값(코드 포인트)을 갖거나 그 UTF-8 표현이 특정 바이트로 구성되어 있다고 가정하지 않는 것으로 귀결돼요.

테스트에서 문자와 코드 포인트를 이식 가능하게 지정하는 여러 함수가 있어요. 항상 미리 로드된 utf8::unicode_to_native()와 그 역인 utf8::native_to_unicode()는 코드 포인트를 받아 적절히 변환해요. t/charset_tools.pl 파일에는 유용한 여러 함수가 있어요. 앞선 두 함수를 문자열 입력(단일 숫자 코드 포인트가 아닌)으로 받는 버전인 uni_to_native()native_to_uni()가 있어요. UTF-8 인코딩 문자열을 구성하는 개별 바이트를 봐야 한다면, byte_utf8a_to_utf8n()은 ASCII 플랫폼용으로 인코딩된 그 바이트 문자열을 입력으로 받아 네이티브 플랫폼의 등가 문자열을 반환해요. 예를 들어 byte_utf8a_to_utf8n("\xC2\xA0")U+00A0의 UTF-8을 형성하는 현재 플랫폼의 바이트 시퀀스를 반환해요. 그 코드 포인트에 대한 ASCII 플랫폼의 UTF-8 바이트가 "\xC2\xA0"이기 때문이에요. 이 함수는 ASCII 플랫폼에서는 "\xC2\xA0"를, EBCDIC 1047에서는 "\x80\x41"을 반환해요.

하지만 가장 쉬운 것은, 문자가 "A""%" 같은 리터럴로 지정할 수 있으면 그것을 사용하고, 그렇게 지정할 수 없으면 부작용이 문제가 되지 않는다면 \N{}을 사용하는 거예요. 모든 문자를 16진수로 \xZZ 대신 \N{U+ZZ}를 사용해 지정하세요. \N{}은 Unicode 이름이며, 그래서 항상 Unicode 문자를 주는 것을 의미해요. \N{U+41}은 Unicode 코드 포인트가 0x41인 문자로, 따라서 모든 플랫폼에서 'A'예요. 부작용은:

  • 이것들이 Unicode 규칙을 선택해요. 즉 큰따옴표 문자열에서 문자열은 항상 Unicode 해석을 강제하기 위해 UTF-8로 변환돼요(가능하면 나중에 utf8::downgrade()로 비UTF-8로 되돌릴 수 있어요). 정규 표현식 패턴에서는 변환이 이루어지지 않지만, 문자 집합 수정자가 /d라면 /u로 바뀌어요.

  • \N{*character name*} 형태를 사용하면 charnames 모듈이 자동으로 로드돼요. 이것은 여러분이 하는 테스트 수준에 적합하지 않을 수 있어요.

로케일을 테스트한다면(perllocale 참조), t/loc_tools.pl에 현재 플랫폼에 어떤 로케일이 있는지 볼 수 있게 해주는 헬퍼 함수가 있어요.

특별한 make test 타깃 (Special make test targets)

표준 "test" 타깃과 약간 다르게 Perl을 테스트하는 데 사용할 수 있는 다양한 특별 make 타깃이 있어요. 전부 100% 성공률을 줄 것으로 기대되진 않아요. 여러 개는 별칭이 있고, 여러 개는 특정 운영체제에서는 사용할 수 없어요.

  • test_porting

소스 트리에서 몇 가지 기본적 온전성 테스트를 실행하고 패치를 제출하기 전에 기본 오류를 잡는 데 도움이 돼요.

  • minitest

miniperlt/base, t/comp, t/cmd, t/run, t/io, t/op, t/uni, t/mro 테스트에서 실행해요.

miniperl은 확장, 유틸리티, 문서 등을 부트스트랩하기 위해 빌드된 최소한의 perl이에요. 동적 로딩을 지원하지 않고, 빌드 과정의 시점에 따라 제한된 코어 모듈 집합에만 접근할 수 있어요. miniperl은 일상적인 사용을 위한 것이 아니에요.

  • test.valgrind check.valgrind

(Linux에서만) 메모리 누수 + 나쁜 메모리 접근 도구 "valgrind"로 모든 테스트를 실행해요. 로그 파일은 testname.valgrind라는 이름이 붙을 거예요.

  • test_harness

t/TEST 대신 t/harness 제어 프로그램으로 테스트 스위트를 실행해요. t/harness는 더 정교하고 Test::Harness 모듈을 사용하므로, 이 테스트 타깃을 사용하는 것은 perl이 대부분 작동한다고 가정해요. 우리 목적에서의 주요 장점은 마지막에 실패한 테스트의 상세한 요약을 출력한다는 거예요. 또한 t/TEST와 달리 stderr를 stdout으로 리다이렉트하지 않아요.

Win32에서는 t/TEST 대신 t/harness가 항상 사용되므로 특별한 "test_harness" 타깃이 없어요.

Unix 빌드 과정에서는 TEST_ARGS와 TEST_FILES 매개변수를 사용해 밑에 있는 harness 호출에 인자를 전달할 수 있어요. 예를 들어:

make test_harness TEST_ARGS="-v -re pat"

이것은 "pat"을 포함하는 파일들에 대해 상세 모드로 테스트 harness를 실행하게 해요. 또는:

make test_harness TEST_ARGS="-torture" TEST_FILES="op/*.t"

glob "op/*.t"와 일치하는 파일들에 대해 토처(torture) 테스트를 실행해요.

Win32의 "test" 타깃에서는 TEST_SWITCHES와 TEST_FILES 환경 변수를 사용해 t/harness의 동작을 제어할 수 있어요. 예를 들어:

nmake test TEST_FILES="op/*.t"
nmake test TEST_SWITCHES="-torture" TEST_FILES="op/*.t"

Unix 빌드 과정과의 호환성을 위해 TEST_ARGS도 전통적인 TEST_SWITCHES 인자 대신 사용될 수 있어요.

  • test-notty test_notty

정상 테스트를 실행하기 전에 PERL_SKIP_TTY_TEST를 true로 설정해요.

병렬 테스트 (Parallel tests)

코어 배포판은 이제 Unix 계열과 Windows 플랫폼에서 회귀 테스트를 병렬로 실행할 수 있어요. Unix에서는 make test를 실행하는 대신 환경에 TEST_JOBS를 실행할 테스트 수로 설정하고 make test_harness를 실행하세요. Bourne 계열 셸에서:

TEST_JOBS=3 make test_harness  # Run 3 tests in parallel

병렬 make 자체보다 환경 변수를 사용하는 이유는 TAP::Harness가 개별의 충돌하지 않는 테스트 스크립트를 스스로 스케줄할 수 있어야 하고, make 유틸리티의 작업 스케줄러와 상호작용하는 표준 인터페이스가 없기 때문이에요.

테스트는 보통 논리적 순서로 실행되는데, 먼저 온전성 테스트, 그다음 Perl 코어 기능의 주요 테스트, 그다음 비코어 모듈 테스트예요. 멀티코어 시스템에서는 이것이 하드웨어를 가능한 한 효과적으로 사용하지 못할 수 있어요. 또한:

TEST_JOBS=19 PERL_TEST_HARNESS_ASAP=1 make -j19 test_harness

라고 지정하면 테스트가 가능한 한 짧은 벽시계 시간에 끝나길 원한다는 신호예요. 온전성 테스트가 완료된 후, 이것은 나머지를 우리가 아는 한 빡빡하게 사용 가능한 코어에 채워 넣어요. 이것은 더 느리고 멀티코어가 많은 시스템에서 가장 큰 효과가 있어요. 낡은 24코어 시스템에서는 처리량이 20% 빨라졌어요; 코어가 적은 더 최신의 빠른 시스템에서는 덜했죠.

위 명령줄이 make에 -j 매개변수를 추가해서 병렬 컴파일을 일으킨다는 것을 주의하세요. 이것은 플랫폼에 따라 작동할 수도, 안 할 수도 있어요.

보통 테스트가 얼마나 걸리는지에 대한 데이터는 t/test_state에 저장되지만, PERL_TEST_STATE_FILE 환경 변수를 다른 것으로 설정하거나, 상태 메커니즘 사용을 완전히 비활성화하려면 false 값(0 또는 빈 문자열)으로 설정해 다른 파일 이름을 사용하게 할 수 있어요. 상태 파일의 형식이 시간에 따라 바뀌는 것에 대한 보호는 없어요. 그래서 이 파일 관련 문제가 있으면 파일을 수동으로 삭제하고 harness가 다시 만들게 하는 것은 여러분의 몫이에요. 다만 파일 형식은 자주 바뀌지 않으므로 자주 필요하지는 않을 거예요.

테스트를 수동으로 실행 (Running tests by hand)

  • t/* 디렉토리에서 다음 명령 중 하나를 사용해 테스트 스위트의 일부를 수동으로 실행할 수 있어요:
./perl -I../lib TEST list-of-.t-files

또는

./perl -I../lib harness list-of-.t-files

(테스트 스크립트를 지정하지 않으면 전체 테스트 스위트가 실행돼요.)

테스트에 t/harness 사용 (Using t/harness for testing)

테스트에 harness를 사용하면 여러 명령줄 옵션을 사용할 수 있어요. 인자는 다음과 같고, 함께 사용할 때 나타나야 하는 순서대로예요.

harness -v -torture -re=pattern LIST OF FILES TO TEST
harness -v -torture -re LIST OF PATTERNS TO MATCH

LIST OF FILES TO TEST가 생략되면 파일 목록은 매니페스트에서 얻어요. 파일 목록에는 확장될 셸 와일드카드가 포함될 수 있어요.

  • -v

상세 모드로 테스트를 실행해 어떤 테스트가 실행됐는지, 그리고 디버그 출력을 볼 수 있게 해요.

  • -torture

정상 집합과 함께 토처 테스트도 실행해요.

  • -re=PATTERN

파일 목록을 필터링해 실행되는 모든 테스트 파일이 PATTERN과 일치하게 해요. 아래의 -re LIST OF PATTERNS 형태와는 파일 목록도 제공할 수 있다는 점에서 구별돼요.

  • -re LIST OF PATTERNS

파일 목록을 필터링해 실행되는 모든 테스트 파일이 /(LIST|OF|PATTERNS)/와 일치하게 해요. 이 형태에서는 패턴이 '|'로 결합되고 파일 목록을 제공할 수 없으며, 테스트 파일은 MANIFEST에서 얻어요.

개별 테스트는 다음과 유사한 명령으로 실행할 수 있어요:

./perl -I../lib path/to/foo.t

다만 harness는 테스트 실행에 영향을 줄 수 있는 몇 가지 환경 변수를 설정해요:

  • PERL_CORE=1

이 테스트를 perl 코어 테스트 스위트의 일부로 실행하고 있음을 나타내요. CPAN에서 이중 생활을 하는 모듈에 유용해요.

  • PERL_DESTRUCT_LEVEL=2

이미 설정되지 않았다면 2로 설정돼요(perlhacktips의 "PERL_DESTRUCT_LEVEL" 참조).

  • PERL

(t/TEST에서만 사용) 설정되면 테스트를 실행하는 데 사용할 perl 실행 파일의 경로를 덮어써요(기본은 ./perl).

  • PERL_SKIP_TTY_TEST

설정되면 터미널이 필요한 테스트를 건너뛰라고 알려줘요. 실제로 Makefile이 자동으로 설정하지만, 'make test_notty'를 실행해 인위적으로 강제할 수도 있어요.

테스트에 영향을 줄 수 있는 다른 환경 변수

  • PERL_TEST_Net_Ping

이 변수를 설정하면 모든 Net::Ping 모듈 테스트를 실행하고, 그렇지 않으면 외부 세계와 상호작용하는 일부 테스트는 건너뛰어요. perl58delta를 보세요.

  • PERL_TEST_NOVREXX

이 변수를 설정하면 OS2::REXX의 vrexx.t 테스트를 건너뛰어요.

  • PERL_TEST_NUMCONVERTS

이것은 op/numconvert.t에 변수를 설정해요.

  • PERL_TEST_MEMORY

이 변수를 설정하면 *t/bigmem/*의 테스트를 포함해요. 테스트에 사용할 수 있는 메모리의 GB 수로 설정해야 해요, 예: PERL_TEST_MEMORY=4는 4GiB의 사용 가능한 메모리가 필요한 테스트를 안전하게 실행할 수 있음을 나타내요.

테스트에 영향을 주는 더 많은 환경 변수에 대해서는 Test와 Test::Harness 모듈의 문서도 보세요.

성능 테스트 (Performance testing)

t/perf/benchmarks 파일에는 Porting/bench.pl 도구가 일련의 perl에 걸쳐 벤치마킹하도록 의도된 perl 코드 조각이 들어 있어요. 성능 문제를 고치거나 향상시키면 대표 코드 샘플을 파일에 추가한 다음, 이전과 현재 perl에 대해 bench.pl을 실행해 어떤 차이를 만들었고 다른 것이 그 결과로 느려지지 않았는지 볼 수 있어요.

t/perf/opcount.t 파일은 특정 코드 조각이 지정된 수의 특정 op 타입을 포함하는 optree로 컴파일됐는지 테스트하도록 설계됐어요. 이것은 aelem op를 aelemfast op로 변환하는 것 같은, ops를 변경하는 최적화가 실제로 그렇게 하는지 테스트하는 데 좋아요.

t/perf/speed.tt/re/speed.t 파일은 특정 최적화가 깨지면 수천 배 느리게 실행되는 것들(예: 긴 utf8 문자열의 utf8 길이 캐시)을 테스트하도록 설계됐어요. 보통 1초 미만이 걸리지만 실패하면 몇 분 걸려 테스트 파일이 타임아웃되게 하는 테스트를 추가하세요.

오래된 커밋에서 perl 빌드 (Building perl at older commits)

Perl 코어 배포판을 해킹하는 과정에서 오래된 커밋에서 perl을 configure, build, test해야 할 일이 있을 수 있어요. 때로 make가 이 과정에서 실패해요. 그런 일이 생기면 CPAN의 Devel::PatchPerl 라이브러리(코어에 포함되지 않음)를 사용해 그 커밋의 소스 코드를 빌드 가능한 상태로 만들 수 있어요.

다음은 perl #10118을 해결하는 데 사용된 실제 예제예요. Porting/bisect.pl 사용이 버그가 수정된 커밋으로 커밋 ba77e4cc9d1ceebf472c9c5c18b2377ee47062e6을 식별했어요. 확인을 위해 P5P 개발자가 커밋 ba77e4c^(아마 "나쁜")와 ba77e4c(아마 "좋은")에서 perl을 configure, build하려 했어요. 정상 구성과 빌드를 시도했어요:

$ sh ./Configure -des -Dusedevel
$ make test_prep

make는 하지만 (발췌된) 이런 출력으로 실패했어요:

cc -fstack-protector -L/usr/local/lib -o miniperl \
  gv.o toke.o perly.o pad.o regcomp.o dump.o util.o \
  mg.o reentr.o mro.o hv.o av.o run.o pp_hot.o sv.o \
  pp.o scope.o pp_ctl.o pp_sys.o doop.o doio.o regexec.o \
  utf8.o taint.o deb.o universal.o globals.o perlio.o \
  numeric.o mathoms.o locale.o pp_pack.o pp_sort.o  \
  miniperlmain.o opmini.o perlmini.o
pp.o: In function `Perl_pp_pow':
pp.c:(.text+0x2db9): undefined reference to `pow'
...
collect2: error: ld returned 1 exit status
makefile:348: recipe for target 'miniperl' failed
make: *** [miniperl] Error 1

다른 P5P 기여자가 이 상황에 Devel::PatchPerl의 설치와 사용을 권장했어요. 먼저 문제의 커밋에서 perl의 버전을 결정한 다음, 그 지점의 소스 코드를 패치해 빌드를 촉진하도록요.

$ perl -MDevel::PatchPerl -e \
    'print Devel::PatchPerl->determine_version("/path/to/sourcecode"),
           "\n";'
5.11.1
$ perl -MDevel::PatchPerl -e \
    'Devel::PatchPerl->patch_source("5.11.1", "/path/to/sourcecode");'

소스가 패치되면 ./Configuremake test_prep가 호출되어 성공적으로 완료됐고, RT #72414의 발견을 확인할 수 있었어요.

깊은 내부 해킹을 위한 더 읽을거리 (MORE READING FOR GUTS HACKERS)

Perl 내부(guts)를 해킹하려면 다음을 읽어야 해요:

  • perlsource

Perl 소스 트리의 개요. 찾고 있는 파일을 찾는 데 도움이 돼요.

  • perlinterp

Perl 인터프리터 소스 코드의 개요와 Perl이 무엇을 하는지에 대한 몇 가지 세부사항.

  • perlhacktut

이 문서는 Perl의 C 코드에 대한 작은 패치 생성을 안내해요. Perl 코어 해킹을 시작하는 경우 이것이 어떻게 작동하는지 이해하는 데 도움이 돼요.

  • perlhacktips

Perl 코어 해킹에 대한 더 많은 세부사항. 테스트 작성 방법, 컴파일 이슈, 이식성, 디버깅 같은 더 낮은 수준의 세부사항에 초점을 맞춰요.

심각한 C 해킹을 계획한다면 반드시 이것을 읽어야 해요.

  • perlguts

이것은 가장 중요해요, Perl 소스에서 무엇이 어디로 가는지에 대한 문서이니까요. 두어 번 읽으면 이해가 되기 시작할 거예요—아직 안 된다고 걱정하지 마세요. 가장 좋은 공부 방법은 Perl 소스를 직접 뒤져 보면서 읽는 것이고, 우리는 나중에 그렇게 할 거예요.

Gisle Aas의 "illustrated perlguts"(일명 illguts)에는 매우 유용한 그림이 있어요: https://metacpan.org/release/RURBAN/illguts-0.49

  • perlxstutperlxs

XSUB 프로그래밍에 대한 실무 지식은 코어 해킹에 매우 유용해요; XSUB는 PP 코드, 즉 Perl 프로그램을 실제로 실행하는 guts 부분에서 끌어낸 기법을 사용해요. 그 기법을 코어 자체보다 간단한 예제와 설명에서 배우는 것이 훨씬 부드러워요.

  • perlapi

Perl API 문서는 일부 내부 함수가 무엇을 하는지, 그리고 소스에서 사용되는 많은 매크로를 설명해요.

  • Porting/pumpkin.pod

이것은 Perl 포터를 위한 지혜의 말 모음이에요; 일부는 펌킨 보유자에게만 유용하지만, 대부분은 Perl 개발을 시작하려는 누구에게나 적용돼요.

CPAN 테스터와 펄 스모커 (CPAN TESTERS AND PERL SMOKERS)

CPAN 테스터(https://cpantesters.org/)는 다양한 플랫폼에서 CPAN 모듈을 테스트하는 자원봉사자 그룹이에요.

Perl Smokers(https://www.nntp.perl.org/group/perl.daily-build/https://www.nntp.perl.org/group/perl.daily-build.reports/)는 다양한 구성을 가진 플랫폼에서 Perl 소스 릴리스를 자동으로 테스트해요.

두 노력 모두 자원봉사자를 환영해요. perl 자체의 스모크 테스트에 참여하려면 https://metacpan.org/release/Test-Smoke 를 방문하세요. CPAN 모듈 스모크 테스트를 시작하려면 https://metacpan.org/release/CPANPLUS-YACSmoke , https://metacpan.org/release/minismokebox , 또는 https://metacpan.org/release/CPAN-Reporter 를 방문하세요.

다음은? (WHAT NEXT?)

이 문서와 위에 나열된 문서의 모든 문서를 읽었다면 Perl을 해킹할 준비가 충분히 됐어요.

여기 몇 가지 추가 권장사항이 있어요:

  • perl5-porters에 구독하고, 패치를 따라가며 이해하려고 노력하세요; 명확하지 않은 부분이 있으면 묻기를 두려워하지 마세요—누가 알겠어요, 패치에서 버그를 발견할지도...

  • 자신의 운영체제와 관련된 README를 읽으세요, 예: IBM AIX OS의 README.aix. 새 OS 릴리스에서 빠진 것이나 바뀐 것을 발견하면 그 README에 패치를 제공하는 것을 주저하지 마세요.

  • Perl에서 흥미로워 보이는 영역을 찾아 작동 방식을 알아보세요. 소스를 훑고 디버거에서 한 단계씩 밟아보세요. 놀고, 찔러보고, 조사하고, 만져보세요! 선택한 영역뿐 아니라 훨씬 더 넓은 범위의 perl 활동을 이해하게 될 거예요, 아마 생각보다 더 빨리요.

"길은 계속되고 또 이어지네, 시작된 문에서 내려가서"

이것들을 할 수 있다면 Perl 포팅의 긴 길을 시작한 거예요. Perl을 더 좋게 만드는 것을 돕고 싶어해줘서 고마워요 - 해킹을 즐기세요!

은유적 인용 (Metaphoric Quotations)

위의 길에 대한 인용을 알아봤다면 운이 좋은 거예요.

대부분의 소프트웨어 프로젝트는 각 파일을 각 파일의 목적에 대한 문자적 설명으로 시작해요. Perl은 대신 각각을 그 파일의 목적에 대한 문학적 암시로 시작해요.

많은 책의 장처럼, 모든 최상위 Perl 소스 파일(여기에 저기 몇 개 더 포함)은 읽게 될 자료를 간접적이고 은유적으로 암시하는 에피그램 금언(epigrammatic inscription)으로 시작해요.

인용은 J.R.R. Tolkien의 Legendarium에 관한 저작에서 취했으며, 거의 항상 The Lord of the Rings에서 왔어요. 장과 페이지 번호는 다음 판본을 사용해 제공돼요:

  • The Hobbit, J.R.R. Tolkien. 2007년 하드커버 70주년 기념판 사용, UK는 Harper Collins Publishers, US는 Houghton Mifflin Company 출판.

  • The Lord of the Rings, J.R.R. Tolkien. 2004년 하드커버 50주년 기념판 사용, UK는 Harper Collins Publishers, US는 Houghton Mifflin Company 출판.

  • The Lays of Beleriand, J.R.R. Tolkien, 아들인 문학 집행자 C.J.R. Tolkien이 사후 편집 출판, Christopher의 거대한 History of Middle Earth 12권 중 3번째. 페이지 번호는 1983년 George Allen & Unwin이 처음 출판한 하드커버 판에서 유래; 2002년 특별 3권 옴니버스 판이나 다양한 트레이드 페이퍼 판에는 페이지 번호가 바뀌지 않았으며, 지금은 모두 Harper Collins나 Houghton Mifflin이 출판.

인용에 나올 법한 다른 JRRT 책은 The Adventures of Tom Bombadil, The Silmarillion, Unfinished Tales, The Tale of the Children of Hurin을 포함하며, 첫 번째를 빼고 모두 CJRT가 사후 편집했어요. 하지만 The Lord of the Rings 자체가 완벽히 괜찮고 아마 인용하기 가장 좋은데, 거기서 적절한 인용을 찾을 수 있으면요.

그래서 Perl에 추가할 새롭고 완전한 최상위 소스 파일을 제공한다면, Tolkien에서 적절한 인용을 직접 선택하고, 원래 철자와 구두점을 유지하며 나머지 인용과 같은 형식을 사용해 이 독특한 관행에 순응해야 해요. 간접적이고 완곡해도 괜찮아요; 기억하세요, 그것은 은유이고, 메타인 것이 결국 그 목적이니까요.

저자 (AUTHOR)

이 문서는 원래 Nathan Torkington이 작성했으며, perl5-porters 메일링 리스트가 관리해요.

더 알아보기 (Learn more)

  • perlhacktut — 간단한 C 패치 만들기 워크스루
  • perlhacktips — 코어 해킹 팁
  • perlsource — 소스 트리 개요
  • perlinterp — 인터프리터 개요
  • perlguts — Perl 내부 구조
  • perlgit — git 저장소 사용법
  • perlxstut, perlxs — XSUB 프로그래밍
  • perlapi — Perl API