-
Notifications
You must be signed in to change notification settings - Fork 5
Adding initial sample project #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
144fa1e
efed021
3def015
2a42c07
eeac196
be7ecf3
2317c9c
edef00c
3b1ca99
57f500a
c20c77f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,9 @@ gen/ | |
| .gradle/ | ||
| build/ | ||
|
|
||
| # Kotlin | ||
| .kotlin/ | ||
|
|
||
| local.properties | ||
|
|
||
| Pods | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # C Klib sample: passphrase-encrypted notes with Monocypher | ||
|
|
||
| A sample for C Klib that packages the C library [Monocypher](https://monocypher.org). It's a simple passphrase-encrypted note implementation. | ||
|
|
||
| ```kotlin | ||
| val sealed: ByteArray = SecureNote.seal("hunter2", "meet me at the docks at midnight") | ||
| val note: String? = SecureNote.open("hunter2", sealed) // null if the passphrase is wrong | ||
| ``` | ||
|
|
||
| C Klib compiles C to LLVM bitcode; cinterop reads the same headers and generates the Kotlin | ||
| declarations; the Kotlin/Native compiler links the two together. | ||
|
|
||
| ## Running the sample | ||
|
|
||
| From the repository root, using the root wrapper: | ||
| ```bash | ||
| ./gradlew -p sample build # compile every declared target | ||
| ./gradlew -p sample macosArm64Test # the host-runnable test suite | ||
| ./gradlew -p sample allMonocypher # just the bitcode, for every target | ||
| ``` | ||
|
|
||
| `sample/settings.gradle.kts` uses `pluginManagement { includeBuild("..") }`, so the plugin is built | ||
| from this working tree rather than downloaded. No `version` on the plugin id, and no | ||
| `include(":sample")` in the root build. | ||
|
|
||
| > **Note:** The first run downloads an LLVM toolchain into `~/.cklib` (about 1.6 GB) and Kotlin/Native into | ||
| `~/.konan`. | ||
|
|
||
| ## Notes | ||
|
|
||
| * **`srcDirs` defaults to `srcRoot/cpp`, even for `Language.C`.** `headersDirs` defaults to | ||
| `srcDirs + srcRoot/headers`. If you want your C in a directory not named `cpp`, override both: | ||
|
|
||
| ```kotlin | ||
| create("monocypher", srcDir = file("src/monocypher")) { | ||
| language = CompileToBitcode.Language.C | ||
| srcDirs = files("src/monocypher/c") | ||
| headersDirs = files("src/monocypher/headers") | ||
| } | ||
| ``` | ||
|
|
||
| * **`mingwX64`** is deliberately not declared: `secure_random.c` has no Windows branch, and adding one | ||
| means `BCryptGenRandom` plus linking `bcrypt.lib`. | ||
|
|
||
| * **`Language.C` compiles with `-std=gnu11 -O3 -Wall -Wextra -Werror`, hardcoded.** The only escape | ||
| hatch is `compilerArgs`, which is appended after those flags, so `-Wno-error=<specific>` works. | ||
| This sample needs **no suppressions at all**: Monocypher 4.0.3 and `secure_random.c` both build | ||
| clean. Vendored code that is not warning-clean will stop the build dead, so check before you commit | ||
| to a library. | ||
|
|
||
| * **Shared `nativeMain` + cinterop needs `kotlin.mpp.enableCInteropCommonization=true`.** Without it, | ||
| per-target tasks like `compileKotlinMacosArm64` and `macosArm64Test` work fine, but | ||
| `compileNativeMainKotlinMetadata` — which `build` runs — fails with `Unresolved reference | ||
| 'cinterop'` for every binding. It is in `gradle.properties`. | ||
|
|
||
| * **`config.kotlinVersion` must match the Kotlin plugin version.** CKlib resolves the toolchain at | ||
| `~/.konan/kotlin-native-prebuilt-<os>-<arch>-<kotlinVersion>` and fails with a bare | ||
| `InvocationTargetException` if that directory is missing. On a machine with no Kotlin/Native | ||
| installed yet, the bitcode task can therefore fail before anything has had a chance to download it; | ||
| running any Kotlin/Native task first (`./gradlew -p sample cinteropMonocypherMacosArm64`) fetches | ||
| the distribution and unblocks it. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| /* | ||
| * Copyright (c) 2021 Touchlab | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | ||
| * in compliance with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software distributed under the License | ||
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | ||
| * or implied. See the License for the specific language governing permissions and limitations under | ||
| * the License. | ||
| */ | ||
|
|
||
| import co.touchlab.cklib.gradle.CompileToBitcode | ||
|
|
||
| plugins { | ||
| kotlin("multiplatform") version "2.0.0" | ||
| id("co.touchlab.cklib") | ||
| } | ||
|
|
||
| kotlin { | ||
| val nativeTargets = listOf( | ||
| macosArm64(), | ||
| macosX64(), | ||
| iosArm64(), | ||
| iosSimulatorArm64(), | ||
| linuxX64(), | ||
| ) | ||
|
|
||
| nativeTargets.forEach { target -> | ||
| target.compilations.getByName("main").cinterops.create("monocypher") { | ||
| defFile(project.file("src/nativeInterop/cinterop/monocypher.def")) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this line is required if the def file name matches the create name above
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch I removed it |
||
| // cinterop only needs the headers. The compiled code arrives as bitcode from cklib, | ||
| // which is why the .def declares no staticLibraries or libraryPaths. | ||
| includeDirs(project.file("src/monocypher/headers")) | ||
| } | ||
| } | ||
|
|
||
| sourceSets { | ||
| val commonTest by getting { | ||
| dependencies { | ||
| implementation(kotlin("test")) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| cklib { | ||
| config.kotlinVersion = "2.0.0" | ||
|
|
||
| create("monocypher", srcDir = file("src/monocypher")) { | ||
| language = CompileToBitcode.Language.C | ||
|
|
||
| // Both default to a `cpp` subdirectory (headersDirs additionally to `headers`) even for | ||
| // Language.C, so point them at the real layout instead of naming a C folder "cpp". | ||
| srcDirs = files("src/monocypher/c") | ||
| headersDirs = files("src/monocypher/headers") | ||
|
|
||
| // No compilerArgs. Language.C compiles with a hardcoded | ||
| // `-std=gnu11 -O3 -Wall -Wextra -Werror`, and both Monocypher 4.0.3 and secure_random.c | ||
| // build clean under it, so no -Wno-error= escape hatch is needed. | ||
| // compilerArgs.addAll( | ||
| // listOf( | ||
| // ) | ||
| // ) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| kotlin.code.style=official | ||
| org.gradle.jvmargs=-Xmx3g | ||
|
|
||
| # Required because SecureNote.kt lives in the shared `nativeMain` source set and references cinterop | ||
| # declarations. Per-target compilation (`compileKotlinMacosArm64`) works without this, but | ||
| # `compileNativeMainKotlinMetadata`, which type-checks the shared source set and runs as part of | ||
| # `build`, fails with "Unresolved reference 'cinterop'" unless commonization is on. | ||
| kotlin.mpp.enableCInteropCommonization=true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| distributionBase=GRADLE_USER_HOME | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gradle-wrapper.properties, but no gradlew binary for the sample
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated |
||
| distributionPath=wrapper/dists | ||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip | ||
| networkTimeout=10000 | ||
| validateDistributionUrl=true | ||
| zipStoreBase=GRADLE_USER_HOME | ||
| zipStorePath=wrapper/dists | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * Copyright (c) 2021 Touchlab | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | ||
| * in compliance with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software distributed under the License | ||
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | ||
| * or implied. See the License for the specific language governing permissions and limitations under | ||
| * the License. | ||
| */ | ||
|
|
||
| pluginManagement { | ||
| // Resolves `co.touchlab.cklib` from the plugin sources in this repository, so the sample | ||
| // always exercises the working tree rather than a published release. | ||
| includeBuild("..") | ||
| repositories { | ||
| gradlePluginPortal() | ||
| mavenCentral() | ||
| google() | ||
| } | ||
| } | ||
|
|
||
| dependencyResolutionManagement { | ||
| repositories { | ||
| mavenCentral() | ||
| google() | ||
| } | ||
| } | ||
|
|
||
| rootProject.name = "cklib-sample" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fun fact AI caught. This isn't a comment. The
#has to be the first character of the line and there is a space here. So it's actually a functioning rule which ignores a file named# KotlinThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huh interesting, ok I updated those comments