Keep on moving

あんまりまとまってないことを書きますよ

Gradle+KotlinでのJavaのtarget versionの指定のしかたをまとめた

software version
gradle 7.2
Kotlin 1.5.30

Gradle+ Kotlinの環境でライブラリを書いていたらいつの間にか以下のようなwarningが出るようになってしまいました。

% ./gradlew test  

> Task :compileKotlin
'compileJava' task (current target is 11) and 'compileKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.

> Task :compileTestKotlin
'compileTestJava' task (current target is 11) and 'compileTestKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.

TL;DR

Gradleに以下の設定を入れる。以下はJava8の場合で KotlinDSLを使う場合の例

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

// こちらの書き方でもOK
// java {
//    toolchain.languageVersion.set(JavaLanguageVersion.of(8))
// }

val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.jvmTarget = "1.8" // javaの方とversionをあわせる

ググってみた

stackoverflow.com

どうもJavaのtarget versionとKotlinでのjvmTargetの値を両方指定しないといけないらしい。

toolchainの話が出てきたので調べてみたところどうもGradle 6.7から追加された概念らしい(後でもうちょい調べてみよう)

Gradle 6.7 で追加された Toolchain サポート - A Memorandum

Gradleはjava_homeで指定されているバージョンを使おうとするので私はadoptopenjdk11を使っていることもありtarget versionの互換性が〜〜〜というエラーが出るようになった様子。

というわけでこういう書き方をするようにbuild.gradle.ktsを書き直したところビルド時にwarningが出なくなりました。

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

// こちらの書き方でもOK
// java {
//    toolchain.languageVersion.set(JavaLanguageVersion.of(8))
// }

val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.jvmTarget = "1.8" // javaの方とversionをあわせる

余談

ちなみに 私はm1 macを使っているせいか toolchain.languageVersion.set(JavaLanguageVersion.of(8)) と書くと adoptOpenJDKから aarch64版のopenjdk8をダウンロードしてくれようとするのですが、adoptopendjdkでは提供していないため ビルドしようとするとエラーになってしまうので toolchainを使っていません

gh-extensionsを書いてみた

小ネタです。

ghコマンドが2.0.0になりました

forest.watch.impress.co.jp

で、mattnさんのこちらのTweetを見て一個ネタを思いついたので早速素振りがてら作ってみました。 何番煎じよと言わないでねw

mobile.twitter.com

作ったもの

github.com

いつでもきゅうり(Gherkin)がみられるコマンドです。

f:id:Ehren:20210828233638p:plain
gh erkin

Please enjoy!

Gradleで条件によってdependencyを変える

こんにちは, 僕です。

近頃 Apache Beam にたまにパッチを送るのを趣味で行っているのですが、そこで学んだtipsを紹介します。 今回のテーマはGradleを使っていて条件によってdependencyを変えたい的な要件です。

ちなみにGradleのバージョンは6以降が対象です。

TL;DR

github.com

条件によってGradleのdependencyを切り替える。

Gradleだとできそうだなーと思って調べたら結構簡単に見つかりました。

stackoverflow.com

こんな感じでgradleの実行時引数をとって分岐することができるとのこと。

$ gradle -Pgson dependencies --configuration implementation

これを利用すると呼び出しもとのgradleファイル内で変数を参照することも可能でした。 以下のような感じです。

