Common Executable Format for eMbedded Visual C++ in Microsoft Windows CE 3.0

Microsoft Corporation

June 2000

Summary: This article discusses Common Executable Format (CEF), a processor-neutral code format that enables the creation of portable applications across CPUs supported by Microsoft Windows CE. CEF enables Windows CE application developers to deliver products that support all the CPU architectures that run the Windows CE operating system. (17 printed pages)


Introduction CEF for Microsoft eMbedded Visual C++ Advantages and Disadvantages of CEF How CEF Works The Device Translator The Desktop Translator CEF Language Requirements Configuring a CEF Project Limitations and Recommendations Building and Linking a CEF Application Debugging a CEF Application Delivering a CEF Application Distributing CEF Applications as Bare .exe, .dll, or .ocx File CEF Translator Reference MkCEFlib Reference Requirements for the Native-Code DLL Preparing to Run MkCEFlib Running MkCEFlib Actions Performed by MkCEFlib Troubleshooting MkCEFlib MkCEFlib Command Line Conclusion


Common Executable Format (CEF) is a processor-neutral code format that enables the creation of portable applications across CPUs supported by Microsoft® Windows® CE. Microsoft eMbedded Visual C++® can be configured to produce CEF code instead of a native machine language code (such as MIPS or x86 code). In eMbedded Visual C++, CEF Tools (compilers, linkers, and SDK) are made available to the developer the same way a specific CPU target (such as MIPS or ARM) is selected. When a developer compiles a CEF application, the compiler and linker does everything but generate machine-specific code. You still get a .dll or .exe, but the file contains intermediate language instructions instead of native machine code instructions. When the user installs a CEF application on a Windows CE device, a translator generates the corresponding native machine code for the device.

CEF enables Windows CE application developers to deliver products that support all the CPU architectures that run the Windows CE operating system. Because CEF is an intermediate language, processor vendors can easily add a new CPU family that runs CEF applications. They just port Windows CE to their process and write the CEF compiler.

CEF for Microsoft eMbedded Visual C++

CEF for Microsoft eMbedded Visual C++ builds applications that can be installed on any of the supported Windows CE processors (currently ARM, MIPS, PPC, SHx, and x86) for that device category (for example, Pocket PC).

Because CEF is an intermediate CPU-independent language, a CEF application can also be installed and run on any future CEF-supported processor for that device category. All that would be required is for the device operating system to include the CEF translator whenever a new processor is supported.

CEF-based applications run on a single platform (for example, Pocket PC), but on different processors. For example, a CEF executable file built for the Pocket PC will run on any Pocket PC device. It will not run on a Handheld PC. CEF support is available on the Pocket PC platform and any Windows CE platform created with Microsoft Windows CE Platform Builder 3.0 where CEF support has been enabled.

Advantages and Disadvantages of CEF

Deploying applications to multiple CPUs imposes a cost to developers who want to support a Windows CE platform. Although standardized APIs and tools are generally available, it takes resources to test, package, and distribute a product for multiple CPUs. Multiple CPUs also impose costs on users. To install applications, users also must know which CPU runs their Windows CE devices. If a customer has a new device, the available software may be limited. Users with devices supported by different CPUs may also find that moving or sharing software is complicated.

Advantages of CEF

  • CEF enables shrink-wrap software and Web-based programs (for example, Microsoft ActiveX® controls) to support multiple processor architectures, including processors that were not available when the application was written.
  • CEF requires reduced support because users need not know what CPU is running on their device.
  • Users need only to download executable(s) in CEF if they are getting their application from the Web. Without CEF, they must download a .cab file with executable(s) of all the CPU variants for their device.
  • CEF requires no change to programming languages or run-time environments. You use eMbedded Visual C++ just as you would for a specific processor.

Disadvantages of CEF

  • Most internal benchmarks show that CEF code runs 3 percent to 20 percent slower than code compiled for a specific processor. However, in real-world applications, this performance hit is not distinguishable because real-world code spends most of its time in the system.
  • In the internal benchmark tests, native code converted from CEF may be from 10 percent to 20 percent larger than code compiled and optimized for a specific processor. However, this penalty affects code only. Since most real-world applications are made up mainly of data and resources, the overall penalty to a full-blown application is much less than the benchmark figures.

