為 Kotlin 項目設置編譯選項

  • 2020 年 1 月 21 日
  • 筆記

經常用終端的人都知道,終端命令有很多選項可以指定,這裡我們以相關的kotlinc為例,我們可以在終端這樣指定選項

1 2 3 4 5

kotlinc -Werror ./app/src/main/java/com/example/compileroptionssample/Simple.kt error: warnings found and -Werror specified app/src/main/java/com/example/compileroptionssample/Simple.kt:4:19: warning: unnecessary safe call on a non-null receiver of type String println(string?.toString()) ^

上面的程式碼

  • 我們指定了-Werror 意思是當編譯器遇到了警告時當做錯誤拋出,中斷執行。
  • 上面的命令執行中斷,不會導致class文件生成

編譯選項有哪些

Kotlin的編譯選項分為標準選項和高級選項

如下是一些標準選項的內容(使用kotlinc -help獲取)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

kotlinc -help Usage: kotlinc-jvm <options> <source files> where possible options include: -classpath (-cp) <path> Paths where to find user class files -d <directory|jar> Destination for generated class files -include-runtime Include Kotlin runtime in to resulting .jar -java-parameters Generate metadata for Java 1.8 reflection on method parameters -jdk-home <path> Path to JDK home directory to include into classpath, if differs from default JAVA_HOME -jvm-target <version> Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6 -module-name <name> Name of the generated .kotlin_module file -no-jdk Don't include Java runtime into classpath -no-reflect Don't include kotlin-reflect.jar into classpath -no-stdlib Don't include kotlin-stdlib.jar or kotlin-reflect.jar into classpath -script Evaluate the script file -script-templates <fully qualified class name[,]> Script definition template classes -Werror Report an error if there are any warnings -api-version <version> Allow to use declarations only from the specified version of bundled libraries -X Print a synopsis of advanced options -help (-h) Print a synopsis of standard options -kotlin-home <path> Path to Kotlin compiler home directory, used for runtime libraries discovery -language-version <version> Provide source compatibility with specified language version -P plugin:<pluginId>:<optionName>=<value> Pass an option to a plugin -progressive Enable progressive compiler mode. In this mode, deprecations and bug fixes for unstable code take effect immediately, instead of going through a graceful migration cycle. Code written in the progressive mode is backward compatible; however, code written in non-progressive mode may cause compilation errors in the progressive mode. -nowarn Generate no warnings -verbose Enable verbose logging output -version Display compiler version @<argfile> Expand compiler arguments from the given file, containing one argument or file path per line

如下是更加高級的選項(使用kotlinc -X獲取)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

