Gradle的settings.gradle.kts你真的理解吗?

你还在用.gradle文件吗?例如build.gradle、settings.gradle,那么你就out了。现在我们有必要了解一下kts脚本了。在Android项目中,默认有3个文件可以替换成kts脚本,即project的build.gradle、app模块的build.gradle和project的settings.gradle,它们更名后分别为build.gradle.kts、build.gradle.kts和settings.gradle.kts。

settings.gradle简介

我们的gradle脚本本质上是执行一个个gradle plugin,即apply plugin,可以执行外部导入的,也可以执行项目编写的编译脚本代码。所以settings.gradle.kts也是编译过程中一个gradle plugin。在
org.gradle.initialization.DefaultSettings中有个getSettings方法,调用这个方法拿到我们配置的settings gradle plugin。settings.gradle.kts中可以配置的内容我们参考Settings这个类。在settings.gradle.kts这个文件中,主要配置一些项目全局的设置。

Settings全局设置解析

package org.gradle.api.initialization;

import org.gradle.StartParameter;
import org.gradle.api.Action;
import org.gradle.api.Incubating;
import org.gradle.api.UnknownProjectException;
import org.gradle.api.initialization.dsl.ScriptHandler;
import org.gradle.api.initialization.resolve.DependencyResolutionManagement;
import org.gradle.api.invocation.Gradle;
import org.gradle.api.plugins.ExtensionAware;
import org.gradle.api.plugins.PluginAware;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.ProviderFactory;
import org.gradle.api.toolchain.management.ToolchainManagement;
import org.gradle.api.cache.CacheConfigurations;
import org.gradle.caching.configuration.BuildCacheConfiguration;
import org.gradle.internal.HasInternalProtocol;
import org.gradle.plugin.management.PluginManagementSpec;
import org.gradle.vcs.SourceControl;

import javax.annotation.Nullable;
import java.io.File;
import java.util.Arrays;

/**
 * <p>Declares the configuration required to instantiate and configure the hierarchy of {@link
 * org.gradle.api.Project} instances which are to participate in a build.</p>
 *
 * <p>There is a one-to-one correspondence between a <code>Settings</code> instance and a <code>{@value
 * #DEFAULT_SETTINGS_FILE}</code> settings file. Before Gradle assembles the projects for a build, it creates a
 * <code>Settings</code> instance and executes the settings file against it.</p>
 *
 * <h3>Assembling a Multi-Project Build</h3>
 *
 * <p>One of the purposes of the <code>Settings</code> object is to allow you to declare the projects which are to be
 * included in the build. You add projects to the build using the {@link #include(String...)} method.  There is always a
 * root project included in a build.  It is added automatically when the <code>Settings</code> object is created.  The
 * root project's name defaults to the name of the directory containing the settings file. The root project's project
 * directory defaults to the directory containing the settings file.</p>
 *
 * <p>When a project is included in the build, a {@link ProjectDescriptor} is created. You can use this descriptor to
 * change the default values for several properties of the project.</p>
 *
 * <h3>Using Settings in a Settings File</h3>
 *
 * <h4>Dynamic Properties</h4>
 *
 * <p>In addition to the properties of this interface, the {@code Settings} object makes some additional read-only
 * properties available to the settings script. This includes properties from the following sources:</p>
 *
 * <ul>
 *
 * <li>Defined in the {@value org.gradle.api.Project#GRADLE_PROPERTIES} file located in the settings directory of the
 * build.</li>
 *
 * <li>Defined the {@value org.gradle.api.Project#GRADLE_PROPERTIES} file located in the user's {@code .gradle}
 * directory.</li>
 *
 * <li>Provided on the command-line using the -P option.</li>
 *
 * </ul>
 */
@HasInternalProtocol
public interface Settings extends PluginAware, ExtensionAware {
    /**
     * <p>The default name for the settings file.</p>
     */
    String DEFAULT_SETTINGS_FILE = "settings.gradle";

    /**
     * <p>Adds the given projects to the build. Each path in the supplied list is treated as the path of a project to
     * add to the build. Note that these path are not file paths, but instead specify the location of the new project in
     * the project hierarchy. As such, the supplied paths must use the ':' character as separator (and NOT '/').</p>
     *
     * <p>The last element of the supplied path is used as the project name. The supplied path is converted to a project
     * directory relative to the root project directory. The project directory can be altered by changing the 'projectDir'
     * property after the project has been included (see {@link ProjectDescriptor#setProjectDir(File)})</p>
     *
     * <p>As an example, the path {@code a:b} adds a project with path {@code :a:b}, name {@code b} and project
     * directory {@code $rootDir/a/b}. It also adds the a project with path {@code :a}, name {@code a} and project
     * directory {@code $rootDir/a}, if it does not exist already.</p>
     *
     * <p>Some common examples of using the project path are:</p>
     *
     * <pre class='autoTestedSettings'>
     *   // include two projects, 'foo' and 'foo:bar'
     *   // directories are inferred by replacing ':' with '/'
     *   include 'foo:bar'
     *
     *   // include one project whose project dir does not match the logical project path
     *   include 'baz'
     *   project(':baz').projectDir = file('foo/baz')
     *
     *   // include many projects whose project dirs do not match the logical project paths
     *   file('subprojects').eachDir { dir -&gt;
     *     include dir.name
     *     project(":${dir.name}").projectDir = dir
     *   }
     * </pre>
     *
     * @param projectPaths the projects to add.
     */
    default void include(String... projectPaths) {
        include(Arrays.asList(projectPaths));
    }