CEF delivers a single executable file for multiple CPUs. This feature can be useful whenever you must support multiple CPUs. For example, you can post a single executable file for Pocket PC devices on a Web site, which users can download for any Pocket PC device using any processor. CEF is not appropriate when you want an application optimized to run only on a particular processor. This applies particularly if you are going to put an application in ROM or otherwise design it for a particular processor.

How CEF Works

CEF provides processor compatibility for any application created to run on a particular device (for example, the Pocket PC or the Handheld PC, but not both). CEF does not provide for running an application on different devices/platforms.

Building a CEF application is simply a matter of choosing the WCE CEF configuration for the build process. During compilation, this configuration invokes the clcef.exe compiler to generate code. When linking, it invokes the linkcef.exe linker. The final binary is output in the same manner and named in the same manner as processor-specific executables, but marked with a machine type of CEF within the binary.

When a user installs the common executable on a CEF-enabled Windows CE device, the translator translates the common executable file to the native executable file. Translators are available for all Windows CE-supported processors. Two modes of translation are available with CEF: device-side translation or host (desktop)-side translation. The device-side translator generates a native executable from a CEF executable with the translator resident on the device ROM. The host-side or desktop (PC) translator generates a native executable with a translator resident on the desktop. The host-side translator is made available with embedded Visual C++.

The Device Translator

The device translator is specific to a particular processor and Windows CE device. The device version normally translates a CEF executable to the native code of that processor when the user installs the executable on the device. This occurs seamlessly, without any indication to the user other than a brief pause for translation. An operating system hook also catches any attempt to load and execute a CEF .exe, .dll, or .ocx file automatically and invokes the translator before running the file.

The Desktop Translator

The desktop translator is most useful during the development and debugging of CEF applications. The desktop translator supports debugging by translating .pdb information from CEF into native form so that the result can be debugged. After translation occurs, the native form of the application (with debug information) is downloaded to the target device. Now the application can be debugged remotely from the desktop with the debugger in eMbedded Visual C++.

Desktop translators for every processor family are included with eMbedded Visual C++. These translators run on Microsoft Windows 2000, Microsoft Windows NT®, or Windows 98 host computers running the Microsoft eMbedded Visual Tools.

CEF Language Requirements

One advantage of CEF is that you do not need to learn any new language or language constructs to create a CEF application. You can code in C++ and use the Windows CE APIs just as you would for any specific processor.

Although you must use C++, CEF does support C code with the /TP /C /CEF build switches. The /TP switch is required to compile C code as C++. However, if you do use C code, it must meet C++ rules to provide valid input for a C++ compiler. Function definitions, type conversions, and other language elements must follow C++ rules. If you want to use code that currently does not meet C++ requirements, you must upgrade it. All changes for C++ rules are backward compatible; so, after you make changes, you can still build your code with an ANSI C compiler.

  • If you use Kernighan and Ritchie (K&R) C you will find that there are function definitions that do not work in C++. K&R C also has problems handling type conversions and function declarations as required by C++ rules. You will need to update your function declarations to the modern "prototype" form, in which both the function name and type are given in the argument list. In the code, the function calls must also be changed to match the declarations.
  • ANSI C more closely fulfills C++ requirements. Almost all ANSI C syntax is accepted by C++. Some typecasts, most commonly involving pointers, that C accepts implicitly must be made explicit for C++.
  • The basic Unicode wide-character data type wchar_t (the 16-bit counterpart to an 8-bit signed char) is defined as unsigned short in native eMbedded Visual C++ compilers, but is an intrinsic type in the eMbedded Visual C++ CEF compiler (according to recent changes in ANSI C). This occasionally requires an explicit wchar_t cast in places where an integer has been used.
  • You may need to place extern "C" { ... } bracketing around headers and sources that must export names with C linkage rules rather than the C++ decorated name rules. This is necessary only in the rare case that you are creating a DLL to which a native C-rules executable program or DLL will link by named imports. If your application is completely self-contained or it exports its functionality only through COM interfaces, then you can probably compile and link using C++ linkage.

These are the most common syntax changes required to meet C++ rules. Refer to a comprehensive book on the C++ language for a more complete discussion of the differences between C and C++. The changes themselves are syntactic and result from the stricter compiler philosophy of C++. Changing your code to conform to the stricter rules will not change your algorithms nor prevent you from compiling your source code as ANSI C for other projects.

Configuring a CEF Project

