Skip to content

Commit

Permalink
[BUILD] Separate transitive dependencies in core
Browse files Browse the repository at this point in the history
so that the core can act as a dependency-container without leaking it's
own (non-transitive) dependencies into the classpaths of the packages
importing it while still providing the transitive dependencies that
are needed by those packages.

This is implemented by creating the two new configurations "bundle" and
"bundleApi" which replace the previously used "releaseDep".
Dependencies of the "bundle"-configuration gets extend from the
"implementation"-configuration (by the gradle-java-plugin) which is not
transitive and therefore it's dependencies are only visible to the core
package itself while the dependencies in "bundleApi" (which the
corresponding "api"-config extends from) can be used by all packages
that import the core.
Extension in the context of configurations means that that all the
dependencies in the "bundle"-config also get added to the
"implementation"-config.

This solution has the advantage to other solutions (e.g. creating a new
OSGI package) that the complexity of the build system is not
significantly increased and no versioning of any additional OSGI
packages needs to be considered.

This solution was proposed and explained to the authors by @m273d15
following the PR saros-project#1118.

Co-authored-by: FKHals <[email protected]>
Co-authored-by: paun42 <[email protected]>
Co-authored-by: panphil <[email protected]>
  • Loading branch information
4 people committed Feb 19, 2021
1 parent 2b64170 commit 5056243
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 25 deletions.
10 changes: 10 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ subprojects {
create("releaseDep") { // contains all dependencies which has to be included into the release jar/zip
isTransitive = false // avoid that the whole dependency tree is released
}
create("bundle") { // contains all which are used by core
isTransitive = false // avoid that the whole dependency tree is released
}
create("bundleApi") { // contains all dependencies which are used by all java subprojects
isTransitive = false // avoid that the whole dependency tree is released
}
}

