I have library target with private dependencies which are not exposed through the public API. I also have testing target to unit-test the library -- it should have access to all of the library's headers, even the ones not exposed through the public API. Because of it, I need to link testing to library's private dependencies. How can I achieve this apart from manually specifying them all?
Speaking in OOP terms, I would like library either to have its private dependencies protected so that testing can "inherit" from library and access them or to have testing as a "friend" so it can exclusively access the private dependencies.
Alternatively, I would like to temporarily make all library's dependencies public, link library to testing (with all of its dependencies now public), and make them private again.
Related
I have to add some kotlin-written classes at groovy-written shared library to use it in my jenkins pipeline. However, these classes aren't available:
WorkflowScript: 19: unable to resolve class package.name.KotlinClass
And i don't have the same problem with groovy classes. I think the problem is i don't declare any tasks like compileKotlin, but where should i declare it? What drives the building of sources from shared plugin libraries and is this process configurable?
If I understand the problem correctly, you have a shared library in Jenkins, which a pipeline makes use of. Within that shared library, you would like your groovy to call onto classes compiled from kotlin.
The best approach to this would be to have a separate process compile the kotlin and publish a JAR into a maven repository. Once that is done, your groovy shared library can fetch the JAR using #Grab. This is covered in https://www.jenkins.io/doc/book/pipeline/shared-libraries/#using-third-party-libraries and broadly works like so:
#Grab('org.apache.commons:commons-math3:3.4.1')
import org.apache.commons.math3.primes.Primes
void parallelize(int count) {
if (!Primes.isPrime(count)) {
error "${count} was not prime"
}
// …
}
If you want to resolve that JAR from your own private maven repository as opposed to Maven Central, you can also add the #GrabResolver annotation as documented here https://docs.groovy-lang.org/latest/html/documentation/grape.html#Grape-SpecifyAdditionalRepositories
#GrabResolver(name='restlet', root='http://maven.restlet.org/')
#Grab('org.apache.commons:commons-math3:3.4.1')
A problem you will run into here is that you cannot add credentials into that #GrabResolver and I am not aware of a way to get credentials into the groovy sandbox to make that work for Jenkins shared libraries.
An alternative approach, as hinted by Jenkins own documentation is to build the required functionality into it's own executable, and make sure that executable is available in the build process the Jenkins shared library is being called in.
I am trying to build a kotlin library for discord bots, which can be found at https://github.com/TheDrone7/discord-kt , published to jcenter (bintray link - https://bintray.com/thedrone7/discordKt/discord-kt). The library has a few dependencies of it's own as well.
When I add my own library to my test app, the library's dependencies were not installed and I started getting some errors. Is there a way to specify the library's dependencies so that they get automatically installed when a user uses my library?
EDIT: -
So basically my test app's build.gradle.kts file's dependencies section is given below
dependencies {
// Use the Kotlin JDK 8 standard library.
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.theDrone:discordKt:0.0.1a")
// Use the Kotlin test library.
testImplementation("org.jetbrains.kotlin:kotlin-test")
// Use the Kotlin JUnit integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}
And my library is dependent on the following packages: -
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0
org.java-websocket:Java-WebSocket:1.4.0
com.beust:klaxon:5.0.5
org.slf4j:slf4j-jdk14:1.7.26
now when I run my test app, it shows gives error that there is no class named WebSocketClient which is a part of the org.java-websocket:Java-WebSocket:1.4.0 package and is also the base of my entire library.
When I add the listed packages to my test app's dependencies, it works perfectly fine. So is there a way that I could define in my library that the apps using it will also automatically depend on the packages my library depends on?
You declared the Java-WebSocket library as a dependency of your library using the implementation configuration.
This configuration means: I need that for my code to work, but it's an implementation detail and it's thus not part of my public API, so users of my library won't have access to it in their compile classpath.
So Gradle, when it generates the pom.xml file for your library, adds Java-WebSocket as a runtime dependency, and not as a compile dependency.
Read the java-library plugin documentation, which explains all of that in details. Once you have understood it, use api instead of implementation in your library's build.gradle.kts file for the dependencies that are part of your API, and should thus be compile dependencies and not runtime dependencies:
api("org.java-websocket:Java-WebSocket:1.4.0")
I have a project with multiple framework targets, that also have pods dependencies.
I have:
No circular dependencies between targets
Everything, including pods, is in Objective-C, no Swift at all.
use_frameworks! in Podfile, so all pods are frameworks, not libraries.
Here is my structure:
TUSystemKit depends on TUModels (which is a framework).
TUModels depends on Pods_TUModels (generated by pods).
Pods_TUModels depends on JSONModel
TUModels is automatically linked with its own pod framework (which contains JSONModel).
TUSystemKit has TUModels as target dependency.
TUSystemKit is linked with TUModels.
Visually, the dependencies are like this:
TUSystemKit ➔ TUModels ➔ Pods_TUModels ➔ JSONModel
When I select MyModels as the build target in Xcode, build succeeds. However, when I select TUSystemKit, the build fails, saying that module JSONModel is not found while building module TUSystemKit (TUUser in screenshot belongs to TUModels):
What am I doing wrong? Obviously I shouldn't be explicitly linking against all the frameworks in the dependency tree. Why does TUModels build perfectly but TUSystemKit errs on a module import inside a linked framework's code? Do I need to change something with pods?
After hours of refactoring, I've managed to build my project. I can't tell what exactly was wrong as it took me literally a day to organize all the dependencies and frameworks and it kept failing at a different point, more than a 100 times, but here are some observations to lead to a successful build:
All the public-facing classes are added as public headers to the target, and not to any other target.
All the code (.m files) are in Compile Sources section of the target, and not in any other target.
All the public facing classes' headers are included at umbrella header (a header with the exact same name with the framework)
The application embeds all the custom frameworks (not the pods).
All the files inside a framework target only #import required files within the same target or a file listed on any targets umbrella header that the framework has a dependency on.
Obvious, redundant, but worth noting again: no classes between frameworks should have circular dependencies (e.g. ClassA in FrameworkA depends on ClassB in FrameworkB, while some class in FrameworkB depends on some class on FrameworkA). I had some, and created delegates. Do whatever pattern fits your design: IoT/dependency injection, notifications/publisher-subscriber etc. But do it: separate the concerns clearly.
Try to avoid using same classes in multiple targets. Instead, have it in one target, and make the other target depend on the containing target, creating a dependency chain.
After refactoring many files and playing with project settings, I managed to build and run everything again. My previous setup had various number of combinations of the issues that I mentioned above, messing everything up. After cleaning all the bits and grouping code into functional, modular frameworks, I could build it.
If you came here due to the parse error -> module not found,
in certain occasions you may be forced to add the path manually.
This is...
go to your project at the top
select your project target
select build settings
search the parameter Framework Search Paths under the title Search Paths
add the one where yours is located. Example: (using cocoa pods) $(SRCROOT)/Pods
indicate/set it to be recursive (access to the option by double-clicking your previously added path)
The problem should have been resolved by the 3erd party lib with commands like install / update / build or similar but if it fails and you are stuck, this is an option in order to continue.
In the same tone, if you get an error from pods indicating that
The sandbox is not in sync with the Podfile because the builder is unable to find files like Podfile.lock, then you may consider to go in the same direction adding some user-defined settings:
select build settings
press the '+' symbol, "Add User-Defined Setting".
add this pair:
param= PODS_PODFILE_DIR_PATH value = ${SRCROOT}/.
param = PODS_ROOT value = ${SRCROOT}/Pods
Cheers
In the Kotlin documentation they are mentioning some kind of module for instance in the documentation for the internal modifier.
However I couldn't find any definition of the term module itself. So what is meant by module?
A module is a set of Kotlin sources compiled together:
an IntelliJ IDEA module;
a Maven project;
a Gradle source set;
a set of files compiled with one invocation of the Ant task.
This is in the same docs article about visibility modifiers. :)
From the Kotlin's documentation, a module is a set of Kotlin files compiled together:
an IntelliJ IDEA module
a Maven project;
a Gradle source set
a set of files compiled with one invocation of the <kotlinc> Ant task.
That is #hotkey's, but I would like to complement this answer.
According to Andrey Breslav, the Lead Language Designer of Kotlin:
a Kotlin module maps one-to-one to IntelliJ's module (iml-file).
According to IntelliJ's documentation:
Modules allow you to combine several technologies and frameworks in one application. In IntelliJ IDEA, you can create several modules for a project and each of them can be responsible for its own framework.
When it comes to a Maven project or a command line compilation, Andrey states:
Each compiler run, by default, is a separate module: all the binary dependencies will be treated as being not in the module being compiled at the moment.
Also, a Gradle source set is a module, with the exception that the test source set can access the internal declarations of main.
This means that if you have different build flavors in your Gradle configuration resulting in different source sets, for production and debug versions for example, then an internal class from one source set would not be available to be used in another source set.
Per Kotlin language specification §10.2 Modules:
A module is a concept on the boundary between the code itself and the
resulting application, thus it depends on and influences both of them.
A Kotlin module is a set of Kotlin files which are considered to be
interdependent and must be handled together during compilation.
In a simple case, a module is a set of files compiled at the same time
in a given project.
A set of files being compiled with a single Kotlin compiler invocation
A Maven module
A Gradle project
In a more complicated case involving multi-platform projects, a module
may be distributed across several compilations, projects and/or platforms.
For the purposes of Kotlin/Core, modules are important for internal
visibility. How modules influence particular platforms is
described in their respective sections of this specification.
I think you might be referring to org.koin.core.module.Module
A Koin module is a "space" to gather Koin definition. It's declared with the module function.
val myModule = module {
// Your definitions ...
}
This documentation would be helpful in that case.
I am trying to distribute static lib that contain static lib (google adMob).
In my test application that uses the static library, it crashes when trying to access the static library within the static library.
Any ideas on how to distribute static library that contain static library?
10x
Tamir
There is no such thing as a "static library within a static library". A static library is just a container of object files. And they are all equal.
You have two options:
Distribute your own library and the third party library as two separate files. The final project then needs to include both libraries.
Merge the two libraries, i.e. create a library that contains all your object files and the object files of the third party library. Have a look at the man pages for ar, libtool, ranlib etc. for more information.
Option 1 seems the easier one. If your static library has additional dependencies on dynamically linked libraries (such as an iOS framework or libiconv), then you'll have to provide instructions about how to add these dependencies anyway.
(I don't quite understand when and how your test app crashes. You'd have to provide more information such as the full error message and the stack trace. Normally, I'd expect that the app doesn't even build since it can't find all dependencies.)