• gradle-2初始化篇(LoadSetings)


    Gradle-2 初始化篇(LoadSetings)

    调试

    法一:

    https://docs.gradle.org/current/userguide/troubleshooting.html

    ./gradlew taskname -Dorg.gradle.debug=true --no-daemon
    
    • 1

    在这里插入图片描述

    法二:

    找到GradleRunConfiguration类
    在这里插入图片描述
    这样可以方便gradle源码调试

    参考:https://medium.com/dan-on-coding/debugging-gradle-source-code-in-intellij-e1224bec9b6e

    入口

    DefaultGradleLauncher

    public GradleInternal executeTasks() {
            doBuildStages(Stage.RunTasks);
            return gradle;
        }
    
    private void doBuildStages(Stage upTo) {
            Preconditions.checkArgument(
                upTo != Stage.Finished,
                "Stage.Finished is not supported by doBuildStages."
            );
            try {
                if (stage == null && gradle.isRootBuild()) {
                    buildOptionBuildOperationProgressEventsEmitter.emit(gradle.getStartParameter());
                }
    
                if (upTo == Stage.RunTasks && configurationCache.canLoad()) {
                    doConfigurationCacheBuild();
                } else {
                    doClassicBuildStages(upTo);
                }
            } catch (Throwable t) {
                finishBuild(upTo.getDisplayName(), t);
            }
        }
    private void doClassicBuildStages(Stage upTo) {
            if (stage == null) {
                configurationCache.prepareForConfiguration();
            }
            prepareSettings();
            if (upTo == Stage.LoadSettings) {
                return;
            }
            prepareProjects();
            if (upTo == Stage.Configure) {
                return;
            }
            prepareTaskExecution();
            if (upTo == Stage.TaskGraph) {
                return;
            }
            configurationCache.save();
            runWork();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    代码可以看到doClassicBuildStages中调用了prepareSettings方法,该方法就是我们理解的gradle配置阶段,本篇主要来梳理下内部实现流程

    private void prepareSettings() {
            if (stage == null) {
                buildListener.buildStarted(gradle);
    
                settingsPreparer.prepareSettings(gradle);
    
                stage = Stage.LoadSettings;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    配置篇小结:

    1. 生命接口方法buildStarted调用

      首先是触发了buildListenerbuildStarted方法(该监听器可以通过grade.addListener来实现)

    2. 执行初始化脚本

      InitScriptHandler.executeScripts

    3. 寻找并解析setting.gradle文件

    4. 加载gradle.properties文件

    5. 解析buildSrc工程文件

    prepareSettings分析

    1. 调用链路

    BuildOperationFiringSettingsPreparer.prepareSettings
    LoadBuild.run
    DefaultSettingsPreparer.prepareSettings

    涉及服务类参见BuildScopeServices;有关服务类如何注入参见启动篇

    在这里插入图片描述

    // DefaultSettingsPreparer.java
    public void prepareSettings(GradleInternal gradle) {
            // 1. Evaluate init scripts
            initScriptHandler.executeScripts(gradle);
      
            // Build `buildSrc`, load settings.gradle, and construct composite (if appropriate)
            SettingsLoader settingsLoader = gradle.isRootBuild() ? settingsLoaderFactory.forTopLevelBuild() : settingsLoaderFactory.forNestedBuild();
      			
      		//CompositeBuildSettingsLoader
            settingsLoader.findAndLoadSettings(gradle);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. 实现操作

    主要做了三件事。

    1. 执行初始化脚本(.gradle) InitScriptHandler.executeScripts

    2. 构建buildSrc工程

    3. 寻找并解析settings.gradle

      CompositeBuildSettingsLoader.findAndLoadSettings ==>

      ChildBuildRegisteringSettingsLoader.findAndLoadSettings ==>

      CommandLineIncludedBuildSettingsLoader.findAndLoadSettings==>

      SettingsAttachingSettingsLoader.findAndLoadSettings ==>

      DefaultSettingsLoader.findAndLoadSettings ==>

      // CompositeBuildSettingsLoader.java
      public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
              SettingsInternal settings = delegate.findAndLoadSettings(gradle);
      
              // Lock-in explicitly included builds
              buildRegistry.finalizeIncludedBuilds();
      
              return settings;
          }
      
      // ChildBuildRegisteringSettingsLoader.java
      public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
        			// delegate :CommandLineIncludedBuildSettingsLoader
              SettingsInternal settings = delegate.findAndLoadSettings(gradle);
      
              // Add included builds defined in settings
              List<IncludedBuildSpec> includedBuilds = settings.getIncludedBuilds();
              if (!includedBuilds.isEmpty()) {
                  Set<IncludedBuild> children = new LinkedHashSet<>(includedBuilds.size());
                  for (IncludedBuildSpec includedBuildSpec : includedBuilds) {
                      if (!includedBuildSpec.rootDir.equals(buildRegistry.getRootBuild().getBuildRootDir())) {
                          IncludedBuildState includedBuild = addIncludedBuild(includedBuildSpec, gradle);
                          children.add(includedBuild.getModel());
                      } else {
                          buildRegistry.registerSubstitutionsForRootBuild();
                          children.add(new IncludedRootBuild((CompositeBuildParticipantBuildState) buildRegistry.getRootBuild()));
                      }
                  }
      
                  // Set the visible included builds
                  gradle.setIncludedBuilds(children);
              } else {
                  gradle.setIncludedBuilds(Collections.emptyList());
              }
      
              return settings;
          }
      
      // CommandLineIncludedBuildSettingsLoader.java
      public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
        			// delegate: SettingsAttachingSettingsLoader
              SettingsInternal settings = delegate.findAndLoadSettings(gradle);
      
              // Add all included builds from the command-line
              for (File rootDir : gradle.getStartParameter().getIncludedBuilds()) {
                  settings.includeBuild(rootDir);
              }
      
              return settings;
          }
      
      // SettingsAttachingSettingsLoader.java
      public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
        			// delegate:DefaultSettingsLoader
              SettingsInternal settings = delegate.findAndLoadSettings(gradle);
              gradle.setSettings(settings);
              projectRegistry.registerProjects(gradle.getServices().get(BuildState.class));
              return settings;
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59

    DefaultSettingsLoader.findAndLoadSettings

    /**
     * Handles locating and processing setting.gradle files.  Also deals with the buildSrc module, since that modules is
     * found after settings is located, but needs to be built before settings is processed.
     */
    public class DefaultSettingsLoader implements SettingsLoader {
     	
      	....
          
      	public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
            StartParameter startParameter = gradle.getStartParameter();
    				
            // 1. 寻找setting.gradle位置
            SettingsLocation settingsLocation = buildLayoutFactory.getLayoutFor(new BuildLayoutConfiguration(startParameter));
            if (settingsLocation.isSettingsLoadedFromMasterDirectory()) {
                DeprecationLogger.deprecateBehaviour("Searching for settings files in a directory named 'master' from a sibling directory has been deprecated.")
                    .willBeRemovedInGradle7()
                    .withUpgradeGuideSection(6, "master_subdirectory_root_build")
                    .nagUser();
            }
          
          	// 2. 加载gradle.properties文件
            loadGradlePropertiesFrom(settingsLocation);
    				
          	// 3. 解析settings.gradle 文件
            SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter, settingsLocation, gradle.getClassLoaderScope());
            ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);
            if (useEmptySettings(spec, settings, startParameter)) {
                settings = createEmptySettings(gradle, startParameter, settings.getClassLoaderScope());
            }
    				
          	// 4. 设置默认工程
            setDefaultProject(spec, settings);
            return settings;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    可以看到DefaultSettingsLoader类注释说明可以知道它的职责是

    1. 处理setting.gradle文件
    2. build buildSrc工程

    1. 寻找setting.gradle

    在这里插入图片描述

    2. 加载grade.properties

    最终调用到DefaultGradlePropertiesLoader.loadProperties

    @Override
    public GradleProperties loadGradleProperties(File rootDir) {
      return loadProperties(rootDir, startParameter, getAllSystemProperties(), getAllEnvProperties());
    }
    
    GradleProperties loadProperties(File rootDir, StartParameterInternal startParameter, Map<String, String> systemProperties, Map<String, String> envProperties) {
      Map<String, String> defaultProperties = new HashMap<>();
      Map<String, String> overrideProperties = new HashMap<>();
    
      // 1. gradle-home-dir:/Users/dingbaosheng/.gradle/wrapper/dists/gradle-6.9-bin/2ecsmyp3bolyybemj56vfn4mt/gradle-6.9
      addGradleProperties(defaultProperties, new File(startParameter.getGradleHomeDir(), GRADLE_PROPERTIES));
      // 2. eg:/Users/dingbaosheng/work/open-source-project/gradle
      addGradleProperties(defaultProperties, new File(rootDir, GRADLE_PROPERTIES));
      
      // 3. gradle-user-home-dir:/Users/dingbaosheng/.gradle
      addGradleProperties(overrideProperties, new File(startParameter.getGradleUserHomeDir(), GRADLE_PROPERTIES));
    
      addSystemPropertiesFromGradleProperties(defaultProperties);
      addSystemPropertiesFromGradleProperties(overrideProperties);
      System.getProperties().putAll(startParameter.getSystemPropertiesArgs());
    	
      // 从环境变量中读取ORG_GRADLE_PROJECT_开头的key,有就返回,无就返回空
      overrideProperties.putAll(getEnvProjectProperties(envProperties));
      // 从系统属性中读取org.gradle.project.开头key,有则返回,无则返回空
      overrideProperties.putAll(getSystemProjectProperties(systemProperties));
      // 启动命令参数重读取
      overrideProperties.putAll(startParameter.getProjectProperties());
    
      return new DefaultGradleProperties(defaultProperties, overrideProperties);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    上面主要是从
    gradle-home-dir、项目根工程目录、gradle-user-home目录,环境变量,系统属性及启动参数中加载properties属性

    3. 解析settings.gradle文件

    调用链路

    DefaultSettingsLoader.findSettingsAndLoadIfAppropriate

    /**
         * Finds the settings.gradle for the given startParameter, and loads it if contains the project selected by the
         * startParameter, or if the startParameter explicitly specifies a settings script.  If the settings file is not
         * loaded (executed), then a null is returned.
         */
        private SettingsInternal findSettingsAndLoadIfAppropriate(
            GradleInternal gradle,
            StartParameter startParameter,
            SettingsLocation settingsLocation,
            ClassLoaderScope classLoaderScope
        ) {
          	// 此处的settingsProcessor为BuildOperationSettingsProcessor
            SettingsInternal settings = settingsProcessor.process(gradle, settingsLocation, classLoaderScope, startParameter);
            // 交验工程名称合法性(不能是buildSrc)
            validate(settings);
            return settings;
        }
    
        private void validate(SettingsInternal settings) {
            settings.getProjectRegistry().getAllProjects().forEach(project -> {
                if (project.getPath().equals(BUILD_SRC_PROJECT_PATH)) {
                    Path buildPath = settings.getGradle().getIdentityPath();
                    String suffix = buildPath == Path.ROOT ? "" : " (in build " + buildPath + ")";
                    throw new GradleException("'" + SettingsInternal.BUILD_SRC + "' cannot be used as a project name as it is a reserved name" + suffix);
                }
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    链路调用:

    BuildOperationSettingsProcessor.process
    RootBuildCacheControllerSettingsProcessor.process
    SettingsEvaluatedCallbackFiringSettingsProcessor.process
    ScriptEvaluatingSettingsProcessor.process

    参见:BuildScopeService

    在这里插入图片描述

    // BuildOperationSettingsProcessor.java
    @Override
    public SettingsInternal process(final GradleInternal gradle, final SettingsLocation settingsLocation, final ClassLoaderScope buildRootClassLoaderScope, final StartParameter startParameter) {
      return buildOperationExecutor.call(new CallableBuildOperation<SettingsInternal>() {
        @Override
        public SettingsInternal call(BuildOperationContext context) {
          // 直接委托给RootBuildCacheControllerSettingsProcessor处理
          SettingsInternal settingsInternal = settingsProcessor.process(gradle, settingsLocation, buildRootClassLoaderScope, startParameter);
          context.setResult(RESULT);
          return settingsInternal;
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    可以看到BuildOperationSettingsProcessor类中的process方法将任务直接委派给RootBuildCacheControllerSettingsProcessor.process处理了

    public class RootBuildCacheControllerSettingsProcessor implements SettingsProcessor {
    
        public static void process(GradleInternal gradle) {
            // The strategy for sharing build cache configuration across included builds in a composite,
            // requires that the cache configuration be finalized (and cache controller available)
            // before configuring them. This achieves that.
            if (gradle.isRootBuild()) {
                BuildCacheController rootController = gradle.getServices().get(BuildCacheController.class);
                RootBuildCacheControllerRef rootControllerRef = gradle.getServices().get(RootBuildCacheControllerRef.class);
                rootControllerRef.set(rootController);
            }
        }
    
        private final SettingsProcessor delegate;
    
        public RootBuildCacheControllerSettingsProcessor(SettingsProcessor delegate) {
            this.delegate = delegate;
        }
    
        @Override
        public SettingsInternal process(GradleInternal gradle, SettingsLocation settingsLocation, ClassLoaderScope buildRootClassLoaderScope, StartParameter startParameter) {
          	// 1. 交给SettingsEvaluatedCallbackFiringSettingsProcessor类处理
            SettingsInternal settings = delegate.process(gradle, settingsLocation, buildRootClassLoaderScope, startParameter);
            // 2. 设置缓存相关配置
            process(gradle);
            return settings;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    RootBuildCacheControllerSettingsProcessor类顾名思义就是在执行配置阶段,设置缓存配置参见process(grade)

    执行process时做了2件事情

    1. 委托SettingsEvaluatedCallbackFiringSettingsProcessor类处理
    2. 缓存配置设置
    public class SettingsEvaluatedCallbackFiringSettingsProcessor implements SettingsProcessor {
    
        private final SettingsProcessor delegate;
    
        public SettingsEvaluatedCallbackFiringSettingsProcessor(SettingsProcessor delegate) {
            this.delegate = delegate;
        }
    
        @Override
        public SettingsInternal process(GradleInternal gradle, SettingsLocation settingsLocation, ClassLoaderScope buildRootClassLoaderScope, StartParameter startParameter) {
          	// 1. 委托ScriptEvaluatingSettingsProcessor类处理
            SettingsInternal settings = delegate.process(gradle, settingsLocation, buildRootClassLoaderScope, startParameter);
          	// 2. 执行gradle中setting.gradle方法被解析的生命周期方法
            gradle.getBuildListenerBroadcaster().settingsEvaluated(settings);
            // 3. I don't know, 
            settings.preventFromFurtherMutation();
            return settings;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    上述操作经过层层委托,终于来到类ScriptEvaluatingSettingsProcessor类处理,我们看下其内部实现

    public class ScriptEvaluatingSettingsProcessor implements SettingsProcessor {
        private static final Logger LOGGER = LoggerFactory.getLogger(ScriptEvaluatingSettingsProcessor.class);
    
        private final SettingsFactory settingsFactory;
        private final GradleProperties gradleProperties;
        private final ScriptPluginFactory configurerFactory;
        private final TextFileResourceLoader textFileResourceLoader;
    
        public ScriptEvaluatingSettingsProcessor(ScriptPluginFactory configurerFactory,
                                                 SettingsFactory settingsFactory,
                                                 GradleProperties gradleProperties,
                                                 TextFileResourceLoader textFileResourceLoader) {
            this.configurerFactory = configurerFactory;
            this.settingsFactory = settingsFactory;
            this.gradleProperties = gradleProperties;
            this.textFileResourceLoader = textFileResourceLoader;
        }
    
        @Override
        public SettingsInternal process(GradleInternal gradle,
                                        SettingsLocation settingsLocation,
                                        ClassLoaderScope baseClassLoaderScope,
                                        StartParameter startParameter) {
            Timer settingsProcessingClock = Time.startTimer();
            Map<String, String> properties = gradleProperties.mergeProperties(emptyMap());
            TextResourceScriptSource settingsScript = new TextResourceScriptSource(textFileResourceLoader.loadFile("settings file", settingsLocation.getSettingsFile()));
          
          	// 1. 创建一个DefaultSettings的一个包装对象
            SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(), settingsScript, properties, startParameter, baseClassLoaderScope);
    				
          	// 2. 生命周期调用
            gradle.getBuildListenerBroadcaster().beforeSettings(settings);
          
          	// 3. 应用脚本
            applySettingsScript(settingsScript, settings);
            LOGGER.debug("Timing: Processing settings took: {}", settingsProcessingClock.getElapsed());
            return settings;
        }
    
        private void applySettingsScript(TextResourceScriptSource settingsScript, final SettingsInternal settings) {
          	// 1. 生成一个BuildOperationScriptPlugin类型对象
            ScriptPlugin configurer = configurerFactory.create(settingsScript, settings.getBuildscript(), settings.getClassLoaderScope(), settings.getBaseClassLoaderScope(), true);
            // 2. apply
            configurer.apply(settings);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述

    因为gradle源码中的settings文件采用了kotlin语言编写,所以此处apply选择为kotlin脚本插件解析

    BuildOperationScriptPlugin.java
    在这里插入图片描述

    4. 设置默认工程

    private void setDefaultProject(ProjectSpec spec, SettingsInternal settings) {
            settings.setDefaultProject(spec.selectProject(settings.getSettingsScript().getDisplayName(), settings.getProjectRegistry()));
        }
    
    • 1
    • 2
    • 3
  • 相关阅读:
    redis
    手把手教你深度学习和实战-----循环神经网络
    听GPT 讲Istio源代码--pkg(5)
    《Principles of Model Checking》Charpter 1 System Verification
    python编程复习系列——week3决策声明(if-else)
    NDT方法总结与公式推导
    刷题记录(NC16884 食物链,NC51097 Parity game,NC235745 拆路)
    想知道视频二维码制作方法吗?方法很简单
    如何在Linux系统中安装MySQL数据库
    低压配电箱监测报警系统:智能化监控的重要
  • 原文地址:https://blog.csdn.net/dbs1215/article/details/126002246