What is a target dependency? - xcode

I feel so noob asking this question, but what is a target dependency? I see it all the time in Xcode.

A dependency is another target that must be built before the current target can be. For example, if you have an app target and a framework target, the app target can have the framework target as a dependency, to ensure that the framework is built first. That is, the app target "depends" on the framework.

Xcode Explicit Dependency
Xcode Dependency[About] is a dependency required to build a selected target.
Explicit dependency
Explicit dependency is a source code aka Non-compiled dependency. Xcode builds all explicit dependencies before the dependent target. Explicit dependency overrides implicit dependency with the same product_name.
Explicit Dependency is specified in Build Phases -> Target Dependencies.
There are multiple ways to specify in Xcode that our target depends on other target’s products:
If a target is located in the same project
No additional setup
If a targets is located in different projects using cross-project reference[About]
Specify search path
Additional notes:
Dynamic Framework
You should specify General -> Embedded Binaries. If not - on the real device you will get dyld: Library not loaded[About]
If you start adding your dependency from General -> Embedded Binaries and select a product that is explicit dependency, Xcode automatically add it into Build Phases -> Target Dependencies
Static binary
You can fill out only Build Phases -> Target Dependencies
[Implicit dependency]
[Vocabulary]

Related

How to add project dependencies to specific platform targets created by the `kotlin-multiplatform` plugin?