To build a CEF executable file for an application, you must configure the Project for WCE CEF instead of a native processor. Use Set Active Configuration on the Build menu to select the active project configuration. You can also select the active configuration on the WCE Configuration toolbar. Then, when you build your project, eMbedded Visual C++ compiles the source code as CEF-based .exe, .dll, or .ocx file.

Project Settings for a CEF Build

Choose Settings on the Project menu to configure project settings for a CEF project. Choose the C/C++ tab of the Project Settings dialog box to check the settings for each category listed in the Category box.

Figure 1. Project Settings dialog box

The following table lists the appropriate C/C++ tab settings for a CEF project.

Category Setting Notes
General Optimization CEF optimization is less drastic than for other build configurations. This means that there will be less difference between size and speed in optimized code compared with non-optimized code.
  Common Options /CEF switch required/TP switch required for C code.
C++ Language Representation method Best-Case Always* (only available option).
Code Generation Processor DEFAULT (only available option).
  Use run-time library CE Run time* (only available option).
  Struct member alignment 8 Bytes* (required).
Customize   No special settings.
Listing Files   No special settings.
Optimizations   Optimizations for CEF builds do not have nearly the effect as when building for a native compiler.
Precompiled Headers   No precompiled headers available.
Preprocessor   No special preprocessor settings.

Limitations and Recommendations

  • Use Structured Exception Handling (SEH). This is recommended but not required. Jmpbuf (setjmp/longjmp) is deprecated, so SEH is better. A portable jmpbuf for a CEF application is set to the largest possible case of all the CPUs, which is very large. Mixing jmpbuf with native code is a poor practice. Do not use setjmp with new code.
  • The entry point to an image must be from one of the two groups of functions listed in the table. If there are functions from both the first group and the second, the function from the first group is used as the entry point. This is usually the case, because corelibc.lib normally provides a member from the first group.
Group 1
Group 2
  • The xxxCRTStartup functions also make a call to our virtual pointer fix-up function. If the use overrides xxxCRTStartup, the functions will not get that functionality.
  • You cannot use inline native assembler code. Your C++ code can call native code, but inline assembly is unsupported.
  • You cannot use the rare APIs that are specific for a particular processor.
  • Avoid large, zero data segments (global or static data) in a program. The linker puts all the zero data in contiguous memory and optimizes it out of the .exe or .dll size, but it still takes space at translation time because the full program image is loaded as part of the translation process. Small amounts of static data are no problem, but it is best to allocate large arrays on the heap at startup.
  • Test CEF builds on at least two different CPUs before shipping a product. The Microsoft development team does its best to make code portable, but it is still important to assure that your code runs satisfactorily on more than one CPU. After you demonstrate that your code runs fine on a couple of CPUs, you can assume fairly safely that it can run on any CEF-enabled device target.
  • You may want to confirm that performance (speed and size) is satisfactory on Windows CE devices. Normally, performance of CEF applications decreases less than 20 percent from that of the native code, but the actual decrease depends on the application.

Building and Linking a CEF Application


In the eMbedded Visual C++ IDE, building a CEF application is no different from building an application for any specific CPU. Compilation is performed by Clcef.exe and linking by Linkcef.exe. The CEF compiler and linker do support a few special options. To see all the options available for either Clcef.exe or Linkcef.exe, type clcef /? or linkcef /? at the command prompt.

CEF Compiler Options

The following switches are specific to the CEF compiler:

Switch Description
/cef Compile for Windows CE CEF (required)
/noHRESULT Disable intrinsic HRESULT type
/noWchar_t Disable wchar_t keyword
/noBool Disable bool keyword
/MP Compile using multiple processes

The noWchar_t and the /noResult and /noBool switches may cause problems for linking to standard Windows CE import libraries. If the types disabled by these switches are used in function signatures, the linker will fail to match the functions when the types are disabled.

CEF Linker Options

The /MACHINE:CEF switch is required for linking CEF files. The CEF argument is the only one supported for the /MACHINE switch for Linkcef.exe. The CEF argument is not supported by Link.exe, which does not link CEF binaries.

The /SUBSYSTEM switch tells the operating system how to run an .exe file generated by a build. For a CEF build, specify /SUBSYSTEM:WINDOWSCE. The /SUBSYSTEM:WINDOWSCE option is required for Linkcef.exe. This is also the only subsystem you can specify for Linkcef.exe.

