Kotlin's cinterop .def wont work with relative paths - kotlin

I have a static library that needs to link to other static libraries.
When I attempt to run ./gradlew common:cinteropSomeLibIos :
I always get IllegalStateException: Could not find 'libabseil.a' binary in neither of [external/lib]
my def file:
headers = SomeHeader.h
language = Objective-C
package = com.mypackage
staticLibraries = libabseil.a libMyLib.a
libraryPaths = external/lib
linkerOpts = -lObjC -all_load
Everything works within AndroidStudio/IntelliJ but when using the command line interface or building with bazel i consistently get the above error.
I tried adding:
val main by compilations.getting {
kotlinOptions {
freeCompilerArgs = listOf(
"-include-binary", "$libLocation/libabseil.a"
)
}
}
as well as setting linkerOpts within the gradle file but that results in:
warning: -linker-option(s)/-linkerOpts option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.
Is there any way to get this working or at least to call the cinterop task in a way that the relative paths in the .def file will work?

Related

Kotlin/Native project built without errors, but fails to run

I create a Kotlin/Native project with gradle init, and follow the instructions from here, managed to build the project without problems, being generated a build/bin/native/debugExecutable/executable.kexe executable file.
But when I try to run the project, I got the message:
/build/bin/native/debugExecutable/executable.kexe: error while loading shared libraries: libone.so: cannot open shared object file: No such file or directory
I am using a C library, located in the directory ../libone/libone.so (relative to the project folder). I have this *.dex file on the directory src/nativeInterop/cinterop of my project:
headers = libone.h
package = libone
compilerOpts.linux = -I/.../libone
linkerOpts.linux = -L/.../libone -lone
I have tried put the executable (executable.kexe) and the library (libone.so) in the same directory, but do not work either (same error occurs). What I am missing here?
UPDATE I made work manually setting the linux environment variable LD_LIBRARY_PATH to the library directory. I wonder if I could make work without this change in the system.
build.gradle
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.5.31'
}
repositories {
mavenCentral()
}
kotlin {
def hostOs = System.getProperty("os.name")
def isMingwX64 = hostOs.startsWith("Windows")
def nativeTarget
if (hostOs == "Mac OS X") nativeTarget = macosX64('native')
else if (hostOs == "Linux") nativeTarget = linuxX64("native")
else if (isMingwX64) nativeTarget = mingwX64("native")
else throw new FileNotFoundException("Host OS is not supported in Kotlin/Native.")
nativeTarget.with {
compilations.main { // NL
cinterops { // NL
libone // NL
} // NL
} // NL
binaries {
executable {
entryPoint = 'main'
}
}
}
sourceSets {
nativeMain {
}
nativeTest {
}
}
}
Makefile for libone
all: libone
libone: libone.o
gcc -shared -o libone.so libone.o -Wl,--out-implib,libone.a
libone.o: libone.c
gcc -fPIC -c libone.c -o libone.o
You can try changing the path in the def file to an absolute path, in my project I usually generate the def dynamically and make it a gradle task. But I still recommend you to use absolute paths anyway, there are enough examples here kotlin native samples

Breakpoints not working with GroovyShell evaluate()

I'm trying to add breakpoints in IntelliJ to debug foo.groovy when used like this:
def binding = new Binding();
binding.lineList = [list1];
binding.count = 5;
def shell = new GroovyShell(binding);
def result = shell.evaluate(new File("../../not-src-main-groovy/foo.groovy"));
This compiles and runs fine, BUT IntellIj won't stop at my breakpoints.
On the other hand, if I place foo.groovy in src/main/groovy/com/... then IntellIJ DOES stop at my breakpoints, as suggested in this stackoverflow answer.
But unlike that post, foo.groovy does multiple import statements. Those statements reference code from a different github repo, cloned locally outside my project at ../../not-src-main-groovy.
I've tried changing IntelliJ > Project Structure > Modules > mymodule > Dependencies > + > JARS or Directories > "../../not-src-main-groovy" but IntelliJ doesn't stop at the breakpoints.
How can I configure IntelliJ to stop at foo.groovy breakpoints?
I found a solution. Because my project uses gradle, I added the following to build.gradle.
dependencies {
...
compile files("include-me/**")
...
}
That way, gradle will include the files in the classpath during the compilation phase, but not actually compile them, since they're not in here:
sourceSets {
main.groovy {
srcDirs = [ 'src/main/groovy']
}
}

android two buildTypes - error: duplicate class

