2.2 Build Description File Format
EDK II build description files--DSC, FDF, DEC and INF files, along with other files like build_rules.txt, target.txt and tools_def.txt, contain information used by the parsing utility to create makefiles that process source files to generate binary (PE32/PE32+/Coff) files. The binary files can be distributed as EDK II binary packages or used to create a platform are defined in an FDF file, rather than the EDK II DSC file unless the binary modules included in a platform use PCDs.
2.2.1 Section Entries
To simplify parsing, the EDK II meta-data files continue using the INI format. This style was introduced for EDK meta-data files, when only the Windows tool chains were supported. It was decided that for compatibility purposes, that INI format would continue to be used. EDK II formats differ from the de facto INI format in that the semicolon ";" character cannot be used to indicate a comment.
Leading and trailing space/tab characters must be ignored.
Duplicate section names must be merged by tools.
This description file consists of sections delineated by section tags enclosed
within square []
brackets. Section tag entries are case-insensitive. The
different sections and their usage are described below. The text of a given
section can be used for multiple section names by separating the section names
with a comma. For example:
[LibraryClasses.X64, LibraryClasses.EBC]
The content below each section heading is processed by the parsing utilities in the order that they occur in the file. The precedence for processing these architecture section tags is from right to left, with sections defining an architecture having a higher precedence than a section which uses common (or no architecture extension) as the architecture.
Note: Content, such as filenames, directory names, macros and C variable names, within a section IS case sensitive. IA32, Ia32 and ia32 within a section are processed as separate items. (Refer to Naming Conventions below for more information on directory and/or file naming.)
Sections are terminated by the start of another section or the end of the file.
Comments are not permitted between square brackets of a section specifier.
Duplicate sections (two sections with identical section tags) will be merged by tools, with the second section appended to the first.
If architectural modifiers are used in the section tag, the section is merged by tools with content from common sections (if specified) with the architectural section appended to the first, into an architectural section. For example, given the following:
[BuildOptions]
MSFT:*_*_*_CC_FLAGS = /nologo
[BuildOptions.IA32]
MSFT:*_*_IA32_CC_FLAGS = /D MDEPKG_NDEBUG
[BuildOptions.X64]
MSFT:*_*_X64_CC_FLAGS = /Gy
After the first pass of the tools, when building the module for IA32, the source files will logically be:
[BuildOptions.IA32]
MSFT:*_*_*_CC_FLAGS = /nologo
MSFT:*_*_IA32_CC_FLAGS = /D MDEPKG_NDEBUG
When building the module for X64, the source files will logically be:
[BuildOptions.X64]
MSFT:*_*_*_CC_FLAGS = /nologo
MSFT:*_*_X64_CC_FLAGS = /Gy
The [Defines]
section tag prohibits use of architectural modifiers. All other
sections can specify architectural modifiers.
2.2.2 Comments
The hash "#" character indicates comments in the Platform Description (DSC)
file. In line comments terminate the processing of a line. In line comments
must be placed at the end of the line, and may not be placed within the section
[]
tags.
Only FIX_LOAD_TOP_MEMORY_ADDRESS = 0xF0000000
in the following example is
processed by tools; the remainder of the line is ignored:
FIX_LOAD_TOP_MEMORY_ADDRESS = 0xF0000000 # set top memory address
Note: Blank lines and lines that start with the hash "#" character must be ignored by tools.
Hash characters appearing within a quoted string are permitted, with the string being processed as a single entity. The following example must handle the quoted string as single element by tools.
UI = "# Copyright 2007, NoSuch, ltd. All rights reserved."
2.2.3 Valid Entries
Processing of the line is terminated if a comment is encountered.
Processing of a line is terminated by the end of the line.
Items in quotation marks are treated as a single token and have the highest precedence. Items encapsulated in parenthesis are also treated as tokens, with embedded tokens being processed first. All other processing occurs from left to right.
In the following example, B - C is processed first, then result is added to A followed by adding 2; finally 3 is added to the result.
(A + (B - C) + 2) + 3
In the next example, A + B is processed first, then C + D is processed and finally the two results are added.
(A + B) + (C + D)
Space and tab characters are permitted around field separators.
2.2.4 Naming Conventions
The EDK II build infrastructure is supported under Microsoft Windows, Linux* and MAC OS/X operating systems. All directory and file names must be treated as case sensitive because of multiple environment support.
The use of special characters in directory names and file names is restricted to the dash, underscore, and period characters, respectively "-", "_", and ".".
Period characters may not be followed by another period character. File and Directory names must not start with "./", "." or "..".
Directory names and file names must not contain space characters.
Directory Names must only contain alphanumeric characters, the dash and underscore characters and start with an alpha character. A single period character is permitted in the name provided that alphanumeric characters appear before and after the period character (as in: MdePkg.1).
Additionally, all EDK II directories that are architecturally dependent must use a name with only the first character capitalized. Ia32, X64 and Ebc are valid architectural directory names. IA32, X64 and EBC are not acceptable directory names, and may cause build breaks. From a build tools perspective, IA32 is not equivalent to Ia32 or ia32.
The build tools must be able to process the tool definitions file:
tools_def.txt
(describing the location and flags for compiler and user
defined tools), which may contain space characters in paths on Windows* systems.
Note: The toolsdef.txt file and [BuildOptions]
sections are the
places that permit the use of space characters in a directory path.
The EDK II Coding Style specification covers naming conventions for use within C Code files, and as well as specifying the rules for directory and file names. This section is meant to highlight those rules as they apply to the content of the INF files.
Architecture keywords (IA32
, X64
and EBC
) are used by build tools
and in metadata files for describing alternate threads for processing of files.
These keywords must not be used for describing directory paths. Additionally,
directory names with architectural names (Ia32, X64 and Ebc) do
not automatically cause the build tools or meta-data files to follow these
alternate paths. Directories and Architectural Keywords are similar in name
only.
All directory paths within EDK II INF files must use the "/" forward slash character to separate directories as well as directories from filenames. Example:
C:/Work/Edk2/edksetup.bat
File names must also follow the same naming convention required for directories. No space characters are permitted. The special characters permitted in directory names are the only special characters permitted in file names.
2.2.5 !include Statement Processing
The !include
statement may appear within any section of EDK II DSC file. The
included file content must match the content type of the current section
definition, contain complete sections, or combination of both. And the keyword
!include
is case-insensitive.
The argument of this statement is a filename. The file is relative to the
directory that contains this DSC file, and if not found the tool must attempt
to find the file relative to the paths listed in the system environment
variable $(WORKSPACE)
. If the file is still not found, the parsing tools
must terminate with an error.
Macros, defined in this file, are permitted in the path or file name of the
!include statement, as these files are included prior to processing the file
for macros. The system environment variable $(WORKSPACE)
, may also be used;
only these system environment variables are permitted to start the path of the
included file.
Statements in !include
files must not break the integrity of the DSC file,
the included file is read in by tools in the exact position of the file, and is
functionally equivalent of copying the contents of the included file and
inserting (paste) the content into the DSC file.
The following examples show the valid usage of the !include
statement.
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
!include MyPlatformCommonLibs.txt
[LibraryClasses]
DEFINE MDELIBUAEP = MdePkg/Library/UefiApplicationEntryPoint
UefiApplicationEntryPoint|$(MDELIBUAEP)/UefiApplicationEntryPoint.inf
!include Sample.txt
### Contents of Sample.txt
DEFINE EMULATE = 1
!if $(EMULATE) == 0
[LibraryClasses.IA32]
TimerLib|Some/Existing/TimerLib/Instance.inf
[LibraryClasses.X64]
TimerLib|Another/Existing/TimerLib/Instance.inf
!else
TimerLib|The/NULL/TimerLib/Instance.inf
!endif
2.2.6 Macro Statements
The use of MACRO statements, which assign a value to a variable. Macros defined
in the [Defines]
section are considered global during the processing of the
DSC file and the FDF file. This means that a Macro can be used in the FDF file
without defining it in the FDF as long as it is defined in the DSC file.
Token names (words defined in the EDK II meta-data file specifications) cannot
be used as macro names. As an example, using PLATFORM_NAME as a macro name is
not permitted, as it is a token defined in the DSC file's [Defines]
section.
Macros in the DSC file can be used to specify paths (and paths and filenames), and build options. They can define other items, such as values for PCDs, expressions or names that can be used in conditional directive statements, which allows customization of the build, allowing the platform integrator to select features from the command-line.
The format for the macro statements is:
DEFINE MACRO = Path
Any portion on a path or path and filename can be defined by a macro.
When assigning a string value to a macro, the string must follow the C format for specifying a string, as shown below:
DEFINE MACRO1 = "SETUP"
DEFINE MACRO2 = L"SETUP"
When assigning a numeric value to a macro, the number may be a decimal, integer or hex value, as shown below:
DEFINE MACRO1 = 0xFFFFFFFF
DEFINE MACRO2 = 2.3
DEFINE MACRO3 = 10
The format for usage of a Macro varies. When used as a value, the Macro name must be encapsulated by "$(" and ")" as shown below:
$(MACRO)/filename.foo
When a macro is tested in a conditional directive statement, determining whether it has been define or undefined uses the following format:
!ifdef MACRO
Note: For backward compatibility, tools may allow $(MACRO)
in the
!ifdef
and !ifndef
statements. This functionality may disappear in
future releases, therefore, it is recommended that platform integrators update
their DSC files if they also alter other content.
When using string comparisons of Macro elements to string literals, the format of the conditional directive must be:
!if $(MACRO) == "Literal String"
Note: For backward compatibility, tools may allow testing literal strings that are not encapsulated by double quotation marks. This functionality may disappear in future releases, therefore, it is recommended that platform integrators update their DSC files if they also alter other content.
When testing Macro against another Macro:
!if $(MACROALPHA) == $(MACROBETA)
When testing a Macro against a value:
!if $(MACRONUM) == 2
or
!if $(MACROBOOL) == TRUE
When used with the !if
or !elseif
statements or in an expression used in a
value field, a macro that has not been defined has a value of 0
.
Any defined MACRO definitions will be expanded by tools when they encounter the
entry in the section except when the macro is within double quotation marks in
build options sections. The expectation is that macros in the quoted values
will be expanded by external build scripting tools, such as nmake or gmake;
they will not be expanded by the build tools. If a macro that is not defined is
used in locations that are not expressions (where the tools would just do macro
expansion as in C flags in a [BuildOptions]
section), nothing will be
emitted. If the macro, MACRO1, has not been defined, then:
MSFT:*_*_*_CC_FLAGS = /c /nologo $(MACRO1) /Od
After macro expansion, the logical result would be equal to:
MSFT:*_*_*_CC_FLAGS = /c /nologo /Od
It is recommended that tools remove any excess space characters when processing these types of lines.
Macro evaluation is done at the time the macro is used in an expression,
conditional directive or value field, not when a macro is defined. Macros in
quoted strings will not be expanded by parsing tools; all other macro values
will be expanded, without evaluation, as other elements of the build system
will perform any needed tests. Macro Definition statements that appear within a
section of the file (other than the [Defines]
section) are scoped to the
section they are defined in. If the Macro statement is within the [Defines]
section, then the Macro is considered global to the entire DSC file, files
included using the !include statement and global to the FDF file, with local
definitions taking precedence (if the same MACRO name is redefined in
subsequent sections, then that MACRO value is local to only that section.)
Macros may be used in conditional statements located within the DSC (and FDF)
file. Conditional MACROs may be defined on a command line of a parsing tool. It
is highly recommended that a macro defined in this manner have a DEFINE
statement to set a default value in the [Defines]
section. (Macro values
specified on the command-line override all definitions of that Macro.) In the
reference build (Nt32Pkg/Nt32Pkg.dsc), macros set on a command line override
any macro value defined in the DSC (or FDF) file.
MACROs may also be used as values in PCD statements. See Section 3.10 for more information on PCD statements.
Macros that appear within double quotation marks in build options sections are not expanded. It is assumed that they will be expanded by the OS or external scripting tools.
Global variables that may be used in EDK II DSC and FDF meta-data files are listed in the Well-known Macro Statements table, while the format of the System Environment variables that may be used in EDK II DSC and FDF files are in the next table.
Table 2 Well-known Macro Statements
Exact Notation | Derivation |
---|---|
$(OUTPUT_DIRECTORY) |
Used in FDF [FV] and [Capsule] sections; the value comes from parsing either the DSC file or via a command line option. This is commonly the Build/Platform name directory created by the build system in the EDK II WORKSPACE, however, it is possible to specify the output directory outside of the EDK II WORKSPACE. |
$(TARGET) |
Used in various locations; valid values are derived from INF, DSC, target.txt, tool options and tools_def.txt. FDF parsing tools may obtain these values from command-line options. |
$(TOOL_CHAIN_TAG) |
Used in various locations; valid values are derived from INF, DSC, target.txt, tool options and tools_def.txt. FDF parsing tools may obtain these values from command-line options. |
$(TOOLCHAIN) |
A synonym for $(TOOL_CHAIN_TAG), with the value derived from INF, DSC, target.txt and tools_def.txt. |
This item has been deprecated, and must not be used. | |
$(ARCH) |
Used in various locations, valid values are derived from INF, DSC, target.txt, tool options and tools_def.txt. FDF parsing tools may obtain these values from command-line options. |
System environment variables may be referenced, however their values must not be altered.
Table 3 Using System Environment Variable
Macro Style Used in Meta-Data Files | Matches Windows Environment Variable | Matches Linux & OS/X Environment Variable |
---|---|---|
$(WORKSPACE) | %WORKSPACE% | $WORKSPACE |
$(EDK_TOOLS_PATH) | %EDK_TOOLS_PATH% | $EDK_TOOLS_PATH |
The system environment variables, PACKAGES_PATH and EDK_TOOLS_BIN, are not permitted in EDK II meta-data files.
Macros defined in the DSC file's [Defines]
section may be used within an FDF
file. They are also positional in nature, with later definitions overriding
previous definitions for the remainder of the file.
Additionally, the macros defined in the DSC file may be used in conditional
directive statements located within the DSC and FDF files. Macros in the DSC
file can be used for file names, paths, PCD values, in the [BuildOptions]
section, on the right (value) side of the statements and in conditional
directives. Macros can also be defined or used in the [Defines]
,
[LibraryClasses]
, [Libraries]
, [Components]
and all PCD sections.
Macros defined by the user cannot be used in the !include
statements in
either the DSC or FDF file.
Macros defined in common sections may be used in the architecturally modified sections of the same section type. Macros defined in architectural sections cannot be used in other architectural sections, nor can they be used in the common section. Section modifiers in addition to the architectural modifier follow the same rules as architectural modifiers.
Example
[LibraryClasses.common]
DEFINE MDE = MdePkg/Library
BaseLib|$(MDE)/BaseLib.inf
[LibraryClasses.X64, LibraryClasses.IA32]
# Can use $(MDE), cannot use $(MDEMEM)
DEFINE PERF = PerformancePkg/Library
TimerLib|$(PERF)/DxeTscTimerLib/DxeTscTimerLib.inf
[LibraryClasses.X64.PEIM]
# Can use $(MDE) and $(PERF)
DEFINE MDEMEM = $(MDE)/PeiMemoryAllocationLib
MemoryAllocationLib|$(MDEMEM)/PeiMemoryAllocationLib.inf
[LibraryClasses.EBC]
# Cannot use $(PERF) or $(MDEMEM)
# Can use $(MDE) from the common section
PalLib|$(MDE)/UefiPalLib/UefiPalLib.inf
TimerLib|$(MDE)/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
2.2.7 Conditional Directive Statements (!if...)
Conditional directive statements are used by the build tools preprocessor function to include or exclude statements in the DSC file. A limited number of statements are supported, and nesting of conditionals is also supported. Statements are prefixed by the exclamation "!" character. Conditional statements may appear anywhere within the DSC file.
Note: A limited number of statements are supported. This specification does not support every conditional statement that C programmers are familiar with.
Supported following statements and the keyword are case-insensitive:
!ifdef, !ifndef, !if, !elseif, !else and !endif
Refer to the Macro Statement section for information on using Macros in conditional directives.
When using the !ifdef
or !ifndef
, the macro name can be used; the macro
name must not be encapsulated between $(
and )
. It is the name of the macro
that is used for testing, not the value of the macro.
PCDs must not be used in the !ifdef
or !ifndef
statements.
Note: For backward compatibility, the EDK II build system will also process
the !ifdef
or !ifndef
statements with the macro encapsulated between
"$(" and ")".
When using a marco in the !if
or !elseif
conditionals, the macro name must
be encapsulated between $(
and )
.
A macro that is not defined has a default value of 0
(FALSE
) when used in a
conditional comparison statement.
When using a PCD in the !if
or !elseif
conditionals, the PCD name
(TokenSpaceGuidCName.PcdCname
) can be used; the PCD name must not be
encapsulated between "$(" and ")" nor between "PCD(" and ")". Do not
encapsulate the PCD name in the "$(" and ")" required for macro values as shown
in the example below.
!if ( gTokenSpaceGuid.PcdCname == 1 ) AND ( $(MY_MACRO) == TRUE )
DEFINE FOO=TRUE
!endif
If the PCD is a string, only the string needs to be encapsulated by double quotation marks, while a Unicode string can have the double quoted string prefixed by "L", as in the following example:
!if gTokenSpaceGuid.PcdCname == L"Setup"
DEFINE FOO=TRUE
!endif
If a PCD is used in a conditional statement, the value must first come from the FDF file, then from the DSC file. If the value cannot be determined from these two locations, the build system should break with an error message.
Note: PCDs, used in conditional directives, must be defined and the value set in either the FDF or DSC file in order to be used in a conditional statement; values from INF or DEC files are not permitted.
When used in !if
and !elseif
conditional comparison statements, it is the
value of the Macro or the PCD that is used for testing, not the name of the
macro or PCD.
Strings can only be compared to strings of a like type (testing an ASCII string
against a Unicode format string must fail), numbers can only be compared
against numbers and boolean objects can only evaluate to TRUE
or FALSE
. See
the Operator Precedence table, in the Expressions section below for a list of
restrictions on comparisons.
Using macros in conditional directives that contain flags for use in the
[BuildOptions]
sections is not recommended.
The following external macro names can be used in conditional directives without defining them in DSC or FDF files.
Table 4 Well-known Macro Statements
Tag | Value | Notes |
---|---|---|
$(FAMILY) |
Tool Chain Family | The value must be a string comparison against a FAMILY value that is defined in the Conf/ tools_def.txt file |
$(TARGET) |
Build Target | The value must be a string comparison against a TARGET value that is defined in the Conf/ tools_def.txt file |
$(TOOL_CHAIN_TAG) |
Tool Chain Name | The value must be a string comparison against a tool chain tag name value that is defined in the Conf/tools_def.txt file. |
$(ARCH) |
Architecture | The value must be a string comparison against an architecture that is defined in the Conf/ tools_def.txt file. |
The macro values listed above are derived from the build command-line options
(highest priority) or the Conf/target.txt
file. They may be combined in
directive statements using logical expressions.
Most section definitions in the EDK II meta-data files have architecture modifiers. Use of architectural modifiers in the section tag is the recommended method for specifying architectural differences. Some sections do not have architectural modifiers and there are some unique cases where having a method for specifying architectural specific items would be valuable, hence the ability to use these values.
The following are examples of conditional directives.
!if ("MSFT" IN $(FAMILY)) or ("INTEL" IN $(FAMILY))
... statements
!elseif $(FAMILY) == "GCC"
... statements
!endif
!ifdef FOO
!ifndef BAR
# FOO defined, BAR not defined
!else
# FOO defined, BAR is defined
!endif
!elseif $(BARFOO)
# FOO is not defined, BARFOO evaluates to TRUE
!elseif $(BARFOO) == $(FOOBAR)
# FOO is not defined, BARFOO equals the value of FOOBAR
# (in this case, FALSE)
!else
# FOO is not defined while BARFOO evaluates to FALSE and FOOBAR
# evaluates to TRUE
!endif
!if $(FOO) == 2
# The numeric value of FOO was defined as 2, as in DEFINE FOO = 2
!endif
!if MyTspGUID.MyPcd == 2
# The value of PCD, MyTspGUID.MyPcd, is 2
!endif
!if $(FOO) == "MyPlatformName"
# This is a string comparison, where the MACRO FOO was set using:
# DEFINE FOO = "MyPlatformName"
!endif
!if MyTspGUID.MyTspGUID == "MyPlatform"
# This is a string comparison where PCD VOID* value is "MyPlatform",
# and must be a null terminated string.
!else
# The strings do not match exactly
!endif
2.2.8 !error Statement
The !error
statement may appear within any section of EDK II DSC file. The
argument of this statement is an error message, it causes build tool to stop
at the location where the statement is encountered and error message following
the !error
statement is output as a message. The keyword !error
is not
case-sensitive.
The following example show the valid usage of the !error
statement.
!if $(FEATURE_ENABLE) == TRUE
!error "unsupported feature!"
!endif
2.2.9 Expressions
Expressions can be used in conditional directive comparison statements and in value fields for Macros and PCDs in the DSC and FDF files.
Refer to the EDK II Expression Syntax Specification for additional information.
Note: Note that the data types are not required to be literal numbers, but rather they can be a Macro or a PCD whose value is a number or a boolean. The same rule applies for strings, where the value of the Macro or a VOID* PCD can be tested as a string.
Table 5 Operator Precedence and Supported Operands
Operator | Use with Data Types | Notes | Priority |
---|---|---|---|
? : |
All | conditional operator | Lowest |
or , OR , || |
Number, Boolean | ||
XOR , xor |
Number, Boolean | ||
and , AND , && |
Number, Boolean | ||
| |
Number, Boolean | Bitwise OR | |
^ |
Number, Boolean | Bitwise XOR | |
& |
Number, Boolean | Bitwise AND | |
== , != , EQ , NE , IN |
All types | The IN operator can only be used to test a quoted unary literal string for membership in a list. | |
Strings compared to boolean or numeric values using "==" or "EQ" will always return FALSE, while using the "!=" or "NE" operators will always return TRUE | |||
<= , >= , < , > , LE , GE , LT , GT |
All | ||
<< , >> |
Number, Boolean | ||
+ , - |
Number, Boolean | Cannot be used with strings - the system does not automatically do concatenation. | |
* , / , % , |
Number, Boolean | Cannot be used with strings. | |
! , not , NOT , ~ |
Number, Boolean | Highest |
The "IN" operator can only be used to test a literal string against elements in the following global variables:
$(FAMILY)
$(FAMILY)
is considered a list of families that different TOOL_CHAIN_TAG
values belong to. The TOOL_CHAIN_TAG
is defined in the Conf/target.txt
or
on the command-line. The FAMILY
is associated with the TOOL_CHAIN_TAG
in
the Conf/tools_def.txt
file (or the TOOLS_DEF_CONF
file specified in the
Conf/target.txt
file) file. While different family names can be defined,
ARMGCC, GCC, INTEL, MSFT, RVCT, RVCTCYGWIN and XCODE have been predefined in
the tools_def.txt
file.
$(ARCH)
$(ARCH)
is considered the list of architectures that are to be built, that
were specified on the command line or come from the Conf/target.txt
file.
$(TOOL_CHAIN_TAG)
$(TOOL_CHAIN_TAG)
is considered the list of tool chain tag names specified on
the command line
$(TARGET)
$(TARGET)
is considered the list of target (such as DEBUG, RELEASE and NOOPT)
names specified on the command line or come from the Conf/target.txt
file.
For logical expressions, any non-zero value must be considered TRUE
.
Invalid expressions must cause a build break with an appropriate error message.
2.2.10 Section Handling
The DSC file parsing routines must process the sections so that common architecture sections are logically merged with the architecturally specific sections. The architectural sections need to be processed so that they are logically after the common section. It is recommended that EDK II developers use a logical ordering of the sections.
Other section modifiers must also be logically appended to the merged sections (for DSC files that have architectural and common architecture sections) after the merge.
For [BuildOptions]
sections in the DSC file, the entries with a common left
side (of the "=") will be either appended or replace previous entries based
on the "==" replace or "=" append assignment character sequence.
Common Section + Architectural Section + Common Section w/extra Modifier
+ Architectural Section w/extra Modifier
Example:
[BuildOptions.Common]
MSFT:*_*_*_CC_FLAGS = /nologo
[BuildOptions.IA32]
MSFT:*_*_IA32_CC_FLAGS = /D EFI32
For IA32 architecture builds of an EDK II INF file would logically be:
MSFT:*_*_IA32_CC_FLAGS = /nologo /D EFI32