    /**
     * <p>Adds the given projects to the build. Each path in the supplied list is treated as the path of a project to
     * add to the build. Note that these path are not file paths, but instead specify the location of the new project in
     * the project hierarchy. As such, the supplied paths must use the ':' character as separator (and NOT '/').</p>
     *
     * <p>The last element of the supplied path is used as the project name. The supplied path is converted to a project
     * directory relative to the root project directory. The project directory can be altered by changing the 'projectDir'
     * property after the project has been included (see {@link ProjectDescriptor#setProjectDir(File)})</p>
     *
     * <p>As an example, the path {@code a:b} adds a project with path {@code :a:b}, name {@code b} and project
     * directory {@code $rootDir/a/b}. It also adds the a project with path {@code :a}, name {@code a} and project
     * directory {@code $rootDir/a}, if it does not exist already.</p>
     *
     * <p>Some common examples of using the project path are:</p>
     *
     * <pre class='autoTestedSettings'>
     *   // include two projects, 'foo' and 'foo:bar'
     *   // directories are inferred by replacing ':' with '/'
     *   include(['foo:bar'])
     *
     *   // include one project whose project dir does not match the logical project path
     *   include(['baz'])
     *   project(':baz').projectDir = file('foo/baz')
     *
     *   // include many projects whose project dirs do not match the logical project paths
     *   file('subprojects').eachDir { dir -&gt;
     *     include([dir.name])
     *     project(":${dir.name}").projectDir = dir
     *   }
     * </pre>
     *
     * @param projectPaths the projects to add.
     *
     * @since 7.4
     */
    void include(Iterable<String> projectPaths);

    /**
     * <p>Adds the given projects to the build. Each name in the supplied list is treated as the name of a project to
     * add to the build.</p>
     *
     * <p>The supplied name is converted to a project directory relative to the <em>parent</em> directory of the root
     * project directory.</p>
     *
     * <p>As an example, the name {@code a} add a project with path {@code :a}, name {@code a} and project directory
     * {@code $rootDir/../a}.</p>
     *
     * @param projectNames the projects to add.
     */
    default void includeFlat(String... projectNames) {
        includeFlat(Arrays.asList(projectNames));
    }

    /**
     * <p>Adds the given projects to the build. Each name in the supplied list is treated as the name of a project to
     * add to the build.</p>
     *
     * <p>The supplied name is converted to a project directory relative to the <em>parent</em> directory of the root
     * project directory.</p>
     *
     * <p>As an example, the name {@code a} add a project with path {@code :a}, name {@code a} and project directory
     * {@code $rootDir/../a}.</p>
     *
     * @param projectNames the projects to add.
     *
     * @since 7.4
     */
    void includeFlat(Iterable<String> projectNames);

    /**
     * <p>Returns this settings object.</p>
     *
     * @return This settings object. Never returns null.
     */
    Settings getSettings();

    /**
     * Returns the build script handler for settings. You can use this handler to query details about the build
     * script for settings, and manage the classpath used to compile and execute the settings script.
     *
     * @return the classpath handler. Never returns null.
     *
     * @since 4.4
     */
    ScriptHandler getBuildscript();

    /**
     * <p>Returns the settings directory of the build. The settings directory is the directory containing the settings
     * file.</p>
     *
     * @return The settings directory. Never returns null.
     */
    File getSettingsDir();

    /**
     * <p>Returns the root directory of the build. The root directory is the project directory of the root project.</p>
     *
     * @return The root directory. Never returns null.
     */
    File getRootDir();

    /**
     * <p>Returns the root project of the build.</p>
     *
     * @return The root project. Never returns null.
     */
    ProjectDescriptor getRootProject();

    /**
     * <p>Returns the project with the given path.</p>
     *
     * @param path The path.
     * @return The project with the given path. Never returns null.
     * @throws UnknownProjectException If no project with the given path exists.
     */
    ProjectDescriptor project(String path) throws UnknownProjectException;

    /**
     * <p>Returns the project with the given path.</p>
     *
     * @param path The path
     * @return The project with the given path. Returns null if no such project exists.
     */
    @Nullable
    ProjectDescriptor findProject(String path);

    /**
     * <p>Returns the project with the given project directory.</p>
     *
     * @param projectDir The project directory.
     * @return The project with the given project directory. Never returns null.
     * @throws UnknownProjectException If no project with the given path exists.
     */
    ProjectDescriptor project(File projectDir) throws UnknownProjectException;

    /**
     * <p>Returns the project with the given project directory.</p>
     *
     * @param projectDir The project directory.
     * @return The project with the given project directory. Returns null if no such project exists.
     */
    @Nullable
    ProjectDescriptor findProject(File projectDir);

    /**
     * <p>Returns the set of parameters used to invoke this instance of Gradle.</p>
     *
     * @return The parameters. Never returns null.
     */
    StartParameter getStartParameter();

