ClangSharp icon indicating copy to clipboard operation
ClangSharp copied to clipboard

Windows header binding generation workflow concerns

Open nathan-alden-sr opened this issue 5 years ago • 0 comments

Related to #131 #132.

To set the stage, I'll state some facts up-front. TerraFX's organization is the following:

  • The generation folder is mapped to headers in the shared and um Windows SDK folders
  • The sources folder tends to map to specific Windows API DLLs with certain exceptions (e.g., TerraFX.Interop.Windows).

Windows headers can contain at least three basic elements:

  • Type declarations (usually structs)
  • Function declarations
  • Macros

ClangSharp's API as exposed through generate.rsp unfortunately forces a 1:1 relationship between header file and output project (DLL). The reality is that function declarations in many Windows headers do not map cleanly in this way; WinBase.h, for example, declares functions that live in several DLLs. The impact on my workflow is that I have to do the following, using WinBase.h as an example:

  1. Choose a DLL I care about (e.g., advapi32.dll)
  2. Change um/WinBase/generate.rsp to output to TerraFX.Interop.Advapi32
  3. Run the generator
  4. Delete all content that doesn't belong in TerraFX.Interop.Advapi32, specifically types that I might not consider logically related to advapi32.dll and function declarations belonging to other DLLs
  5. Note any remappings that I have to add (e.g., HANDLE, ULONG_PTR, etc. etc.)
  6. Rerun the generator
  7. Go to step 4 until all desired mappings are correct

The problem is that steps 4 through 7 are very time-consuming as I am forced to delete the same unwanted generated artifacts over and over, potentially 10s of times depending on the number of remappings I have to add. Also, generate.rsp must have some --libraryPath specified, even if there is a set of DLLs to choose from. This could be confusing to people who don't understand the nuances because they may think all bindings belong in Advapi32.

There are many headers that we consider "low-level" enough to output their types to TerraFX.Interop.Windows, regardless of whether those same headers contain function declarations living in different DLLs. The currently strategy of most of the sources projects "owning" generated bindings from specific headers might not be the correct one. A better approach may be to make the projects more granular, where projects named after DLLs contain only function exports and exported types and macros are put in a separate project named after the header, with project references linking them together.

If the project structure is changed to be more granular then ClangSharp's CLI would also have to change. Fine-grained control over target directories, projects, etc. should be allowed on a per-type and per-function declaration level, with the goals being to remove any ambiguity about where the generated bindings should live for any header and avoid repetitive generate/delete/modify workflows. As referenced in one of the linked issues, the ability to include only specific types and function declarations per generator execution would be very useful as it would allow me to slowly work my way through a header with many function declarations, mapping them explicitly to the correct DLL project and avoiding aforementioned generate/delete/modify workflows.

nathan-alden-sr avatar May 12 '20 17:05 nathan-alden-sr