ANT 기초 - jar

 

JAR?

이전 ANT기초에서는 ant와 관련된 기초적인 기능과 ant를 자동화하는 맛보기를 작성하였습니다.

하지만 이번에는 좀 더 실용적인 활용법에 관하여 다루어 보도록 하겠습니다.

그 중 하나로써 ant를 사용하여 jar 파일 압축을 자동화를 해보도록 하겠습니다.

먼저 jar파일이 어떤 것인지 부터 알아야합니다.

jar파일은 java를 활용한 실행 가능한 압축 파일이며 내부에는 java를 실행하기 위한 파일들이 들어 있습니다.

jar파일이 무엇인지 알았다면 이제 간단한 hello ant with jar를 만들어 보면서 ant에 관하여 알아보도록 하겠습니다.

준비

먼저 jar 파일을 생성하기 위하여 Hello Ant With Java를 출력하는 java파일을 하나 만들도록 하겠습니다.

(java 폴더를 만든 다음 해당 폴더에서 파일을 만들어 메모장으로 아래 내용을 작성한 다음 HelloAntBuild.java로 명칭을 변경 하도록 합니다.)

class HelloAntBuild {

    public static void main(String[] args) {
        System.out.println("Hello Ant With Java");
    }
}

이제 빌드를 위한 build.xml파일을 생성하여 project태그를 등록 하세요.

<project>

</project>

기초에서 포스팅한 내용처럼 기본적인 target을 만든 다음 default로 지정하도록 하세요.

(기본 target명은 build로 하겠습니다.)

<project default="build">
    <target name="build">
    </target>
</project>

다음으로는 경로를 설정해보겠습니다.

이전 포스트에서는 경로를 직접 지정하였지만 이번에는 사용할 경로를 설정해 두고 시작하도록 하겠습니다.

설정은 property를 사용하여 할수 있습니다.

설정 폴더는 목적파일(.class)파일을 놓아둘 dist폴더와 결과물을 놓아둘 dest를 지정하도록 하겠습니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build">
    </target>
</project>

Compile - .class파일로 변환

자바 파일은 JVM에서 온전히 읽어 들여 사용할 수 없는 파일입니다.

실제로 실행 시 JVM에서 필요한 것은 저장 공간(table)과 목적 행위(store, load, invoke 등)와 목적대상(l1, i1 ,a1 등)로 이루어진 바이너리 파일이 필요하며 부가적인 자료는 의미가 없습니다.

따라서 소스 파일(모든파일)을 목적파일로 변환하는 행위를 컴 파일 이라고 합니다.

자바 언어에서 컴파일을 담당하는 것은 javac라는 실행파일이 하게 됩니다.

javac의 옵션 항목으로는 여러가지가 있으며 이 항목 중 사용하게 될 항목은 많지 않습니다.

대표적으로 알아야 할 옵션 3가지를 짚고 넘어 가겠습니다.

cp - 클래스 기준 경로

자바 언어를 사용해본 사람이이라면 한번씩은 들어보았을 클래스 패스를 지정하는 옵션입니다.

자바의 클래스들은 클래스패스를 기준으로 경로가 사용되며 하위 패키지 단위로 관리하고 있습니다.

그 패키지들의 기준이 되는 옵션이 바로 cp(classpath)입니다.

아래 명령어를 사용하여 클래스패스를 지정할 수 있습니다.

javac -cp or -classpath 경로

source & target - 컴파일 시 처리할 버전

자바 언어는 컴파일과 실행 환경이 온전히 동일하다면 좋겠지만 다를때가 존재 합니다.

가령 IDE에서는 1.8을 기준으로 작성하였지만 실제 실행 시에는 1.7 기준으로 동작하여야 하는 상황들을 말합니다.

이럴때 사용하는 옵션이 sourcetarget 옵션입니다.

source는 IDE의 버전을 target에는 배포시 사용할 버전을 지정하여 주도록 합니다.

javac --source 8 --target 7

compile Task - 실행

돌아가서 이번에는 ant에서 자바 컴파일을 자동화 해보도록 하겠습니다.

(ant는 기본적으로 자바의 javac를 사용할 수 있으므로 어렵지 않게 사용할수 있습니다.)

기존 파일에 javac task 를 등록합니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build">
        <javac />
    </target>
</project>

이렇게 되면 java를 활용할 준비는 끝났습니다.

이번에는 srcdir속성을 사용하여 java파일이 있는 곳을 등록해 보도록 하겠습니다.

(현재 java폴더의 .java 파일이 존재하므로 <p>srcDir</p>로는 java를 지정하였습니다.)

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build">
        <javac srcdir="java"/>
    </target>
</project>

다음으로는 destdir 속성을 사용하여 컴파일 후 class 파일이 풀릴 경로를 지정합니다.

(설정 값으로 지정하여 둔 dist 폴더를 사용합니다.)

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build">
        <javac srcdir="java" destdir="${dist}"/>
    </target>
