]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools: Generate multiple rules when multiple output files
authorPierre Gondois <pierre.gondois@arm.com>
Wed, 1 Jul 2020 14:06:01 +0000 (22:06 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 2 Jul 2020 10:09:17 +0000 (10:09 +0000)
This patch modifies the Makefile generation not to stop
adding Makfile rules when the first final target is found.
E.g.:
If the following rules are described in build_rule.txt:
 -[Rule1]: .X files generate .Y and .Z files;
 -[Rule2]: .Z files generate .Z1 files.
Currently, if a File1.X file was part of the sources of a
module, only [Rule1] would be generated in the Makefile.
Indeed, there are no rules to apply to .Y files: .Y files
are a final target. However, there is still [Rule2] to
apply to .Z files.

This patch also adds a dependency between the first
ouput file of a rule and the other output files.
For instance, with the same example as above, File1.Y
and File1.Z are generated by the following rule:
File1.Y: File1.X
    <Generate File1.Y>
    <Generate File1.Z>

and the new dependency is:
File1.Z: File1.Y

This is necessary to keep a dependency order during the
execution of the Makefile. Indeed, .Y and .Z files are
generated by the execution of a common set of commands,
and without this rule, there is no explicit dependency
relation between them.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
Suggested-by: Tomas Pilar <Tomas.Pilar@arm.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
BaseTools/Source/Python/AutoGen/GenMake.py
BaseTools/Source/Python/AutoGen/ModuleAutoGen.py

index bbb3c29446f53fa7f2cb61a216a5b119f72c3fbc..0314d0ea34d99a014379e8d30c46ac0f0a7068ce 100755 (executable)
@@ -1054,6 +1054,12 @@ cleanlib:
                     TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": Deps}\r
                     self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))\r
 \r
+                    # Add a Makefile rule for targets generating multiple files.\r
+                    # The main output is a prerequisite for the other output files.\r
+                    for i in T.Outputs[1:]:\r
+                        AnnexeTargetDict = {"target": self.PlaceMacro(i.Path, self.Macros), "cmd": "", "deps": self.PlaceMacro(T.Target.Path, self.Macros)}\r
+                        self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(AnnexeTargetDict))\r
+\r
     def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):\r
         if not CmdSumDict:\r
             for item in self._AutoGenObject.Targets[Type]:\r
index aad591de65f086043d55aeea5661f59c53792e7c..dc8b1fe3d160cac2da22227fc233e3aa0d92cb1e 100755 (executable)
@@ -860,7 +860,8 @@ class ModuleAutoGen(AutoGen):
         SubDirectory = os.path.join(self.OutputDir, File.SubDir)\r
         if not os.path.exists(SubDirectory):\r
             CreateDirectory(SubDirectory)\r
-        LastTarget = None\r
+        TargetList = set()\r
+        FinalTargetName = set()\r
         RuleChain = set()\r
         SourceList = [File]\r
         Index = 0\r
@@ -870,6 +871,9 @@ class ModuleAutoGen(AutoGen):
         self.BuildOption\r
 \r
         while Index < len(SourceList):\r
+            # Reset the FileType if not the first iteration.\r
+            if Index > 0:\r
+                FileType = TAB_UNKNOWN_FILE\r
             Source = SourceList[Index]\r
             Index = Index + 1\r
 \r
@@ -886,29 +890,25 @@ class ModuleAutoGen(AutoGen):
             elif Source.Ext in self.BuildRules:\r
                 RuleObject = self.BuildRules[Source.Ext]\r
             else:\r
-                # stop at no more rules\r
-                if LastTarget:\r
-                    self._FinalBuildTargetList.add(LastTarget)\r
-                break\r
+                # No more rule to apply: Source is a final target.\r
+                FinalTargetName.add(Source)\r
+                continue\r
 \r
             FileType = RuleObject.SourceFileType\r
             self._FileTypes[FileType].add(Source)\r
 \r
             # stop at STATIC_LIBRARY for library\r
             if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:\r
-                if LastTarget:\r
-                    self._FinalBuildTargetList.add(LastTarget)\r
-                break\r
+                FinalTargetName.add(Source)\r
+                continue\r
 \r
             Target = RuleObject.Apply(Source, self.BuildRuleOrder)\r
             if not Target:\r
-                if LastTarget:\r
-                    self._FinalBuildTargetList.add(LastTarget)\r
-                break\r
-            elif not Target.Outputs:\r
-                # Only do build for target with outputs\r
-                self._FinalBuildTargetList.add(Target)\r
+                # No Target: Source is a final target.\r
+                FinalTargetName.add(Source)\r
+                continue\r
 \r
+            TargetList.add(Target)\r
             self._BuildTargets[FileType].add(Target)\r
 \r
             if not Source.IsBinary and Source == File:\r
@@ -916,12 +916,16 @@ class ModuleAutoGen(AutoGen):
 \r
             # to avoid cyclic rule\r
             if FileType in RuleChain:\r
-                break\r
+                EdkLogger.error("build", ERROR_STATEMENT, "Cyclic dependency detected while generating rule for %s" % str(Source))\r
 \r
             RuleChain.add(FileType)\r
             SourceList.extend(Target.Outputs)\r
-            LastTarget = Target\r
-            FileType = TAB_UNKNOWN_FILE\r
+\r
+        # For each final target name, retrieve the corresponding TargetDescBlock instance.\r
+        for FTargetName in FinalTargetName:\r
+            for Target in TargetList:\r
+                if FTargetName == Target.Target:\r
+                    self._FinalBuildTargetList.add(Target)\r
 \r
     @cached_property\r
     def Targets(self):\r