From: "PierreGondois" <pierre.gondois@arm.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
Pierre Gondois <Pierre.Gondois@arm.com>
Cc: "bob.c.feng@intel.com" <bob.c.feng@intel.com>,
"liming.gao@intel.com" <liming.gao@intel.com>,
Sami Mujawar <Sami.Mujawar@arm.com>, nd <nd@arm.com>
Subject: Re: [edk2-devel] [PATCH v2 1/1] BaseTools: Rationalise makefile generation
Date: Tue, 4 Feb 2020 12:02:55 +0000 [thread overview]
Message-ID: <DB7PR08MB3113DCB5AEC807CB472BAA768B030@DB7PR08MB3113.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <15F0315032D95F8E.2867@groups.io>
Hello Liming and Bob,
To answer Liming's questions, I am building the DynamicTablesPkg with the patch with the AARCH64-DEBUG and the following configurations:
Windows - GCC - GNUmake
Windows - GCC - nmake
Windows - VS2017 - GNUmake
Windows - VS2017 - nmake
Linux - GCC5 - GNUmake
For the record, when building with the Windows-VS2017-GNUmake configuration, the *_*_*_MAKE_FLAG(S) variable is set to "/nologo". As this is a nmake specific flag, it has to be removed when using GNUmake. Some warning flags also need to be slightly modified when building with VS2017.
To modify the type of make tool to use (GNUmake or nmake), I modify the following variable in Conf/tools_def.txt:
*_[GCC5|VS2017]_*_MAKE_PATH = [nmake|GNUmake]
I am building the ShellPkg with the patch and a small modification on how nasm files are added for IA32 and X64 for the following configurations:
Windows - VS2017 - GNUmake
Windows - VS2017 - nmake
Linux - GCC - GNUmake
Unfortunately, the gcc compiler available on windows doesn't provide all the options of the one available on linux. For instances:
* When building ShellPkg-DEBUG build-X64 -Windows-GCC-[nmake], the "-mcmodel=small" option provided is not supported.
* When building ShellPkg-DEBUG build-IA32-Windows-GCC-[nmake], the "-m,elf_i386" option provided is not supported.
These issues are related to the compiler and not to the patch.
The Windows-GCC-GNUmake configuration is very important for Arm. This configuration was working fine until patch "0c3e8e9947a6c13b4327dd11b20acb95441701cf BaseTools: Enhance Basetool for incremental build" was merged in edk2.
Regards,
Pierre
-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of PierreGondois via Groups.Io
Sent: 04 February 2020 12:01
To: devel@edk2.groups.io
Cc: Pierre Gondois <Pierre.Gondois@arm.com>; bob.c.feng@intel.com; liming.gao@intel.com; Sami Mujawar <Sami.Mujawar@arm.com>; Pierre Gondois <Pierre.Gondois@arm.com>; nd <nd@arm.com>
Subject: [edk2-devel] [PATCH v2 1/1] BaseTools: Rationalise makefile generation
From: Pierre Gondois <pierre.gondois@arm.com>
The GenMake.py script tests the platform environment to determine the type of makefile that needs to be generated. If a Windows build host is detected, the makefile generated is of Nmake type. Otherwise a GNUmake type is generated.
Furthermore, the <TARGET>_<TAGNAME>_<ARCH>_MAKE_PATH
option in tools_def.template defines the make tool to use.
E.g.: for VS2017 this is configured to use Nmake, cf.
*_VS2017_*_MAKE_PATH = DEF(VS2017_BIN_HOST)\nmake.exe while for GCC5 it is setup to use GNU make.
*_GCC5_*_MAKE_PATH = DEF(GCC_HOST_PREFIX)make
This prevents using the GCC compiler toolchain on a Windows build host.
To address this issue this patch introduces 2 factors to determine the generated makefile output.
1. Platform -> to determine shell commands used
in makefile.
2. MakeTool -> to determine the type of makefile
that needs to be generated.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
The changes can be seen at https://github.com/PierreARM/edk2/tree/720_BaseTools_Rationalise_makefile_generation_v2
Notes:
v2:
- Rebase on latest master [Pierre]
BaseTools/Source/Python/AutoGen/GenMake.py | 122 ++++++++++----------
BaseTools/Source/Python/AutoGen/IncludesAutoGen.py | 34 +++---
BaseTools/Source/Python/build/build.py | 7 +-
3 files changed, 88 insertions(+), 75 deletions(-)
diff --git a/BaseTools/Source/Python/AutoGen/GenMake.py b/BaseTools/Source/Python/AutoGen/GenMake.py
index ba199c1aa73dc46856b41c13e07e3d9770081acd..f49c765c791d57c06fcccf7059b37a018dc68ae6 100755
--- a/BaseTools/Source/Python/AutoGen/GenMake.py
+++ b/BaseTools/Source/Python/AutoGen/GenMake.py
@@ -2,6 +2,7 @@
# Create makefile for MS nmake and GNU make # # Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent #
@@ -52,13 +53,6 @@ gIncludeMacroConversion = {
"EFI_PPI_DEPENDENCY" : gPpiDefinition,
}
-## default makefile type
-gMakeType = ""
-if sys.platform == "win32":
- gMakeType = "nmake"
-else:
- gMakeType = "gmake"
-
## BuildFile class
#
@@ -77,6 +71,13 @@ class BuildFile(object):
"gmake" : "GNUmakefile"
}
+ # Get Makefile name.
+ def getMakefileName(self):
+ if not self._FileType:
+ return _DEFAULT_FILE_NAME_
+ else:
+ return self._FILE_NAME_[self._FileType]
+
## Fixed header string for makefile
_MAKEFILE_HEADER = '''#
# DO NOT EDIT
@@ -106,7 +107,7 @@ class BuildFile(object):
# $(RD) remove dir command
#
_SHELL_CMD_ = {
- "nmake" : {
+ "win32" : {
"CP" : "copy /y",
"MV" : "move /y",
"RM" : "del /f /q",
@@ -114,7 +115,7 @@ class BuildFile(object):
"RD" : "rmdir /s /q",
},
- "gmake" : {
+ "posix" : {
"CP" : "cp -f",
"MV" : "mv -f",
"RM" : "rm -f",
@@ -125,35 +126,35 @@ class BuildFile(object):
## directory separator
_SEP_ = {
- "nmake" : "\\",
- "gmake" : "/"
+ "win32" : "\\",
+ "posix" : "/"
}
## directory creation template
_MD_TEMPLATE_ = {
- "nmake" : 'if not exist %(dir)s $(MD) %(dir)s',
- "gmake" : "$(MD) %(dir)s"
+ "win32" : 'if not exist %(dir)s $(MD) %(dir)s',
+ "posix" : "$(MD) %(dir)s"
}
## directory removal template
_RD_TEMPLATE_ = {
- "nmake" : 'if exist %(dir)s $(RD) %(dir)s',
- "gmake" : "$(RD) %(dir)s"
+ "win32" : 'if exist %(dir)s $(RD) %(dir)s',
+ "posix" : "$(RD) %(dir)s"
}
## cp if exist
_CP_TEMPLATE_ = {
- "nmake" : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
- "gmake" : "test -f %(Src)s && $(CP) %(Src)s %(Dst)s"
+ "win32" : 'if exist %(Src)s $(CP) %(Src)s %(Dst)s',
+ "posix" : "test -f %(Src)s && $(CP) %(Src)s %(Dst)s"
}
_CD_TEMPLATE_ = {
- "nmake" : 'if exist %(dir)s cd %(dir)s',
- "gmake" : "test -e %(dir)s && cd %(dir)s"
+ "win32" : 'if exist %(dir)s cd %(dir)s',
+ "posix" : "test -e %(dir)s && cd %(dir)s"
}
_MAKE_TEMPLATE_ = {
- "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
- "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
+ "win32" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s',
+ "posix" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s'
}
_INCLUDE_CMD_ = {
@@ -169,22 +170,30 @@ class BuildFile(object):
#
def __init__(self, AutoGenObject):
self._AutoGenObject = AutoGenObject
- self._FileType = gMakeType
- ## Create build file
+ MakePath = AutoGenObject.BuildOption.get('MAKE', {}).get('PATH')
+ if not MakePath:
+ self._FileType = ""
+ elif "nmake" in MakePath:
+ self._FileType = "nmake"
+ else:
+ self._FileType = "gmake"
+
+ if sys.platform == "win32":
+ self._Platform = "win32"
+ else:
+ self._Platform = "posix"
+
+ ## Create build file.
#
- # @param FileType Type of build file. Only nmake and gmake are supported now.
+ # Only nmake and gmake are supported.
#
- # @retval TRUE The build file is created or re-created successfully
- # @retval FALSE The build file exists and is the same as the one to be generated
+ # @retval TRUE The build file is created or re-created successfully
+ # @retval FALSE The build file exists and is the same as the one to be generated
#
- def Generate(self, FileType=gMakeType):
- if FileType not in self._FILE_NAME_:
- EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType,
- ExtraData="[%s]" % str(self._AutoGenObject))
- self._FileType = FileType
+ def Generate(self):
FileContent = self._TEMPLATE_.Replace(self._TemplateDict)
- FileName = self._FILE_NAME_[FileType]
+ FileName = self.getMakefileName()
if not os.path.exists(os.path.join(self._AutoGenObject.MakeFileDir, "deps.txt")):
with open(os.path.join(self._AutoGenObject.MakeFileDir, "deps.txt"),"w+") as fd:
fd.write("")
@@ -203,7 +212,7 @@ class BuildFile(object):
# @retval list The directory creation command list
#
def GetCreateDirectoryCommand(self, DirList):
- return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
+ return [self._MD_TEMPLATE_[self._Platform] % {'dir':Dir} for
+ Dir in DirList]
## Return a list of directory removal command string
#
@@ -212,7 +221,7 @@ class BuildFile(object):
# @retval list The directory removal command list
#
def GetRemoveDirectoryCommand(self, DirList):
- return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList]
+ return [self._RD_TEMPLATE_[self._Platform] % {'dir':Dir} for
+ Dir in DirList]
def PlaceMacro(self, Path, MacroDefinitions=None):
if Path.startswith("$("):
@@ -462,11 +471,8 @@ cleanlib:
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict(self):
- if self._FileType not in self._SEP_:
- EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType,
- ExtraData="[%s]" % str(self._AutoGenObject))
MyAgo = self._AutoGenObject
- Separator = self._SEP_[self._FileType]
+ Separator = self._SEP_[self._Platform]
# break build if no source files and binary files are found
if len(MyAgo.SourceFileList) == 0 and len(MyAgo.BinaryFileList) == 0:
@@ -628,10 +634,10 @@ cleanlib:
BcTargetList = []
- MakefileName = self._FILE_NAME_[self._FileType]
+ MakefileName = self.getMakefileName()
LibraryMakeCommandList = []
for D in self.LibraryBuildDirectoryList:
- Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)}
+ Command = self._MAKE_TEMPLATE_[self._Platform] %
+ {"file":os.path.join(D, MakefileName)}
LibraryMakeCommandList.append(Command)
package_rel_dir = MyAgo.SourceDir @@ -683,8 +689,8 @@ cleanlib:
"separator" : Separator,
"module_tool_definitions" : ToolsDef,
- "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
- "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
+ "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
+ "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
"module_entry_point" : ModuleEntryPoint,
"image_entry_point" : ImageEntryPoint,
@@ -721,7 +727,7 @@ cleanlib:
self.ResultFileList.append(Dst)
if '%s :' %(Dst) not in self.BuildTargetList:
self.BuildTargetList.append("%s :" %(Dst))
- self.BuildTargetList.append('\t' + self._CP_TEMPLATE_[self._FileType] %{'Src': Src, 'Dst': Dst})
+ self.BuildTargetList.append('\t' +
+ self._CP_TEMPLATE_[self._Platform] %{'Src': Src, 'Dst': Dst})
FfsCmdList = Cmd[0]
for index, Str in enumerate(FfsCmdList):
@@ -1222,7 +1228,7 @@ ${BEGIN}\t-@${create_directory_command}\n${END}\
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict(self):
- Separator = self._SEP_[self._FileType]
+ Separator = self._SEP_[self._Platform]
MyAgo = self._AutoGenObject
if self._FileType not in MyAgo.CustomMakefile:
EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType, @@ -1252,7 +1258,7 @@ ${BEGIN}\t-@${create_directory_command}\n${END}\
ToolsDef.append("%s_%s = %s" % (Tool, Attr, MyAgo.BuildOption[Tool][Attr]))
ToolsDef.append("")
- MakefileName = self._FILE_NAME_[self._FileType]
+ MakefileName = self.getMakefileName()
MakefileTemplateDict = {
"makefile_header" : self._FILE_HEADER_[self._FileType],
"makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName),
@@ -1285,8 +1291,8 @@ ${BEGIN}\t-@${create_directory_command}\n${END}\
"separator" : Separator,
"module_tool_definitions" : ToolsDef,
- "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
- "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
+ "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
+ "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
"create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList),
"custom_makefile_content" : CustomMakefile
@@ -1413,7 +1419,7 @@ cleanlib:
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict(self):
- Separator = self._SEP_[self._FileType]
+ Separator = self._SEP_[self._Platform]
MyAgo = self._AutoGenObject
if "MAKE" not in MyAgo.ToolDefinition or "PATH" not in MyAgo.ToolDefinition["MAKE"]:
@@ -1424,13 +1430,13 @@ cleanlib:
self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList()
self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList()
- MakefileName = self._FILE_NAME_[self._FileType]
+ MakefileName = self.getMakefileName()
LibraryMakefileList = []
LibraryMakeCommandList = []
for D in self.LibraryBuildDirectoryList:
D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
Makefile = os.path.join(D, MakefileName)
- Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
+ Command = self._MAKE_TEMPLATE_[self._Platform] %
+ {"file":Makefile}
LibraryMakefileList.append(Makefile)
LibraryMakeCommandList.append(Command)
self.LibraryMakeCommandList = LibraryMakeCommandList @@ -1440,7 +1446,7 @@ cleanlib:
for D in self.ModuleBuildDirectoryList:
D = self.PlaceMacro(D, {"BUILD_DIR":MyAgo.BuildDir})
Makefile = os.path.join(D, MakefileName)
- Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile}
+ Command = self._MAKE_TEMPLATE_[self._Platform] %
+ {"file":Makefile}
ModuleMakefileList.append(Makefile)
ModuleMakeCommandList.append(Command)
@@ -1460,8 +1466,8 @@ cleanlib:
"toolchain_tag" : MyAgo.ToolChain,
"build_target" : MyAgo.BuildTarget,
- "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
- "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
+ "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
+ "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
"build_architecture_list" : MyAgo.Arch,
"architecture" : MyAgo.Arch,
"separator" : Separator,
@@ -1519,7 +1525,7 @@ class TopLevelMakefile(BuildFile):
# Compose a dict object containing information used to do replacement in template
@property
def _TemplateDict(self):
- Separator = self._SEP_[self._FileType]
+ Separator = self._SEP_[self._Platform]
# any platform autogen object is ok because we just need common information
MyAgo = self._AutoGenObject
@@ -1575,10 +1581,10 @@ class TopLevelMakefile(BuildFile):
else:
ExtraOption += " --pcd " + pcdname + '=' + pcd[3]
- MakefileName = self._FILE_NAME_[self._FileType]
+ MakefileName = self.getMakefileName()
SubBuildCommandList = []
for A in MyAgo.ArchList:
- Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
+ Command = self._MAKE_TEMPLATE_[self._Platform] %
+ {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)}
SubBuildCommandList.append(Command)
MakefileTemplateDict = {
@@ -1593,8 +1599,8 @@ class TopLevelMakefile(BuildFile):
"toolchain_tag" : MyAgo.ToolChain,
"build_target" : MyAgo.BuildTarget,
- "shell_command_code" : list(self._SHELL_CMD_[self._FileType].keys()),
- "shell_command" : list(self._SHELL_CMD_[self._FileType].values()),
+ "shell_command_code" : list(self._SHELL_CMD_[self._Platform].keys()),
+ "shell_command" : list(self._SHELL_CMD_[self._Platform].values()),
'arch' : list(MyAgo.ArchList),
"build_architecture_list" : ','.join(MyAgo.ArchList),
"separator" : Separator,
diff --git a/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py b/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py
index 1ca1798907ef9b46a17d8938bb2f673d5ade662f..ca9e02d19b4afad82241abb8e15845731cabd22f 100644
--- a/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py
@@ -2,6 +2,7 @@
# Build cache intermediate result and state # # Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent # from Common.caching import cached_property @@ -12,20 +13,6 @@ from Common.Misc import SaveFileOnChange, PathClass from Common.Misc import TemplateString import sys gIsFileMap = {} -if sys.platform == "win32":
- _INCLUDE_DEPS_TEMPLATE = TemplateString('''
-${BEGIN}
-!IF EXIST(${deps_file})
-!INCLUDE ${deps_file}
-!ENDIF
-${END}
- ''')
-else:
- _INCLUDE_DEPS_TEMPLATE = TemplateString('''
-${BEGIN}
--include ${deps_file}
-${END}
- ''')
DEP_FILE_TAIL = "# Updated \n"
@@ -59,6 +46,25 @@ class IncludesAutoGen():
def CreateDepsInclude(self):
deps_file = {'deps_file':self.deps_files}
+
+ MakePath = self.module_autogen.BuildOption.get('MAKE', {}).get('PATH')
+ if not MakePath:
+ EdkLogger.error("build", PARAMETER_MISSING, Message="No Make path available.")
+ elif "nmake" in MakePath:
+ _INCLUDE_DEPS_TEMPLATE = TemplateString('''
+ ${BEGIN}
+ !IF EXIST(${deps_file})
+ !INCLUDE ${deps_file}
+ !ENDIF
+ ${END}
+ ''')
+ else:
+ _INCLUDE_DEPS_TEMPLATE = TemplateString('''
+ ${BEGIN}
+ -include ${deps_file}
+ ${END}
+ ''')
+
try:
deps_include_str = _INCLUDE_DEPS_TEMPLATE.Replace(deps_file)
except Exception as e:
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index 1e47e382cba94dc6fba7d8ecad2bc924b02cea1d..8e6625ae42afe5ed5fddbdb72ef5e8ca044609b4 100755
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -4,6 +4,7 @@
# Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR> # Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
+# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -1251,7 +1252,7 @@ class Build():
(AutoGenObject.BuildTarget, AutoGenObject.ToolChain, AutoGenObject.Arch),
ExtraData=str(AutoGenObject))
- makefile = GenMake.BuildFile(AutoGenObject)._FILE_NAME_[GenMake.gMakeType]
+ makefile = GenMake.BuildFile(AutoGenObject).getMakefileName()
# run
if Target == 'run':
@@ -2040,10 +2041,10 @@ class Build():
ModuleBuildDirectoryList = data_pipe.Get("ModuleBuildDirectoryList")
for m_build_dir in LibraryBuildDirectoryList:
- if not os.path.exists(os.path.join(m_build_dir,GenMake.BuildFile._FILE_NAME_[GenMake.gMakeType])):
+ if not os.path.exists(os.path.join(m_build_dir,GenMake.BuildFile.getMakefileName())):
return None
for m_build_dir in ModuleBuildDirectoryList:
- if not os.path.exists(os.path.join(m_build_dir,GenMake.BuildFile._FILE_NAME_[GenMake.gMakeType])):
+ if not os.path.exists(os.path.join(m_build_dir,GenMake.BuildFile.getMakefileName())):
return None
Wa = WorkSpaceInfo(
workspacedir,active_p,target,toolchain,archlist
--
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
next parent reply other threads:[~2020-02-04 12:03 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <15F0315032D95F8E.2867@groups.io>
2020-02-04 12:02 ` PierreGondois [this message]
2020-02-04 13:50 ` [edk2-devel] [PATCH v2 1/1] BaseTools: Rationalise makefile generation Liming Gao
2020-02-04 14:42 ` PierreGondois
2020-02-05 12:01 ` Bob Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DB7PR08MB3113DCB5AEC807CB472BAA768B030@DB7PR08MB3113.eurprd08.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox