증분 프로젝트 빌더는 특정 방식으로 프로젝트의 자원을 조작하는 오브젝트입니다. 증분 프로젝트 빌더는 또다른 유형의 항목 또는 자원을 작성하기 위해 자원에 변환을 적용하는 데 자주 사용됩니다.
플러그인은 특수 자원 변환을 구현할 수 있도록 플랫폼에 증분 프로젝트 빌더를 제공합니다. 예를 들어 JDT(Java Development Tools)는 Java 프로젝트에서 파일이 추가되거나 수정될 때마다 Java 소스 파일을 클래스 파일로 컴파일하는 증분 프로젝트 빌더를 정의합니다. 또한 종속 파일을 지속적으로 추적하고 필요할 때 이 파일을 다시 컴파일합니다.
API의 관점에서 플랫폼은 다음과 같이 두 개의 기본 빌드 유형을 정의합니다.
증분 빌드는 자원 변경 델타로 수행됩니다. 델타는 빌더가 프로젝트를 마지막으로 빌드한 이후로 모든 자원에서 변경사항에 대한 최종 결과를 반영합니다. 이 델타는 자원 변경 이벤트 내에서 사용되는 델타와 유사합니다.
프로젝트는 다음에 증분 빌드가 해당 프로젝트에서 수행될 때 완전한 프로젝트를 다시 빌드하도록 강제 실행하기 위해 사용자가 주기적으로 정리할 수 있습니다. 프로젝트를 정리하면 문제점 마커 및 클래스 파일과 같은 빌드 정보가 제거됩니다.
예를 들어 빌더를 설명하면 이해하기 쉽습니다. JDT Java 컴파일러는 변경사항으로 영향을 받는 프로젝트의 파일을 다시 컴파일하는 Java 증분 프로젝트 빌더를 통해 구동됩니다. 전체 빌드(또는 정리 후 증분 빌드)가 트리거되면 프로젝트의 모든 .java 파일이 컴파일됩니다. 발생한 컴파일 문제점은 영향을 받은 .java 파일에 문제점 마커로 추가됩니다. 증분 빌드가 트리거되면, 추가, 변경 또는 영향을 받은 .java 파일을 선택적으로 다시 컴파일합니다. 이 .java 파일은 자원 델타에 설명되며 필요할 경우 문제점 마커를 갱신합니다. 더 이상 적합하지 않은 .class 파일 또는 마커는 제거됩니다.
증분 빌드는 수백 또는 수천개의 자원을 가지고 있는 프로젝트에 대해 높은 성능상의 이점을 제공하는 데 대부분의 자원은 주어진 특정 시간에 변경되지 않습니다.
증분 빌드의 기술적 어려움은 어떤 항목을 다시 빌드해야 하는지 정확히 판별하는 것입니다. 예를 들어 Java 빌더로 유지보수되는 내부 상태에는 종속성 그래프 및 보고된 컴파일 문제점 목록과 같은 사항이 포함되어 있습니다. 이 정보는 증분 빌드 시 Java 자원의 변경에 응답하여 다시 컴파일해야 하는 클래스를 식별하는 데 사용됩니다.
빌드의 기본 구조가 플랫폼에 정의되어 있더라도 실제 작업은 빌더 코드에서 수행됩니다. 복잡한 증분 빌더를 구현하기 위한 패턴에 대해서는 여기에서 설명하지 않습니다. 각 구현은 특정 빌더 설계에 따라 다르기 때문입니다.
다음 방법 중 하나를 사용하여 명시적으로 빌더를 호출할 수 있습니다.
실제로 Workbench 사용자는 자원 네비게이터 메뉴에서 해당 명령을 선택하여 빌드를 트리거합니다.
증분 프로젝트 빌더는 자동 빌드 동안 플랫폼에 의해 암시적으로 호출되기도 합니다. 자동 빌드를 사용할 경우, 작업공간이 변경될 때마다 실행됩니다.
org.eclipse.core.resources.builders 확장점은 플랫폼에 증분 프로젝트 빌더를 제공하는 데 사용됩니다. 다음 마크업은 가상의 플러그인 com.example.builders가 증분 프로젝트 빌더를 제공하는 방법을 표시한 것입니다.
<extension id="mybuilder" name="My Sample Builder" point="org.eclipse.core.resources.builders"> <builder <run class="com.example.builders.BuilderExample"> <parameter name="optimize" value="true" /> <parameter name="comment" value="Builder comment" /> </run> </builder> </extension>
확장점에서 식별된 클래스는 IncrementalProjectBuilder 플랫폼 클래스를 확장해야 합니다.
public class BuilderExample extends IncrementalProjectBuilder { IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { // add your build logic here return null; } protected void startupOnInitialize() { // add builder init logic here } protected void clean(IProgressMonitor monitor) { // add builder clean logic here } }
빌드 처리는 build() 메소드로 시작되는데, 이 메소드에는 요청된 빌드 유형에 대한 정보가 포함되어 있습니다. 빌드는 다음 값 중 하나입니다.
증분 빌드가 요청된 경우 마지막 빌드 이후의 자원 변경사항을 설명하기 위해 자원 델타가 제공됩니다. 다음 스니펫은 build() 메소드를 상세히 설명합니다.
protected IProject[] build(int kind, Map args, IProgressMonitor monitor throws CoreException { if (kind == IncrementalProjectBuilder.FULL_BUILD) { fullBuild(monitor); } else { IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(monitor); } else { incrementalBuild(delta, monitor); } } return null; }
프로젝트 "X"를 빌드할 때, 빌더가 일부 다른 프로젝트 "Y"의 변경사항에 대한 정보를 필요로 하는 경우(예: X의 Java 클래스가 Y에 제공된 인터페이스를 구현)가 있습니다. X를 빌드하는 동안 getDelta(Y)를 호출하면 Y의 델타를 사용할 수 있습니다. 플랫폼이 해당 델타를 제공하도록 하려면 X의 빌더가 이전 build() 호출에서 Y가 들어 있는 배열을 리턴하여 X와 Y 간에 종속성을 선언해야 합니다. 빌더에 종속성이 없으면 단순히 널(null)을 리턴할 수 있습니다. 추가 정보는 IncrementalProjectBuilder를 참조하십시오.
전체 빌드 요청을 처리하는 데 필요한 논리는 플러그인에 고유합니다. 프로젝트 간에 종속성이 있을 경우 프로젝트의 모든 자원을 방문하거나 다른 프로젝트도 검사해야 합니다. 다음 스니펫은 전체 빌드의 구현 방법을 제안합니다.
protected void fullBuild(final IProgressMonitor monitor) throws CoreException { try { getProject().accept(new MyBuildVisitor()); } catch (CoreException e) { } }
빌드 방문자는 특정 자원에 대해 빌드를 수행하고 모든 하위 자원을 계속 방문하기 위해 'true'를 응답합니다.
class MyBuildVisitor implements IResourceVisitor { public boolean visit(IResource res) { //build the specified resource. //return true to continue visiting children. return true; } }
방문 프로세스는 전체 자원 트리를 방문할 때까지 계속됩니다.
증분 빌드를 수행할 때 빌더는 전체 자원 트리 대신 자원 변경 델타를 사용합니다.
protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException { // the visitor does the work. delta.accept(new MyBuildDeltaVisitor()); }
방문 프로세스는 전체 자원 델타 트리를 방문할 때까지 계속됩니다. 변경사항의 개별 속성은 자원 변경 리스너 구현에 설명된 것과 유사합니다. 한가지 중요한 차이점은 증분 프로젝트 빌더의 경우 일반적으로 전체 작업공간이 아닌 특정 프로젝트를 기반으로 하는 자원 델타를 사용하여 작업한다는 점입니다.
Workbench를 사용하면 사용자가 빌드를 시작하기 전에 프로젝트 또는 프로젝트 세트를 정리할 수 있습니다. 이 기능으로 사용자는 특정 프로젝트의 스크래치에서만 다시 빌드를 강제 실행할 수 있습니다. 빌더는 이 메소드를 구현하여 프로젝트의 모든 문제점 마커 및 파생된 자원을 정리해야 합니다.
주어진 프로젝트에 빌더를 사용할 수 있도록 하려면 프로젝트의 빌드 스펙에 해당 빌더가 포함되어야 합니다. 프로젝트의 빌드 스펙은 프로젝트가 빌드될 때 순서대로 실행할 명령 목록입니다. 각 명령은 하나의 증분 프로젝트 빌더를 이름 지정합니다.
참고: 빌드 명령의 빌더 이름은 빌더 확장의 완전한 ID입니다. 확장의 완전한 ID는 플러그인 ID를 plugin.xml 파일의 단순 확장자 ID와 결합하여 작성됩니다. 예를 들어, "com.example.builders" 플러그인에서 단순 확장자 ID가 "mybuilder"인 빌더의 이름은 "com.example.builders.mybuilder"입니다.
다음 스니펫은 기존의 빌더 목록에서 새 빌더를 첫 번째 빌더로 추가합니다.
final String BUILDER_ID = "com.example.builders.mybuilder"; IProjectDescription desc = project.getDescription(); ICommand[] commands = desc.getBuildSpec(); boolean found = false; for (int i = 0; i < commands.length; ++i) { if (commands[i].getBuilderName().equals(BUILDER_ID)) { found = true; break; } } if (!found) { //add builder to project ICommand command = desc.newCommand(); command.setBuilderName(BUILDER_ID); ICommand[] newCommands = new ICommand[commands.length + 1]; // Add it before other builders. System.arraycopy(commands, 0, newCommands, 1, commands.length); newCommands[0] = command; desc.setBuildSpec(newCommands); project.setDescription(desc, null); }
프로젝트 빌더 구성은 프로젝트 작성 시 한 번만 수행됩니다.