Use /WINDOWSCE:CONVERT for linking CEF builds. The EMULATION argument is used for building a desktop Windows CE application that runs under the emulator, and Linkcef.exe does not link binaries for emulation.

Debugging a CEF Application


When you build a debug version of a CEF application, all debugging takes place on a native translation of the application. The linker builds a CEF PE (such as .exe, .dll, or .ocx) file and a .pdb file. The desktop translator converts the CEF PE and .pdb files to a native format. This enables the source code and the native executable to stay synchronized, so that the native version of the .pdb correctly references source line numbers while you debug the native version.


The primary objective of CEF is to provide developers with a simple way to distribute their product for multiple CPUs with Windows CE. For most of your debugging, use the native executable for the CPU on your Windows CE device. The CEF code is optimized, and optimized code can be difficult to debug. You also lose a lot of information in the compilation of source code to CEF and in the translation to native code. Develop the product on an available CPU. Test the CEF build only after the code has been debugged in the native format for the CPU, and the project is near completion. CEF is for delivering a product, not for developing a product.

We also recommend against transferring the debug version of a CEF build, particularly a debug static MFC build, to a device. A debug build requires several times more translation resources than a regular build. Transferring a debug version to the host may work if the device CPU has a lot of memory, but the design is not made for doing this.


Automatic Binary Download

For testing purposes, you can choose whether to automatically download an application to the attached device after building it. You can change the download options on the Download tab of the Options dialog box (choose Options on the Tools menu).

Figure 2. Options dialog box

Select or clear the check boxes to always download the binary or dependencies to the target device after you compile the project.

Manual Binary Download

If you clear the Always download ... checkboxes on the Download tab of the Options dialog box, you can download the application manually after you compile it by choosing Update Remote Output File on the Tools/Build menu.

Figure 3. Choosing Update Remote Output File(s)

Host/Device-Side Translation

You can also choose whether to translate the CEF executable to native format before downloading by selecting Always translate CEF executable to native format before downloading on the Download tab of the Options dialog box. If you clear this option, the executable will be translated to native format when it is executed on the target device.

Figure 4. Options dialog box

Delivering a CEF Application

Using a CAB File to Distribute CEF Applications

If a CEF application is going to be installed on more than one computer (for example, passed around on a flash card), you should always use a CAB file to install the application. When the translator installs from an .exe, .dll, or .ocx file, it replaces the original file with the translated file. In contrast, when you use a CAB file, the Windows CE loader (Wceload.exe) first unpacks the CAB and stores the executable files. The loader then calls a Setup.dll unpacked from the CAB, and it in turn calls the CEF translator. The CEF files are still overwritten by the native executable files, but the CAB files are retained and can be used elsewhere.

Distributing CEF Applications as Bare .exe, .dll, or .ocx File

If a CEF application is to be installed only once (for example, an .ocx file or isolated binary downloaded and installed from a Web page), you may choose to use a bare .exe, .dll, or .ocx file. Because no CAB is involved, the file will simply be translated and overwritten the first time it is run. In order to use it on another device, the user will have to get a new copy from the Web page or other source.

If you are using Platform Builder to define your own platform, you should configure Wceload.exe as part of your platform to provide CEF support.

CEF Translator Reference

The CEF translator can be invoked by running an executable (Ceft.exe) or by having the operating system automatically detect the CEF application when the application is first executed.

On a custom-built platform configured with the Platform Builder product, Ceft.exe is available only when it is included in the platform configuration.

Configuring CEF Translation During Host Download

When you are working in eMbedded Visual C++, the IDE is initially configured to automatically translate the CEF file to the native executable file before it downloads the executable file to the native device. To turn this option on or off for testing and debugging, choose Options on the Tools menu to display the Options dialog box. Then, on the Download tab, select or clear the Always translate CEF executable to native format before downloading check box.

Figure 5. Options dialog box

If you clear this check box but leave the other two Download Options check boxes selected, the IDE downloads the CEF file to the target device without translating it to the native executable. The CEF file will then be translated on the target device the first time that you run it.

Translating a CEF Application While Debugging

If the CEF executable file has not been translated when you begin a debugging session, the IDE prompts you to convert the file before beginning the session. Furthermore, during a debugging session, the debugger requires translation of any program not translated during the download, even if you manually translate it in the output directory or on the device. This is because the debugger requires translation of the debug information, and only the translator on the host computer supports translation of the debug information.