    /**
     * Provides access to methods to create various kinds of {@link Provider} instances.
     *
     * @since 6.8
     */
    ProviderFactory getProviders();

    /**
     * Returns the {@link Gradle} instance for the current build.
     *
     * @return The Gradle instance. Never returns null.
     */
    Gradle getGradle();

    /**
     * Includes a build at the specified path to the composite build.
     * @param rootProject The path to the root project directory for the build.
     *
     * @since 3.1
     */
    void includeBuild(Object rootProject);

    /**
     * Includes a build at the specified path to the composite build, with the supplied configuration.
     * @param rootProject The path to the root project directory for the build.
     * @param configuration An action to configure the included build.
     *
     * @since 3.1
     */
    void includeBuild(Object rootProject, Action<ConfigurableIncludedBuild> configuration);

    /**
     * Returns the build cache configuration.
     *
     * @since 3.5
     */
    BuildCacheConfiguration getBuildCache();

    /**
     * Configures build cache.
     *
     * @since 3.5
     */
    void buildCache(Action<? super BuildCacheConfiguration> action);

    /**
     * Configures plugin management.
     *
     * @since 3.5
     */
    void pluginManagement(Action<? super PluginManagementSpec> pluginManagementSpec);

    /**
     * Returns the plugin management configuration.
     *
     * @since 3.5
     */
    PluginManagementSpec getPluginManagement();

    /**
     * Configures source control.
     *
     * @since 4.4
     */
    void sourceControl(Action<? super SourceControl> configuration);

    /**
     * Returns the source control configuration.
     *
     * @since 4.4
     */
    SourceControl getSourceControl();

    /**
     * Enables a feature preview by name.
     *
     * @param name the name of the feature to enable
     *
     * @since 4.6
     */
    void enableFeaturePreview(String name);

    /**
     * Configures the cross-project dependency resolution aspects
     * @param dependencyResolutionConfiguration the configuration
     *
     * @since 6.8
     */
    void dependencyResolutionManagement(Action<? super DependencyResolutionManagement> dependencyResolutionConfiguration);

    /**
     * Returns the dependency resolution management handler.
     *
     * @since 6.8
     */
    DependencyResolutionManagement getDependencyResolutionManagement();

    /**
     * Configures toolchain management.
     *
     * @since 7.6
     */
    @Incubating
    void toolchainManagement(Action<? super ToolchainManagement> toolchainManagementConfiguration);

    /**
     * Returns the toolchain management configuration.
     *
     * @since 7.6
     */
    @Incubating
    ToolchainManagement getToolchainManagement();

    /**
     * Returns the configuration for caches stored in the user home directory.
     *
     * @since 8.0
     */
    @Incubating
    CacheConfigurations getCaches();

    /**
     * Configures the settings for caches stored in the user home directory.
     *
     * @param cachesConfiguration the configuration
     *
     * @since 8.0
     */
    @Incubating
    void caches(Action<? super CacheConfigurations> cachesConfiguration);
}

比如要索引哪些模块。

include(":app")

以及项目的编译期间的名称。

rootProject.name = "DoraMusic"

PluginManagementSpec插件管理规格

我们可以看到,在这里我们还可以配置pluginManagement函数,pluginManagement传入的是一个PluginManagementSpec。

package org.gradle.plugin.management;

import org.gradle.api.Action;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.initialization.ConfigurableIncludedPluginBuild;
import org.gradle.internal.HasInternalProtocol;
import org.gradle.plugin.use.PluginDependenciesSpec;

/**
 * Configures how plugins are resolved.
 *
 * @since 3.5
 */
@HasInternalProtocol
public interface PluginManagementSpec {

    /**
     * Defines the plugin repositories to use.
     */
    void repositories(Action<? super RepositoryHandler> repositoriesAction);

    /**
     * The plugin repositories to use.
     */
    RepositoryHandler getRepositories();

    /**
     * Configure the plugin resolution strategy.
     */
    void resolutionStrategy(Action<? super PluginResolutionStrategy> action);

    /**
     * The plugin resolution strategy.
     */
    PluginResolutionStrategy getResolutionStrategy();

    /**
     * Configure the default plugin versions.
     * @since 5.6
     */
    void plugins(Action<? super PluginDependenciesSpec> action);

    /**
     * The Plugin dependencies, permitting default plugin versions to be configured.
     * @since 5.6
     */
    PluginDependenciesSpec getPlugins();

    /**
     * Includes a plugin build at the specified path to the composite build.
     * Included plugin builds can contribute settings and project plugins.
     * @param rootProject The path to the root project directory for the build.
     *
     * @since 7.0
     */
    void includeBuild(String rootProject);

    /**
     * Includes a plugin build at the specified path to the composite build, with the supplied configuration.
     * Included plugin builds can contribute settings and project plugins.
     * @param rootProject The path to the root project directory for the build.
     * @param configuration An action to configure the included build.
     *
     * @since 7.0
     */
    void includeBuild(String rootProject, Action<ConfigurableIncludedPluginBuild> configuration);

}