configure<PmdExtension> {
Expand Down Expand Up @@ -110,6 +116,8 @@ subprojects {
register("generateLib", Copy::class) {
into("${project.projectDir}/lib")
from(projectToConf.configurations.getByName("releaseDep"))
from(projectToConf.configurations.getByName("bundle"))
from(projectToConf.configurations.getByName("bundleApi"))
}

val aggregateTestResults: String? by project
Expand Down Expand Up @@ -139,6 +147,8 @@ subprojects {
// Bridge that routes log4j calls to log4j2
val log4j2Bridge = "org.apache.logging.log4j:log4j-1.2-api:$log4j2VersionNr"

projectToConf.extra["commons-lang3"] = "org.apache.commons:commons-lang3:3.8.1"

projectToConf.extra["junitVersion"] = junitVersion
projectToConf.extra["log4j2ApiVersion"] = log4j2Api
projectToConf.extra["log4j2CoreVersion"] = log4j2Core
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class SarosEclipseExtension {
private boolean addDependencies = false;
private boolean addPdeNature = false;
private boolean createBundleJar = false;
private List<String> configs = new ArrayList<>();

public File getManifest() {
return manifest;
Expand Down Expand Up @@ -106,4 +107,23 @@ public boolean isCreateBundleJar() {
public void setCreateBundleJar(boolean createBundleJar) {
this.createBundleJar = createBundleJar;
}

public void setConfigs(List<String> configs) {
this.configs = configs;
}

public List<String> getConfigs() {
return configs;
}

/**
* Get the list of (gradle) configurations or a given default if the list of configurations is
* empty.
*
* @param defaultConfigs The list of (gradle) configurations to be returned when an empty
* configurations-list is given.
*/
public List<String> getConfigs(List<String> defaultConfigs) {
return configs.isEmpty() ? defaultConfigs : configs;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package saros.gradle.eclipse;

import java.util.Arrays;
import java.util.List;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
Expand All @@ -16,6 +18,7 @@
public class SarosEclipsePlugin implements Plugin<Project> {
private static final String EXTENSION_NAME = "sarosEclipse";
private static final String PLUGIN_VERSION_CHANGE_TASK_NAME = "changeEclipsePluginVersion";
private static final List<String> DEFAULT_CONFIG_NAMES = Arrays.asList("releaseDep");

/**
* Method which is called when the plugin is integrated in a gradle build (e.g. with {@code apply
Expand Down Expand Up @@ -70,7 +73,8 @@ private void configureEclipseAfterEvaluate(Project p, SarosEclipseExtension e) {

if (e.isCreateBundleJar()) {
methodRequiresManifest("create bundle jar", e);
new JarConfigurator(p).createBundleJar(e.getManifest());
List<String> jarConfigs = e.getConfigs(DEFAULT_CONFIG_NAMES);
new JarConfigurator(p, jarConfigs).createBundleJar(e.getManifest());
}

if (e.isAddDependencies()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package saros.gradle.eclipse.configurator;

import java.io.File;
import java.util.List;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.file.CopySpec;
Expand All @@ -14,13 +15,14 @@ public class JarConfigurator {
private static final String JAVA_PLUGIN_ID = "java";
private static final String JAR_TASK_NAME = "jar";

private static final String RELEASE_CONFIG_NAME = "releaseDep";
private static final String JAR_LIB_DESTINATION = "lib";

private Project project;
private final List<String> configs;

public JarConfigurator(Project project) {
public JarConfigurator(Project project, List<String> configs) {
this.project = project;
this.configs = configs;
project.getPluginManager().apply(JAVA_PLUGIN_ID);
}

Expand All @@ -33,8 +35,10 @@ public void createBundleJar(File manifestFile) {
jarTask.manifest((Manifest mf) -> mf.from(manifestFile));
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
jarTask.from(sourceSets.getByName(JAVA_MAIN_SOURCE_SET_NAME).getOutput());
jarTask.into(
JAR_LIB_DESTINATION,
(CopySpec cs) -> cs.from(project.getConfigurations().getByName(RELEASE_CONFIG_NAME)));
for (String jarConfig : this.configs) {
jarTask.into(
JAR_LIB_DESTINATION,
(CopySpec cs) -> cs.from(project.getConfigurations().getByName(jarConfig)));
}
}
}
50 changes: 31 additions & 19 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
plugins {
id("saros.gradle.eclipse.plugin")
`java-library`
}

val versionQualifier = ext.get("versionQualifier") as String
val commonsLang = ext.get("commons-lang3") as String

val log4j2ApiVersion = ext.get("log4j2ApiVersion") as String
val log4j2CoreVersion = ext.get("log4j2CoreVersion") as String
val log4j2BridgeVersion = ext.get("log4j2BridgeVersion") as String

configurations {
val bundle by getting {}
val bundleApi by getting {}
val api by getting {
extendsFrom(bundleApi)
}
val implementation by getting {
extendsFrom(bundle)
}
// Defined in root build.gradle
val testConfig by getting {}
val releaseDep by getting {}

// Default configuration
val compile by getting {
extendsFrom(releaseDep)
// populate releaseDep while it is still used by other projects
val releaseDep by getting {
extendsFrom(bundle, bundleApi)
}

// Default configuration
val testCompile by getting {
extendsFrom(testConfig)
}
val plain by creating {
extendsFrom(compile)
extendsFrom(implementation, api)
}
}

Expand All @@ -30,29 +41,30 @@ sarosEclipse {
isCreateBundleJar = true
isAddPdeNature = true
pluginVersionQualifier = versionQualifier
configs = listOf("bundle", "bundleApi")
}

dependencies {
releaseDep("commons-codec:commons-codec:1.3")
releaseDep("commons-io:commons-io:2.0.1")
releaseDep("org.apache.commons:commons-lang3:3.8.1")
bundle("commons-codec:commons-codec:1.3")
bundleApi("commons-io:commons-io:2.0.1")
bundleApi(commonsLang)

releaseDep("javax.jmdns:jmdns:3.4.1")
releaseDep("xpp3:xpp3:1.1.4c")
releaseDep("com.thoughtworks.xstream:xstream:1.4.10")
releaseDep("org.gnu.inet:libidn:1.15")
bundleApi("javax.jmdns:jmdns:3.4.1")
bundleApi("xpp3:xpp3:1.1.4c")
bundleApi("com.thoughtworks.xstream:xstream:1.4.10")
bundle("org.gnu.inet:libidn:1.15")

releaseDep(log4j2ApiVersion)
releaseDep(log4j2CoreVersion)
releaseDep(log4j2BridgeVersion)
bundleApi(log4j2ApiVersion)
bundleApi(log4j2CoreVersion)
bundleApi(log4j2BridgeVersion)

// TODO: use real release. This version is a customized SNAPSHOT
releaseDep(files("libs/weupnp.jar"))
bundleApi(files("libs/weupnp.jar"))
// Workaround until we updated to a newer smack version
releaseDep(files("libs/smack-3.4.1.jar"))
releaseDep(files("libs/smackx-3.4.1.jar"))
bundleApi(files("libs/smack-3.4.1.jar"))
bundleApi(files("libs/smackx-3.4.1.jar"))
// Workaround until we can publish and use (without a user token) the repackaged jar in GitHub Packages
releaseDep(rootProject.files("libs/picocontainer-2.11.2-patched_relocated.jar"))
bundleApi(rootProject.files("libs/picocontainer-2.11.2-patched_relocated.jar"))
}

sourceSets {
Expand Down

0 comments on commit 5056243

Please sign in to comment.