Android Studio 3.4
I have 2 build types:
debug
release
so my project structure is:
src/debug/java/
src/main/java/
src/release/java/
I has CartActivity. This class has different implementation for release version and debug version.
So this class location is in TWO folders:
src/debug/java/activityCartActivity
src/main/java/activityCartActivity
But when I build project by gradlew assemble I get error:
> Task :scanlib:processDebugJavaRes NO-SOURCE
> Task :scanlib:transformClassesAndResourcesWithPrepareIntermediateJarsForDebug
> Task :app:javaPreCompileDebug FROM-CACHE
> Task :app:compileDebugJavaWithJavac FAILED
\app\src\debug\java\com\myproject\app\cart\CartActivity.java:66: error: duplicate class: com.myproject.app.cart.CartActivity
public class CartActivity extends AppCompatActivity {
You can't do it.
src/debug/java/activityCartActivity
src/main/java/activityCartActivity
Check the official doc:
All source code in the java/ directories are compiled together to generate a single output.
And in particular:
Note: For a given build variant, Gradle throws a build error if it encounters two or more source set directories that have defined the same Java class. For example, when building a debug APK, you cannot define both src/debug/Utility.java and src/main/Utility.java. This is because Gradle looks at both these directories during the build process and throws a "duplicate class" error. If you want different versions of Utility.java for different build types, you can have each build type define its own version of the file and not include it in the main/ source set.
Move CartActivity class from 'src/main/java/activityCartActivity' to src/release/java/activityCartActivity'.
"If above mentioned change does not work" modify java source path in app/build.gradle as
sourceSets {
main {
//java.srcDirs = ['src/main/java']
aidl.srcDirs = ['src/main/aidl']
renderscript.srcDirs = ['src/main/rs']
jni.srcDirs = []
jniLibs.srcDirs = []
res.srcDirs = ['src/main/res']
assets.srcDirs = []
}
test{
java.srcDirs = ['test']
}
debug {
java.srcDirs = ['src/debug/java']
}
release {
java.srcDirs = ['src/release/java']
}
}

Kotlin native interop linker could not find framework

I'm trying to use cocoapods framework in Kotlin Multiplatform project.
So I
added framework to Pods file.
ran pod install.
created .def file
added cinterop config in build.gradle
./gradlew cinteropFirebaseIos runs successfully. It generates .klib so I can see classes in kotlin code.
But when I'm trying to run iOS app build fails with message:
Showing Recent Messages
> Task :app:linkDebugFrameworkIos
ld: framework not found FirebaseDatabase
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors
Here is my config in build.gradle
fromPreset(presets.iosX64, 'ios') {
compilations.main {
outputKinds('FRAMEWORK')
cinterops {
firebase {
def proj = "${System.getProperty("user.home")}/Projects/kmpp"
def pods = "${proj}/iosApp/Pods"
defFile "${proj}/app/src/iosMain/c_interop/libfirebase.def"
includeDirs "${pods}/Firebase",
"${pods}/Firebase/CoreOnly/Sources",
"${pods}/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers"
}
}
}
}
here is my .def file:
language = Objective-C
headers = /Users/oleg/Projects/klug/crckalculator/iosApp/Pods/FirebaseCore/Firebase/Core/Public/FIRApp.h /Users/oleg/Projects/klug/crckalculator/iosApp/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h /Users/oleg/Projects/klug/crckalculator/iosApp/Pods/FirebaseCore/Firebase/Core/Public/FirebaseCore.h
compilerOpts = -framework FirebaseDatabase
linkerOpts = -framework FirebaseDatabase
How can I figure out what is wrong ? Did I miss something in .def file ? In build.gradle ?
There are two problematic moments here:
full paths to C headers in .def file are usually not desirable, instead passing includeDirs to Firebase installation, like in https://github.com/JetBrains/kotlin-native/blob/c7c566ce0f12221088a8908b6dc8e116c56a931b/samples/gtk/build.gradle#L22 would be helpful
linking problem comes from the similar issue - linker just got no idea where to look for framework libraries, so passing to compilations.main.linkerOpts smth like -F /Users/oleg/Projects/klug/crckalculator/iosApp/Pods/FirebaseCore/ shall help, see for example https://github.com/JetBrains/kotlin-native/blob/c7c566ce0f12221088a8908b6dc8e116c56a931b/samples/videoplayer/build.gradle#L15

How to specify IntelliJ Exclude Directories using Gradle?

Using IntelliJ to open a build.gradle file, in the "Import Project from Gradle" window, the "Excluded Roots" are pre-populated with the .gradle and build directories.
How do I specify what directories should be excluded (or not excluded) in the build.gradle file?
Specifically I am using a protocol buffer plugin that places generated sources in the /build/generated-sources/ directory. If the build directory is excluded then my source class do not see the generated classes.
Details: IntelliJ 12.1.3, Gradle 1.4
As shown in the Gradle Build Language Reference, you can configure the idea.module.excludeDirs property, which is of type List<File>. Apparently IDEA doesn't support including subdirectories of excluded directories, so you'll have to exclude all siblings of build/generated-sources. For example:
idea {
module {
excludeDirs = [file(".gradle")]
["classes", "docs", "dependency-cache", "libs", "reports", "resources", "test-results", "tmp"].each {
excludeDirs << file("$buildDir/$it")
}
}
}
If supported by the Protocol Buffer plugin, it may be easier to put the generated sources into a place outside build, and make that place known to the clean task (e.g. clean.delete "generated-sources").
Another solution. Works with Idea 13.
idea.module {
excludeDirs -= file(buildDir) //1
buildDir.listFiles({d,f->f != 'generated-sources'} as FilenameFilter).each {excludeDirs += it}} //2
Remove buildDir from excludeDirs.
Exclude each buildDir child (except generating-source).
If you are using the Gradle Kotlin DSL, use the following snippet:
idea {
module {
excludeDirs.add(file("..."))
}
}
for exclude folder in module i'm use
idea {
module.apply {
val file = file("$projectDir/node_modules")
val exclude = HashSet<File>(excludeDirs)
exclude.add(file)
excludeDirs = exclude
}
}