/OpenGLRawgen

Generator for C-imports to Haskell for OpenGL.

Primary LanguageHaskellBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

OpenGLRawgen

OpenGLRawgen is a generator tool to make a Raw FFI import of OpenGL to Haskell in style of OpenGLRaw.

Build Status

Project goal

The current (01-2013) OpenGLRaw is quite outdated and not practical to keep up to date as everything needs to be done by hand. The goal of this project is to make a generator which can produce most of the otherwise handwritten source of OpenGLRaw. The generated sources should strike a balance between being similar to OpenGLRaw and being future proof.

Output

The generator creates all sources in the Graphics.Rendering.OpenGL.Raw namespace, which is currently hard coded. In will generate

  • The top level module Raw.hs, which will export the most recent Core version of OpenGL.
  • The Core namespace for the definition of the OpenGL profiles. This will in turn contain
    • Modules CoreXY and CoreXYCompatibility which contain the functions and enumerations for OpenGL version X.Y, one for the Core profile and one for the one with Compatibility profile. These modules are build by reexporting from the internal modules.
    • Modules Internal.CoreXY and Internal.CoreXYCompatibility for the definitions of enumerations and functions that are introduced in version XY of OpenGL. The Compatibility version contains the ones that were later deprecated.
  • Extension granter (e.g. ARB and NV) modules and namespaces, where each extension gets its own module under the namespace of the maker. For example the ARB_sync extension is created in the module ARB.Sync. All the extensions of a single maker are grouped under a module with the name of the vendor (e.g. ARB.hs). Though this latter functionality can be disabled.

Furthermore if asked (-c flag) it can generate modules for backwards compatibility with the old OpenGLRaw. These are Core31 and Core32 and Core31.Types.

Apart from the Haskell sources the generator also outputs several other files.

  • For generating a cabal file it creates modulesI.txt and modulesE.txt which contain all the internal and exposed modules for in the cabal file.
  • A set of interface files describing the mapping between OpenGL names and the corresponding Haskell names, including the module from which they are exported.

Building

Several steps are needed to be preformed to generate a working cabal package out of the generated sources. These steps are detailed in BuildSources.BUILDING.md. All the steps are also combined, mostly for testing purposes, in the testbuild.sh script.

Other sources

Some building blocks of the OpenGLRaw package have been reused from the old package. These parts are those representing types and the several of the internals (e.g. the ones for retrieving proc-addresses). These are also found in BuildSources, with their License.

Changes from OpenGLRaw

There are of course some changes from the OpenGLRaw. (The list is probably not complete, but these are the major points.)

Core modules

The major change is probably that the core modules have been rearranged. Compatibility modules can be generated by giving the generator the -c flag. Raw.hs now exports the latest OpenGL specification in stead of every binding.

Naming schemes

The old naming scheme for functions and enumeration was not very clear on when the extension suffixes should be kept for a function and when not. It seemed to keep the suffix only when there is a version without suffix and the one without suffix is different in specification is different from the one with suffix.

Implementing such a naming scheme in the generator would require quite a bit of extra information about the equality of functions. In the past the generator included two naming schemes, one where all suffixes are kept while the other dropped all of them. After the introduction of the specification in xml format it became clear that the dropping version would generate many name clashes. Therefore it was disabled and later removed. The only naming scheme now available is to keep all extension names.

An example such a name clash is PRIMARY_COLOR and PRIMARY_COLOR_NV in the NV_path_rendering extension, which would both be mapped to gl_PRIMARY_COLOR while they have different numerical values. Furthermore there are also similar clashes that would prevent the generation of extension grouping modules.

Implementation

The generator can roughly be split in several steps.

  1. Parsing of the specification files into a specific format (found in Spec.Parsing).
  2. Amending and filtering the specification. (found in Spec.Processing).
  3. Generating RawModules, a specification of the modules to be generated (found in the Modules namespace).
  4. Generating files from these RawModules (Currently done in Main and Code.ModuleCode).

Apart from these steps there are several other modules,

  • Modules.Types Defines the types for the abstract modules.
  • Spec.RawSpec Defines the types for working with the original specification.
  • Main.Options Defines the commandline options.
  • Main.Monad Defines the RawGen monads that distribute the options and does the error handling.

1. Parsing

The implementation is based around the .spec files from the OpenGL registry which provide a source of all function and enumerations in use. The files are parsed by a separately packaged spec parser.

2. Processing

The further processing is relatively simple. As the amount of extensions is quite large there is the possibility to exclude them based on vendor. Therefore a file (novendor) is used to filter the categories.

3. RawModule generating

The translation from the specification to code is done via RawModule, which specify the contents of a module in the final OpenGLRaw. This extra layer is added to separate the logic creating the contents from the actual templates used to generate the code. In addition these intermediate forms can be used to generate other output. Different types of modules to generate have all there own module,

  • Modules.Types Defines the RawModule and associated types.
  • Modules.Builder represents the builder monads used to generate them.
  • Modules.Compatibility has some functions for generating modules that are no longer present in the new file structure.
  • Modules.GroupModule has builders for modules that group other modules together to reexport them for easy imports (e.g. for Core and vendor modules).
  • Modules.Module makes the actual enumeration and functions.
  • Modules.Raw binds all the modules together to generate the full OpenGLRaw.

4. Generating output

The RawModules are used to generate to forms of output.

  • The real haskell modules are generated using the template from Code.ModuleCode.
  • Two listings specifying the internal modules (other-modules field in cabal) in modulesI.txt and the external modules (exposed-modules in cabal) in modulesE.txt.
  • The interface, which describes what each module defines, useful to lookup where a piece (function or enum) has been defined and what its haskell name and type are.

Dependencies

The generator has some quite some dependencies, of which some are managed by using git submodules. The current submodules are

  • CodeGenerating to add some extra functions to haskell-src-exts for generating source code.
  • opengl-xml the parser for the xml specification.
  • OpenGLRawgenBase basic types also used in the interface, which could be used without the generator. This also includes the interface reader and writer.

To simplify the installation (for both users and travis CI) there is a dependecy installation script depsinstall.sh. This should be invoked with your favorite cabal command e.g. ./depsinstall.sh cabal or ./depsinstall.sh cabal-dev. Doing so will update the git submodules and install all the dependencies.