Make part of a C lib "private" - c

I'm developing a shared library, and since the code is big, I've decided to split it in many headers and source files, like any normal program :).
The problem is that most of these headers are for internal use, i.e. I don't want them to be accessible from outside of my library. So I'm thinking to move them all to a big source file and only provide headers for what is going to be visible.
It's a good idea do that? Should I worry on visibility?
Thanks

Instead of merging the headers, just keep them alongside your source files and don't "publish" them as a part of your development package. As an example of this, the linux kernel has many headers in the source tree, but only certain headers are exposed to applications (in the include structure).

You should approach it from a "cleanliness" angle; don't ship headers which include functions you aren't intending people to call. Don't document functions which you aren't shipping headers for.
If someone really wants to call a function in your library, they can, but you should try to make it clear that that's an unsupported use case and it's their problem if it all goes wrong.

Yes you should worry about symbol visibility. On Windows, set up to use DLLEXPORT. On Linux, define DLLEXPORT to set default symbol visibility, but compile everything with -fvisibility=hidden. There's an Ulrich Drepper article on it that is useful.
For the include files, you can separate them into directories and/or you can use your packaging system to just copy the public files.

Related

What, if any, are the disadvantages having a header file of header files?

I came onto a project that employs the method of using a header file MyProject.h that has all the headers of each .c file. Each .c file has their own header file that has #include "MyProject.h", whatever libraries are needed, and any other declarations necessary for the file.
To me it seems redundant and somewhat unnatural, but it compiles and subsequently runs as expected. My thought is that the compiler would be doing way more work than necessary and is possibly over-bloating the .exe. What are the disadvantages, if any, to doing this?
A subsequent question I have is, say I included a library like Time.h in one file using the above example. Will the compiler only build Time.h once into the binary or for every file now because of MyProject.h? What about with structs, enums, etc...?
To have such a header file is poor practice and bad design. The problem is that it will create a tight coupling dependency between every single file of your project, even if they are completely unrelated.
Good program design is to create autonomous modules that only include the resources they are using. They should do this from their own h files, to document exactly which dependencies a particular module has.
The main downside is increased build times. Every source file includes every header of the project, whether it needs it or not.
It's also conceptually unclean. A source file should include the headers it needs. It should be possible to search for a header's name to find the parts of the source code that uses these facilities. Minimizing unnecessary includes is evidence of a loosely coupled system. However, include-what-you-use is hard to enforce, because you cannot prevent transitive availability of facilities through headers in C.
It should not lead to increased executable size. Even if the headers contain code (which is rare in C, but common in C++), the linker should eliminate duplicates and remove unused code.
All previous answers were clear enough, but.
The main disadvantage of "one big header file" is the problem with code reusability. For example, you've created some module as a part of your application. Let's say, this module implements API for some hardware. And then you want to make another application, which should use this module.
In this case you have to remember which header files you have to include to compile this module, or, if you just copy your previous "big header file", it requires a lot of unnecessary third party libraries and header files.
Nobody wants to spend a lot of time to make some module working. It's much better if you can use it right out-of-the-box, isn't it?
Most of my libraries have one precompiled header containing external includes and one "main" header for each library that contains the precompiled header items + all the .h files for the library in question. All of my .cpp files first include the precompiled header and then the main header.
That's it. None of my other .h files have any includes in at all. My .cpp files only include these two headers. Other libraries that need to use the library will #include that same main header.
Doing this has greatly simplified header file headache/complexity issue for me though I would add that most of my libraries are relatively small in the grand scheme of things. I don't know if this would work for a very large (monster) project. Perhaps not.
The way this works is actually quite nice. Others above, concerned about "coupling" want to minimise it, but if you don't include any headers at all you're 100% uncoupled, even from your dependencies. If you want to reuse the class, use the library that contains it.
Simple.

Cross-platform Library

Basically, I want to seperate some common functionality from existing projects into a seperate library project, but also allow a project to remain cross-platform when I include this library.
I should clarify that when I say "cross-platform" I'm primarily concerned with compiling for multiple CPU architectures (x86/x86_64/ARM).
I have a few useful functions which I use across many of my software projects. So I decided that it was bad practice to keep copying these source code files between projects, and that I should create a seperate library project from them.
I decided that a static library would suit my needs better than a shared library. However, it occurred to me that the static library would be plaform dependent, and by including it with my projects that would cause these projects to also be platform dependent. This is clearly a disadvantage over including the source code itself.
Two possible solutions occur to me:
Include a static library compiled for each platform.
Continue to include the source code.
I do have reservations about both of the above options. Option 1 seems overly complex/wasteful. Option 2 seems like bad practice, as it's possible for the "library" to be modified per project and become out-of-sync; especially if the library source code is stored in the same directory as all the other project source code.
I'd be really grateful for any suggestions on how to overcome this problem, or information on how anyone else has previously overcome this problem?
You could adopt the standard approach of open source project (even if your project is not open source). There would be one central point where one can obtain the source code, presumably under revision control (subversion, git...). Anyone who wishes to use the library should check out the source code, compile it (a Makefile or something similar should be included), and then they are all set. If someone needs to change something in the library, they do so, test their changes, and send you a patch so that you can apply the change to the project (or not, depending on your opinion on the patch).