// aaa.gradle
spark_scala_version = '2.12'
// bbb.gradle
//      aaa.gradleから呼ばれる
dependencies {
  // ...
  if(project.property("spark_scala_version").equals("2.11")){
    runtimeOnly library.java.jackson_module_scala_2_11
  } else {
    runtimeOnly library.java.jackson_module_scala_2_12
  }
  // ...

こんな感じで、Javaのバージョンによって参照するライブラリのバージョン分けることも可能なようです。 先人に感謝

Kotlinで書いたアプリのMaven Central Repository への公開手順(Gradle KotlinDSL 版)

- version
Date 2021.02.13
OpenJDK OpenJDK Runtime Environment Zulu11.43+1017-CA (build 11.0.9.1+1-LTS)
kotlin 1.4.30
gradle 6.8.2

Kotlinで書いたアプリのMaven Central Repository への公開手順(Gradle(KotlinDSL)版)

TL;DR

  • bintrayに公開していたものを移行するのは割と簡単
    • sonatypeへの登録は初回だけちょいと面倒かも(JIRAでissue作ったりが必要)
    • singingの追加
      • pgp keyの登録が必要
    • maven-publish pluginを使っていればアップロード先をbintray -> maven-centralに変える
  • 僕が使っているbuild.gradle.ktsを共有

流れ

こちらのブログが素晴らしく良くまとまっているので参照すると良いと思います。

blog1.mammb.com

  1. sonatype の JIRA で issue を通してリポジトリ作成を依頼
  2. GnuPG で jar を署名できる環境を作成
  3. Gradle プラグインリポジトリへ登録
  4. Repository Manager で Maven Central Repository へリリース

Tips

いくつか捕捉しておくと良さそうなことを書いておきます。

windowsを使っている方向け

windowsで表題の件をやりたい場合はこちらでgpg keyを作成すると良いと思います。 https://www.gpg4win.org/

gnupgmacportsで入れる

sudo port install gnupg2 # XCodeが必要

RSA keys may be between 1024 and 4096 bits long

ここは (3072) [デフォルト]になったみたいです。

すでにbintrayに公開済みのjarをmavencentralに移行

jfrog.com

JVM言語界隈に激震が走ったこの件について。 bintrayにpublishしているものをmaven centralに移行したい方は以下の感じになります

  1. sonatype の JIRA で issue を通してリポジトリ作成を依頼
  2. GnuPG で jar を署名できる環境を作成
  3. Gradle プラグインを変更してリポジトリへ登録
  4. Repository Manager で Maven Central Repository へリリース

build.gradle.ktsの書き換えは以下のような感じになります。

github.com

抜粋すると

plugins {
    ...
    signing // signingを追加. bintrayではこれが必要なかった
}
...
//    repositories {
//        maven {
//            name = "bintray"
//            val bintrayUsername = "masahitojp"
//            val bintrayRepoName = "maven"
//            val bintrayPackageName = "com.github.masahitojp.bqdatamapper4k"
//            setUrl("https://api.bintray.com/content/$bintrayUsername/$bintrayRepoName/$bintrayPackageName/${project.version};publish=0;override=1")
//            credentials {
//                username = project.findProperty("bintray_user") as String?
//                password = project.findProperty("bintray_api_key") as String?
//             }
//    }
    repositories {
        maven {
            name = "MavenCentral"
            val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
            credentials {
                username = project.findProperty("sonatypeUsername")?.toString() ?: ""
                password = project.findProperty("sonatypePassword")?.toString() ?: ""
            }
        }
    }
// PGP署名(Mavenセントラルリポジトリに公開するのに必要な署名形式)の追加
signing {
    sign(publishing.publications["maven"])
}

私がよく使っているbuild.gradle.ktsGradle(KotlinDSL)

plugins {
    val kotlinVersion = "1.4.30"
    kotlin("jvm") version kotlinVersion
    id("org.jetbrains.dokka") version "1.4.20" // Docにはdokkaを使う(ここは自分の好きなのに入れ替えてよし)
    `maven-publish`
    signing
}

group = 'Your Group Id'
version = 'X.X.X'
val artifactID = "プロジェクト名"

repositories {
    mavenCentral()
    jcenter() // dokka dependency
}

dependencies {

    // Use the Kotlin JDK 8 standard library.
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")


   // 必要ならライブラリがあれば追加

    // Use the Kotlin test library.
    testImplementation("org.jetbrains.kotlin:kotlin-test")

    // Use the Kotlin JUnit integration.
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

// Configure existing Dokka task to output HTML to typical Javadoc directory
tasks.dokkaHtml.configure {
    outputDirectory.set(buildDir.resolve("javadoc"))
}

// Create dokka Jar task from dokka task output
val dokkaJar by tasks.creating(Jar::class) {
    group = JavaBasePlugin.DOCUMENTATION_GROUP
    description = "Assembles Kotlin docs with Dokka"
    archiveClassifier.set("javadoc")
    // dependsOn(dokka) not needed; dependency automatically inferred by from(dokka)
    from(tasks.dokkaHtml)
}

// Create sources Jar from main kotlin sources
val sourcesJar by tasks.creating(Jar::class) {
    description = "Assembles sources JAR"
    archiveClassifier.set("sources")
    from(sourceSets["main"].allSource)
}

artifacts {
    add("archives", sourcesJar)
    add("archives", dokkaJar)
}

val jar by tasks.getting(Jar::class) {
    manifest {
        attributes(
            "Implementation-Title" to project.name,
            "Implementation-Version" to project.version,
            "Implementation-Vendor" to "masahito.me",
            "Built-JDK" to "${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})",
            "Built-Gradle" to gradle.gradleVersion
        )
    }
}

val sonatypeUsername = project.findProperty("sonatypeUsername")?.toString() ?: ""
val sonatypePassword = project.findProperty("sonatypePassword")?.toString() ?: ""

publishing {
    publications {
        create<MavenPublication>("maven") {
            groupId = project.group.toString()
            from(components.findByName("kotlin"))
            artifact(sourcesJar)
            artifact(dokkaJar)
            pom {
                name.set(artifactId)
                description.set("BigQuery datamapper for Kotlin")
                url.set("https://github.com/masahitojp/bqdatamapper4k")
                licenses {
                    license {
                        name.set("Apache License, Version 2.0")
                        url.set("https://opensource.org/licenses/Apache-2.0")
                    }
                }
                developers {
                    developer {
                        id.set("Your ID")
                        name.set("Your name")
                        email.set("Your email address")
                    }
                }
                scm {
                    connection.set("scm:git:git@github.com:XXXXX.git")
                    developerConnection.set("scm:git:ssh://github.com:XXXXX.git")
                    url.set("https://github.com/XXXXX")
                }
            }
        }
    }
    repositories {
        maven {
            name = "MavenCentral"
            val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
            credentials {
                username = sonatypeUsername
                password = sonatypePassword
            }
        }
    }
}

signing {
    sign(publishing.publications["maven"])
}

まとめ

  • bintrayに公開していたものを移行するのは割と簡単
    • sonatypeへの登録は初回だけちょいと面倒かも(JIRAでissue作ったりが必要)
    • singingの追加
      • pgp keyの登録が必要
    • maven-publish pluginを使っていればアップロード先をbintray -> maven-centralに変える
  • 僕が使っているbuild.gradle.ktsを共有

上記をしました。すでにsonatypeにアカウントを作っていればそんなに大変なことはないと思います。 ちょっと古かったりしますがまとめ直してくれていたりする素敵なかたがたくさんいたので僕は1時間くらいで作業を終えることができました。 先人たちに感謝。

karabiner-elementsとM1 MacBook Airでの問題が解決された

- version
macos Big Sur 11.6
karabiner elements 13.7.1

2021-09-16 update: 無事対解決 タイトルも s/解決されつつある/解決された/g とした


2021-03-04 update: バージョンが上がったが、状況変わらず

https://github.com/pqrs-org/Karabiner-Elements/issues/2517#issuecomment-787000561

こちらによると BigSur 11.3(beta)に上げると解消されたとのこと。macOS側に原因があるということなのかなぁ.


Krabiner Elements v13.1.0をインストールしているとMacを再起動やシステム終了した際に画面がピンクになり、 kernel panicになることが報告されてます。

gori.me

が、Karabiner ElementsのBeta版を使うことでこの件が修正され、正常に動作した方がいるようです。(M1 mac miniらしい)

github.com

I don't see this issue anymore after updating to 13.3.1 with M1 Mac mini and Big sur 11.2. Not sure if this is same for everyone, but anyways thanks a lot for dev team for providing this awesome app!

TL;DR

  • Karabiner-Elements beta版を使う(本日時点では 13.3.1)
  • ただし効果は人による(少なくともkarabiner-elementsを[システム終了]する前に終了すれば問題が出ない)

Krabiner-Elements Beta の使い方

  1. Krabiner-Elementsで [preference] を開く
  2. misc > [Check for beta update] を押下する

f:id:Ehren:20210208234736p:plain

  1. これだけで治る人がいるみたいですが、私の環境ではkarabiner-elementsを終了する -> システム終了 とすることで問題が出なくなりました。(因みにM1 Macbook Air)

Karabiner Elements causes Apple silicon MacBook Air to crash during system shutdown · Issue #2517 · pqrs-org/Karabiner-Elements · GitHub

参考

engisuke.hatenablog.com

先人とKarabiner-Elements開発者に感謝

aferoを使ってGoでのファイル生成のUnitTestを書きやすくする

Go言語の永遠の初心者です。 自分用の便利スクリプトを用意するときにシェルスクリプトではなくGoを使うときのTIpsです。 Goでファイル生成するときによく使っているライブラリを紹介します。

TL;DR

  • aferoを使うことでファイル生成のUnitTestが書きやすくなる

背景

Goでスクリプトを書いていてある程度処理をしてからファイルを生成することがあると思います。 ただスクリプトでの条件が増えてきたりするとそこからUnitTestsが書きたくなることがあると思います。 osライブラリを使うとファイルが作れるのですが... テストのタイミングでは現物のファイルを作るのではなく、 メモリ上でファイルを展開できるといいなーと思うことが多いですよね。

今回紹介するライブラリ

背景 のところで説明した話はこのライブラリを使うと行うことができます。 github.com

install

$ go get github.com/spf13/afero

使い方の例

import "github.com/spf13/afero"


// os packagと同じように扱える
AppFs := afero.NewOsFs()
MakeEmptyFile(AppFs, fileName)

func MakeEmptyFile(fs afero.Fs, s string) {
    dirName := filepath.Dir(s)
    exists, err := afero.DirExists(fs, dirName)
    if !exists && err != nil {
        mkdirErr := fs.MkdirAll(dirName, os.ModePerm)
        if err != nil {
            log.Fatal(mkdirErr)
        }
    }
    emptyFile, err := fs.Create(s)
    if err != nil {
        log.Fatal(err)
    }
    emptyFile.Close()
}

テストの例

func TestMakeEmptyFile(t *testing.T) {

        // テスト用にメモリ上でFSのmockを扱う
    AppFs := afero.NewMemMapFs()
    fileName := "./test.py"

        // メモリ上で扱ってくれるのでファイル本体ができることはない.
    MakeEmptyFile(AppFs, fileName)

        // でもUnitTestは実行可能
    // file exists
    exists, _ := afero.Exists(AppFs, fileName)
    assert(t, exists, true)

    // file is empty
    bytes, _ := afero.ReadFile(AppFs, fileName)
    assert(t, string(bytes), "")

}

func assert(t *testing.T, actual, expected interface{}) {
    if actual != expected {
        t.Errorf("got: %v\nwant: %v", actual, expected)
    }
}

まとめ

osパッケージと同じ使い方ができるのでaferoに切り替えるのは非常に簡単です。 つまりやめたくなったら元に戻すのも簡単です。 UnitTestsもやりやすくなるのでぜひ皆様も使ってみてください。

2020振り返り

Python界隈の魅惑の何かです。久しぶりに今年の振り返りをしたいと思います。

発表

Covid-19の今年はあんまり外で話せなかったなという印象。自分から話に行くのではなく、受け身になっちゃったなとか割と反省点は多い。 そんな中でもいくつか話せて楽しかった。

masahito.hatenablog.com 初めてのオンラインでの発表を経験した。オンラインは話すの難しいなというのも感じましたね~

pyconjp.blogspot.com pyconjp.blogspot.com 実は2018,2019と連続で話させていただいていました。CfP通ったのでオンラインでも話せるように準備だけしてました。 また再開したらCfPを出させてもらおう。(pycon kyushuは今のところCfPが皆勤賞だったりします 😆

OSS活動

今年はあまり時間が取れなかったので、気がついたtypoにPR投げたりとかしていた。 仕事で使ってるやつに少しはPR投げられたのでまた来年にでも。

[BEAM-11523] Bump Gradle to 6.7.1 by masahitojp · Pull Request #13414 · apache/beam · GitHub

仕事

毎日会社に通ってた毎日からフルリモートの生活に変わって最初は非常に戸惑ったんだけど、段々慣れてはきたかなと。 チームビルディング的なことをやったり、(実は自分ではあんまり興味がなかった)振り返りとかを久々にチームでやるようになったり とか変化が大きかったなと思う。

買ってよかったもの

マイク & オーディオインターフェース

ベリンガー 2入力2出力 USBオーディオインターフェース UMC22 U-PHORIA

ベリンガー 2入力2出力 USBオーディオインターフェース UMC22 U-PHORIA

  • 発売日: 2018/09/01
  • メディア: エレクトロニクス

zoomでの会議が増えたこともあり購入。これに安めのアームをつけて受けて運用してる。 フルリモートになってから話す機会が増えたこともあり、話してる内容がクリアに相手に伝わるので重宝している。 ちなみに初めて話す方からから [マイクすごいっすね] と言ってもらえるのである程度アイスブレイク的な会話のネタにできるのも 助かっています。

イヤフォン

出張や運動用にこっちを買って使っていた。

が、zoomでの会議が増えてTwitterでも話題になっていたこともあり思い切って骨伝導のやつを買ってみたんですが大当たりでした。

特に一時間以上のミーティングでも耳が痛くならないので重宝してます。

USB type-c hub

出張用に買ったこれを在宅でも使っている。値段の割にGigabit Etherに対応してくれていて重宝している。

M1 Macbook Air

ARMで動くとか面白いじゃんと思って購入。渋川さんのこの記事はだいぶ読ませてもらっていろいろ遊んでいる。

qiita.com

Ryzenが動くPCも持ってるんだけど、起動がめんどくさいせいかこっちのpcでとりあえずコード書くとかが近頃増えてる。 バッテリーの充電間隔が前より減ったり、ベッドサイドに置いておいてとりあえず調べ物したいときに非常に便利、 おかげで久々にブログを書く気が湧いてきたりとこのpcにはいろいろありがとうと言いたい。

その他

この企画のレビューのお手伝いができたて楽しかったですね。 id:t2y-1979 さんお声がけいただいてありがとうございました. Pythonでの型ヒントも色んな人がふつーに使ってくれるようになりつつあり、個人的には嬉しい限りですね。

最後に

なんだかんだで大変な一年ではありましたが今考えると変化に富んでいて色んなことが経験できた年だったなと思います。 私は変化がない生活は考えられないタチなので、来年もいろいろ手を出しつつ生きていきたいなと思います。 何かあったら声がけしていただけるようにしてきたいなと思ってます!

来年やってみたいことはまた来年にでもまとめます。