</project>

이제 ant명령문을 사용하여 ant를 실행하게 되면 아래와 같은 에러메시지를 만날 수 있습니다.

> ant
Buildfile: 경로/build.xml

build:

BUILD FAILED
경로/build.xml:5: destination directory "경로/target/dist" does not exist or is not a directory

Total time: 0 seconds

에러문을 읽어 보니 결과물을 지정할 경로에 폴더가 존재 하지 않는 다는 에러 라고합니다.

prepare - 실행 전 초기화

이 에러는 실핼 전 사용할 폴더를 생성하지 않아서 출력 되는 에러이며 폴더를 생성할 단계가 필요해 보입니다.

먼저 사용할 폴더를 생성해 주거나 미리 처리되어여 할부분을 처리하는 단계를 추가 해보겠습니다.

dist 폴더를 생성하기 위하여 prepare라는 target을 추가 하겠습니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build">
        <javac srcdir="java" destdir="${dist}"/>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
    </target>
</project>

만들어진 두 타켓을 depends 속성값을 사용하여 의존성을 주도록 하겠습니다.

( 의존성 : build > prepare )

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
    </target>
</project>

이제 ant 명령문을 실행하게 되면 class파일이 생성 되는 것을 알수 있습니다.

이번에는 source와 target속성을 사용해보겠습니다.

그전에 이미 빌드 된 파일을 삭제 하는 과정을 추가해 보겠습니다.

clean - 실행 후 초기화

목적 파일(.class/resource)인 결과물은 빌드툴에서 자동을 제거하지는 않습니다.

따라서 목적파일은 만든 다음 결과물을 제거해야 하는 단계가 필요합니다.

target을 만든 다음 clean이라고 명창을 부여합니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
    </target>
    <target name="clean">
    </target>
</project>

dist 를 삭제하는 기능을 추가해 보겠습니다.

( 삭제는 delete task를 사용하며 폴더를 지정할 때는 dir의 속성값을 사용합니다. )

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
    </target>
</project>

이제 명령문 창으로 돌아가 아래 명령문을 실행할 경우 빌드 결과 값이 초기화 됩니다.

ant clean

중간 작업물을 확인하기 위해서는 커맨드나 터미널창에서 target/dist로 이동한 다음 아래 명령어를 실행하세요

> cd target/dist

> java HelloAntBuild
Hello Ant With Java

jar

이번에는 실질적으로 jar로 패키징해보도록 하겠습니다.

jar는 이전 javac로 컴파일 된 파일을 사용하여 처리할 수 있습니다.

또한 jar가 아닌 일반적인 파일(리소스) 역시 처리할 수 있습니다.

이번에는 리소스를 하나 추가해보도록 하겠습니다.

기존 java 폴더안에 설정파일(properties) 파일은 추가한 다음 아래와 같이 설정 값을 등록해 보도록 합니다.

( 명칭은 ant.properties로 지정하였습니다. )

projectName=AntSkill
version=1.0.0

이번에는 자바 파일은 수정해보도록 하겠습니다.

자바 파일은 설정 정보를 불러온 다음 정보를 출력하도록 수정하겠습니다.

import java.util.Properties;

class HelloAntBuild {

    public static void main(String[] args) throws Exception {

		Properties properties = new Properties();

        try{
			properties.load(Class.class.getResourceAsStream("/ant.properties"));
		}catch(Exception e) {
			System.out.println("설정 파일을 불러오는 중 에러가 발생하였습니다.");
		}

		String projectName = properties.getProperty("projectName");
		String version     = properties.getProperty("version");
		
		System.out.println("projectName : "+projectName);
		System.out.println("version : "+version);
    }
}

ant 명령어를 사용하여 빌드한 다음 파일을 읽게 되면 아래와 같은 에러메시지를 출력하게 될것입니다.

>java HelloAntBuild

설정 파일을 불러오는 중 에러가 발생하였습니다.
projectName : null
version : null

에러가 난 이유는 ant.properties 파일을 복사하지 않아서 발생한 것이므로 파일을 복사 하는 작업을 추가해 보도록 하겠습니다.

(java는 java를 class파일로 변환하여 목적 폴더에 떨어뜨리는 역활을 합니다. 따라서 리소스 파일은 따로 복사하는 구문이 필요합니다.)

복사는 copy task을 사용하여 처리할 수 있습니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
		<copy todir="${dist}">
			<fileset dir="java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
    </target>
</project>

Tip. fileset

여러 파일을 선택할 때에는 fileset구문을 사용하여 처리할수 있습니다.

fileset은 Resource Collections으로써 여러 리소스를 묶어 처리할 수 있도록 하는 역활을 합니다.

자세한 내용은 공식 문서를 참고 하도록 하세요

fileset은 기본적으로 아래와 같이 루트 폴더를 지정합니다.

<fileset dir="rootFolder"/>