XC8 Library organization and #defines across multiple source files

This is a complicated post so please be patient. I have tried to condense it as much as possible...
I am coming to XC8 from using a different tool chain for PIC microcontrollers. With the previous compiler, setting up and using my own libraries and using defines across those libraries seems to be much easier.
I want to write my own libraries of functions for re-use. I also want to store them all in a directory structure of my own choosing (this is so that they sync automatically between multiple machines and for various other reasons). Here is a simplified fictional file structure.
\projects\my_project //the current project directory
\some_other_directory\my_library\comms_lib //my communications library
\some_other_directory\my_library\adc_lib //my ADC library
Now let’s say for arguments sake that each of my libraries needs the __XTAL_FREQ definition. The frequency will likely be different for each project.
Here are my questions:
What is the best/most efficient way to tell the compiler where my library files are located?
Short of adding __XTAL_FREQ to every header file how do I make the define available to all of them?
Likely someone is going to say that it should be in a separate header file (let’s call it project_config.h). This file could then be located with each future project and changed accordingly. If the separate header file is the answer then question that follows is, how do I get the library headers (not in the same directory as the project) to reference the project_config.h file correctly for each new project?
Thanks in advance, Mark
If you are using MPLABX, you could consider making one or more library projects for your libraries, which can then be included from other MPLABX projects.
As for a global definition of __XTAL_FREQ, I'm thinking that it should be possible to pass a symbol definition to the command line, not sure though.

Reliable portability for C code without relying on the preprocessor

Relying on the preprocessor and predefined compiler macros for achieving portability seems hard to manage. What's a better way to achieve portability for a C project? I want to put environment-specific code in headers that behave the same way. Is there a way to have the build environment choose which headers to include?
I was thinking that I'd put the environment-specific headers into directories for specific environments. The build environment would then just copy the headers from the platform's directory into the root directory, build the project, and then remove the copies.
That depends entirely on your build environment of course and has nothing to do with C itself.
One thing you can try is to set up your include paths in your makefiles thus:
INCDIRS=-I ./solaris
#INCDIRS=-I ./windows
#INCDIRS=-I ./linux
:
CC=gcc $(INCDIRS) ...
and uncomment the one you're working on. Then put your platform specific headers in those directories:
./solaris/io.h
./windows/io.h
./linux/io.h
You could, at a pinch, even have different platform makefiles such as solaris.mk and windows.mk and not have to edit any files at all.
But I don't see your aversion to the preprocessor, that's one of the things it's good at, and people have been doing it successfully for decades. On top of that, what happens when your code needs to change per-platform. You can abstract the code into header files but that seems far harder to manage than a few #ifdefs to me.
This is basically what a configure script does - i.e. work out the specifics of the system and then modify the makefile for that system. Have a look at the documentation for GNU autoconf, it might do what you want, although I'm not sure how portable it would be to windows if that is necessary.
pax's answer is good, but I'll add that you can
Mix and Match Handle some system dependencies in the build system (big things, generally) and others with the preprocessor (small things)
Confine the trouble Define a thin glue layer between your code and the system dependent bits, and stick all the preprocessor crap in there. So you always call MyFileOpen() which calls fopen on unix and something else on windows. Now the only part of your code that has any preprocessor cruft related to file opening is the MyFileOps module.

Exporting shared library symbols in a crossplatform way?

Is there a cross platform way to selectively export certain functions and structs from a C project which builds a shared library?
I want to do in a way that does not require a specific build system (the visibility should be defined in the code, eg as a macro), and in a way which both GCC and MSVC can understand.
Thank you.
Strictly no, of course, because the toolchains aren't the same.
But people do this. The complexities are that in windows, you need to
specifically tag the declarations of functions you want exported from
a DLL with __declspec(dllexport) in the location in the library where
the function is defined and __declspec(dllimport) in the locations
in client code where the funciton is referenced. Because standard
C practice has only one declaration in a single header file, this
means that you generally need to do some macro work to have a single
prefix that works in both locations. It seems like every project
picks its own standard for this.
On the Unix side, you don't need to tag exports at all, which is nice.
This is because every non-static function is exported by default,
which is not so nice. Often you can get away with this as long as
your non-public/non-static symbols have sane prefixes, which is what
most projects seem to do. If you need finer control over your
exported symbols, you can use a Solaris-style "mapfile" with the GNU
linker's --version-script (-M under solaris) argument to define explicitly which symbols should appear
in the external namespace.
There are a few more gotchas between the platforms, like the way the
per-library global namespace works and the handling of
startup/shutdown code. Basically, it's a rats nest that can't be
sanely explained in a post this short, but as long as you're careful
that your library contains simple functions and your namespace doesn't
pollute, you shouldn't have much trouble. Look to some of the more
popular cross-platform shared libraries (e.g. Qt, Glib/Gtk+, anything
distributed with msys, etc...) for guidance.

Resources