AppFramework
From Nocturnal Initiative
|
Overview
AppFramework is basically a generalized snapshot of the core application and library code that Insomniac Games' uses for its own proprietary tool set.
Features
The big ticket features provided by the Nocturnal Initiative include (but are by no means limited to):
- Handy Code Snippets
- C++ Delegate/Event System
- Pointer to reference counted objects
- Pointer to heap allocated arrays
- Endian conversion code
- Insertion ordered std::set
- Reversible key and value std::map
- Interprocess Communication
- Fast non-blocking message-based design
- Works over BSD-style sockets (TCP) or Named Pipes
- Windows platform included, additional platforms are easily added
- Debugging Helpers
- PDB-based symbol information querying
- Capture stacks within your program making heap object tracking and leak debugging easier
- Give your application automatic crash reports dispatched via email that contain handy user/machine informaton, call stack, and memory page allocation stats
- Console Output Manager
- Log console output to one or more trace files
- Color code the console output based on Error/Warning/Debug print statements
- Throttle output verbosity (configured via command line arg or environment variable)
- Outline nested stages of processing performed by your application (for builders/exporters)
- Augment crash reports with the current outline state of your application (very useful for tracking down new crash bugs)
- Instrumenting Profiler
- Cross platform (Windows and PS3 currently)
- Macro-instrumented stack timer based profiler
- Concise profile report printed out at program exit
- Logs instance data out to human readable log file (Profile Analyzer is in development)
- Perforce Integration
- We use perforce for both code and data here at Insomniac
- This wrapper wraps the string-command based P4API with a more structured API
- C++ Reflection
- Serialize objects to binary or human-readable XML
- Flexible parsing mechanics allow you to read in old versions of your class
- Supports changing member type (automatically within reasonable limits), and supports renaming member variables via virtual API
- Supports serializing std::vector, std::set, and std::map containers with primitives or pointers to other reflect objects
- Supports serializing enumerations and bitfields using string representation (supports reordering enum elements)
- Supports automated object comparison, conversion, and cloning
- Supports introspection using a visitor interface
- Data-Driven Property UI
- Uses standard wxWidgets controls
- Interpreter classes examine your objects, create controls, bind data
- Simple UI script can truly data drive the presentation of the properties
Contents
For now this project is organized as a monolithic set of libraries and applications. All of our libraries compile to Windows DLLs. Thoughts on how we could organize our projects better can be found here.
Core Libraries
- Common - Basic library code that provides simple features
- Windows - A support library of windows-specific convenience functionality
- Console - A color coded, verbosity throttled, remotable, outlining console printing library
- Platform - A platform abstraction layer for threading, mutex, etc...
- Profile - A basic broad-phase performance and memory profiler
- IPC - Asynchronous message-based interprocess communcation via TCP or Named Pipe
- Math - Very basic reference implementation of 3D math vector/matrix/rotations/colors
- Debug - Win32/C++ exception handler/emailer and memory profiler
- Config - A simple C++ config system that can be driven by XML files
- AppUtils - Application structured startup/shutdown manager
- FileSystem - File System abstraction layer and convenience code
- SmartBuffer - Buffer objects that support pointers and serialization
- SmartLoader - Fixed-memory loader for SmartBuffer files
Unique IDs
- TUID - A simple 64-bit unique identifier
- UniqueID - A utility library to make working with TUIDs and GUIDs easier
Revision Control
- Perforce - Slim C++ Perforce abstraction layer
- RCS - Revision Control System module for managing files under revision control
C++ Reflection
- Reflect - An implementation of C++ reflection
- Rebuild - A command line utility for files serialized with Reflect
- Inspect - A widget engine for property-sheet style UI
- InspectReflect - An interpreter for the Reflect C++ reflection format to drive Inspect UI
- Reflector - A GUI utility for perusing the contents of files serialized with Reflect
Dependencies
The following libraries are used by this project:
- Boost
- http://www.boost.org/
- You can get a built distribution from http://www.boost-consulting.com/products/free
- P4API
- http://www.perforce.com/
- Libraries to link against are at ftp://ftp.perforce.com/perforce/r07.3/bin.ntx86 (you may need to upgrade your server version to use these)
- Use the libraries in p4api_vs2005_dyn.zip for Release and p4api_vs2005_dyn_vsdebug.zip for Debug
- Make sure to use recent versions of these libraries. Older versions had serious performance issues.
- DbgHelp
- http://www.microsoft.com/whdc/devtools/debugging/default.mspx
- Included with Debugging Utilites for Windows, these libs work better than the version included with Windows XP
- You must package the DLLs (dbg*.dll) with the tools using our modules due to Windows' DLL search order
- wxWidgets
- http://wxwidgets.org
- We compile wxWidgets with these settings:
- wxUSE_ON_FATAL_EXCEPTION 0
- wxUSE_STACKWALKER 0
- wxUSE_DEBUGREPORT 0
- wxUSE_EXCEPTIONS 0
- wxUSE_CRASHREPORT 0
Roadmap
The following sections outline directions for improving the organization of this project to pave way for better cross-platform support.
There are some more thoughts regarding future development in AppFramework Improvements. Those thoughts should be integrated with this section at some point.
Bundles
The AppFramework project is made of of several bundles with different requirements. I propose that we have 3 distinct strata of bundles. 1 Foundation bundle, a number of intermediate bundles, and a single App bundle.
Foundation
^ ^ ^
/ | \
Data RCS SQL
^ ^ ^
\ | /
App
Foundation
Lowest common denominator code, all this code is one of the following:
- Platform-agnostic
- Ported to our supported platforms
- Stubbed out functions that are full of asserts
Each platform has a source file suffix:
- _Win32.cpp, _PS3.cpp, _Stub.cpp
Modules:
- Platform - merged into Foundation root, in namespace Nocturnal
- Windows - merged into Foundation root, in namespace Nocturnal
- Common - merged into Foundation root, in namespace Nocturnal
- Profile
- Console
- Config
- Debug - needs generalization and stubbing for non-windows platforms
- FileSystem
- IPC
- UniqueID
- TUID
Data
Ubiquitous data structures, persistence, and introspection
- Depends on Foundation
Modules:
- Math
- Reflect
- SmartBuffer
- SmartLoader
RCS
Revision Control
- Depends on Foundation
Modules:
- RCS
- RCS-UI (This should replace PerforceUI, or at least be a base class for provider-specific UIs)
- Perforce
SQL
SQL DB support
- Depends on Foundation
Modules:
- SQL
Application
Highest level bundle, can depend on any lower level bundle's modules
- Command line interfaces all compiled together with usage information
- GUI programs and libraries
Modules:
- AppUtils - consider rename - Application?
- Undo
- UIToolKit
- Inspect
- InspectReflect
- UnitTest - merged into NocCLI.exe
- Rebuild - merged into NocCLI.exe
Code Organization
/AppFramework /Foundation Thread.h Thread.cpp /Profile Profile.h Profile.cpp
In this example everything in a bundle folder just exists in the Nocturnal namespace. Folders nested within bundles are modules of code with their own namespace. Nesting namespaces is up for debate.
Build
Then entire project can be built as static or dynamic as well as monolithic or piecemeal.
- Static monolithic would yield Nocturnal.lib only
- Dynamic monolithic would yield Nocturnal.lib+dll
- Static piecemeal would yield multiple lib files
- Dynamic piecemeal would yeild multiple lib+dll files