在PluginManagementSpec的源码中,我们可以得知,这个高阶函数传入的block可以配置repositories、resolutionStrategy、plugins、includeBuild这几个函数。我们用的比较多的是前面三个。我们再细看repositories,需要传入的是Action<? super RepositoryHandler>,那么问题来了,我明明是要传入的Action,怎么编译器提示的是Action里面的泛型类。
比如:

pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
        maven { setUrl("xxx")
    }
}

截屏2023-08-27 21.11.10.png

不信你就看,this指代的是RepositoryHandler。我们观摩一下Action类。

package org.gradle.api;

/**
 * Performs some action against objects of type T.
 *
 * @param <T> The type of object which this action accepts.
 */
@HasImplicitReceiver
public interface Action<T> {
    /**
     * Performs this action against the given object.
     *
     * @param t The object to perform the action on.
     */
    void execute(T t);
}

如果你理解T.() -> Unit,那么就会很好理解这个概念了。这里其实是kotlin的一个高级的用法,SAM接口。Kotlin中的SAM接口是指"Single Abstract Method"接口,它也被称为函数式接口。在Kotlin中,可以使用lambda表达式来代替这些只有一个抽象方法的接口。通过使用lambda表达式,可以更简洁地表示函数或方法。

Kotlin的SAM转换是指将lambda表达式转换为这些SAM接口的实例,从而可以像使用普通函数一样使用它们。这在使用Java的库或与Java代码交互时特别有用,因为在Java中,通常需要使用匿名内部类来实现SAM接口,而在Kotlin中可以直接使用lambda表达式。

例如,如果有一个只有一个抽象方法的Java接口OnClickListener,在Kotlin中可以这样使用lambda表达式来代替:

button.setOnClickListener { view ->
    // 点击事件的处理逻辑
}

这样我们就好理解为什么这么配置RepositoryHandler了。

/*
 * Copyright 2009 the original author or authors.
 *
 * 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.
 */
package org.gradle.api.artifacts.dsl;

import groovy.lang.Closure;
import groovy.lang.DelegatesTo;
import org.gradle.api.Action;
import org.gradle.api.artifacts.ArtifactRepositoryContainer;
import org.gradle.api.artifacts.repositories.ArtifactRepository;
import org.gradle.api.artifacts.repositories.ExclusiveContentRepository;
import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository;
import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.internal.HasInternalProtocol;

import java.util.Map;

/**
 * A {@code RepositoryHandler} manages a set of repositories, allowing repositories to be defined and queried.
 */
@HasInternalProtocol
public interface RepositoryHandler extends ArtifactRepositoryContainer {

    /**
     * Adds a resolver that looks into a number of directories for artifacts. The artifacts are expected to be located in the
     * root of the specified directories. The resolver ignores any group/organization information specified in the
     * dependency section of your build script. If you only use this kind of resolver you might specify your
     * dependencies like <code>":junit:4.4"</code> instead of <code>"junit:junit:4.4"</code>.
     *
     * The following parameter are accepted as keys for the map:
     *
     * <table summary="Shows property keys and associated values">
     * <tr><th>Key</th>
     *     <th>Description of Associated Value</th></tr>
     * <tr><td><code>name</code></td>
     *     <td><em>(optional)</em> The name of the repository.
     * The default is a Hash value of the rootdir paths. The name is used in the console output,
     * to point to information related to a particular repository. A name must be unique amongst a repository group.</td></tr>
     * <tr><td><code>dirs</code></td>
     *     <td>Specifies a list of rootDirs where to look for dependencies. These are evaluated as per {@link org.gradle.api.Project#files(Object...)}</td></tr>
     * </table>
     *
     * <p>Examples:</p>
     * <pre class='autoTested'>
     * repositories {
     *     flatDir name: 'libs', dirs: "$projectDir/libs"
     *     flatDir dirs: ["$projectDir/libs1", "$projectDir/libs2"]
     * }
     * </pre>
     *
     * @param args The arguments used to configure the repository.
     * @return the added resolver
     * @throws org.gradle.api.InvalidUserDataException In the case neither rootDir nor rootDirs is specified of if both
     * are specified.
     */
    FlatDirectoryArtifactRepository flatDir(Map<String, ?> args);

    /**
     * Adds and configures a repository which will look for dependencies in a number of local directories.
     *
     * @param configureClosure The closure to execute to configure the repository.
     * @return The repository.
     */
    FlatDirectoryArtifactRepository flatDir(@DelegatesTo(FlatDirectoryArtifactRepository.class) Closure configureClosure);

    /**
     * Adds and configures a repository which will look for dependencies in a number of local directories.
     *
     * @param action The action to execute to configure the repository.
     * @return The repository.
     */
    FlatDirectoryArtifactRepository flatDir(Action<? super FlatDirectoryArtifactRepository> action);

    /**
     * Adds a repository which looks in Gradle Central Plugin Repository for dependencies.
     *
     * @return The Gradle Central Plugin Repository
     * @since 4.4
     */
    ArtifactRepository gradlePluginPortal();

    /**
     * Adds a repository which looks in Gradle Central Plugin Repository for dependencies.
     *
     * @param action a configuration action
     * @return the added resolver
     * @since 5.4
     */
    ArtifactRepository gradlePluginPortal(Action<? super ArtifactRepository> action);

