Difference between revisions of "Deimos"

From D Wiki
Jump to: navigation, search
(Translation: Mention .di files and the inline pragma)
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
Deimos is an endeavor to host and maintain D bindings for popular libraries and projects, notably which have a C ABI.
+
Deimos is an endeavor to host and maintain D bindings for popular non-D libraries and projects, notably which have a C ABI.
  
 
The original proposal for Deimos can be found in [[DIP12]].
 
The original proposal for Deimos can be found in [[DIP12]].
Line 11: Line 11:
  
 
Agreeing on a common layout and conventions will also make usage and contribution easier.
 
Agreeing on a common layout and conventions will also make usage and contribution easier.
 +
 +
Hosting bindings under the D-Programming-Deimos organization is orthogonal to, and provides benefits in addition to, publishing the bindings on the Dub registry (code.dlang.org).
  
 
== Description ==
 
== Description ==
  
A repository for each project is created under https://github.com/D-Programming-Deimos. It should have the following directory structure:
+
A repository for each project is created under https://github.com/D-Programming-Deimos.
 +
 
 +
Following these conventions should maximize consistency and simplify distribution / usage:
 +
 
 +
=== Directory structure ===
 +
 
 +
Repositories have the following directory structure:
  
 
  |--- library name (repository root)
 
  |--- library name (repository root)
Line 23: Line 31:
 
         |--- bar
 
         |--- bar
 
             |--- baz.h
 
             |--- baz.h
     |--- deimos
+
     |--- source
        |--- foo.d
+
        |--- deimos
        |--- bar
+
            |--- foo.d
            |--- baz.d
+
            |--- bar
 +
                |--- baz.d
  
 
The C directory should contain a copy of the original C headers that were translated. Doing so allows updating them to newer versions easily, as only the diffs between the old and new C headers need to be translated and applied to the D bindings.
 
The C directory should contain a copy of the original C headers that were translated. Doing so allows updating them to newer versions easily, as only the diffs between the old and new C headers need to be translated and applied to the D bindings.
  
The layout of the C directory corresponds to /usr/include on UNIX machines. Thus, if a C header file would be installed to <tt>/usr/include/bar/baz.h</tt>, in the repository it should be added as <tt>C/bar/baz.h</tt>.
+
The layout of the C directory corresponds to <code>/usr/include</code> on UNIX machines. Thus, if a C header file would be installed to <code>/usr/include/bar/baz.h</code>, in the repository it should be added as <code>C/bar/baz.h</code>.
  
The D module/package names should map such that <tt>#include &lt;path/to/header.h&gt;</tt> should correspond to <tt>import path.to.header;</tt>.
+
The D module/package names should map such that <code>#include &lt;path/to/header.h&gt;</code> should correspond to <code>import deimos.path.to.header;</code>.  
  