CEFT Command Line

On the desktop computer and on Windows CE devices that support the CEFT utility, you can use Ceft.exe to manually translate CEF executables. Ceft.exe on the desktop is stored in the Microsoft Embedded Tools\EVC\osfolder\Bin folder (where osfolder is WCE300 or later). Use the following command line syntax for the CEFT utility.

Desktop Syntax

CEFT -cpu cefexecutable [[path]nativeexecutable]

Windows CE Device Syntax

CEFT cefexecutable [[path]nativeexecutable]

The cpu is one of the CEF-supported operating systems. Currently, you can use ARM, MIPS, SH3, SH4, PPC, or x86. These can change as Microsoft supports additional Windows CE operating systems. The help displayed by typing CEFT /? lists the operating systems supported by the Ceft.exe. This argument is unavailable on a Windows CE device, where CEFT automatically calls the device-specific translator stored in ROM.

The cefexecutable is a CEF executable file that was compiled in the IDE or by Clcef.exe on the command prompt.

The nativeexecutable specifies the output file, which is an executable for the designated operating system. If you do not specify an output file, then CEFT generates a name using cpu.cefexecutable.

Performing Device-Side Translation on an ODO

If you are testing a CEF application on an ODO, device-side translation of the CEF executable cannot take place when attempting to execute a CEF application in the release directory (specified by the _FLATRELEASEDIR environmental variable). Kernel-mode hooks for CEF applications do not affect applications run in the _FLATRELEASEDIR directory. In order to perform device side translation on an ODO, the executable must be transferred to the device itself.

ODO refers to the Hitachi D9000 Handheld PC hardware development platform. This device supports microprocessors from multiple vendors.

MkCEFlib Reference

MkCEFlib prepares import libraries for CEF applications, which allow native code DLLs to be called by CEF applications or CEF DLLs. CEF uses a different binary format for its libraries to which native-code libraries must be converted to be used by a CEF application. MkCEFlib extracts the contents of native import libraries and compiles an equivalent CEF import library. You link this library to your CEF project to enable the compiled CEF application to use the native DLL.

The CEF translator handles APIs exported by name. Although C++ decorated names vary slightly on different CPU architectures, the translator transforms the CEF form of the name to the appropriate decorated name for a particular CPU.

Requirements for the Native-Code DLL

The native-code DLL must provide a uniform API that exports the same functions on all supported CPUs. If a native-code DLL exports CPU-specific functions, a CEF application should never call them. We strongly recommend that you exclude any CPU-specific functions from the CEF import library.

If your native-code DLL exports any functions by ordinal, you must be careful to use identical ordinals on all CPUs. There are different ways to set up ordinals, but you must be sure that they are the same on every CPU supported by your DLL. If a DLL is not standardized across CPUs, then CEF application cannot use it transparently on every CPU.

Preparing to Run MkCEFlib