    /**
     * Adds a repository which looks in Bintray's JCenter repository for dependencies.
     * <p>
     * The URL used to access this repository is {@literal "https://jcenter.bintray.com/"}.
     * The behavior of this repository is otherwise the same as those added by {@link #maven(org.gradle.api.Action)}.
     * <p>
     * Examples:
     * <pre class='autoTestedWithDeprecations'>
     * repositories {
     *   jcenter {
     *     artifactUrls = ["http://www.mycompany.com/artifacts1", "http://www.mycompany.com/artifacts2"]
     *   }
     *   jcenter {
     *     name = "nonDefaultName"
     *     artifactUrls = ["http://www.mycompany.com/artifacts1"]
     *   }
     * }
     * </pre>
     *
     * @param action a configuration action
     * @return the added repository
     * @deprecated JFrog announced JCenter's <a href="https://blog.gradle.org/jcenter-shutdown">sunset</a> in February 2021. Use {@link #mavenCentral()} instead.
     */
    @Deprecated
    MavenArtifactRepository jcenter(Action<? super MavenArtifactRepository> action);

    /**
     * Adds a repository which looks in Bintray's JCenter repository for dependencies.
     * <p>
     * The URL used to access this repository is {@literal "https://jcenter.bintray.com/"}.
     * The behavior of this repository is otherwise the same as those added by {@link #maven(org.gradle.api.Action)}.
     * <p>
     * Examples:
     * <pre class='autoTestedWithDeprecations'>
     * repositories {
     *     jcenter()
     * }
     * </pre>
     *
     * @return the added resolver
     * @see #jcenter(Action)
     * @deprecated JFrog announced JCenter's <a href="https://blog.gradle.org/jcenter-shutdown">sunset</a> in February 2021. Use {@link #mavenCentral()} instead.
     */
    @Deprecated
    MavenArtifactRepository jcenter();

    /**
     * Adds a repository which looks in the Maven central repository for dependencies. The URL used to access this repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#MAVEN_CENTRAL_URL}.
     *
     * <p>The following parameter are accepted as keys for the map:
     *
     * <table summary="Shows property keys and associated values">
     * <tr><th>Key</th>
     *     <th>Description of Associated Value</th></tr>
     * <tr><td><code>name</code></td>
     *     <td><em>(optional)</em> The name of the repository. The default is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_CENTRAL_REPO_NAME} is used as the name. A name
     * must be unique amongst a repository group.
     * </td></tr>
     * <tr><td><code>artifactUrls</code></td>
     *     <td>A single jar repository or a collection of jar repositories containing additional artifacts not found in the Maven central repository.
     * But be aware that the POM must exist in Maven central.
     * The provided values are evaluated as per {@link org.gradle.api.Project#uri(Object)}.</td></tr>
     * </table>
     *
     * <p>Examples:</p>
     * <pre class='autoTested'>
     * repositories {
     *     mavenCentral artifactUrls: ["http://www.mycompany.com/artifacts1", "http://www.mycompany.com/artifacts2"]
     *     mavenCentral name: "nonDefaultName", artifactUrls: ["http://www.mycompany.com/artifacts1"]
     * }
     * </pre>
     *
     * @param args A list of urls of repositories to look for artifacts only.
     * @return the added repository
     */
    MavenArtifactRepository mavenCentral(Map<String, ?> args);

    /**
     * Adds a repository which looks in the Maven central repository for dependencies. The URL used to access this repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#MAVEN_CENTRAL_URL}. The name of the repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_CENTRAL_REPO_NAME}.
     *
     * <p>Examples:</p>
     * <pre class='autoTested'>
     * repositories {
     *     mavenCentral()
     * }
     * </pre>
     *
     * @return the added resolver
     * @see #mavenCentral(java.util.Map)
     */
    MavenArtifactRepository mavenCentral();

    /**
     * Adds a repository which looks in the Maven central repository for dependencies. The URL used to access this repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#MAVEN_CENTRAL_URL}. The name of the repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_CENTRAL_REPO_NAME}.
     *
     * <p>Examples:</p>
     * <pre class='autoTested'>
     * repositories {
     *     mavenCentral()
     * }
     * </pre>
     *
     * @param action a configuration action
     * @return the added resolver
     * @since 5.3
     */
    MavenArtifactRepository mavenCentral(Action<? super MavenArtifactRepository> action);

    /**
     * Adds a repository which looks in the local Maven cache for dependencies. The name of the repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_LOCAL_REPO_NAME}.
     *
     * <p>Examples:</p>
     * <pre class='autoTested'>
     * repositories {
     *     mavenLocal()
     * }
     * </pre>
     * <p>
     * The location for the repository is determined as follows (in order of precedence):
     * </p>
     * <ol>
     * <li>The value of system property 'maven.repo.local' if set;</li>
     * <li>The value of element &lt;localRepository&gt; of <code>~/.m2/settings.xml</code> if this file exists and element is set;</li>
     * <li>The value of element &lt;localRepository&gt; of <code>$M2_HOME/conf/settings.xml</code> (where <code>$M2_HOME</code> is the value of the environment variable with that name) if this file exists and element is set;</li>
     * <li>The path <code>~/.m2/repository</code>.</li>
     * </ol>
     *
     * @return the added resolver
     */
    MavenArtifactRepository mavenLocal();