The D import files should try to do as least modifications as possible to simplify updates of the C headers. This includes leaving comments intact (unless e.g. adapting them to [https://dlang.org/spec/ddoc.html DDoc] syntax).
+
Module and package names should match file and directory names, i.e. the module <code>path.to.header</code> should be at <code>deimos/path/to/header.d</code> (or <code>.di</code>), but not somewhere else.
  
Translated header should not require linkage of any D binary. Macros can be written as templates, e.g.:
+
==== Recommendations ====
  
C: #define GET(x) x.value
+
* Each library should contain a README file (<code>README</code>, or <code>README.md</code> for Markdown syntax) in the root folder.<br>The README file should contain exact source and version of the C library.<br>Any specific notes regarding the usage or translation of the bindings should also be placed there.
D: int GET(X)(X x) { return x.value; }
 
  
Version tags should match the ones being used by the C headers.
+
* Every library should contain a simple D example under an examples directory.
  
The copyright for the D import files should match the one being used by the C header as they constitute a derived work.
+
=== Translation ===
  
If the C header file has a name that is a D keyword, an underscore will be appended to the D module name.
+
<ul>
 +
<li>Deimos repositories should aim to provide 1:1 bindings of C APIs, without any higher-level wrapping. Higher-level wrappers can be included alongside low-level ones, but are best provided as separate projects / repositories on top of the Deimos bindings.<br><b>Rationale</b>:
 +
<ul><li>Low-level bindings will generally satisfy the constraints of all D projects, regardless of platform / architecture / toolchain, and usable from <code>nothrow</code> / <code>@nogc</code> / <code>-betterC</code> code. Higher-level bindings will generally compromise on some of these constraints in order to provide a more idiomatic D API.
 +
<li>Low-level bindings, being a 1:1 translation of C header files, are generally uncontroversial (as in, there isn't really more than one way to write them). Higher-level wrappers can be potentially written using a variety of approaches / paradigms / style, thus there not being one single obviously correct way to write them.</ul>
  
If a C type name matches a C function name (stat), the type name will have a "_t" appended.
+
<li>The D import files should try to do as least modifications as possible to simplify updates of the C headers. This includes leaving comments intact (unless e.g. adapting them to [https://dlang.org/spec/ddoc.html DDoc] syntax).
  
== Recommendations ==
+
<li>The copyright for the D import files should match the one being used by the C header as they constitute a derived work.</li>
  
Each library should contain a README in the root folder. The README file should contain exact source and version of the C library. Furthermore, it should contain specific notes about the usage of the D import file.
+
<li>If the C header file has a name that is a D keyword, an underscore will be appended to the D module name and file name.
  
Every library should contain a simple D example under an examples directory.
+
<li>If a C type name matches a C function name (e.g. <code>stat</code>), the type name will have a <code>_t</code> appended (e.g. <code>stat_t</code>).
 +
 
 +
<li>Ideally, translated header modules should not require linkage of any D binary (library or object file). The <code>.di</code> file extension should be used for all bindings files. Macros and inline functions can be translated as templates, e.g.:
 +
 
 +
<ul>
 +
<li><b>C</b>: <code>#define GET(x) x.value</code>
 +
<li><b>D</b>: <code>int GET(X)(X x) { pragma(inline, true); return x.value; }</code>
 +
</ul>
 +
 
 +
One way to test if your bindings satisfy this property is to write a program making use of these bindings, and compile it without including the bindings' source files in the compilation, e.g. <code>dmd -Lmytestlib.lib test.d</code> (as opposed to using <code>dub</code>, <code>rdmd</code>, or <code>dmd -i</code>).
 +
</ul>
 +
 
 +
=== Versioning ===
 +
 
 +
When the bindings target a specific version of the library, version tags should match the ones being used by the C headers.
 +
 
 +
For repositories providing bindings for projects which use a versioning scheme incompatible with semantic versioning, the preferred approach is to use semantic versioning and append the original library version past a <code>+</code> sign.
  
 
== Submitting ==
 
== Submitting ==
Line 68: Line 95:
  
 
If you get no response to your pull request, or if you would like to be added as a project maintainer, ping an [https://github.com/orgs/D-Programming-Deimos/people organization member].
 
If you get no response to your pull request, or if you would like to be added as a project maintainer, ping an [https://github.com/orgs/D-Programming-Deimos/people organization member].
 
 
  
 
[[Category:Binding]]
 
[[Category:Binding]]

Latest revision as of 01:07, 4 January 2023

Deimos is an endeavor to host and maintain D bindings for popular non-D libraries and projects, notably which have a C ABI.

The original proposal for Deimos can be found in DIP12.

Rationale

Having a central place for bindings allows them to be:

  1. easily discovered;
  2. maintained by the community, even past the original author's interest in the project.

Agreeing on a common layout and conventions will also make usage and contribution easier.

Hosting bindings under the D-Programming-Deimos organization is orthogonal to, and provides benefits in addition to, publishing the bindings on the Dub registry (code.dlang.org).

Description

A repository for each project is created under https://github.com/D-Programming-Deimos.

Following these conventions should maximize consistency and simplify distribution / usage:

Directory structure

Repositories have the following directory structure:

|--- library name (repository root)
    |--- README.md
    |--- dub.sdl
    |--- C
        |--- foo.h
        |--- bar
            |--- baz.h
    |--- source
        |--- deimos
            |--- foo.d
            |--- bar
                |--- baz.d

The C directory should contain a copy of the original C headers that were translated. Doing so allows updating them to newer versions easily, as only the diffs between the old and new C headers need to be translated and applied to the D bindings.

The layout of the C directory corresponds to /usr/include on UNIX machines. Thus, if a C header file would be installed to /usr/include/bar/baz.h, in the repository it should be added as C/bar/baz.h.

The D module/package names should map such that #include <path/to/header.h> should correspond to import deimos.path.to.header;.

Module and package names should match file and directory names, i.e. the module path.to.header should be at deimos/path/to/header.d (or .di), but not somewhere else.

Recommendations

  • Each library should contain a README file (README, or README.md for Markdown syntax) in the root folder.
    The README file should contain exact source and version of the C library.
    Any specific notes regarding the usage or translation of the bindings should also be placed there.
  • Every library should contain a simple D example under an examples directory.

Translation

  • Deimos repositories should aim to provide 1:1 bindings of C APIs, without any higher-level wrapping. Higher-level wrappers can be included alongside low-level ones, but are best provided as separate projects / repositories on top of the Deimos bindings.
    Rationale:
    • Low-level bindings will generally satisfy the constraints of all D projects, regardless of platform / architecture / toolchain, and usable from nothrow / @nogc / -betterC code. Higher-level bindings will generally compromise on some of these constraints in order to provide a more idiomatic D API.
    • Low-level bindings, being a 1:1 translation of C header files, are generally uncontroversial (as in, there isn't really more than one way to write them). Higher-level wrappers can be potentially written using a variety of approaches / paradigms / style, thus there not being one single obviously correct way to write them.
  • The D import files should try to do as least modifications as possible to simplify updates of the C headers. This includes leaving comments intact (unless e.g. adapting them to DDoc syntax).
  • The copyright for the D import files should match the one being used by the C header as they constitute a derived work.
  • If the C header file has a name that is a D keyword, an underscore will be appended to the D module name and file name.
  • If a C type name matches a C function name (e.g. stat), the type name will have a _t appended (e.g. stat_t).
  • Ideally, translated header modules should not require linkage of any D binary (library or object file). The .di file extension should be used for all bindings files. Macros and inline functions can be translated as templates, e.g.:
    • C: #define GET(x) x.value
    • D: int GET(X)(X x) { pragma(inline, true); return x.value; }

    One way to test if your bindings satisfy this property is to write a program making use of these bindings, and compile it without including the bindings' source files in the compilation, e.g. dmd -Lmytestlib.lib test.d (as opposed to using dub, rdmd, or dmd -i).

Versioning

When the bindings target a specific version of the library, version tags should match the ones being used by the C headers.

For repositories providing bindings for projects which use a versioning scheme incompatible with semantic versioning, the preferred approach is to use semantic versioning and append the original library version past a + sign.

Submitting

To propose a new binding project to be added to Deimos, contact a member of the D-Programming-Deimos organization:

https://github.com/orgs/D-Programming-Deimos/people

If you are already a member of D-Programming-Deimos, consider making your membership public, so that you can be contacted by submitters.

Contributing

To submit updates or improvements, send a pull request as usual.

If you get no response to your pull request, or if you would like to be added as a project maintainer, ping an organization member.