summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2010-11-26 01:54:49 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2010-11-26 01:54:49 +0000
commit3e99020dbf0a159e34b84e7ae9125f2e368d5390 (patch)
tree0eb6339318f7bf7da1b679b8009cf267b2234566 /EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc
parent68bb5ce77e51cf35791e46f2202e36da97e5e6be (diff)
downloadedk2-platforms-3e99020dbf0a159e34b84e7ae9125f2e368d5390.tar.xz
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11094 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc')
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c80
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile27
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.c905
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.h116
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c326
5 files changed, 1321 insertions, 133 deletions
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c
index 3e60b0344b..5181373a54 100644
--- a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c
@@ -1,6 +1,6 @@
/*++
-Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -35,18 +35,7 @@ Abstract:
#define EFI_BASE_ADDRESS "EFI_BASE_ADDRESS"
#define DEFAULT_FV_INF_DIR "FV" // default dir for where we create the FV INF file
#define DEFAULT_FV_DIR "$(BUILD_DIR)" // where the FV file comes from
-#define MALLOC(size) malloc (size)
-#define FREE(ptr) free (ptr)
-//
-// Disable warning for unused function arguments
-//
-#pragma warning(disable : 4100)
-//
-// Disable warning for while(1) code
-//
-// #pragma warning (disable : 4127)
-//
typedef struct {
char *ComponentType;
char *Extension;
@@ -196,8 +185,7 @@ static
void
AddFirmwareVolumes (
char *FVs,
- int ComponentsInstance,
- FILE_LIST *FileListPtr
+ int ComponentsInstance
);
static
@@ -503,7 +491,7 @@ Returns:
// Add these firmware volumes to the list of known firmware
// volume names.
//
- AddFirmwareVolumes (FVs, ComponentsInstance, Ptr);
+ AddFirmwareVolumes (FVs, ComponentsInstance);
return STATUS_SUCCESS;
}
@@ -528,7 +516,7 @@ CFVDestructor (
//
while (mFVList != NULL) {
mFVListLast = mFVList->Next;
- FREE (mFVList);
+ free (mFVList);
mFVList = mFVListLast;
}
}
@@ -957,10 +945,10 @@ Returns:
//
// Now go through the list of all NonFFS FVs they specified and search for
// a [build.fv.$(FV)] or [build.fv] command and emit the commands to the
- // output makefile. Add them to the "fvs" target as well.
+ // output makefile. Add them to the "fvs_0" target as well.
//
if (mNonFfsFVList != NULL) {
- fprintf (MakeFptr, "fvs ::");
+ fprintf (MakeFptr, "fvs_0 ::");
FVPtr = mNonFfsFVList;
while (FVPtr != NULL) {
fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);
@@ -1022,43 +1010,40 @@ Returns:
DSCFileRestorePosition (DSC);
}
}
+
//
- // Go through our list of firmware volumes and create an "fvs" target that
- // builds everything. It has to be a mix of components and FV's in order.
- // For example: fvs : components_0 fv\fv001.fv fv\fv002.fv components_1 fv\fv003.fv
+ // Get the components count
//
- ComponentsInstance = 0;
- ComponentCount = 0;
- fprintf (MakeFptr, "fvs ::");
- for (;;) {
- //
- // First see if we have any components for this section. If we don't,
- // then we're done
- //
- for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {
- if (FileListPtr->ComponentsInstance == ComponentsInstance) {
- break;
- }
- }
-
- if (FileListPtr == NULL) {
- break;
+ ComponentCount = -1;
+ for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {
+ if (FileListPtr->ComponentsInstance > ComponentCount) {
+ ComponentCount = FileListPtr->ComponentsInstance;
}
+ }
+ ComponentCount++;
- fprintf (MakeFptr, " components_%d", ComponentsInstance);
- ComponentCount++;
- //
- // Now print any firmware volumes that match this components instance
- //
+ //
+ // Now print firmware volumes build targets fvs_0, fvs_1 etc.
+ //
+ for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) {
+ fprintf (MakeFptr, "fvs_%d ::", ComponentsInstance);
for (FVPtr = mFVList; FVPtr != NULL; FVPtr = FVPtr->Next) {
if (FVPtr->ComponentsInstance == ComponentsInstance) {
fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);
}
}
-
- ComponentsInstance++;
+ fprintf (MakeFptr, "\n\n");
+ }
+
+ //
+ // Create an "fvs" target that builds everything. It has to be a mix of
+ // components and FV's in order. For example:
+ // fvs :: components_0 fvs_0 components_1 fvs_1
+ //
+ fprintf (MakeFptr, "fvs ::");
+ for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) {
+ fprintf (MakeFptr, " components_%d fvs_%d", ComponentsInstance, ComponentsInstance);
}
-
fprintf (MakeFptr, "\n\n");
//
@@ -1351,8 +1336,7 @@ static
void
AddFirmwareVolumes (
char *FVs,
- int ComponentsInstance,
- FILE_LIST *FileListPtr
+ int ComponentsInstance
)
{
FV_LIST *FvPtr;
@@ -1386,7 +1370,7 @@ AddFirmwareVolumes (
// If we didn't find a match, then create a new one
//
if (FvPtr == NULL) {
- FvPtr = MALLOC (sizeof (FV_LIST));
+ FvPtr = malloc (sizeof (FV_LIST));
if (FvPtr == NULL) {
Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed");
return ;
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile
index 417951cf59..e2a4b5f06b 100644
--- a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile
@@ -1,6 +1,6 @@
#/*++
#
-# Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
@@ -49,25 +49,31 @@ TARGET_EXE = $(EDK_TOOLS_OUTPUT)\ProcessDsc.exe
all: $(TARGET_EXE)
-INC_DEPS = $(TARGET_SRC_DIR)\DSCFile.h $(INC_DEPS)
-INC_DEPS = $(TARGET_SRC_DIR)\FWVolume.h $(INC_DEPS)
-INC_DEPS = $(TARGET_SRC_DIR)\Exceptions.h $(INC_DEPS)
-INC_DEPS = $(TARGET_SRC_DIR)\Common.h $(INC_DEPS)
+INC_DEPS = $(TARGET_SRC_DIR)\DSCFile.h $(INC_DEPS)
+INC_DEPS = $(TARGET_SRC_DIR)\MultiThread.h $(INC_DEPS)
+INC_DEPS = $(TARGET_SRC_DIR)\FWVolume.h $(INC_DEPS)
+INC_DEPS = $(TARGET_SRC_DIR)\Exceptions.h $(INC_DEPS)
+INC_DEPS = $(TARGET_SRC_DIR)\Common.h $(INC_DEPS)
LIBS = $(LIBS) "$(EDK_TOOLS_OUTPUT)\Common.lib"
-OBJECTS = $(EDK_TOOLS_OUTPUT)\DSCFile.obj \
- $(EDK_TOOLS_OUTPUT)\FWVolume.obj \
- $(EDK_TOOLS_OUTPUT)\ProcessDsc.obj \
+OBJECTS = $(EDK_TOOLS_OUTPUT)\DSCFile.obj \
+ $(EDK_TOOLS_OUTPUT)\MultiThread.obj \
+ $(EDK_TOOLS_OUTPUT)\FWVolume.obj \
+ $(EDK_TOOLS_OUTPUT)\ProcessDsc.obj \
$(EDK_TOOLS_OUTPUT)\Exceptions.obj
#
# Compile each source file
#
+C_FLAGS = $(C_FLAGS) /MT /wd4201
$(EDK_TOOLS_OUTPUT)\DSCFile.obj : $(TARGET_SRC_DIR)\DSCFile.c $(INC_DEPS)
$(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\DSCFile.c /Fo$@
+$(EDK_TOOLS_OUTPUT)\MultiThread.obj : $(TARGET_SRC_DIR)\MultiThread.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\MultiThread.c /Fo$@
+
$(EDK_TOOLS_OUTPUT)\FWVolume.obj : $(TARGET_SRC_DIR)\FWVolume.c $(INC_DEPS)
$(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\FWVolume.c /Fo$@
@@ -88,7 +94,9 @@ $(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe
copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y
!ELSE
$(TARGET_EXE) : $(OBJECTS) $(LIBS)
- $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) shlwapi.lib \
+ /NODEFAULTLIB:libc.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcd.lib \
+ /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib
!IF ("$(EFI_BINARY_BUILD)" == "YES")
if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools
if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y
@@ -100,5 +108,6 @@ $(TARGET_EXE) : $(OBJECTS) $(LIBS)
clean:
@if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
@if exist $(EDK_TOOLS_OUTPUT)\DscFile.* del $(EDK_TOOLS_OUTPUT)\DscFile.* > NUL
+ @if exist $(EDK_TOOLS_OUTPUT)\MultiThread.* del $(EDK_TOOLS_OUTPUT)\MultiThread.* > NUL
@if exist $(EDK_TOOLS_OUTPUT)\Exceptions* del $(EDK_TOOLS_OUTPUT)\Exceptions.* > NUL
@if exist $(EDK_TOOLS_OUTPUT)\FwVolume.* del $(EDK_TOOLS_OUTPUT)\FwVolume.* > NUL
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.c
new file mode 100644
index 0000000000..b6a72eca78
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.c
@@ -0,0 +1,905 @@
+/*++
+
+Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MultiThread.c
+
+Abstract:
+
+ This module is used to add multi-thread build support to ProcessDsc utility
+ to improve the build performance.
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <direct.h>
+#include "Common.h"
+#include "MultiThread.h"
+
+BUILD_ITEM *
+AddBuildItem (
+ BUILD_ITEM **BuildList,
+ INT8 *BaseName,
+ INT8 *Processor,
+ INT8 *Makefile
+ )
+/*++
+
+Routine Description:
+
+ Add a build item to a specified build list
+
+Arguments:
+
+ BuildList - build list where the new build item will be added
+ BaseName - base name of the new module
+ Processor - processor type of the new module
+ Makefile - makefile name of the new module
+
+Returns:
+
+ Pointer to the newly added build item
+
+--*/
+{
+ BUILD_ITEM *NewBuildItem;
+
+ //
+ // Create a new build item
+ //
+ NewBuildItem = malloc (sizeof (BUILD_ITEM));
+ if (NewBuildItem == NULL) {
+ return NULL;
+ }
+ memset (NewBuildItem, 0, sizeof (BUILD_ITEM));
+ NewBuildItem->BaseName = _strdup (BaseName);
+ NewBuildItem->Processor = _strdup (Processor);
+ NewBuildItem->Makefile = _strdup (Makefile);
+
+ //
+ // Add the build item to the head of the build list
+ //
+ NewBuildItem->Next = *BuildList;
+ *BuildList = NewBuildItem;
+
+ return NewBuildItem;
+}
+
+SOURCE_FILE_ITEM *
+AddSourceFile (
+ BUILD_ITEM *BuildItem,
+ INT8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ Add a source file for a build item
+
+Arguments:
+
+ BuildItem - build item to add the source file
+ FileName - source file name to be added
+
+Returns:
+
+ Pointer to the newly added source file item
+
+--*/
+{
+ SOURCE_FILE_ITEM *NewSourceFile;
+
+ //
+ // Create a new source file item
+ //
+ NewSourceFile = malloc (sizeof (SOURCE_FILE_ITEM));
+ if (NewSourceFile == NULL) {
+ return NULL;
+ }
+ memset (NewSourceFile, 0, sizeof (SOURCE_FILE_ITEM));
+ NewSourceFile->FileName = _strdup (FileName);
+
+ //
+ // Add the source file item to the head of the source file list
+ //
+ NewSourceFile->Next = BuildItem->SourceFileList;
+ BuildItem->SourceFileList = NewSourceFile;
+
+ return NewSourceFile;
+}
+
+DEPENDENCY_ITEM *
+AddDependency (
+ BUILD_ITEM *BuildList,
+ BUILD_ITEM *BuildItem,
+ INT8 *BaseName,
+ INT8 AdjustIndex
+ )
+/*++
+
+Routine Description:
+
+ Add a build dependency for a build item in the specified build list
+
+Arguments:
+
+ BuildList - build list where to search the dependency
+ BuildItem - build item to add the dependency
+ BaseName - dependency module base name
+ AdjustIndex - Adjust BuildItem->Index when non-zero
+
+Returns:
+
+ Pointer to the newly added build dependency
+
+--*/
+{
+ BUILD_ITEM *TempBuildItem;
+ DEPENDENCY_ITEM *NewDependency;
+
+ //
+ // Search the dependency in the build list
+ //
+ TempBuildItem = BuildList;
+ while (TempBuildItem != NULL) {
+ if ((_stricmp (TempBuildItem->BaseName, BaseName) == 0) &&
+ (_stricmp (TempBuildItem->Processor, BuildItem->Processor) == 0) &&
+ (TempBuildItem != BuildItem)) {
+ break;
+ }
+ TempBuildItem = TempBuildItem->Next;
+ }
+ if (TempBuildItem == NULL) {
+ return NULL;
+ }
+
+ //
+ // This index is used to isolate two modules with same base name and processor.
+ // (ProcessDsc allows duplicate base name libraries.)
+ //
+ if (AdjustIndex) {
+ BuildItem->Index = TempBuildItem->Index + 1;
+ }
+
+ //
+ // Create a new build dependency item
+ //
+ NewDependency = malloc (sizeof (DEPENDENCY_ITEM));
+ if (NewDependency == NULL) {
+ return NULL;
+ }
+ memset (NewDependency, 0, sizeof (DEPENDENCY_ITEM));
+ NewDependency->Dependency = TempBuildItem;
+
+ //
+ // Add the build dependency item to the head of the dependency list
+ //
+ NewDependency->Next = BuildItem->DependencyList;
+ BuildItem->DependencyList = NewDependency;
+
+ return NewDependency;
+}
+
+void
+FreeBuildList (
+ BUILD_ITEM *BuildList
+ )
+/*++
+
+Routine Description:
+
+ Free a build list
+
+Arguments:
+
+ BuildList - build list to be freed
+
+Returns:
+
+--*/
+{
+ BUILD_ITEM *TempBuildItem;
+ BUILD_ITEM *FreeBuildItem;
+ SOURCE_FILE_ITEM *TempSourceFile;
+ SOURCE_FILE_ITEM *FreeSourceFile;
+ DEPENDENCY_ITEM *TempDependency;
+ DEPENDENCY_ITEM *FreeDependency;
+
+ TempBuildItem = BuildList;
+ while (TempBuildItem != NULL) {
+ free (TempBuildItem->BaseName);
+ free (TempBuildItem->Processor);
+ free (TempBuildItem->Makefile);
+
+ //
+ // Free source file list
+ //
+ TempSourceFile = TempBuildItem->SourceFileList;
+ while (TempSourceFile != NULL) {
+ FreeSourceFile = TempSourceFile;
+ TempSourceFile = TempSourceFile->Next;
+ free (FreeSourceFile);
+ }
+
+ //
+ // Free dependency list
+ //
+ TempDependency = TempBuildItem->DependencyList;
+ while (TempDependency != NULL) {
+ FreeDependency = TempDependency;
+ TempDependency = TempDependency->Next;
+ free (FreeDependency);
+ }
+
+ FreeBuildItem = TempBuildItem;
+ TempBuildItem = TempBuildItem->Next;
+ free (FreeBuildItem);
+ }
+}
+
+COMPONENTS_ITEM *
+AddComponentsItem (
+ COMPONENTS_ITEM **ComponentsList
+ )
+/*++
+
+Routine Description:
+
+ Add a new components item to a specified components list
+
+Arguments:
+
+ ComponentsList - components list where the new components item will be added
+
+Returns:
+
+ Pointer to the newly added components item
+
+--*/
+{
+ COMPONENTS_ITEM *NewComponents;
+ COMPONENTS_ITEM *TempComponents;
+
+ //
+ // Create a new components item
+ //
+ NewComponents = malloc (sizeof (COMPONENTS_ITEM));
+ if (NewComponents == NULL) {
+ return NULL;
+ }
+ memset (NewComponents, 0, sizeof (COMPONENTS_ITEM));
+
+ //
+ // Add the components item to the tail of the components list
+ //
+ TempComponents = *ComponentsList;
+ if (TempComponents == NULL) {
+ *ComponentsList = NewComponents;
+ } else {
+ while (TempComponents->Next != NULL) {
+ TempComponents = TempComponents->Next;
+ }
+ TempComponents->Next = NewComponents;
+ }
+
+ return NewComponents;
+}
+
+void
+FreeComponentsList (
+ COMPONENTS_ITEM *ComponentsList
+ )
+/*++
+
+Routine Description:
+
+ Free a components list
+
+Arguments:
+
+ ComponentsList - components list to be freed
+
+Returns:
+
+--*/
+{
+ COMPONENTS_ITEM *TempComponents;
+ COMPONENTS_ITEM *FreeComponents;
+
+ TempComponents = ComponentsList;
+ while (TempComponents != NULL) {
+ FreeBuildList (TempComponents->BuildList);
+ FreeComponents = TempComponents;
+ TempComponents = TempComponents->Next;
+ free (FreeComponents);
+ }
+}
+
+//
+// Module globals for multi-thread build
+//
+static INT8 mError; // non-zero means error occurred
+static INT8 mDone; // non-zero means no more build items available for build
+static UINT32 mThreadNumber; // thread number
+static INT8 *mBuildDir; // build directory
+static INT8 mLogDir[MAX_PATH]; // build item log dir
+static CRITICAL_SECTION mCriticalSection; // critical section object
+static HANDLE mSemaphoreHandle; // semaphore for "ready for build" items in mWaitingList
+static HANDLE mEventHandle; // event signaled when one build item is finished
+static BUILD_ITEM *mPendingList; // build list for build items which are not ready for build
+static BUILD_ITEM *mWaitingList; // build list for build items which are ready for build
+static BUILD_ITEM *mBuildingList; // build list for build items which are buiding
+static BUILD_ITEM *mDoneList; // build list for build items which already finish the build
+
+//
+// Restore the BuildList (not care about the sequence of the build items)
+//
+static void
+RestoreBuildList (
+ BUILD_ITEM **BuildList
+ )
+{
+ BUILD_ITEM *TempBuildItem;
+
+ if (mPendingList != NULL) {
+ //
+ // Add the mPendingList to the header of *BuildList
+ //
+ TempBuildItem = mPendingList;
+ while (TempBuildItem->Next != NULL) {
+ TempBuildItem = TempBuildItem->Next;
+ }
+ TempBuildItem->Next = *BuildList;
+ *BuildList = mPendingList;
+ }
+
+ if (mWaitingList != NULL) {
+ //
+ // Add the mWaitingList to the header of *BuildList
+ //
+ TempBuildItem = mWaitingList;
+ while (TempBuildItem->Next != NULL) {
+ TempBuildItem = TempBuildItem->Next;
+ }
+ TempBuildItem->Next = *BuildList;
+ *BuildList = mWaitingList;
+ }
+
+ if (mBuildingList != NULL) {
+ //
+ // Add the mBuildingList to the header of *BuildList
+ //
+ TempBuildItem = mBuildingList;
+ while (TempBuildItem->Next != NULL) {
+ TempBuildItem = TempBuildItem->Next;
+ }
+ TempBuildItem->Next = *BuildList;
+ *BuildList = mBuildingList;
+ }
+
+ if (mDoneList != NULL) {
+ //
+ // Add the mDoneList to the header of *BuildList
+ //
+ TempBuildItem = mDoneList;
+ while (TempBuildItem->Next != NULL) {
+ TempBuildItem = TempBuildItem->Next;
+ }
+ TempBuildItem->Next = *BuildList;
+ *BuildList = mDoneList;
+ }
+}
+
+//
+// Return non-zero when no source file build conflict
+//
+static INT8
+CheckSourceFile (
+ SOURCE_FILE_ITEM *SourceFileList
+ )
+{
+ BUILD_ITEM *TempBuildItem;
+ SOURCE_FILE_ITEM *TempSourceFile;
+
+ while (SourceFileList != NULL) {
+ TempBuildItem = mBuildingList;
+ while (TempBuildItem != NULL) {
+ TempSourceFile = TempBuildItem->SourceFileList;
+ while (TempSourceFile != NULL) {
+ if (_stricmp (SourceFileList->FileName, TempSourceFile->FileName) == 0) {
+ return 0;
+ }
+ TempSourceFile = TempSourceFile->Next;
+ }
+ TempBuildItem = TempBuildItem->Next;
+ }
+ SourceFileList = SourceFileList->Next;
+ }
+
+ return 1;
+}
+
+//
+// Return non-zero when all the dependency build items has been built
+//
+static INT8
+CheckDependency (
+ DEPENDENCY_ITEM *DependencyList
+ )
+{
+ while (DependencyList != NULL) {
+ if (!(DependencyList->Dependency->CompleteFlag)) {
+ return 0;
+ }
+ DependencyList = DependencyList->Next;
+ }
+
+ return 1;
+}
+
+//
+// Run the build task. The system() function call will cause stdout conflict
+// in multi-thread envroment, so implement this through CreateProcess().
+//
+static INT8
+RunBuildTask (
+ INT8 *WorkingDir,
+ INT8 *LogFile,
+ INT8 *BuildCmd
+ )
+{
+ HANDLE FileHandle;
+ SECURITY_ATTRIBUTES SecAttr;
+ PROCESS_INFORMATION ProcInfo;
+ STARTUPINFO StartInfo;
+ BOOL FuncRetn;
+ DWORD ExitCode;
+
+ //
+ // Init SecAttr
+ //
+ SecAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
+ SecAttr.bInheritHandle = TRUE;
+ SecAttr.lpSecurityDescriptor = NULL;
+
+ //
+ // Create the log file
+ //
+ FileHandle = CreateFile (
+ LogFile, // file to create
+ GENERIC_WRITE, // open for writing
+ 0, // do not share
+ &SecAttr, // can be inherited by child processes
+ CREATE_ALWAYS, // overwrite existing
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL // no attr. template
+ );
+
+ if (FileHandle == INVALID_HANDLE_VALUE) {
+ EnterCriticalSection (&mCriticalSection);
+ Error (NULL, 0, 0, NULL, "could not open file %s", LogFile);
+ LeaveCriticalSection (&mCriticalSection);
+ return 1;
+ }
+
+ //
+ // Init ProcInfo and StartInfo
+ //
+ ZeroMemory (&ProcInfo, sizeof (PROCESS_INFORMATION));
+ ZeroMemory (&StartInfo, sizeof (STARTUPINFO));
+ StartInfo.cb = sizeof (STARTUPINFO);
+ StartInfo.hStdError = FileHandle;
+ StartInfo.hStdOutput = FileHandle;
+ StartInfo.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
+ StartInfo.dwFlags = STARTF_USESTDHANDLES;
+
+ //
+ // Create the child process
+ //
+ FuncRetn = CreateProcess (
+ NULL, // no application name
+ BuildCmd, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ WorkingDir, // set current directory
+ &StartInfo, // STARTUPINFO pointer
+ &ProcInfo // receives PROCESS_INFORMATION
+ );
+
+ if (FuncRetn == FALSE) {
+ EnterCriticalSection (&mCriticalSection);
+ Error (NULL, 0, 0, NULL, "could not create child process");
+ LeaveCriticalSection (&mCriticalSection);
+ CloseHandle (FileHandle);
+ return 1;
+ }
+
+ //
+ // Wait until child process exits
+ //
+ WaitForSingleObject (ProcInfo.hProcess, INFINITE);
+ GetExitCodeProcess (ProcInfo.hProcess, &ExitCode);
+ CloseHandle (ProcInfo.hProcess);
+ CloseHandle (ProcInfo.hThread);
+ CloseHandle (FileHandle);
+
+ if (ExitCode != 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+//
+// Thread function
+//
+static DWORD WINAPI
+ThreadProc (
+ LPVOID lpParam
+ )
+{
+ UINT32 ThreadId;
+ BUILD_ITEM *PreviousBuildItem;
+ BUILD_ITEM *CurrentBuildItem;
+ BUILD_ITEM *NextBuildItem;
+ INT8 WorkingDir[MAX_PATH];
+ INT8 LogFile[MAX_PATH];
+ INT8 BuildCmd[MAX_PATH];
+
+ ThreadId = (UINT32)lpParam;
+ //
+ // Loop until error occurred or no more build items available for build
+ //
+ for (;;) {
+ WaitForSingleObject (mSemaphoreHandle, INFINITE);
+ if (mError || mDone) {
+ return 0;
+ }
+
+ //
+ // When code runs here, there must have one build item available for this
+ // thread. Loop until error occurred or get one build item for build.
+ //
+ for (;;) {
+ EnterCriticalSection (&mCriticalSection);
+ PreviousBuildItem = NULL;
+ CurrentBuildItem = mWaitingList;
+ while (CurrentBuildItem != NULL) {
+ NextBuildItem = CurrentBuildItem->Next;
+ //
+ // CheckSourceFile() is to avoid concurrently build the same source file
+ // which may cause the muti-thread build failure
+ //
+ if (CheckSourceFile (CurrentBuildItem->SourceFileList)) {
+ //
+ // Move the current build item from mWaitingList
+ //
+ if (PreviousBuildItem != NULL) {
+ PreviousBuildItem->Next = NextBuildItem;
+ } else {
+ mWaitingList = NextBuildItem;
+ }
+ //
+ // Add the current build item to the head of mBuildingList
+ //
+ CurrentBuildItem->Next = mBuildingList;
+ mBuildingList = CurrentBuildItem;
+ //
+ // If no more build items is pending or waiting for build,
+ // wake up every child thread for exit.
+ //
+ if ((mPendingList == NULL) && (mWaitingList == NULL)) {
+ mDone = 1;
+ //
+ // Make sure to wake up every child thread for exit
+ //
+ ReleaseSemaphore (mSemaphoreHandle, mThreadNumber, NULL);
+ }
+ break;
+ }
+ PreviousBuildItem = CurrentBuildItem;
+ CurrentBuildItem = NextBuildItem;
+ }
+ if (CurrentBuildItem != NULL) {
+ //
+ // Display build item info
+ //
+ printf ("\t[Thread_%d] nmake -nologo -f %s all\n", ThreadId, CurrentBuildItem->Makefile);
+ //
+ // Prepare build task
+ //
+ sprintf (WorkingDir, "%s\\%s", mBuildDir, CurrentBuildItem->Processor);
+ sprintf (LogFile, "%s\\%s_%s_%d.txt", mLogDir, CurrentBuildItem->BaseName,
+ CurrentBuildItem->Processor, CurrentBuildItem->Index);
+ sprintf (BuildCmd, "nmake -nologo -f %s all", CurrentBuildItem->Makefile);
+ LeaveCriticalSection (&mCriticalSection);
+ break;
+ } else {
+ LeaveCriticalSection (&mCriticalSection);
+ //
+ // All the build items in mWaitingList have source file conflict with
+ // mBuildingList. This rarely hapeens. Need wait for the build items in
+ // mBuildingList to be finished by other child threads.
+ //
+ Sleep (1000);
+ if (mError) {
+ return 0;
+ }
+ }
+ }
+
+ //
+ // Start to build the CurrentBuildItem
+ //
+ if (RunBuildTask (WorkingDir, LogFile, BuildCmd)) {
+ //
+ // Build failure
+ //
+ mError = 1;
+ //
+ // Make sure to wake up every child thread for exit
+ //
+ ReleaseSemaphore (mSemaphoreHandle, mThreadNumber, NULL);
+ SetEvent(mEventHandle);
+
+ return mError;
+ } else {
+ //
+ // Build success
+ //
+ CurrentBuildItem->CompleteFlag = 1;
+
+ EnterCriticalSection (&mCriticalSection);
+ //
+ // Move this build item from mBuildingList
+ //
+ if (mBuildingList == CurrentBuildItem) {
+ mBuildingList = mBuildingList->Next;
+ } else {
+ NextBuildItem = mBuildingList;
+ while (NextBuildItem->Next != CurrentBuildItem) {
+ NextBuildItem = NextBuildItem->Next;
+ }
+ NextBuildItem->Next = CurrentBuildItem->Next;
+ }
+ //
+ // Add this build item to mDoneList
+ //
+ CurrentBuildItem->Next = mDoneList;
+ mDoneList = CurrentBuildItem;
+ LeaveCriticalSection (&mCriticalSection);
+
+ SetEvent(mEventHandle);
+ }
+ }
+}
+
+INT8
+StartMultiThreadBuild (
+ BUILD_ITEM **BuildList,
+ UINT32 ThreadNumber,
+ INT8 *BuildDir
+ )
+/*++
+
+Routine Description:
+
+ Start multi-thread build for a specified build list
+
+Arguments:
+
+ BuildList - build list for multi-thread build
+ ThreadNumber - thread number for multi-thread build
+ BuildDir - build dir
+
+Returns:
+
+ 0 - Successfully finished the multi-thread build
+ other value - Build failure
+
+--*/
+{
+ UINT32 Index;
+ UINT32 Count;
+ BUILD_ITEM *PreviousBuildItem;
+ BUILD_ITEM *CurrentBuildItem;
+ BUILD_ITEM *NextBuildItem;
+ HANDLE *ThreadHandle;
+ INT8 Cmd[MAX_PATH];
+
+ mError = 0;
+ mDone = 0;
+ mThreadNumber = ThreadNumber;
+ mBuildDir = BuildDir;
+ mPendingList = *BuildList;
+ *BuildList = NULL;
+ mWaitingList = NULL;
+ mBuildingList = NULL;
+ mDoneList = NULL;
+
+ //
+ // Do nothing when mPendingList is empty
+ //
+ if (mPendingList == NULL) {
+ return 0;
+ }
+
+ //
+ // Get build item count of mPendingList
+ //
+ Count = 0;
+ CurrentBuildItem = mPendingList;
+ while (CurrentBuildItem != NULL) {
+ Count++;
+ CurrentBuildItem = CurrentBuildItem->Next;
+ }
+
+ //
+ // The semaphore is also used to wake up child threads for exit,
+ // so need to make sure "maximum count" >= "thread number".
+ //
+ if (Count < ThreadNumber) {
+ Count = ThreadNumber;
+ }
+
+ //
+ // Init mSemaphoreHandle
+ //
+ mSemaphoreHandle = CreateSemaphore (
+ NULL, // default security attributes
+ 0, // initial count
+ Count, // maximum count
+ NULL // unnamed semaphore
+ );
+ if (mSemaphoreHandle == NULL) {
+ Error (NULL, 0, 0, NULL, "failed to create semaphore");
+ RestoreBuildList (BuildList);
+ return 1;
+ }
+
+ //
+ // Init mEventHandle
+ //
+ mEventHandle = CreateEvent(
+ NULL, // default security attributes
+ FALSE, // auto-reset event
+ TRUE, // initial state is signaled
+ NULL // object not named
+ );
+ if (mEventHandle == NULL) {
+ Error (NULL, 0, 0, NULL, "failed to create event");
+ CloseHandle (mSemaphoreHandle);
+ RestoreBuildList (BuildList);
+ return 1;
+ }
+
+ //
+ // Init mCriticalSection
+ //
+ InitializeCriticalSection (&mCriticalSection);
+
+ //
+ // Create build item log dir
+ //
+ sprintf (mLogDir, "%s\\Log", mBuildDir);
+ _mkdir (mLogDir);
+
+ //
+ // Create child threads for muti-thread build
+ //
+ ThreadHandle = malloc (ThreadNumber * sizeof (HANDLE));
+ if (ThreadHandle == NULL) {
+ Error (NULL, 0, 0, NULL, "failed to allocate memory");
+ CloseHandle (mSemaphoreHandle);
+ CloseHandle (mEventHandle);
+ RestoreBuildList (BuildList);
+ return 1;
+ }
+ for (Index = 0; Index < ThreadNumber; Index++) {
+ ThreadHandle[Index] = CreateThread (
+ NULL, // default security attributes
+ 0, // use default stack size
+ ThreadProc, // thread function
+ (LPVOID)Index, // argument to thread function: use Index as thread id
+ 0, // use default creation flags
+ NULL // thread identifier not needed
+ );
+ if (ThreadHandle[Index] == NULL) {
+ Error (NULL, 0, 0, NULL, "failed to create Thread_%d", Index);
+ mError = 1;
+ ThreadNumber = Index;
+ //
+ // Make sure to wake up every child thread for exit
+ //
+ ReleaseSemaphore (mSemaphoreHandle, ThreadNumber, NULL);
+ break;
+ }
+ }
+
+ //
+ // Loop until error occurred or no more build items pending for build
+ //
+ for (;;) {
+ WaitForSingleObject (mEventHandle, INFINITE);
+ if (mError) {
+ break;
+ }
+ Count = 0;
+
+ EnterCriticalSection (&mCriticalSection);
+ PreviousBuildItem = NULL;
+ CurrentBuildItem = mPendingList;
+ while (CurrentBuildItem != NULL) {
+ NextBuildItem = CurrentBuildItem->Next;
+ if (CheckDependency (CurrentBuildItem->DependencyList)) {
+ //
+ // Move the current build item from mPendingList
+ //
+ if (PreviousBuildItem != NULL) {
+ PreviousBuildItem->Next = NextBuildItem;
+ } else {
+ mPendingList = NextBuildItem;
+ }
+ //
+ // Add the current build item to the head of mWaitingList
+ //
+ CurrentBuildItem->Next = mWaitingList;
+ mWaitingList = CurrentBuildItem;
+ Count++;
+ } else {
+ PreviousBuildItem = CurrentBuildItem;
+ }
+ CurrentBuildItem = NextBuildItem;
+ }
+ LeaveCriticalSection (&mCriticalSection);
+
+ ReleaseSemaphore (mSemaphoreHandle, Count, NULL);
+ if (mPendingList == NULL) {
+ break;
+ }
+ }
+
+ //
+ // Wait until all threads have terminated
+ //
+ WaitForMultipleObjects (ThreadNumber, ThreadHandle, TRUE, INFINITE);
+
+ if (mError && (mBuildingList != NULL)) {
+ //
+ // Dump build failure log of the first build item which doesn't finish the build
+ //
+ printf ("\tnmake -nologo -f %s all\n", mBuildingList->Makefile);
+ sprintf (Cmd, "type %s\\%s_%s_%d.txt 2>NUL", mLogDir, mBuildingList->BaseName,
+ mBuildingList->Processor, mBuildingList->Index);
+ _flushall ();
+ if (system (Cmd)) {
+ Error (NULL, 0, 0, NULL, "failed to run \"%s\"", Cmd);
+ }
+ }
+
+ DeleteCriticalSection (&mCriticalSection);
+ for (Index = 0; Index < ThreadNumber; Index++) {
+ CloseHandle (ThreadHandle[Index]);
+ }
+ free (ThreadHandle);
+ CloseHandle (mSemaphoreHandle);
+ CloseHandle (mEventHandle);
+ RestoreBuildList (BuildList);
+
+ return mError;
+}
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.h b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.h
new file mode 100644
index 0000000000..7a5566a913
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/MultiThread.h
@@ -0,0 +1,116 @@
+/*++
+
+Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MultiThread.h
+
+Abstract:
+
+ Defines and function prototypes for the ProcessDsc utility.
+
+--*/
+
+#ifndef _MULTI_THREAD_H_
+#define _MULTI_THREAD_H_
+
+typedef struct _COMPONENTS_ITEM COMPONENTS_ITEM;
+typedef struct _BUILD_ITEM BUILD_ITEM;
+typedef struct _SOURCE_FILE_ITEM SOURCE_FILE_ITEM;
+typedef struct _DEPENDENCY_ITEM DEPENDENCY_ITEM;
+
+//
+// Use this structure to keep track of module build items
+//
+typedef struct _BUILD_ITEM {
+ BUILD_ITEM *Next;
+ INT8 *BaseName;
+ INT8 *Processor;
+ INT8 *Makefile;
+ UINT32 Index;
+ UINT32 CompleteFlag;
+ SOURCE_FILE_ITEM *SourceFileList;
+ DEPENDENCY_ITEM *DependencyList;
+} BUILD_ITEM;
+
+//
+// Use this structure to keep track of module source files
+//
+typedef struct _SOURCE_FILE_ITEM {
+ SOURCE_FILE_ITEM *Next;
+ INT8 *FileName;
+} SOURCE_FILE_ITEM;
+
+//
+// Use this structure to keep track of module build dependencies
+//
+typedef struct _DEPENDENCY_ITEM {
+ DEPENDENCY_ITEM *Next;
+ BUILD_ITEM *Dependency;
+} DEPENDENCY_ITEM;
+
+//
+// Use this structure to keep track of [components] and [components.n] sections
+//
+typedef struct _COMPONENTS_ITEM {
+ COMPONENTS_ITEM *Next;
+ BUILD_ITEM *BuildList;
+} COMPONENTS_ITEM;
+
+//
+// Function prototypes
+//
+BUILD_ITEM *
+AddBuildItem (
+ BUILD_ITEM **BuildList,
+ INT8 *BaseName,
+ INT8 *Processor,
+ INT8 *Makefile
+ );
+
+
+SOURCE_FILE_ITEM *
+AddSourceFile (
+ BUILD_ITEM *BuildItem,
+ INT8 *FileName
+ );
+
+DEPENDENCY_ITEM *
+AddDependency (
+ BUILD_ITEM *BuildList,
+ BUILD_ITEM *BuildItem,
+ INT8 *BaseName,
+ INT8 AdjustIndex
+ );
+
+void
+FreeBuildList (
+ BUILD_ITEM *BuildList
+ );
+
+COMPONENTS_ITEM *
+AddComponentsItem (
+ COMPONENTS_ITEM **ComponentsList
+ );
+
+void
+FreeComponentsList (
+ COMPONENTS_ITEM *ComponentsList
+ );
+
+INT8
+StartMultiThreadBuild (
+ BUILD_ITEM **BuildList,
+ UINT32 ThreadNumber,
+ INT8 *BuildDir
+ );
+
+#endif // ifndef _MULTI_THREAD_H_
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c
index 20faf6f69f..5f64bf5685 100644
--- a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c
@@ -1,6 +1,6 @@
/*++
-Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -27,25 +27,18 @@ Abstract:
#include <direct.h> // for _mkdir()
#include <errno.h>
#include <stdlib.h> // for getenv()
+#include <shlwapi.h> // for PathCanonicalize()
#include "DSCFile.h"
+#include "MultiThread.h"
#include "FWVolume.h"
#include "Exceptions.h"
#include "Common.h"
#include "EfiUtilityMsgs.h"
#include "TianoBind.h"
-//
-// Disable warning for while(1) code
-//
-#pragma warning(disable : 4127)
-//
-// Disable warning for unreferenced function parameters
-//
-#pragma warning(disable : 4100)
-
-extern int errno;
-#define PROGRAM_NAME "ProcessDsc"
+#define UTILITY_NAME "ProcessDsc"
+#define UTILITY_VERSION "v1.0"
//
// Common symbol name definitions. For example, the user can reference
@@ -220,25 +213,39 @@ typedef struct _SYMBOL {
} SYMBOL;
//
-// Define new SYMBOL list to record all module name used in the platform.dsc file.
+// Module globals for multi-thread build
//
-SYMBOL *gModuleList = NULL;
+static BUILD_ITEM **mCurrentBuildList; // build list currently handling
+static BUILD_ITEM *mCurrentBuildItem; // build item currently handling
+
+//
+// Define masks for the build targets
+//
+#define BUILD_TARGET_COMPONENTS 0x01
+#define BUILD_TARGET_LIBRARIES 0x02
+#define BUILD_TARGET_FVS 0x04
+#define BUILD_TARGET_ALL 0xff
+
//
// This structure is used to save globals
//
struct {
- INT8 *DscFilename;
- SYMBOL *Symbol;
- INT8 MakefileName[MAX_PATH]; // output makefile name
- INT8 XRefFileName[MAX_PATH];
- INT8 GuidDatabaseFileName[MAX_PATH];
- INT8 ModuleMakefileName[MAX_PATH];
- FILE *MakefileFptr;
- FILE *ModuleMakefileFptr;
- SYMBOL *ModuleList;
- SYMBOL *OutdirList;
- UINT32 Verbose;
+ INT8 *DscFilename;
+ SYMBOL *Symbol;
+ INT8 MakefileName[MAX_PATH]; // output makefile name
+ INT8 XRefFileName[MAX_PATH];
+ INT8 GuidDatabaseFileName[MAX_PATH];
+ INT8 ModuleMakefileName[MAX_PATH];
+ FILE *MakefileFptr;
+ FILE *ModuleMakefileFptr;
+ SYMBOL *ModuleList;
+ SYMBOL *OutdirList;
+ UINT32 Verbose;
+ UINT32 ThreadNumber;
+ UINT32 BuildTarget;
+ BUILD_ITEM *LibraryList;
+ COMPONENTS_ITEM *ComponentsList;
} gGlobals;
//
@@ -584,16 +591,18 @@ Returns:
--*/
{
- int i;
- DSC_FILE DSCFile;
- SECTION *Sect;
- INT8 Line[MAX_LINE_LEN];
- INT8 ExpLine[MAX_LINE_LEN];
- INT8 *EMsg;
- FILE *FpModule;
- SYMBOL *TempSymbol;
-
- SetUtilityName (PROGRAM_NAME);
+ int i;
+ DSC_FILE DSCFile;
+ SECTION *Sect;
+ INT8 Line[MAX_LINE_LEN];
+ INT8 ExpLine[MAX_LINE_LEN];
+ INT8 *BuildDir;
+ INT8 *EMsg;
+ FILE *FpModule;
+ SYMBOL *TempSymbol;
+ COMPONENTS_ITEM *TempComponents;
+
+ SetUtilityName (UTILITY_NAME);
InitExceptions ();
@@ -710,6 +719,7 @@ Returns:
//
Sect = DSCFileFindSection (&DSCFile, LIBRARIES_SECTION_NAME);
if (Sect != NULL) {
+ mCurrentBuildList = &gGlobals.LibraryList;
ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_LIBRARIES, 0);
}
@@ -721,6 +731,7 @@ Returns:
//
Sect = DSCFileFindSection (&DSCFile, LIBRARIES_PLATFORM_SECTION_NAME);
if (Sect != NULL) {
+ mCurrentBuildList = &gGlobals.LibraryList;
ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_PLATFORM_LIBRARIES, 0);
}
@@ -735,6 +746,8 @@ Returns:
Sect = DSCFileFindSection (&DSCFile, COMPONENTS_SECTION_NAME);
if (Sect != NULL) {
fprintf (gGlobals.MakefileFptr, "components_0 : \n");
+ TempComponents = AddComponentsItem (&gGlobals.ComponentsList);
+ mCurrentBuildList = &TempComponents->BuildList;
ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, 0);
fprintf (gGlobals.MakefileFptr, "\n");
}
@@ -754,6 +767,8 @@ Returns:
Sect = DSCFileFindSection (&DSCFile, Line);
if (Sect != NULL) {
fprintf (gGlobals.MakefileFptr, "components_%d : \n", i);
+ TempComponents = AddComponentsItem (&gGlobals.ComponentsList);
+ mCurrentBuildList = &TempComponents->BuildList;
ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, i);
fprintf (gGlobals.MakefileFptr, "\n");
} else {
@@ -807,12 +822,52 @@ ProcessingError:
fclose (gGlobals.ModuleMakefileFptr);
gGlobals.ModuleMakefileFptr = NULL;
}
-
+
+ //
+ // Start multi-thread build if ThreadNumber is specified and no error status
+ //
+ if ((gGlobals.ThreadNumber != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
+ BuildDir = GetSymbolValue (BUILD_DIR);
+ if (gGlobals.BuildTarget & BUILD_TARGET_LIBRARIES) {
+ if (StartMultiThreadBuild (&gGlobals.LibraryList, gGlobals.ThreadNumber, BuildDir) != 0) {
+ Error (NULL, 0, 0, NULL, "Multi-thread build libraries failure");
+ goto Cleanup;
+ }
+ }
+ i = 0;
+ TempComponents = gGlobals.ComponentsList;
+ while (TempComponents != NULL) {
+ if (gGlobals.BuildTarget & BUILD_TARGET_COMPONENTS) {
+ if (StartMultiThreadBuild (&TempComponents->BuildList, gGlobals.ThreadNumber, BuildDir) != 0) {
+ Error (NULL, 0, 0, NULL, "Multi-thread build components %d failure", i);
+ goto Cleanup;
+ }
+ }
+ if (gGlobals.BuildTarget & BUILD_TARGET_FVS) {
+ sprintf (ExpLine, "nmake -nologo -f %s fvs_%d", gGlobals.MakefileName, i);
+ _flushall ();
+ if (system (ExpLine)) {
+ Error (NULL, 0, 0, NULL, "Build FVs for components %d failure", i);
+ goto Cleanup;
+ }
+ }
+ i++;
+ TempComponents = TempComponents->Next;
+ }
+ }
+
+Cleanup:
//
// Clean up
//
+ FreeBuildList (gGlobals.LibraryList);
+ gGlobals.LibraryList = NULL;
+ FreeComponentsList (gGlobals.ComponentsList);
+ gGlobals.ComponentsList = NULL;
FreeSymbols (gGlobals.ModuleList);
+ gGlobals.ModuleList = NULL;
FreeSymbols (gGlobals.OutdirList);
+ gGlobals.OutdirList = NULL;
FreeSymbols (gGlobals.Symbol);
gGlobals.Symbol = NULL;
CFVDestructor ();
@@ -1312,6 +1367,16 @@ Returns:
}
//
+ // Add a new build item to mCurrentBuildList
+ //
+ mCurrentBuildItem = AddBuildItem (mCurrentBuildList, GetSymbolValue (BASE_NAME), Processor, FileName);
+ //
+ // ProcessDsc allows duplicate base name libraries. Make sure the duplicate
+ // base name libraries will be built in the same order as listed in DSC file.
+ //
+ AddDependency (*mCurrentBuildList, mCurrentBuildItem, mCurrentBuildItem->BaseName, 1);
+
+ //
// Add Module name to the global module list
//
AddModuleName (&gGlobals.ModuleList, GetSymbolValue (BASE_NAME), GetSymbolValue (INF_FILENAME));
@@ -1336,6 +1401,7 @@ Returns:
// files in this component. This macro can then be used elsewhere to
// process all the files making up the component. Required for scanning
// files for string localization.
+ // Also add source files to mCurrentBuildItem.
//
ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_SOURCE_FILES);
//
@@ -1370,7 +1436,8 @@ Returns:
// Process all the libraries to define "LIBS = x.lib y.lib..."
// Be generous and append ".lib" if they forgot.
// Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib...
- // Also add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ...
+ // Add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ...
+ // Also add libs dependency to mCurrentBuildItem.
//
ProcessLibs (&ComponentFile, MakeFptr);
@@ -1829,8 +1896,14 @@ Returns:
OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH);
if (OverridePath != NULL) {
ReplaceSlash (OverridePath);
+ fprintf (MakeFptr, "!IF EXIST(%s)\n", OverridePath);
fprintf (MakeFptr, "INC = $(INC) -I %s\n", OverridePath);
- fprintf (MakeFptr, "INC = $(INC) -I %s\\%s \n", OverridePath, Processor);
+ fprintf (MakeFptr, "!IF EXIST(%s\\%s)\n", OverridePath, Processor);
+ fprintf (MakeFptr, "INC = $(INC) -I %s\\%s\n", OverridePath, Processor);
+ fprintf (MakeFptr, "!ENDIF\n");
+ fprintf (MakeFptr, "!ELSE\n");
+ fprintf (MakeFptr, "!MESSAGE Warning: include dir %s does not exist\n", OverridePath);
+ fprintf (MakeFptr, "!ENDIF\n");
}
//
// Try for an [includes.$(PROCESSOR).$(PLATFORM)]
@@ -1909,43 +1982,45 @@ ProcessIncludesSectionSingle (
//
if (Cptr[1] == 0) {
fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\n");
- fprintf (
- MakeFptr,
- "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
- Processor
- );
+ fprintf (MakeFptr, "!IF EXIST($(SOURCE_DIR)\\%s)\n", Processor);
+ fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\\%s\n", Processor);
+ fprintf (MakeFptr, "!ENDIF\n");
} else {
//
// Handle case of ".\path\path\path" or "..\path\path\path"
//
- fprintf (
- MakeFptr,
- "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
- Cptr
- );
- fprintf (
- MakeFptr,
- "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s \n",
- Cptr,
- Processor
- );
+ fprintf (MakeFptr, "!IF EXIST($(SOURCE_DIR)\\%s)\n", Cptr);
+ fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\\%s\n", Cptr);
+ fprintf (MakeFptr, "!IF EXIST($(SOURCE_DIR)\\%s\\%s)\n", Cptr, Processor);
+ fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s\n", Cptr, Processor);
+ fprintf (MakeFptr, "!ENDIF\n");
+ fprintf (MakeFptr, "!ELSE\n");
+ fprintf (MakeFptr, "!MESSAGE Warning: include dir $(SOURCE_DIR)\\%s does not exist\n", Cptr);
+ fprintf (MakeFptr, "!ENDIF\n");
}
} else if ((Cptr[1] != ':') && isalpha (*Cptr)) {
- fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s \n", Cptr);
- fprintf (
- MakeFptr,
- "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s \n",
- Cptr,
- Processor
- );
+ fprintf (MakeFptr, "!IF EXIST($(EFI_SOURCE)\\%s)\n", Cptr);
+ fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s\n", Cptr);
+ fprintf (MakeFptr, "!IF EXIST($(EFI_SOURCE)\\%s\\%s)\n", Cptr, Processor);
+ fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s\n", Cptr, Processor);
+ fprintf (MakeFptr, "!ENDIF\n");
+ fprintf (MakeFptr, "!ELSE\n");
+ fprintf (MakeFptr, "!MESSAGE Warning: include dir $(EFI_SOURCE)\\%s does not exist\n", Cptr);
+ fprintf (MakeFptr, "!ENDIF\n");
} else {
//
// The line is something like: $(EFI_SOURCE)\dxe\include. Add it to
// the existing $(INC) definition. Add user includes before any
// other existing paths.
//
- fprintf (MakeFptr, "INC = $(INC) -I %s \n", Cptr);
- fprintf (MakeFptr, "INC = $(INC) -I %s\\%s \n", Cptr, Processor);
+ fprintf (MakeFptr, "!IF EXIST(%s)\n", Cptr);
+ fprintf (MakeFptr, "INC = $(INC) -I %s\n", Cptr);
+ fprintf (MakeFptr, "!IF EXIST(%s\\%s)\n", Cptr, Processor);
+ fprintf (MakeFptr, "INC = $(INC) -I %s\\%s\n", Cptr, Processor);
+ fprintf (MakeFptr, "!ENDIF\n");
+ fprintf (MakeFptr, "!ELSE\n");
+ fprintf (MakeFptr, "!MESSAGE Warning: include dir %s does not exist\n", Cptr);
+ fprintf (MakeFptr, "!ENDIF\n");
}
}
}
@@ -2260,16 +2335,35 @@ ProcessSourceFilesSection (
// SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c
//
fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName);
+ //
+ // Save the source absolute path
+ //
+ if (PathCanonicalize (FilePath, TempFileName)) {
+ AddSourceFile (mCurrentBuildItem, FilePath);
+ }
} else if (IsAbsolutePath (FileName)) {
//
// For Absolute path, don't print $(SOURCE_FILE) directory.
//
fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName);
+ //
+ // Save the source absolute path
+ //
+ if (PathCanonicalize (FilePath, FileName)) {
+ AddSourceFile (mCurrentBuildItem, FilePath);
+ }
} else {
//
// SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c
//
fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName);
+ //
+ // Save the source absolute path
+ //
+ sprintf (Str, "%s\\%s", GetSymbolValue (SOURCE_DIR), FileName);
+ if (PathCanonicalize (FilePath, Str)) {
+ AddSourceFile (mCurrentBuildItem, FilePath);
+ }
}
} else if (Mode & SOURCE_MODE_BUILD_COMMANDS) {
//
@@ -2612,6 +2706,10 @@ ProcessLibsSingle (
Cptr[strlen (Cptr) - 4] = 0;
fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr);
}
+ //
+ // Add libs dependency for mCurrentBuildItem
+ //
+ AddDependency (*mCurrentBuildList, mCurrentBuildItem, Cptr, 0);
}
}
}
@@ -2767,8 +2865,9 @@ ProcessIncludeFilesSingle (
if (Cptr >= TempFileName) {
*Cptr = 0;
}
-
+ fprintf (MakeFptr, "!IF EXIST(%s)\n", TempFileName);
fprintf (MakeFptr, "INC = -I %s $(INC)\n", TempFileName);
+ fprintf (MakeFptr, "!ENDIF\n");
}
}
//
@@ -4173,6 +4272,63 @@ Returns:
}
break;
+ //
+ // Enable multi-thread build and specify the thread number
+ //
+ case 'n':
+ case 'N':
+ //
+ // Skip to next arg
+ //
+ Argc--;
+ Argv++;
+ if (Argc == 0) {
+ Argv--;
+ Error (NULL, 0, 0, Argv[0], "missing input thread number with option");
+ Usage ();
+ return STATUS_ERROR;
+ } else {
+ gGlobals.ThreadNumber = atoi (Argv[0]);
+ if (gGlobals.ThreadNumber == 0) {
+ Argv--;
+ Error (NULL, 0, 0, Argv[0], "input thread number should not be %s", Argv[1]);
+ return STATUS_ERROR;
+ } else if (gGlobals.ThreadNumber > MAXIMUM_WAIT_OBJECTS) {
+ Argv--;
+ Error (NULL, 0, 0, Argv[0], "input thread number should not greater than %d", MAXIMUM_WAIT_OBJECTS);
+ return STATUS_ERROR;
+ }
+ }
+ break;
+
+ //
+ // Specify the multi-thread build target
+ //
+ case 't':
+ case 'T':
+ //
+ // Skip to next arg
+ //
+ Argc--;
+ Argv++;
+ if (Argc == 0) {
+ Argv--;
+ Error (NULL, 0, 0, Argv[0], "missing input build target with option");
+ Usage ();
+ return STATUS_ERROR;
+ } else if (_stricmp (Argv[0], "all") == 0) {
+ gGlobals.BuildTarget |= BUILD_TARGET_ALL;
+ } else if (_stricmp (Argv[0], "libraries") == 0) {
+ gGlobals.BuildTarget |= BUILD_TARGET_LIBRARIES;
+ } else if (_stricmp (Argv[0], "components") == 0) {
+ gGlobals.BuildTarget |= BUILD_TARGET_COMPONENTS;
+ } else {
+ Argv--;
+ Error (NULL, 0, 0, Argv[0], "input build target not supported");
+ Usage ();
+ }
+ break;
+
case 'v':
case 'V':
gGlobals.Verbose = 1;
@@ -4228,7 +4384,14 @@ Returns:
if (FreeCwd) {
free (Cptr);
}
-
+
+ //
+ // Default build target is all
+ //
+ if (gGlobals.BuildTarget == 0) {
+ gGlobals.BuildTarget = BUILD_TARGET_ALL;
+ }
+
return 0;
}
@@ -4426,18 +4589,29 @@ Usage (
VOID
)
{
- int i;
- static const INT8 *Help[] = {
- "Usage: ProcessDsc {options} [Dsc Filename]",
- " Options:",
- " -d var=value to define symbol 'var' to 'value'",
- " -v for verbose mode",
- " -g filename to preparse GUID listing file",
- " -x filename to create a cross-reference file",
+ int Index;
+ const char *Str[] = {
+ UTILITY_NAME" "UTILITY_VERSION" - Intel Process DSC File Utility",
+ " Copyright (C), 2004 - 2008 Intel Corporation",
+
+#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
+ " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
+#endif
+ "",
+ "Usage:",
+ " "UTILITY_NAME" [OPTION]... DSCFILE",
+ "Options:",
+ " -d var=value to define symbol 'var' to 'value'",
+ " -v for verbose mode",
+ " -g filename to preparse GUID listing file",
+ " -x filename to create a cross-reference file",
+ " -n threadnumber to build with multi-thread",
+ " -t target to build the specified target:",
+ " all, libraries or components",
NULL
};
- for (i = 0; Help[i] != NULL; i++) {
- fprintf (stdout, "%s\n", Help[i]);
+ for (Index = 0; Str[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Str[Index]);
}
}
@@ -4562,7 +4736,7 @@ SmartOpen (
if (SmartFile->FileContent != NULL) {
memset (SmartFile->FileContent, 0, FileSize + 1);
//
- // Usually FileLength < FileSize, because in text mode, carriage return-linefeed
+ // Usually FileLength < FileSize, because in text mode, carriage return¨Clinefeed
// combinations are translated into single linefeeds on input
//
SmartFile->FileLength = fread (SmartFile->FileContent, sizeof(char), FileSize, Fptr);