그런 다음 includesexcludes를 사용하여 원하는 파일을 분리합니다.

<fileset dir="rootFolder" 또는 [excludes="ant pattern", includes="ant pattern"]>
    <exclude name="ant pattern"/>
    <include name="ant pattern"/>
</fileset>

상단에 fileset구문에 java파일은 제외하는 부분을 꼭 기억하세요.


이제 다시 돌아가서 ant로 빌드한 다음 class파일을 실행해보도록 하겠습니다.

> ant

...
BUILD SUCCESSFUL

> cd target/dist

> java HelloAntBuild
projectName : AntSkill
version : 1.0.0

이제 이렇게 생성된 dist폴더를 jar파일로 만들어 보도록 하겠습니다.

jar task를 사용하여 jar로 압축할 수 있습니다.

새로운 jar target을 생성하여 jar로 이름 지은다음 기존 clean과 build에 의존성을 추가해주세요

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
		<copy todir="${dist}">
			<fileset dir="java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
    </target>
	<target name="jar" depends="clean,build"/>
</project>

하나 이상의 의존성을 등록하게 되면 왼쪽에서부터 의존성이 적용 됩니다.

( 의존성 : jar > clean, jar > build > prepare )

다음은 jar task를 추가하여 jar로 압축할수 있도록 준비합니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
		<copy todir="${dist}">
			<fileset dir="java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
        <mkdir dir="${dest}}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
        <delete dir="${dest}"/>
    </target>
	<target name="jar" depends="clean,build">
		<jar />
	</target>
</project>

이제 jar파일로 압축할 기본 폴더(basedir)와 jar가 생성될 목적 파일(destfile)를 지정하겠습니다.

기본 폴더는 build시 적용되는 목적 폴더(dist)를 참조하며 목적 파일(destfile)은 설정시 잡아둔 dest폴더로 지정하세요.

에러 발생 시 prepare와 clean target에 dest폴더를 추가/삭제 하는 구문을 등록하세요.

(파일명은 설정값을 사용하여 등록한 다음 추가하도록 합니다.)

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <property name="projectName" value="ant"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
		<copy todir="${dist}">
			<fileset dir="java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
        <mkdir dir="${dest}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
        <delete dir="${dest}"/>
    </target>
	<target name="jar" depends="clean,build">
		<jar basedir="${dist}" destfile="${dest}/${projectName}.jar"/>
	</target>
</project>

실행 하게 되면 아래와 같읕 에러가 발생하는 것을 확인 할 수 있을 것입니다.

> ant jar

...

BUILD SUCCESSFUL

> cd target/dest

> java -jar ant.jar
ant.jar에 기본 Manifest 속성이 없습니다.

기본적으로 jar파일은 class들의 묶음입니다.

그러므로 class를 실행할수 있는 기본 설정(내용)이 필요 하며 이 파일이 Manifest 파일이라고 합니다.

이제 이 Manifest를 생성해 보도록 하겠습니다.

Manifest 는 jar task내에 등록 하며 아래와 같이 등록 할 수 있습니다.

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <property name="projectName" value="ant"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
		<copy todir="${dist}">
			<fileset dir="java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
        <mkdir dir="${dest}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
        <delete dir="${dest}"/>
    </target>
	<target name="jar" depends="clean,build">
		<jar basedir="${dist}" destfile="${dest}/${projectName}.jar">
            <manifest/>
        </jar>
	</target>
</project>

이제 Main-Class를 등록하여 실행 가능한 jar파일로 만들어 보겠습니다.

Manifest의 속성값을 등록 하는 방법은 attribute 태그를 사용하여 name 과 value 으로 속성값을 등록 가능합니다.

(메인 클래스로 HelloAntBuild을 등록합니다.)

<project default="build">
    <property name="dist" value="target/dist"/>
    <property name="dest" value="target/dest"/>
    <property name="projectName" value="ant"/>
    <target name="build" depends="prepare">
        <javac srcdir="java" destdir="${dist}"/>
		<copy todir="${dist}">
			<fileset dir="java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
    </target>
    <target name="prepare">
        <mkdir dir="${dist}"/>
        <mkdir dir="${dest}"/>
    </target>
    <target name="clean">
        <delete dir="${dist}"/>
        <delete dir="${dest}"/>
    </target>
	<target name="jar" depends="clean,build">
		<jar basedir="${dist}" destfile="${dest}/${projectName}.jar">
            <manifest>
                <attribute name="Main-Class" value="HelloAntBuild"/>
            </manifest>
        </jar>
	</target>
</project>

더 많은 manifest를 확인하기 위해서는 아래 공식사이트들을 확인하세요.

이제 다시 한번 jar파일을 실행해보면 정상적으로 실행 되는 것을 확인할 수 있습니다.

> ant jar

...

BUILD SUCCESSFUL

> cd target/dest

> java -jar ant.jar
projectName : AntSkill
version : 1.0.0