gradle学习笔记(五)从源码看构建流程之initlization

在初始化阶段主要是对settings.gradle文件进行处理建立项目的构建工程结构
settings处理过程如下:
settings处理时序
1.获取gradle命令行参数,在之前已解析成StartParameter
2.根据命令行参数和gradle惯例查找需要的Settings.gradle文件
3.找到对应的buildSrc目录,并编译相应的代码资源
4.根据以上的结果创建Settings对象
5.为Settings对象设置默认工程
1.gradle命令行参数
这里写图片描述
以上是命令行下的gradle命令参数
如果在命令中使用-p/-b/-c/-u等选项,会影响到Settings文件的定位
2.Settings.gradle文件的定位
策略:
1.在命令行参数里指定了Settings文件,使用指定的文件
2.未指定Settings文件默认从当前目录下开始向上递归查找,在父目录下查找,未找到则在父目录下的master目录下查找,重复以上步骤。
源码实现如下

 /**
     * Determines the layout of the build, given a current directory and some other configuration.
     */
    public BuildLayout getLayoutFor(BuildLayoutConfiguration configuration) {
        if (configuration.isUseEmptySettings()) {
            return new BuildLayout(configuration.getCurrentDir(), configuration.getCurrentDir(), null);
        }
        File explicitSettingsFile = configuration.getSettingsFile();
        if (explicitSettingsFile != null) {
            if (!explicitSettingsFile.isFile()) {
                throw new ResourceNotFoundException(explicitSettingsFile.toURI(), String.format("Could not read settings file '%s' as it does not exist.", explicitSettingsFile.getAbsolutePath()));
            }
            return new BuildLayout(configuration.getCurrentDir(), configuration.getCurrentDir(), explicitSettingsFile);
        }
        File currentDir = configuration.getCurrentDir();
        boolean searchUpwards = configuration.isSearchUpwards();
        return getLayoutFor(currentDir, searchUpwards ? null : currentDir.getParentFile());
    }

    BuildLayout getLayoutFor(File currentDir, File stopAt) {
        File settingsFile = new File(currentDir, "settings.gradle");
        if (settingsFile.isFile()) {
            return layout(currentDir, currentDir, settingsFile);
        }
        for (File candidate = currentDir.getParentFile(); candidate != null && !candidate.equals(stopAt); candidate = candidate.getParentFile()) {
            settingsFile = new File(candidate, "settings.gradle");
            if (settingsFile.isFile()) {
                return layout(candidate, candidate, settingsFile);
            }
            settingsFile = new File(candidate, "master/settings.gradle");
            if (settingsFile.isFile()) {
                return layout(candidate, settingsFile.getParentFile(), settingsFile);
            }
        }
        return layout(currentDir, currentDir, settingsFile);
    }

3.buildSrc目录处理
// We found the desired settings file, now build the associated buildSrc before loading settings. This allows the settings script to reference classes in the buildSrc.
以上是源码只能给的一段注释:在找到Settings文件以后,在加载Settings文件之前需要先对BuildSrc下的文件进行编译,以便zaiSettings脚本里引用buildSrc中的类。
我们可以在buildSrc目录下创建groovy脚本文件或者创建plugin
具体使用参考资料:自定义Task类型
4.Settings对象创建
首先看一下BuildScopeServices中创建的SettingsProcessor

protected SettingsProcessor createSettingsProcessor(ScriptPluginFactory scriptPluginFactory, ScriptHandlerFactory scriptHandlerFactory, Instantiator instantiator,                                        ServiceRegistryFactory serviceRegistryFactory, IGradlePropertiesLoader propertiesLoader, BuildOperationExecutor buildOperationExecutor) {
        return new NotifyingSettingsProcessor(
            new PropertiesLoadingSettingsProcessor(
                new ScriptEvaluatingSettingsProcessor(
                    scriptPluginFactory,
                    scriptHandlerFactory,
                    new SettingsFactory(
                        instantiator,
                        serviceRegistryFactory
                    ),
                    propertiesLoader
                ),
                propertiesLoader
            ),
            buildOperationExecutor);
    }

这里的Processor有三级的链式处理,ScriptEvaluatingSettingsProcessor最终处理交给SettingsFactory生成DefaultSettings 对象
这里写图片描述
Settings构建工程结构解析如下

 public void include(String[] projectPaths) {
        for (String projectPath : projectPaths) {
            String subPath = "";
            String[] pathElements = removeTrailingColon(projectPath).split(":");
            DefaultProjectDescriptor parentProjectDescriptor = rootProjectDescriptor;
            for (String pathElement : pathElements) {
                subPath = subPath + ":" + pathElement;
                DefaultProjectDescriptor projectDescriptor = getProjectDescriptorRegistry().getProject(subPath);
                if (projectDescriptor == null) {
                    parentProjectDescriptor = createProjectDescriptor(parentProjectDescriptor, pathElement, new File(parentProjectDescriptor.getProjectDir(), pathElement));
                } else {
                    parentProjectDescriptor = projectDescriptor;
                }
            }
        }
    }

5.设置默认工程DefaultProject
默认的工程目录是当前工作目录,在命令行使用-p选项可以指定工程目录,当用-b指定构建文件build.gradle,用-p指定构建工程时有不同的策略确定默认构建工程

  @Override
    public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
        StartParameter startParameter = gradle.getStartParameter();
        SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter);

        ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);

        if (spec.containsProject(settings.getProjectRegistry())) {
            setDefaultProject(spec, settings);
            return settings;
        }

        // Try again with empty settings
        StartParameter noSearchParameter = startParameter.newInstance();
        noSearchParameter.useEmptySettings();
        settings = findSettingsAndLoadIfAppropriate(gradle, noSearchParameter);

        // Set explicit build file, if required
        if (noSearchParameter.getBuildFile() != null) {
            ProjectDescriptor rootProject = settings.getRootProject();
            rootProject.setBuildFileName(noSearchParameter.getBuildFile().getName());
        }
        setDefaultProject(spec, settings);

        return settings;
    }


class ProjectSpecs {

    static ProjectSpec forStartParameter(StartParameter startParameter, SettingsInternal settings) {
        File explicitProjectDir = startParameter.getProjectDir();
        File explicitBuildFile = startParameter.getBuildFile();
        if (explicitBuildFile != null) {
            return new BuildFileProjectSpec(explicitBuildFile);
        }
        if (explicitProjectDir != null) {
            return new ProjectDirectoryProjectSpec(explicitProjectDir);
        }
        return new DefaultProjectSpec(startParameter.getCurrentDir(), settings);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值