    /**
     * Adds a repository which looks in the local Maven cache for dependencies. The name of the repository is
     * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_LOCAL_REPO_NAME}.
     *
     * <p>Examples:</p>
     * <pre class='autoTested'>
     * repositories {
     *     mavenLocal()
     * }
     * </pre>
     * <p>
     * The location for the repository is determined as follows (in order of precedence):
     * </p>
     * <ol>
     * <li>The value of system property 'maven.repo.local' if set;</li>
     * <li>The value of element &lt;localRepository&gt; of <code>~/.m2/settings.xml</code> if this file exists and element is set;</li>
     * <li>The value of element &lt;localRepository&gt; of <code>$M2_HOME/conf/settings.xml</code> (where <code>$M2_HOME</code> is the value of the environment variable with that name) if this file exists and element is set;</li>
     * <li>The path <code>~/.m2/repository</code>.</li>
     * </ol>
     *
     * @param action a configuration action
     * @return the added resolver
     * @since 5.3
     */
    MavenArtifactRepository mavenLocal(Action<? super MavenArtifactRepository> action);

    /**
     * Adds a repository which looks in Google's Maven repository for dependencies.
     * <p>
     * The URL used to access this repository is {@literal "https://dl.google.com/dl/android/maven2/"}.
     * <p>
     * Examples:
     * <pre class='autoTested'>
     * repositories {
     *     google()
     * }
     * </pre>
     *
     * @return the added resolver
     * @since 4.0
     */
    MavenArtifactRepository google();

    /**
     * Adds a repository which looks in Google's Maven repository for dependencies.
     * <p>
     * The URL used to access this repository is {@literal "https://dl.google.com/dl/android/maven2/"}.
     * <p>
     * Examples:
     * <pre class='autoTested'>
     * repositories {
     *     google()
     * }
     * </pre>
     *
     * @param action a configuration action
     * @return the added resolver
     * @since 5.3
     */
    MavenArtifactRepository google(Action<? super MavenArtifactRepository> action);

    /**
     * Adds and configures a Maven repository. Newly created instance of {@code MavenArtifactRepository} is passed as an argument to the closure.
     *
     * @param closure The closure to use to configure the repository.
     * @return The added repository.
     */
    MavenArtifactRepository maven(@DelegatesTo(MavenArtifactRepository.class) Closure closure);

    /**
     * Adds and configures a Maven repository.
     *
     * @param action The action to use to configure the repository.
     * @return The added repository.
     */
    MavenArtifactRepository maven(Action<? super MavenArtifactRepository> action);

    /**
     * Adds and configures an Ivy repository. Newly created instance of {@code IvyArtifactRepository} is passed as an argument to the closure.
     *
     * @param closure The closure to use to configure the repository.
     * @return The added repository.
     */
    IvyArtifactRepository ivy(@DelegatesTo(IvyArtifactRepository.class) Closure closure);

    /**
     * Adds and configures an Ivy repository.
     *
     * @param action The action to use to configure the repository.
     * @return The added repository.
     */
    IvyArtifactRepository ivy(Action<? super IvyArtifactRepository> action);

    /**
     * Declares exclusive content repositories. Exclusive content repositories are
     * repositories for which you can declare an inclusive content filter. Artifacts
     * matching the filter will then only be searched in the repositories which
     * exclusively match it.
     *
     * @param action the configuration of the repositories
     *
     * @since 6.2
     */
    void exclusiveContent(Action<? super ExclusiveContentRepository> action);
}

PluginResolutionStrategy插件解决策略

接下来我们看resolutionStrategy,它传入的是一个PluginResolutionStrategy。Kotlin DSL中有大量Action的用法。

pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.namespace == "com.android.tools.build") {
                useModule("com.android.tools.build:gradle:7.1.2")
            }
            if (requested.id.namespace == "com.google.firebase") {
                useModule("com.google.firebase:firebase-crashlytics-gradle:2.9.2")
            }
        }
    }
}
package org.gradle.plugin.management;

import org.gradle.api.Action;
import org.gradle.internal.HasInternalProtocol;

/**
 * Allows modification of {@link PluginRequest}s before they are resolved.
 *
 * @since 3.5
 */
@HasInternalProtocol
public interface PluginResolutionStrategy {

    /**
     * Adds an action that is executed for each plugin that is resolved.
     * The {@link PluginResolveDetails} parameter contains information about
     * the plugin that was requested and allows the rule to modify which plugin
     * will actually be resolved.
     */
    void eachPlugin(Action<? super PluginResolveDetails> rule);

}
package org.gradle.plugin.management;

import javax.annotation.Nullable;

/**
 * Allows plugin resolution rules to inspect a requested plugin and modify which
 * target plugin will be used.
 *
 * @since 3.5
 */
public interface PluginResolveDetails {

    /**
     * Get the plugin that was requested.
     */
    PluginRequest getRequested();

