2016-12-09 57 views
6

Tôi đang làm việc để tích hợp proguard để xây dựng gradle cho một ứng dụng được viết bằng Kotlin. Tôi thấy rằng proguard đang loại bỏ thư viện chuẩn Kotlin (như trong chương trình Hello World đơn giản của tôi) nhưng nó để lại một loạt các tệp trong jar của tôi có phần mở rộng là .kotlin_builtins. Khi tôi cấu hình nhiệm vụ gradle của mình để loại trừ các tệp đó, chương trình vẫn hoạt động tốt. Các tệp đó là gì và chúng phải được gửi bằng uberjar thực thi của tôi?Các tệp .kotlin_builtins là gì và tôi có thể bỏ qua chúng khỏi các uberjars của tôi không?

Dưới đây là nội dung build.gradle tập tin của tôi để tham khảo:

buildscript { 
    ext.kotlin_version = '1.0.5' 
    ext.shadow_version = '1.2.4' 

    repositories { 
    mavenCentral() 
    maven { 
     url "https://plugins.gradle.org/m2/" 
    } 
    flatDir dirs: "gradle/proguard" 
    } 

    dependencies { 
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 
    classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version" 
    classpath ":proguard:" 
    } 
} 

apply plugin: 'kotlin' 
apply plugin: 'application' 
apply plugin: 'com.github.johnrengelman.shadow' 

mainClassName = 'namespace.MainKt' 

defaultTasks 'run' 

repositories { 
    mavenCentral() 
} 

dependencies { 
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 
    testCompile "junit:junit:4.12" 
    testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" 
} 

shadowJar { 
    exclude 'kotlin/**/*.kotlin_builtins' 
    exclude '.keep' 
} 

task minify(type: proguard.gradle.ProGuardTask, dependsOn: 'shadowJar') { 
    libraryjars "${System.getProperty('java.home')}/lib/rt.jar" 

    injars 'build/libs/artful-all.jar' 
    outjars 'build/libs/artful-all.out.jar' 

    printmapping 'build/libs/out.map' 

    keepclasseswithmembers 'public class * { \ 
     public static void main(java.lang.String[]); \ 
    }' 

    assumenosideeffects 'class kotlin.jvm.internal.Intrinsics { \ 
     static void checkParameterIsNotNull(java.lang.Object, java.lang.String); \ 
    }' 
} 

Trả lời

6

Những tập tin chứa dữ liệu cho tờ khai theo tiêu chuẩn ("built-in") lớp Kotlin mà không được biên soạn để .class file, nhưng thay vì được ánh xạ tới các kiểu hiện có trên nền tảng (trong trường hợp này là JVM). Ví dụ, kotlin/kotlin.kotlin_builtins chứa các thông tin cho các lớp học phi vật chất trong gói kotlin: Int, String, Enum, Annotation, Collection vv

Có hai kịch bản chính khi những tập tin này được sử dụng:

1) trình biên dịch tìm kiếm chúng từ kotlin-runtime trên classpath để xác định các khai báo dựng sẵn nào có sẵn.

2) Thư viện phản ánh (kotlin-reflect) tải các tệp này dưới dạng tài nguyên để cung cấp khả năng phản chiếu cho các khai báo tích hợp. Ví dụ, String::class.members trả về tất cả các thành viên của lớp kotlin.String chính xác theo cách tương tự như trình biên dịch Kotlin thấy những thành viên đó (mặc dù không có tệp kotlin/String.class và nó bị xóa thành java.lang.String trong bytecode).

Điểm đầu tiên rõ ràng là không áp dụng được trong trường hợp của bạn. Và nếu bạn không sử dụng sự phản chiếu trên các lớp dựng sẵn, tôi nghĩ sẽ an toàn khi loại trừ hoàn toàn các tệp .kotlin_builtins khỏi kết quả.

0

Bạn có thể tối ưu hóa/bỏ qua những từ lọ bạn/gói ứng dụng:

packagingOptions { 
    exclude "/META-INF/*.kotlin_module" 
    exclude "**/kotlin/**" 
    } 

Thậm chí tốt hơn:

packagingOptions { 
    exclude "/META-INF/*.kotlin_module" 
    exclude "**/kotlin/**" 
    exclude "**/*.txt" 
    exclude "**/*.xml" 
    exclude "**/*.properties" 
    } 

Nguồn: https://github.com/jaredsburrows/android-gif-example/blob/master/build.gradle#L144

Các vấn đề liên quan