Previously, building multiplatform projects using Gradle relied on separate Gradle plugins per targeted platform: kotlin-platform-common, kotlin-platform-js, and kotlin-platform-jvm.
Starting from Kotlin 1.3, this is now unified using one kotlin-multiplatform plugin. The current documentation specifies how to set up multiplatform projects using this approach.
However, in my project I have multiple multiplatform projects with some dependencies between them. With the old multiplatform configuration, each different platform is a separate module and adding dependencies between projects required adding project references in each platform-specific module to corresponding modules in the other project: e.g., project(':some-library:some-library-js') to add a dependency to the JS module from within another JS module.
While migrating to the new multiplatform configuration, I now need to add a dependency from a project configured using the old configuration method to a project configured using the new kotlin-multiplatform plugin.
Given that platform-specific modules are now specified and managed by the new plugin, how do I go about this?
I'm not certain whether the following approach is the recommended method, or I overlooked any potential issues, but my projects compile and all tests pass.
In Gradle, you can add dependencies to specific project configurations:
dependencies {
implementation project(path: ':some-library', configuration: 'configName')
}
By trial and error I figured out that specifying the following configuration dependencies per platform module type works:
common: configuration: 'archives'. Without this, Gradle configuration fails as code dependencies are not found.
Without the following, compilation fails:
jvm: configuration: 'jvmDefault'
js: configuration: 'jsDefault'
For example, for the JS module as specified in the question:
dependencies {
implementation project(path: ':some-library', configuration: 'jsDefault')
}
Basically, you don't need to specify the platform in project-to-project dependencies involving Kotlin Muiltiplatform projects. The Kotlin plugin sets up dependency resolution in a way that Gradle will choose the appropriate target's artifacts automatically.
So, for example, in a Kotlin/JVM single-target project, you can just use a project("...") dependency on a Multiplatform project:
dependencies {
implementation(project(":multiplatform-library")
}
If :multiplatform-library has a JVM target, this dependency will get resolved to the JVM target's artifact. Otherwise, you will encounter a dependency resolution failure with candidate configurartions listed.
This is described in the Kotlin reference, Building Multiplatform Projects with Gradle – Adding Dependencies, but is applicable to single-platform projects, too:
<...> a project('...') dependency on another multiplatform project is resolved to an appropriate target automatically. It is enough to specify a single project('...') dependency in a source set's dependencies, and the compilations that include the source set will receive a corresponding platform-specific artifact of that project, given that it has a compatible target.
If this does not happen for you, please post the specific dependency resolution failure log, or file an issue at https://kotl.in/issue.

xcode target dependencies between two projects

I have a problem with setting dependencies in XCode 4 between separate projects. Currently, I have two projects in the same workspace. The first project have a Framework amongst it's products. I would like to use this framework in the second project, as a dependency for Bundle target.
First project build successfully. However, the second one claims that it cannot access headers from the framework, although it exists in there. I added the framework to Build Phases -> Link Binary With Libraries section of my target, but this does not help. I was looking for an answer, but all I found were suggestions to add library on the Summary page. Unfortunately, in opposite to Application targets, Bundle target does not have this pane. Is there any other place where should I add the framework?
This answer describes the current procedure for adding a library dependency, including headers: https://stackoverflow.com/a/9726445/382938

Target dependencies vs. Link binary with libraries

I don't understand the difference between these Xcode features.
I'm building and app - but the functionality of the app is being abstracted into libraries (so they can be distributed separately as an "SDK").
So I have a workspace of library projects and the app project. I can add library projects to the app project by doing "link binary with libraries". This gives me a list of .a library projects in the current workspace which I can link to.
I can also add frameworks here.
In the "target dependencies" bit all I can add is other targets in the current project.
What I really want to do is both - I want my app project to build all the other library projects when I build it. I also want to make it verbose what libraries the app (and other libraries) depend on.
So can somebody please explain the difference, and whether what I am doing is the right way to go about it?
Many thanks!
It says here...
Drag your framework product (located in the Products folder) to the existing Link Binary With Libraries build phase of your application
target. This causes the application to link against your framework.
And...
In the General tab of the inspector window, add your framework as a dependency for the application. Adding this dependency causes Xcode to
build the framework target before building the application target.
The build dependency you establish in the application target causes
the framework to be built before the application. This is important
because it guarantees that a built version of your framework will be
available to link against and to embed in the application. Because of
this dependency, you can set the active target of your Xcode project
to your application and leave it there.
So it seems that you're supposed to use both. Seems redundant though, because if you're linking to a framework then its a dependency. I suppose you might want to only link to a library and not build it first. Although Xcode seems to build linked libraries even without them being added to the dependency section. Perhaps that's a result of the "Find Implicit Dependencies" option in a scheme's build settings.
I do something similar and was explicitly setting the 'header search path' and 'library search path' in the final executable target. However this all depended on where the objects were being generated. Initially I had set this to be within the source tree (actually a sibling directory called build), however after changing the location of the Xcode DerivedData directory and telling it to build into that directory, the projects no longer built.
The final solution was simply to remove the explicit setting of the 'header/library search path' and set the target dependencies correctly. This resulted in the project building for debugging and archiving without issue.

Xcode aggregate target dependency

I have an XCode project with 3 targets:
The application
An external build system target that builds my assets
An aggregate target that has 1 and 2 as dependencies.
The functionality that I want is:
Building the application will only build the application
Building the external build system will only build the assets
Building the aggregate will build the external build system first and then the application
Currently the aggregate builds both simultaneously which creates a race condition if the application gets to a certain point before the external build system completes. I can't add the build system as a dependecy for the application, because then building the application would do both. Is there a way to accomplish this without making a copy of my application target?
The following works for me in a similarly arranged project.
Under Build Phases -> Target Dependencies arrange the targets in the order that you want them to compile. (external build system then the application).
Second, in the Edit Scheme window for the aggregate project, under Build, uncheck Parallelize Build.
Additionally, to get the application to build only the application, you may need to uncheck Find Implicit Dependencies in the application project's build scheme.

How to create a maven assembly with transitive dependencies for different deployment scenarios?

I'm having a problem reconciling building a project for use within an application server and for use as a stand-alone application.
To give an overall simplified context, say I have three Projects A, B, C.
Project A depends on Project B which depends on Project C.
Project C has a dependency X which is marked as provided since it was expected that it would be available as a JEE library within say an application server. i.e. jms.jar.
So if I perform an assembly build of Project A, I get all the transitive dependencies save for those marked as provided as expected.
Now I have a new deployment scenario where Project A needs to be used in a standalone environment i.e. outside an application server.
So now I need the jms jar to be a compile dependency. Does this mean that I should explicitly add a compile dependency for X in Project A? Doesn't this violate the Law of Demeter, i.e. don't talk to strangers, in the sense Project A shouldn't explicitly know about Project C but only about Project B?
This is a simple example but in reality I have multiple dependencies which have been marked as provided but are now need to be compile or runtime dependencies so they end up in the artifact produced by the maven assembly plugin.
Is this a fundamental problem with Maven or am I not using the tools correctly?
Thanks in advance for any guidance.
If you need your build to have variations in it for different scenarios, you need to use profiles and keep certain things (such as some of the dependencies) in the various profiles.
http://maven.apache.org/pom.html#Profiles
Different dependencies for different build profiles in maven
answers a similar question - but you can swap in the "release" and "debug" for "Project A" and "Project C"
Provided dependencies are a difficult subject. First of all: Provided dependencies are not transitive in the following sense: If your project C has a provided dependency on X, then A will not get the dependency. It is silently ignored. This fits with the following meaning of "provided" which I propose:
Only the artifacts that are actually deployed should mark dependencies as "provided". Libraries or other jars that are not individually deployed to a specific server should not have provided dependencies. Instead, they should declare their dependencies as compile dependencies. In your example: Project C should have a compile dependency on X. If project A knows that X is provided, it sets X to provided in "dependencyManagement". As project A should know the environment in which it runs it should decide what is provided and what is not. And "dependenyManagement" is the right place to declare this.
If your project A should be able to run within and without a given server, you probably need to make a lot of adjustments, even change the type from ear to jar. So you either use build profiles for this, which then have different dependencyManagement entries, or you split A into two projects which depend on some other project that contains the common elements.
If some given project C already has a provided dependency on X and you cannot change that, this is effectively the same as a missing dependency in C. This has to be repaired at some point, and this could be project A itself.

Resources