    /**
     * Sets the implementation module to use for this plugin.
     *
     * @param notation the module to use, supports the same notations as {@link org.gradle.api.artifacts.dsl.DependencyHandler}
     */
    void useModule(Object notation);

    /**
     * Sets the version of the plugin to use.
     *
     * @param version version to use
     */
    void useVersion(@Nullable String version);

    /**
     * The target plugin request to use.
     */
    PluginRequest getTarget();

}

PluginResolveDetails这个类用来允许插件解析规则检查请求的插件并修改将使用目标插件。

DependencyResolutionManagement依赖解决管理

我们再来看看dependencyResolutionManagement和要传入DependencyResolutionManagement。这个类字面意思就告诉我们用来指定依赖解决管理,简单来说,就是我们项目中的那些implementation依赖的库等,从哪些库里面找。

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven {  setUrl("https://jitpack.io") }
    }
}

这里简单讲解下RepositoriesMode。

package org.gradle.api.initialization.resolve;

import org.gradle.api.Incubating;

/**
 * The repository mode configures how repositories are setup in the build.
 *
 * @since 6.8
 */
@Incubating
public enum RepositoriesMode {
    /**
     * If this mode is set, any repository declared on a project will cause
     * the project to use the repositories declared by the project, ignoring
     * those declared in settings.
     *
     * This is the default behavior.
     */
    PREFER_PROJECT,

    /**
     * If this mode is set, any repository declared directly in a project,
     * either directly or via a plugin, will be ignored.
     */
    PREFER_SETTINGS,

    /**
     * If this mode is set, any repository declared directly in a project,
     * either directly or via a plugin, will trigger a build error.
     */
    FAIL_ON_PROJECT_REPOS;
}

PREFER_PROJECT表示,如果设置此模式,项目上声明的任何存储库都会导致项目使用项目声明的存储库,忽略在设置中声明的,简单来说就是项目中的存储库优先使用。这也是默认的模式。如果PREFER_SETTINGS,则正好相反。FAIL_ON_PROJECT_REPOS则表示,强制使用设置中的存储库。建议修改模式为FAIL_ON_PROJECT_REPOS强制全局都使用设置中的存储库,方便管理。无论你使用何种模式,你在dependencyResolutionManagement中配置下就能确保可以使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/645247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库(5)——DDL 表操作

表查询 先要进入到某一个数据库中才可使用这些指令。 SHOW TABLES; 可查询当前数据库中所有的表。 表创建 CREATE TABLE 表名( 字段1 类型 [COMMENT 字段1注释] ...... 字段n 类型 [COMMENT 字段n注释] )[COMMENT 表注释]; 例如&#xff0c;在student数据库里创建一张studen…

哈希表---闭散列

闭散列 当我们用哈希函数的时候&#xff0c;其中一个就是除留余数法 取这个表的长度len,按照哈希函数&#xff1a;Hash(key) key% len,将这个位置映射到表中 通过上面的除留余数法&#xff0c;会有哈希碰撞的问题&#xff0c;可以通过闭散列来解决 闭散列也叫开放定址法&am…

Django与前端框架协作开发实战:高效构建现代Web应用

title: Django与前端框架协作开发实战&#xff1a;高效构建现代Web应用 date: 2024/5/22 20:07:47 updated: 2024/5/22 20:07:47 categories: 后端开发 tags: DjangoREST前端框架SSR渲染SPA路由SEO优化组件库集成状态管理 第1章&#xff1a;简介 1.1 Django简介 Django是一…

新加坡多ip服务器在跨境电商中有哪些优势?

新加坡多IP服务器**在跨境外贸业务中具有明显的优势&#xff0c;适合需要高性能和网络稳定性的业务场景。Rak部落小编为您整理发布新加坡多ip服务器在跨境电商中有哪些优势? 以下是一些具体的优势&#xff1a; 1. **地理位置优越**&#xff1a;新加坡作为亚太地区的国际商业和…

mysql图形化界面及将mysql注册成后台程序

