당신은 Project.file() method 를 이용하여 project directory에 file을 위치시킬 수 있다.
build.gradle
// Using a relative path File configFile = file('src/config.xml') // Using an absolute path configFile = file(configFile.absolutePath) // Using a File object with a relative path configFile = file(new File('src/config.xml'))
당신은 file() method를 이용하여 어떠한 객체도 넘길 수 있고, 이 method는 넘겨 받은 값을 절대 경로 File 객체로 변환하려고 할 것이다.
보통, 당신은 File instance나 String을 이용하여 값을 넘겨주게 될 것이다.
만약 넘겨받은 경로가 절대 경로라면, 이 것은 File instance를 만드는 데에 사용될 것이다.
그렇지 않고, 상대 경로를 전달한다면, File instance는 제공 받은 경로에 project directory path를 추가하여 만들어질 것이다.
또한, file() method는 "file:/some/path.xml" 같은 URL 역시 사용할 수 있다.
이 메서드를 사용하는 것은 user로 부터 제공받는 값을 절대적인 File로 변환하는 데에 유용한 방법이다.
new File(somePath) 을 사용하는 것은, 현재 directory에 상관없이 project directory 기준으로 상대 경로를 측정하기 때문에
선호되는 방법이다.
File collections
file collection은 간단히 file의 set이다.
이 것은 FileCollection 인터페이스에 의해 표현된다.
많은 Gradle의 API는 이 인터페이스를 수행한다.
예를 들어, dependency configurations 는 FileCollection 인터페이스를 수행한다.
FileCollection 인스턴스를 얻을 수 있는 한 가지 방법은 Project.files() method를 사용하는 것이다.
당신은 어떠한 갯수의 객체도 모두 이 메서드를 통해 넘길 수 있고, 그 것들은 File 객체의 set로 변환될 것이다.
files() method는 어떠한 타입의 객체도 파라미터로써 허용한다.
file() method를 통해 이 파라미터들은 project directory로부터 상대적인 경로가 측정된다.
당신은 files() method를 통해 collections, iterables, maps 그리고 arrays 역시 넘겨줄 수 있다.
ex) Creating a file collection
build.gradle
FileCollection collection = files('src/file1.txt', new File('src/file2.txt'), ['src/file3.txt', 'src/file4.txt'])
기본적으로 file collection은 iterable이지만, operator를 사용해 많은 다른 타입으로 변환될 수 있다.
당신은 + operator를 사용하여 2개의 file collection을 합칠 수 있고,
- operator를 사용하여 다른 file collection으로 부터 하나의 file collection을 뺄 수도 있다.
아래에 file collection을 이용하여 당신이 할 수 있는 것의 예가 있다.
ex) Using file collection
build.gradle
// Iterate over the files in the collection collection.each {File file -> println file.name } // Convert the collection to various types Set set = collection.files Set set2 = collection as Set List list = collection as List String path = collection.asPath File file = collection.singleFile File file2 = collection as File // Add and subtract collections def union = collection + files('src/file3.txt') def different = collection - files('src/file3.txt')
당신은 또한 files() method를 closure나 Callable 인스턴스로 넘길 수도 있다.
이 것은 collection의 content가 요청될 때 호출되고, 이 것의 return value는 File 객체의 set로 변환된다.
return value는 files() method에 의해 지원되는 어떠한 타입의 객체도 될 수 있다.
이 것은 FileCollection 인터페이스를 구현하는 간단한 방법이다.
ex) Implementing a file collection
build.gradle
task list << { File srcDir // Create a file collection using a closure FileCollection collection = files { srcDir.listFiles() } srcDir = file('src/main') println "Contents of $srcDir.name" collection.collect { relativePath(it) }.sort().each { println it } srcDir = file('src/test') println "Contents of $srcDir.name" collection.collect { relativePath(it) }.sort().each { println it } }
gradle -q list의 실행 결과
> gradle -q list Contents of main src\main\java src\main\resources src\main\webapp Contents of test src\test\java src\test\resources
files() method를 통해서 다른 종류의 타입도 넘길 수 있다.
FileCollection file collection 안에 포함된 content들. Task file collection 안에 포함된 task의 출력 파일들. TaskOutputs file collection 안에 포함된 TaskOutputs의 출력 파일들. file collection의 content 들은 미리 읽혀지지 않고, 이후 필요해질 때 읽혀진다는 사실은 중요하다.
이 것은 ,예를 들면, 당신은 미래에 생성될 파일을 FileCollection으로 만들 수 있다는 것을 의미한다.
File trees file tree 는 계층적 구조로 이루어져 있는 collection이다.
예를 들면, file tree는 directory tree나 ZIP 파일의 content들로 표현될 수 있다.
이 것은 FileTree 인터페이스로 표현될 수 있다.
FileTree 인터페이스는 FileCollection을 상속받기 때문에, 당신은 file collection을 다루었던 방식으로 file tree를 다룰 수 있다.
source sets와 같은 몇몇 개의 Gradle 안의 객체는 FileTree 인터페이스를 구현한다.
FileTree instance를 얻을 수 있는 한가지 방법은 Project.fileTree() method를 이용하는 것이다.
이 것은 기본 directory를 기본으로 FileTree를 정의하며, 부수적으로 Ant-style을 통해 pattern으로 포함 또는 제외시킬 수 있다.
ex) Creating a file tree
build.gradle
// Create a file tree with a base directory FileTree tree = fileTree(dir: 'src/main') // Add include and exclude patterns to the tree tree.include '**/*.java' tree.exclude '**/Abstract*' // Create a tree using path tree = fileTree('src').include('**/*.java') // Create a tree using closure tree = fileTree('src') { include '**/*.java' } // Create a tree using a map tree = fileTree(dir: 'src', include: '**/*.java') tree = fileTree(dir: 'src', includes: ['**/*.java', '**/*.xml']) tree = fileTree(dir: 'src', include: '**/*.java', exclude: '**/*test*/**')
당신은 file collection을 사용했던 똑같은 방식으로 file tree를 사용할 수 있다.
또한 Ant-style pattern을 통해 tree 혹은 sub-tree의 content를 사용할 수 있다.
ex) Using a file tree
build.gradle
// Iterate over the contents of a tree tree.each {File file -> println file } // Filter a tree FileTree filtered = tree.matching { include 'org/gradle/api/**' } // Add trees together FileTree sum = tree + fileTree(dir: 'src/test') // Visit the elements of the tree tree.visit {element -> println "$element.relativePath => $element.file" }
Using the contents of an archive as a file tree 당신은 ZIP 이나 TAR 파일 같은 archive의 content 를 사용할 수 있다.
이것은 Project.zipTree() 와 Project.tarTree() method를 통해 가능하다.
이 method들은 다른 file tree나 file collection 처럼 사용할 수 있는 FileTree instance를 return 한다.
예를 들어, 당신은 이것을 content를 복사하여 archive를 확장하거나, 몇몇의 archive들을 다른 것에 합치는 것에 사용할 수 있다.
ex) Using an archive as a file tree
build.gradle
// Create a ZIP file tree using path FileTree zip = zipTree('someFile.zip') // Create a TAR file tree using path FileTree tar = tarTree('someFile.tar') //tar tree attempts to guess the compression based on the file extension //however if you must specify the compression explicitly you can: FileTree someTar = tarTree(resources.gzip('someTar.ext'))
Specifying a set of input files
Gradle의 많은 객체들은 input file set를 허용해주는 property들을 가지고 있다.
예를 들어 JavaCompile task는 compile할 source file을 지정하는 source property를 가지고 있다.
당신은 files() method에서 지원하는 모든 type의 값을 이 property에 적용할 수 있다.
이 것은 당신은 File, String, collection, FileCollection, 심지어 closure로도 property를 설정할 수 있다는 것을 의미한다.
아래 예를 보자.
ex) Specifying a set of files
build.gradle
task compile(type: JavaCompile) // Use a File object to specify the source directory compile { source = file('src/main/java') } // Use a String path to specify the source directory compile { source = 'src/main/java' } // Use a collection to specify multiple source directories compile { source = ['src/main/java', '../shared/java'] } // Use a FileCollection (or FileTree in this case) to specify the source files compile { source = fileTree(dir: 'src/main/java').matching { include 'org/gradle/api/**' } } // Using a closure to specify the source files. compile { source = { // Use the contents of each zip file in the src dir file('src').listFiles().findAll {it.name.endsWith('.zip')}.collect { zipTree(it) } } }
build.gradle
compile { // Add some source directories use String paths source 'src/main/java', 'src/main/groovy' // Add a source directory using a File object source file('../shared/java') // Add some source directories using a closure source { file('src/test/').listFiles() } }
Copying files
당신은 파일을 복사하는 데에 Copy task를 사용할 수 있다.
copy task는 매우 유연하다.
예를 들어, file의 content를 필터링할 수 있고, file 이름으로 mapping 할 수도 있다.
Copy task를 사용하기 위해, 당신은 반드시복사할 source file의 set와 복사될 directory를 제공하여야 한다.
아마도 당신은 복사할 때 어떻게 파일을 전송할지도 명시할 것이다.
당신은 이 모든 것을 copy spec을 통해 명시할 수 있다.
copy spec은 CopySpec 인터페이스를 통해 표현된다.
Copy task는 이 인터페이스를 구현한다.
당신은 source file을 명시하기 위해 CopySpec.from() method, destination directory를 명시하기 위해 CopySpec.into() method를 사용할 수 있다.
ex) Copying files using the copy task
build.gradle
task copyTask(type: Copy) { from 'src/main/webapp' into 'build/explodedWar' }
from() method는 files() method가 허용하는 어떠한 argument도 허용한다.
만약 argument가 directory를 가리키면, 이 directory 안래에 있는 모든 것이 destination directory로 복사된다.
만약 argument가 file을 가리키면, 해당 파일은 destination directory로 복사된다.
만약 argument가 존재하지 않는 파일을 가리키면, 해당 argument는 무시된다.
만약 argument가 task를 가리키면 task의 output 파일은 복사되고, 자동적으로 해당 task는 Copy task의 dependency로 추가된다.
into() method는 file() method가 허용하는 모든 argument를 허용한다.
아래 예를 보자.
ex) Specifying copy task source files and destination directory
build.gradle
task anotherCopyTask(type: Copy) { // Copy everything under src/main/webapp from 'src/main/webapp' // Copy a single file from 'src/staging/index.html' // Copy the output of a task from copyTask // Copy the output of a task using Task outputs explicitly. from copyTaskWithPatterns.outputs // Copy the contents of a Zip file from zipTree('src/main/assets.zip') // Determine the destination directory later into { getDestDir() } }
당신은 Ant-style pattern 혹은 closure를 통해 파일을 포함시키거나 제외시킬 수 있다.
ex) Selecting the files to copy
build.gradle
task copyTaskWithPatterns(type: Copy) { from 'src/main/webapp' into 'build/explodedWar' include '**/*.html' include '**/*.jsp' exclude { details -> details.file.name.endsWith('.html') && details.file.text.contains('staging') } }
당신은 또한 파일을 복사하기 위해 Project.copy() method를 사용할 수도 있다.
이 것은 task와 거의 동일한 방식이지만, 몇가지 큰 제한을 가진다.
첫째로, copy()는 점진적이지 않다.
ex) Copying files using the copy() method without up-to-date check
build.gradle
task copyMethod << { copy { from 'src/main/webapp' into 'build/explodedWar' include '**/*.html' include '**/*.jsp' } }
두번째로, copy() method는 task가 copy resource로 사용될 때 task dependency로 인수되지않는다.
왜냐하면, 이 것은 method이지 task가 아니기 때문이다.
만약 당신이 copy() method를 task action의 일부로 사용한다면, 올바른 동작을 위해 당신은 반드시 모든 input과 output을 명시하여야만 한다.
ex) Copying files using the copy() method with up-to-date check
build.gradle
task copyMethodWithExplicitDependencies{ // up-to-date check for inputs, plus add copyTask as dependency inputs.file copyTask outputs.dir 'some-dir' // up-to-date check for outputs doLast{ copy { // Copy the output of copyTask from copyTask into 'some-dir' } } }
만약 가능한 상황이라면 Copy task를 사용하는 것이 점진적인 build와 task dependency에 관해 별도의 노력을 필요하지 않고 진행할 수 있기 때문에, 선호되는 방법이다.
copy() method는 파일을 복사하는 task 구현의 한 부분으로써 사용될 수 있다.
이 것은, copy method는 파일을 복사하는 task 기능의 한 부분으로써 사용되는 의도로 만들어졌다는 것이다.
이러한 시나리오에서, custom task는 copy action에 관련된 input과 output을 표면적으로 선언하여야만 한다.
Renaming files
ex) Renaming files as they are copied
build.gradle
task rename(type: Copy) { from 'src/main/webapp' into 'build/explodedWar' // Use a closure to map the file name rename { String fileName -> fileName.replace('-staging-', '') } // Use a regular expression to map the file name rename '(.+)-staging-(.+)', '$1$2' rename(/(.+)-staging-(.+)/, '$1$2') }
Filtering files
ex) Filtering files as they are copied
build.gradle
import org.apache.tools.ant.filters.FixCrLfFilter import org.apache.tools.ant.filters.ReplaceTokens task filter(type: Copy) { from 'src/main/webapp' into 'build/explodedWar' // Substitute property tokens in files expand(copyright: '2009', version: '2.3.1') expand(project.properties) // Use some of the filters provided by Ant filter(FixCrLfFilter) filter(ReplaceTokens, tokens: [copyright: '2009', version: '2.3.1']) // Use a closure to filter each line filter { String line -> "[$line]" } // Use a closure to remove lines filter { String line -> line.startsWith('-') ? null : line } }
당신이 "filter" operation과 함께 ReplaceTokens를 사용할 때, 결과는 “@tokenName@” 의 값을 주어진 값으로 변경하는 것이다.
"expand" operation은 token의 형식이 “${tokenName}” 라는 것만 제외하고는 동일하다.
Using the CopySpec class
copy spec은 destination path, include path, exclude path, copy action, name mapping 그리고 filter 등을 상속받는다.
ex) Nested copy specs
build.gradle
task nestedSpecs(type: Copy) { into 'build/explodedWar' exclude '**/*staging*' from('src/dist') { include '**/*.html' } into('libs') { from configurations.runtime } }
Using the Sync task
Sync task는 Copy task를 확장한다.
이 것이 실행될 때, source file을 destination directory로 복사하고, destination directory의 복사하지않은 파일들을 지운다.
이 것은 당신의 application을 설치하거나, exploded copy를 생성하거나, project의 dependency의 copy를 유지할 때 유용하다.
아래에 build/lib directory 안의 project의 runtime dependency의 copy를 유지하는 에제가 있다.
ex) Using the Sync task to copy dependencies
build.gradle
task libs(type: Sync) { from configurations.runtime into "$buildDir/libs" }
Creating archives
만약 당신이 원한다면 project는 여러개의 JAR로 이루어질 수 있다.
당신은 WAR,ZIP 그리고 TAR archive 역시 당신의 프로젝트에 추가할 수 있다.
Archive는 여러가지 다양한 task로 이루어진다. (Zip, Tar, Jar, War, Ear).
이 것들은 모두 같은 방식으로 동작한다.
아래 ZIP file의 예제를 살펴보자.
ex) Creating a ZIP archive
build.gradle
apply plugin: 'java' task zip(type: Zip) { from 'src/dist' into('libs') { from configurations.runtime } }
이 archive task는 Copy task와 정확히 같은 방식으로 동작하고, CopySpec 인터페이스를 구현한다.
Copy task와 함께, 당신은 from() method를 통해 input file을 명시할 수 있고, 선택적으로 archive 의 위치를 into() method를 통해 명시할 수 있다.
당신은 copy spec을 통해 file의 content를 필터링하거나, rename하거나, 다른 것들을 할 수 있다.
Archive naming projectName-version.type 포맷은 archive file 이름들을 생성하는 데에 사용이 된다.
아래 예를 보자.
ex) Creation of ZIP archive
build.gradle
apply plugin: 'java' version = 1.0 task myZip(type: Zip) { from 'somedir' } println myZip.archiveName println relativePath(myZip.destinationDir) println relativePath(myZip.archivePath)
gradle -q myZip 의 실행 결과
> gradle -q myZip zipProject-1.0.zip build/distributions build/distributions/zipProject-1.0.zip
이 것은 ZIP file zipProject-1.0.zip을 생성하는 myZip이라는 이름을 가진 task를 Zip archive에 추가한다.
archive task의 이름과 archive task에 의해서 생성된 archive의 이름을 구분하는 것은 중요하다.
archive의 기본적인 이름은 archiveBaseName project property에 의해서 바뀔 수 있다.
또한 archive의 이름은 이후에 언제든지 변경할 수 있다.
archive task의 이름을 설정할 수 있는 다양한 property들이 있다.
아래 예를 보자.
ex) Configuration of archive task - custom archive name
build.gradle
apply plugin: 'java' version = 1.0 task myZip(type: Zip) { from 'somedir' baseName = 'customName' } println myZip.archiveName
gradle -q myZip 의 실행 결과
> gradle -q myZip customName-1.0.zip
당신은 archive 이름을 좀 더 커스토마이징할 수 있다.
ex) Configuration of archive task - appendix & classifier
build.gradle
apply plugin: 'java' archivesBaseName = 'gradle' version = 1.0 task myZip(type: Zip) { appendix = 'wrapper' classifier = 'src' from 'somedir' } println myZip.archiveName
gradle -q myZip 의 실행 결과
> gradle -q myZip gradle-wrapper-1.0-src.zip
Archive tasks - naming properties
Sharing content between multiple archives
당신은 archive 사이에서 content를 공유하는 데에 Project.copySpec() method를 사용할 수 있다.
원본 출처 : https://docs.gradle.org/current/userguide/working_with_files.html
댓글 없음 :
댓글 쓰기