-4

In the past years, I wrote much C source code, parts of which might also be useful to others. So I would like to restructure this code in a way such that it makes sense to publish it on Github and people can use it in a "usual" way. I guess, this would mean that there are certain structure conventions C libraries should be adapted to. However, I could not find out anything about this and, since I am unexperienced with using code of others, I do not see whether a given C library on Github is well structured or not. How do I determine whether a given repository has a good structure and I should take it as an example?

  1. What are mainstream conventions for directory structures of a C repository?
  2. What are mainstream conventions how new data types should be introduced?
  3. Is there a rule of thumb when multiple .c files should be compiled together and when they should be linked together?
  4. Is there a rule of thumb when different libraries, which are mutually dependent, should be put in the same or in different Gibhub repositories?
5
  • 2
    I’m voting to close this question because there's nothing about it which is specific to open source software, and it is off-topic for the programming-focused sites in the network because it is too broad - there is no "mainstream convention" (or rather, there are many conventions). Jun 11, 2022 at 20:15
  • Good structuring of libraries is specific to open-source software because this is an essential aspect to make more people be able to use these libraries. Also, if there are many conventions, please share them in order to help.
    – Kolodez
    Jun 11, 2022 at 20:29
  • Looks like it is unappreciated here if programmers want to start sharing their code and learn about how is the best way to do it.
    – Kolodez
    Jun 12, 2022 at 6:51
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer.
    – Community Bot
    Jun 12, 2022 at 10:02
  • My question is about "how communities collaborate together to produce, distribute ..." (opensource.stackexchange.com/help/on-topic). Yes, the question is quite general, but the answer of amon shows that my question can be answered precisely and helpfully. Others might also benefit from his answer. Imho, none of the criteria from opensource.stackexchange.com/help/dont-ask like "avoid asking subjective questions ..." is applicable. If I missed any guidelines, please link them, or please explain how specific at least a question must be and I'll be happy to edit the question.
    – Kolodez
    Jun 12, 2022 at 10:34

1 Answer 1

1

While there are a lot of Open Source C libraries, there are no particularly strong conventions for distributing them.

In the GNU and Linux ecosystems, it is reasonably common to use Autotools as a build system, so that users can download your source code and then run

./configure
make
sudo make install

to build and install the library.

But many developers do not like globally installed libraries, and would instead vendor your project (copying your files into their source tree) or use a Git-Submodule.

To make this simple, it is typically best if your projects do not have further dependencies, or at least make those dependencies very clear so that other developers can install them.

This ties into your question #4: If you can split thematically distinct parts into different projects, that's probably a good idea. This is the library-level equivalent to the OOP “interface segregation principle”, that users of your libraries should not be forced to depend on functionality they don't need. But since dependency management is such a pain for C projects, combining different parts into a monorepo is often the lesser evil.

Regarding #1, there are no strong conventions for project layouts. You will see everything from

  • a bunch of .c and .h files in the top level of a project, without any directories
  • a separate include directory for public headers (that dependent projects should add to their include path)
  • a src directory for the .c files and internal headers
  • if the repository contains multiple distinct libraries, separate directories for those libraries

If you do anything unusual, consider writing an architecture guide to help others navigate the code base.

Regarding #2, there are no special concerns for Open Source vs other code when it comes to introducing data types. As with all C projects, it makes sense to give those type names a project-specific prefix to prevent name clashes. As you evolve the layout of types, it is good to keep API- and ABI-compatibility in mind.

  • If your library is intended for static linking or is header-only, ABI compatibility doesn't matter. However, developers will appreciate API-stability so that they can upgrade to a new version of your library without having to update their code. For example, adding a field to a struct which is defined in a header file will break API compatibility, unless you provide a function or macro to initialize a default value for that struct.

  • Libraries intended for dynamic linking should be clear about their ABI compatibility guarantees, so that dependent code can use new versions of your library without needing a full recompilation. Anything that affects function signatures or struct layout will likely break binary compatibility. But there are well-known strategies to help here, such as using incomplete types in your header files so that dependent code can only handle pointers to such types.

Regarding #3, there's generally the expectation that one .c file is one compilation unit. If you want to combine a lot of code into a single compilation unit for linkage reasons (i.e. so that all the code has access to some static functions, enabling stronger optimizations), then I'd use the preprocessor to include those code fragments into a single .c file. Note that passing multiple .c files to a single compiler invocation (gcc -o foo file1.c file2.c) is just a shorthand for compiling and linking those files separately. It would be unusual to see this shorthand in build scripts.

1
  • Thank you very much, amon! Is there a tutorial or a good and clear Github example about how to create different repos where one depends on the other and uses it as a submodule? I don't want to just take a random repo as example and then find out years later that that was a bad example to follow.
    – Kolodez
    Jun 12, 2022 at 10:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.