安装图形化界面版本 右键新建数据库 字符集使用utf8防止以后数据库中存在中文字符导致乱码 将mysql注册成后台程序 cmd进入命令行界面 切换路径到cd /mysql/bin 将mysql注册成后台程序 mysqld.exe --install mysql1 (失败&#xff0c;说明没有权限) 以管理员身份打开成功…

R语言:Mantel Test分析与绘图

Mantel Test 1.什么是Mantel Test2. R语言代码13. R语言代码2 1.什么是Mantel Test Mantel test分析对两个矩阵相关关系进行检验。可以用在生态学上&#xff0c;用来检验群落距离矩阵(如 Bray-Curtis distance matrix)和环境变量距离矩阵(如 pH, 温度 或者地理位置的差异矩阵)之…

MySQL——MySQL目录结构

MySQL安装完成后&#xff0c;会在磁盘上生成一个目录&#xff0c;该目录被称为MySQL的安装目录。在MySQL的安装目录中包含了启动文件、配置文件、数据库文件和命令文件等。 下面对 MySQL 的安装目录进行详细讲解 (1)bin 目录 : 用于放置一些可执行文件,如 mysql.exe、mysqld. …

Java面试八股之什么是锁消除和锁粗化

什么是锁消除和锁粗化 锁消除&#xff08;Lock Elimination&#xff09;&#xff1a; 锁消除是Java虚拟机&#xff08;JVM&#xff09;进行的一种高级优化策略&#xff0c;旨在消除那些没有必要存在的同步操作&#xff0c;以减少不必要的性能开销。这一优化发生在即时编译器&a…

MT7628原厂Uboot修改交互串口

工作中&#xff0c;遇到用户用Skylab的SKW92A模组&#xff0c;在参考设计时&#xff0c;将UART接口预留错的情况&#xff0c;对于这种情况&#xff0c;需要将原厂SDK默认的交互串口UART0&#xff0c;改为UART1。在开发过程中&#xff0c;经常需要在Uboot阶段升级固件&#xff0…

抖音运营_抖音推荐算法的机制

目录 一 抖音流量推荐算法机制 二 4大关键指标 三 完播率 1 黄金3秒 2 内容严谨 3 期待感 4 用户痛点 5 通俗易懂 四 转发量 1 分享需求 2 分享快乐 3 共情表达 4 正义传播 五 评论量 1 话题性 2 争议性 3 参与感 4 评论回评 六 点赞量 1 情感共鸣 2 用户喜…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(二十)- JUC(6)

目录 wait , notify wait vs sleep 正确使用方法 同步保护性暂停 join的源码 Future 异步生产者/消费者模型 定义 Park & Unpark 原理 wait , notify 小故事小南需要烟才能工作&#xff0c;但它又要占这锁让别人无法进来。那么这个时候开一个waitSet相当于就是休…

druid 1.2.14,application.yaml配置文件中,如何进行数据库加密配置

步骤一&#xff1a;先生成加密的密码&#xff1a; 步骤二&#xff1a;配置application.yaml文件&#xff1a; spring:datasource:driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:username: rootpassword: aPJ35saFz6ASmnmNt…

ASP.NET MVC 快速入门(图文版)

今年是2024年了&#xff0c;没有多少人在ASP.NET 去做开发&#xff0c;都使用ABP框架 &#xff0c;不过我们仍然需要了解ASP.NET MVC 的一个开发流程 MVC概述 MVC是当前比较流行的WEB程序开发模式之一&#xff0c;ASP.NET MVC是.Net对MVC的一种实现。MVC&#xff08;Model View…

LeetCode 124 —— 二叉树中的最大路径和

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 二叉树的问题首先我们要想想是否能用递归来解决&#xff0c;本题也不例外&#xff0c;而递归的关键是找到子问题。 我们首先来看看一棵最简单的树&#xff0c;也就是示例 1。这样的一棵树总共有六条路径&#xf…

Vita-CLIP: Video and text adaptive CLIP via Multimodal Prompting

标题&#xff1a;Vita-CLIP: 通过多模态提示进行视频和文本自适应CLIP 源文链接&#xff1a;https://openaccess.thecvf.com/content/CVPR2023/papers/Wasim_Vita-CLIP_Video_and_Text_Adaptive_CLIP_via_Multimodal_Prompting_CVPR_2023_paper.pdfhttps://openaccess.thecvf.…

Java中IO流类的体系

Java为我们提供了多种多样的IO流&#xff0c;我们可以根据不同的功能及性能要求挑选合适的IO流&#xff0c;如图所示&#xff0c;为Java中IO流类的体系。 从上图发现&#xff0c;很多流都是成对出现的&#xff0c;比如&#xff1a; FileInputStream/FileOutputStream&#xff0…

国内首个智能体生态大会!2024百度万象大会定档5月30日

最近&#xff0c;百度悄悄「上新」了几个AI神器。 百度搜索上线「互动」功能&#xff0c;可以实时问答&#xff0c;查询信息就像聊天一样简单&#xff0c;还可以艾特相关智能体&#xff0c;更细致精确地满足个性化需求&#xff0c;比如去新加坡旅游&#xff0c;可以让新加坡旅…

Python - 深度学习系列35 重塑实体识别2

说明 上一篇Python - 深度学习系列34 重塑实体识别介绍了如何进行训练&#xff0c;这篇讨论如何应用。 详细review了之后&#xff0c;发现其实早先的服务还是略有欠缺的。例如&#xff1a; 1 最早的时候好像还没有pipeline&#xff0c;我用DataFrame并行处理&#xff0c;然后…

matlab 图像的中值滤波

目录 一、功能概述1、算法概述2、主要函数3、计算公式二、代码实现三、结果展示四、参考链接本文由CSDN点云侠翻译,放入付费专栏只为防不要脸的爬虫。专栏值钱的不是本文,切勿因本文而订阅。 一、功能概述 1、算法概述 中值滤波是图像处理中一种常用的非线性运算,用于减少…

摸鱼大数据——Hive基础理论知识——Hive环境准备

Hive环境准备 1、shell脚本执行方式 方式1: sh 脚本 注意: 需要进入脚本所在目录,但脚本有没有执行权限不影响执行 方式2: ./脚本 注意: 需要进入脚本所在目录,且脚本必须有执行权限 方式3: /绝对路径/脚本 注意: 不需要进入脚本所在目录,但必须有执行…