kotlinc -X Usage: kotlinc-jvm <options> <source files> where advanced options include: -Xadd-compiler-builtins Add definitions of built-in declarations to the compilation classpath (useful with -no-stdlib) -Xadd-modules=<module[,]> Root modules to resolve in addition to the initial modules, or all modules on the module path if <module> is ALL-MODULE-PATH -Xassertions={always-enable|always-disable|jvm|legacy} Assert calls behaviour -Xassertions=always-enable: enable, ignore jvm assertion settings; -Xassertions=always-disable: disable, ignore jvm assertion settings; -Xassertions=jvm: enable, depend on jvm assertion settings; -Xassertions=legacy: calculate condition on each call, check depends on jvm assertion settings in the kotlin package; default: legacy -Xbuild-file=<path> Path to the .xml build file to compile -Xcompile-java Reuse javac analysis and compile Java source files -Xnormalize-constructor-calls={disable|enable} Normalize constructor calls (disable: don't normalize; enable: normalize), default is 'disable' in language version 1.2 and below, 'enable' since language version 1.3 -Xdump-declarations-to=<path> Path to JSON file to dump Java to Kotlin declaration mappings -Xdisable-default-scripting-plugin Do not enable scripting plugin by default -Xdisable-standard-script Disable standard kotlin script support -Xfriend-paths=<path> Paths to output directories for friend modules (whose internals should be visible) -Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade -Xmodule-path=<path> Paths where to find Java 9+ modules -Xjavac-arguments=<option[,]> Java compiler arguments -Xjsr305={ignore/strict/warn}|under-migration:{ignore/strict/warn}|@<fq.name>:{ignore/strict/warn} Specify behavior for JSR-305 nullability annotations: -Xjsr305={ignore/strict/warn} globally (all [email protected] annotations) -Xjsr305=under-migration:{ignore/strict/warn} all @UnderMigration annotations [email protected]<fq.name>:{ignore/strict/warn} annotation with the given fully qualified class name Modes: * ignore * strict (experimental; treat as other supported nullability annotations) * warn (report a warning) -Xjvm-default={disable|enable|compatibility} Allow to use '@JvmDefault' annotation for JVM default method support. -Xjvm-default=disable Prohibit usages of @JvmDefault -Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method in the interface (annotating an existing method can break binary compatibility) -Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor in the 'DefaultImpls' class in addition to the interface method -Xload-builtins-from-dependencies Load definitions of built-in declarations from module dependencies, instead of from the compiler -Xno-call-assertions Don't generate not-null assertions for arguments of platform types -Xno-exception-on-explicit-equals-for-boxed-null Do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type -Xno-optimize Disable optimizations -Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java -Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types -Xsanitize-parentheses Transform '(' and ')' in method names to some other character sequence. This mode can BREAK BINARY COMPATIBILITY and is only supposed to be used as a workaround of an issue in the ASM bytecode framework. See KT-29475 for more details -Xscript-resolver-environment=<key=value[,]> Script resolver environment in key-value pairs (the value could be quoted and escaped) -Xsingle-module Combine modules for source files and binary dependencies into a single module -Xskip-runtime-version-check Allow Kotlin runtime libraries of incompatible versions in the classpath -Xstrict-java-nullability-assertions Generate nullability assertions for non-null Java expressions -Xgenerate-strict-metadata-version Generate metadata with strict version semantics (see kdoc on Metadata.extraInt) -Xsupport-compatqual-checker-framework-annotations=enable|disable Specify behavior for Checker Framework compatqual annotations (NullableDecl/NonNullDecl). Default value is 'enable' -Xuse-ir Use the IR backend -Xuse-javac Use javac for Java source and class files analysis -Xuse-old-class-files-reading Use old class files reading implementation. This may slow down the build and cause problems with Groovy interop. Should be used in case of problems with the new implementation -Xuse-type-table Use type table in metadata serialization -Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info -Xallow-result-return-type Allow compiling code when `kotlin.Result` is used as a return type -Xcommon-sources=<path> Sources of the common module that need to be compiled together with this module in the multi-platform mode. Should be a subset of sources passed as free arguments -Xcoroutines={enable|warn|error} Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier -Xdisable-phases Disable backend phases -Xdump-perf=<path> Dump detailed performance statistics to the specified file -Xeffect-system Enable experimental language feature: effect system -Xexperimental=<fq.name> Enable and propagate usages of experimental API for marker annotation with the given fully qualified name -Xintellij-plugin-root=<path> Path to the kotlin-compiler.jar or directory where IntelliJ configuration files can be found -Xlegacy-smart-cast-after-try Allow var smart casts despite assignment in try block -Xlist-phases List backend phases -Xmetadata-version Change metadata version of the generated binary files -Xmulti-platform Enable experimental language support for multi-platform projects -Xnew-inference Enable new experimental generic type inference algorithm -Xno-check-actual Do not check presence of 'actual' modifier in multi-platform projects -Xno-inline Disable method inlining -Xphases-to-dump Dump backend state both before and after these phases -Xphases-to-dump-after Dump backend state after these phases -Xphases-to-dump-before Dump backend state before these phases -Xplugin=<path> Load plugins from the given classpath -Xprofile-phases Profile backend phases -Xproper-ieee754-comparisons Generate proper IEEE 754 comparisons in all cases if values are statically known to be of primitive numeric types -Xread-deserialized-contracts Enable reading of contracts from metadata -Xreport-output-files Report source to output files mapping -Xreport-perf Report detailed performance statistics -Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes) -Xuse-experimental=<fq.name> Enable, but don't propagate usages of experimental API for marker annotation with the given fully qualified name -Xverbose-phases Be verbose while performing these backend phases Advanced options are non-standard and may be changed or removed without any notice.

編譯選項有什麼用

編譯選項通常有以下這樣的作用,不完全列舉

  • 開啟或關閉某些feature等行為(比如coroutine, 新的類型推斷演算法等)
  • 控制或設置編譯器需要的參數(比如-jvm-target設置class的目標平台)
  • 控制編譯器的輸出(比如method inline,-Xno-param-assertions對參數進行斷言處理)

如何開啟設置

以Android項目為例,增加kotlinOptions配置

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

android { compileSdkVersion 28 defaultConfig { applicationId "com.example.compileroptionssample" minSdkVersion 15 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { } } //Code to be added kotlinOptions { allWarningsAsErrors = true } }

更加複雜的參數傳遞

默認情況下,gradle中只有四個欄位處理編譯選項

  • allWarningsAsErrors 將所有的警告當做錯誤處理,默認值為false
  • suppressWarnings 壓制所有的警告,默認值為false
  • verbose 列印更多的資訊,默認值為false
  • freeCompilerArgs 附加的編譯器選項列表,默認值為[]

1 2 3 4

kotlinOptions { allWarningsAsErrors = true freeCompilerArgs += ['-Xno-param-assertions', '-Xmultifile-parts-inherit'] }

關於上述配置的驗證,大家可以對比如下的程式碼的編譯輸出驗證-Xno-param-assertions選項的作用

1 2 3 4 5

package com.example.compileroptionssample fun dump(string: String) { println(string) }

如何按照Variant進行配置

那我能不能這樣呢?

  • 僅僅在Release編譯下設置某個編譯選項
  • 其他非Release編譯不設置這個編譯選項

答案是可以的,按照下面的方式就行了。

1 2 3 4 5 6 7 8 9 10 11 12

//only add kotlinOptions for the releaseKotlin build task tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { task -> if (task.getName() == "compileReleaseKotlin") { kotlinOptions { allWarningsAsErrors = true } println("Add kotlin options when task=" + task) } else { println("Do not add kotlin options when task=" + task) } }

上述程式碼

  • 所在文件為模組目錄,比如app/build.gradle
  • 上述程式碼與android同級別

利用Kotlin編譯選項我們可以做一些很好玩的事情,後續會輸出更多這方面的內容。