Be sure that the native-code DLL is stable before you run MkCEFlib. MkCEFlib must do a compilation for every API function, which may require something on the order of 10 minutes for every 100 functions. Any time you change the export set of functions for a DLL, you must rerun MkCEFlib. If you are still developing, testing, or debugging a DLL, running MkCEFlib consumes time very likely better spent on those tasks. When you are ready to create the CEF import library for the DLL, complete the following steps before you run MkCEFlib.

  1. Choose one CPU version of your DLL, and locate the export .lib file for that CPU.
    A MIPS version of a DLL is ideal. Do not use an x86 version as the base .lib, because its C++ decoration scheme cannot be reversed into a standard form. Any of the RISC CPUs has simpler decoration schemes and is suitable to use as the base .lib.

  2. Prepare an inclusion source file.

    An inclusion source file is a C++ source file that includes all the header files necessary for using the APIs of the target DLL. Prepare this exactly like a normal C++ source file with all the required headers but no source code. If the DLL exports in C style rather than C++, remember to use extern "C" to prevent the compiler from decorating the C function names:

    extern "C" {
    #include "MyCHeader.h"

    If there are any exports that are not defined in standard header files and you need to make them accessible to the CEF application, then add the proper definitions to your inclusion source file.

  3. Exclude APIs that should not be accessible to a CEF application.

    There may be exported functions, such as CPU-specific function, in the headers specified by the inclusion source file that should not be accessible to a CEF application. Often specified header files may already surround these with CPU-specific #ifdef statements, thereby avoiding any problem.

    If an API has not been defined for CPU-specific compilation, then the easiest way to make it inaccessible to the CEF application is to #define the exported function name to some other name in the inclusion source file prior to including the corresponding header file. MkCEFlib discards any name that it cannot match to an export in the native .lib file. MkCEFlib also discards any export that it cannot match to a declaration in the inclusion source file. MkCEFlib generates a log that you can use to identify included and discarded functions.

  4. After you prepare the inclusion source file, compile it to be sure that it is free of errors.

After you complete these steps, you can run MkCEFlib as follows.

Running MkCEFlib

After you complete the required preparations, follow these steps to create a CEF import library.

  1. Create a working folder to store the files generated by MkCEFlib. Although this is optional, MkCEFlib can generate many intermediate files that are more easily managed in a separate folder.
  2. Open a command window, and run Wcecef.bat (located in Microsoft eMbedded Tools\EVC\WCEversion\BIN) to set environment variables.
  3. Be sure that any header files specified by the inclusion source file are either in the current directory or in a directory specified by the INCLUDE environment variable.
    Prefix any unspecified paths to the INCLUDE environment variable with the set command (for example, set c:\headers;%include% to prefix "c:\headers" directory to the INCLUDE value).
  4. Run MkCEFlib (see MkCEFlib Command Reference for the correct command line format).

Actions Performed by MkCEFlib

When you run MkCEFlib, it performs actions in the following order:

  1. MkCEFlib extracts a list of export names from the native library. It puts these into a text file in the working folder named libName.cefdef. You can inspect the contents of this file to see if a missing API was in the native library. If a native library is not found or if it creates no exports, then MkCEFlib displays an error message and halts.
  2. MkCEFlib preprocesses the inclusion source and creates a source file named inclusionPath.i. This speeds up the remainder of the process and simplifies your investigation if an API does not appear in the log. The preprocessed file clearly shows if the API was not included from the headers.
  3. MkCEFlib performs a trial compilation of the inclusionPath.i preprocessed file to check that it has no errors. If you see any errors at this point, cancel the MkCEFlib process and resolve the errors by looking at the preprocessed file. At this stage, errors are ordinary C++ issues, so you can solve them as you would solve other compilation errors.
  4. MkCEFlib iterates through all the exports, recompiling the inclusionPath.i file with a special switch for each export name. This step normally generates a lot of warnings about missing return types. These warnings are harmless, and you can ignore them.
  5. Finally, after MkCEFlib compiles all the files, it runs the LinkCEF linker to bind them into a library. This completes the process.

Troubleshooting MkCEFlib

You can see a list of the exports in the workDirPath\libName.log text file. If the export had a problem, it is marked in square brackets; for example, "[MISSING OBJ]". You should examine this log file after running MkCEFlib.

The following can cause problems:

  • The export had no matching declaration in the header files. To check this, compare the .cefdef and the .i files. Carefully compare the fully qualified name if it is C++, and ensure that the .i source code uses extern "C" if the export is not a decorated name.
  • Many cases of [SMALL OBJ] are "private:" C++ class members. MkCEFlib cannot import these into CEF.

MkCEFlib Command Line

MkCEFlib creates a .cefdef import library file for a CEF application. The location of Mkceflib.exe is in Microsoft eMbedded Tools\EVC\WCEversion\BIN. Mkceflib.exe is included with version 3.0 or later of the Windows CE operating system. The default location is specified in the PATH variable created by the Wcecef.bat batch file, also located in Microsoft eMbedded Tools\EVC\WCEversion\BIN.

To run MkCEFlib, use the following command line syntax. MkCEFlib.exe returns 0 if there is no error or 1 if it was unsuccessful.

MkCEFlib libname inclusionfile workingfolder

The libname field is the fully qualified name of a native import .lib file. This corresponds to a CPU version of the DLL.

The inclusionfile field is the fully qualified name of the inclusion source file for the project.

The workingfolder is the working directory where MkCEFlib saves all intermediate and result files.


CEF enables Windows CE application developers to deliver products that support all the CPU architectures that run the Windows CE operating system. Because CEF is an intermediate language, processor vendors can easily add a new CPU family that runs CEF applications. They just port Windows CE to their process and write the CEF compiler.