Implementing C file streams (FILE *, fopen, fread, etc.) on embedded platform - c

I've been tasked with adding streams support (C89/C90) to the libraries for my company's legacy embedded C compiler. Our target hardware typically has 1MB or less of code space and does not have an operating system.
We have a lot of stream-like implementations throughout the codebase that I can use as a starting point. For example, a console that works over a TCP sockets or serial port, a web server that reads from FAT on SD card or in-memory file, and even a firmware updater that reads from many sources.
Before I go and re-invent the wheel, I'm wondering if there are existing implementations that I could either port or use as a starting point for my work. Even though we provide full source code to our customers, GPL-licensed code isn't an option since our customers don't want to release source code to their products.
Can anyone recommend a book (annotated Unix source, CompSci text) or public domain/BSD-licensed source? I'd prefer to look at an older OS targeted to a single device, as current operating systems contain a tangle of macros and layers of typedefs that make following even a simple struct definition difficult.

Take a look at P.J. Plauger's book The Standard C Library, which describes in detail one possible implementation of the complete C89 standard library.

You should be able to pull most of what you need from the source code for the GNU C standard library. It is licensed with the Lesser GPL, which means you can link to the library without affecting the license of your software (or forcing your customers to release their code). Porting this to your platform (thus keeping the LGPL-ed code in its own library) may be easier than implementing your own from scratch.
Several different projects have taken GNU GLIBC and optimized it for embedded systems. You may want to look at:
Embedded GLIBC (LGPL)
uLIBC (LGPL)
Newlib (multiple free licenses)
In particular, EGLIBC and uLIBC were designed to run properly on embedded systems that lack a MMU.
You can also have a look at BSD's implementation of libc
Alternatively there is STLSoft, who provides several libraries (including the C standard lib) under a BSD license. I can't attest to their quality since I haven't used their code myself, but it might be worth looking at if you can't work LGPL-ed code into your project.

Wouldn't *BSD (Net|Open|Free)'s libc be suitable? At least as a starting point.

Try looking at http://www.minix3.org/

Check your development tools. Some development tools come with their on source for their software libraries.
I took the source for the Compiler's printf and adapted for a debug port on an embedded system. There is less work when you have a foundation to build from.

Related

Newlib: embedded vs desktop

I'm compiling a Linux toolchain based on Newlib for a toy project.
Newlib's official page reports:
Newlib is a C library intended for use on embedded systems.
but without providing any particular reason.
What I'm trying to figure out is:
Why newlib consider itself embedded "only"?
What are the downsides to use it on desktop or server environments?
Unlike Glibc, which has very specific code to make sure that it is replaceable with later API compatible versions, the Newlib isn't so; nor does it support dynamic linking anyway. And it doesn't make much sense to statically link in the C library in every possible executable in a desktop environment. Therefore, Newlib is mostly suitable for embedded targets with small number of statically linked executables.
Newlib also fulfils only the parts of the C standard library and a a minimal part of the POSIX C library extensions. Specifically it doesn't concern itself with networking at all. It is somewhat debatable if anyone in their right mind, would want to build a desktop system without any networking at all, in 2017.
Another thing to note is the non-technical aspect of licensing. Glibc uses the LGPL license, which does allow linking against proprietary programs, provided that (note that IANAL) the user is able to replace the LGPL-licenced library with another one. In practice this means that either the library is dynamically linked in, or, in case of a statically linked library, the user is provided with object files that they can use to link against the replacement library to produce an executable. This means that the license itself might not be suitable for small embedded systems with proprietary software. Newlib doesn't contain any LGPL code, unless it is built for Linux targets.

Do you have to build a new compiler for a new operating system?

I would like to build an OS some time in the future, and now thinking of some light sketches on how it would be. I have pretty much been coding in C compiled for the Windows environment (and some little Java). I would have to recompile any of my C programs should I want to run it under Linux. So the binaries, the product of compilation, must be different for each operating system. If I design a totally new OS from scratch, for both hobby and academic purpose, without using the Linux kernel or any known base code of an OS, what I understand as to happen is that I cannot compile my C programs with GCC since my OS will not be among its target systems. Here my question written on the title emerges. Thanks in advance for any hints.
It depends. You could easily choose to re-use an existing compiler, such as the immemorial example GCC, and thus you would reap the benefits of an existing compiler. But there are some big provisos that must be cleared up.
Regards of whether or not you choose to build a new compiler, the challenge will remain in porting a C library. You technically can use C without a standard library (which is what the Linux kernel, or any self-hosted example for that matter, has to do, for example) but this is a ridiculous proposition for programs intended to run under an operating system, as most systems impose memory restrictions, etc, meaning that you cannot just have carte blanche in terms of using memory. Thusly, a C library call such as malloc is required.
Since any programs under your kernel (99% of your OS in all likelihood) will need a set of functions to link against, porting a C library is your biggest task. The C library is a huge monolith, and writing your own would be rather silly, especially with many implementations already available, the most well known being GCC's. So, the question you really should be asking is, do you want to write my own version of libc? (The answer is almost always no, and most alternative implementations are for niche use cases.) Plus, if you want to make your OS POSIX-compliant, then you'll have to implement more functions, adding to the hassle.
Whether you write your own compiler for your OS is a minor detail compared to which C library will be included with it. You can always use your own compiler with an already-written implementation of the C library.
My advice to your rather opinion-based question: no. Port an existing compiler such as GCC or clang, and then use that. Plus, that has several advantages:
Compatibility with existing tools and toolchains
A familiar program (no need for your users to learn how to use a new compiler)
They're open source - and in spite of that, you'd be insane to go at it alone. Heck, even Apple integrated two already existing compilers - GCC and clang - into their toolchains rather than do it themselves, and they're a billion-dollar company.
Take a look at this page. It demonstrates how to port GCC to your OS using Newlib as your C library.
No, you can just port an existing compiler. You can even choose an existing executable format, such as ELF, and use your standard GCC + GNU Binutils toolchain. You will need to port the standard library and C runtime, and you will need to write an ELF loader into your operating system.
I suspect the majority of the work will be in porting the C library.
A search turned up this page: Porting GCC to your OS
(1) No, you usually don't have to write your own compiler. Writing a good optimizing compiler can be actually big task which I would better avoid.
But in order to enable writing applications for your OS in some higher level language you will either need to provide
some (2.1) API emulation layer (so that code written and compiled for other OS can be run on your OS)
or you'll have to (2.2) port some existing compiler to your OS
or at least make your OS a new available (2.3) target platform in an existing compiler
or some other option I don't know about
The choices are multiple each with its own pros/cons.
Some examples (other then the obvious GCC already mentioned by #dietrich-epp, #sevenbits) to help you decide which way you want to follow:
(3.1) Free Pascal (see http://www.freepascal.org) compiler can be extended with another target platform
Free Pascal is a 32,64 and 16 bit professional Pascal compiler. It can target multiple processor architectures: Intel x86, AMD64/x86-64, PowerPC, PowerPC64, SPARC, and ARM. Supported operating systems include Linux, FreeBSD, Haiku, Mac OS X/iOS/Darwin, DOS, Win32, Win64, WinCE, OS/2, MorphOS, Nintendo GBA, Nintendo DS, and Nintendo Wii. Additionally, JVM, MIPS (big and little endian variants), i8086 and Motorola 68k architecture targets are available in the development versions
...
Source: http://www.freepascal.org
(3.2) Inferno Operating System (see http://www.vitanuova.com/inferno) has its own application language (see Limbo) with OS specific words, own compiler etc. Applications run in virtual machine (see Dis)
Inferno® is a compact operating system designed for building distributed and networked systems on a wide variety of devices and platforms. With many advanced and unique features, Inferno puts an unrivalled set of tools into your hands...Inferno can run as a user application on top of an existing operating system or as a stand alone operating system...
Source: http://www.vitanuova.com/inferno
(3.3) Squeak (see http://en.wikipedia.org/wiki/Squeak) is a self contained OS with graphics and everything. It uses Smalltalk-80 as the language. Compiler included, applications run in virtual machine (see Cog VM). The VM could be emitted as portable C code and then ported to a bare-bone hardware.
Squeak is a modern, open source, full-featured implementation of the powerful Smalltalk programming language and environment. Squeak is highly-portable, running on almost any platform you could name and you can really truly write once run anywhere. Squeak is the vehicle for a wide range of projects from multimedia applications and educational platforms to commercial web application development...
Source: http://www.squeak.org
(3.4) MenuetOS (see http://www.menuetos.net/) is 64bit OS written in assembly language. Flat Assembler (see FASM) compiler which can emit native binaries was ported to the OS including OS API and is included in basic installation. Later on C library was also ported
MenuetOS is an Operating System in development for the PC written entirely in 32/64 bit assembly language...supports 32/64 bit x86 assembly programming for smaller, faster and less resource hungry applications...Menuet isn't based on other operating system nor has it roots within UNIX or the POSIX standards. The design goal, since the first release in year 2000, has been to remove the extra layers between different parts of an OS, which normally complicate programming and create bugs...
Source: http://www.menuetos.net
(3.5) Google's Android OS (see Wikipedia: Android (operating system)) ported Java Virtual Machine (see Dalvik later replaced by Android Runtime) and provided OS APIs for the Java programming language, reusing existing compilers and IDEs just consuming the produced binaries
Android Runtime (ART) is an application runtime environment used by the Android mobile operating system. ART replaces Dalvik, which is the process virtual machine originally used by Android, and performs transformation of the application's bytecode into native instructions that are later executed by the device's runtime environment...
Source: http://en.wikipedia.org/wiki/Android_Runtime
There are many more useful examples available. Whether you have to or don't have to basically depends on the programming paradigm your new OS will introduce. Why you want to build it and how will it differ from the existing ones.
Examples for no are: (3.1), (3.4), (3.5)
Examples for yes are: (3.2), (3.3)

C Code is too heavily compiler dependent

I'm writing an OS that should run on a variety of SoCs (e.g: Xilinx Zync, Freescale QorIQ).
My problem, not all of the provided IDEs (given by Xilinx, Freescale, etc.) provide the same libraries (standard C & POSIX libraries).
For instance, the CodeWarrior IDE has the timespec structure, while Xilinx's doesn't.
Also, sleep is implemented in some of the provided libs, but I have my own implementation.
I want my code to be independent of the compiler (some manufacturers provide more than one IDE and with a different compiler).
Any suggestions?
My suggestion: Code to POSIX standards. Where the vendor library falls short of POSIX, implement a POSIX layer yourself.
Leave the core OS generally #ifdef-free, and put the mess in a conditionally-compiled compatibility layer.
The simple (though longer-to-implement) solution is to not depend on the library provided by the vendor. Write your own library. Probably this can be done with a little bit of layering. All of them provide strlen(), for example.

Operating system agnostic C library

Is there a C library available for operations such as file operations, getting system information and the like which is generic, which can be used when compiled in different platforms and which behaves in a similar way?
Edit: Something like Java or .NET platform abstracting the hardware.
Have you tried the standard library? It should be implemented on any system that has an ISO compliant C runtime.
Yes; the ISO Standard C library. It may not cover all the functionality you want, but that is exactly because it is generic, and as such is also lowest common denominator. It only supports features that can reasonably be expected to exist on most hardware, including embedded systems.
The way to approach this is perhaps to specify the range of target platforms you need to support, and then the application domains (e.g. GUI, networking, multi-threading, image processing, file handling etc.), and then select the individual cross-platform libraries that suit your needs. There is probably no one library to fulfil all your needs, and in some cases no common library at all.
That said, you will always be better served in this respect by embracing C++ where you can use any C library as well as C++ libraries. Not only is the C++ standard library larger, but libraries such as Boost, wxWidgets, ACE cover a broader domain spectrum too. Another approach is to use a cross-platform language such as Java, which solves the problem by abstracting the hardware to a virtual machine. Similarly .NET/Mono and C# may provide a solution for suitably limited set of target platforms.
Added following comment:
Hardware abstraction in a real-machine targeted language (as opposed to a VM language such as Java or CLR based languages) is provided by the operating system, so what you perhaps need is a common operating system API. POSIX is probably the closest you will get to that, being supported on Linux, Unix, OSX (which is Unix), QNX, VxWorks, BeOS and many others; but not importantly Windows. One way of using POSIX on Windows is to use Cygwin. Another is to use a VM to host a POSIX OS such as Linux.
For anything not found in the standard library, GLib is a good first place to look along with other libraries built to interact with it. It offers for example threads, mutexes and IPC that you won't be able to write portably using plain standard libraries, and you can use many more GNU libraries that follow the same conventions up to a full GUI in GTK+. GLib supports the usual popular operating systems.
If the C standard library is not sufficient for your needs, a minimal hyperportable subset of POSIX might be the target you want to code to. For example, the main non-POSIX operating system Windows still has a number of functions with the same names as POSIX functions which behave reasonably closely - open, read, write, etc.
Documenting what exactly a "hyperportable subset of POSIX" includes, and which non-POSIX operating systems would conform to such a subset, is a moderately difficult task, which would be quite useful in and of itself for the sake of avoiding the plague of "MyCompanyName portable runtime" products which appear again and again every few years and unnecessarily bloat popular software like Firefox and Apache.
If you need facilities beyond what the Standard C library provides, take a look at the Apache Portable Runtime (APR). You should also review whether POSIX provides the functionality you are after, though that comes with its own bag of worms.
If you want to get into graphics and the like, then you are into a different world - GTK, Glib and Qt spring to mind, though I've not used any of them.

Writing cross-platform apps in C

What things should be kept most in mind when writing cross-platform applications in C? Targeted platforms: 32-bit Intel based PC, Mac, and Linux. I'm especially looking for the type of versatility that Jungle Disk has in their USB desktop edition ( http://www.jungledisk.com/desktop/download.aspx )
What are tips and "gotchas" for this type of development?
I maintained for a number of years an ANSI C networking library that was ported to close to 30 different OS's and compilers. The library didn't have any GUI components, which made it easier. We ended up abstracting out into dedicated source files any routine that was not consistent across platforms, and used #defines where appropriate in those source files. This kept the code that was adjusted per platform isolated away from the main business logic of the library. We also made extensive use of typedefs and our own dedicated types so that we could easily change them per platform if needed. This made the port to 64-bit platforms fairly easy.
If you are looking to have GUI components, I would suggest looking at GUI toolkits such as WxWindows or Qt (which are both C++ libraries).
Try to avoid platform-dependent #ifdefs, as they tend to grow exponentially when you add new platforms. Instead, try to organize your source files as a tree with platform-independent code at the root, and platform-dependent code on the "leaves". There is a nice book on the subject, Multi-Platform Code Management. Sample code in it may look obsolete, but ideas described in the book are still brilliantly vital.
Further to Kyle's answer, I would strongly recommend against trying to use the Posix subsystem in Windows. It's implemented to an absolute bare minimum level such that Microsoft can claim "Posix support" on a feature sheet tick box. Perhaps somebody out there actually uses it, but I've never encountered it in real life.
One can certainly write cross-platform C code, you just have to be aware of the differences between platforms, and test, test, test. Unit tests and a CI (continuous integration) solution will go a long way toward making sure your program works across all your target platforms.
A good approach is to isolate the system-dependent stuff in one or a few modules at most. Provide a system-independent interface from that module. Then build everything else on top of that module, so it doesn't depend on the system you're compiling for.
XVT have a cross platform GUI C API which is mature 15+ years and sits on top of the native windowing toollkits. See WWW.XVT.COM.
They support at least LINUX, Windows, and MAC.
Try to write as much as you can with POSIX. Mac and Linux support POSIX natively and Windows has a system that can run it (as far as I know - I've never actually used it). If your app is graphical, both Mac and Linux support X11 libraries (Linux natively, Mac through X11.app) and there are numerous ways of getting X11 apps to run on Windows.
However, if you're looking for true multi-platform deployment, you should probably switch to a language like Java or Python that's capable of running the same program on multiple systems with little or no change.
Edit: I just downloaded the application and looked at the files. It does appear to have binaries for all 3 platforms in one directory. If your concern is in how to write apps that can be moved from machine to machine without losing settings, you should probably write all your configuration to a file in the same directory as the executable and not touch the Windows registry or create any dot directories in the home folder of the user that's running the program on Linux or Mac. And as far as creating a cross-distribution Linux binary, 32-bit POSIX/X11 would probably be the safest bet. I'm not sure what JungleDisk uses as I'm currently on a Mac.
There do exist quite few portable libraries just examples I've worked within the past
1) glib and gtk+
2) libcurl
3) libapr
Those cover nearly every platform and so they are extremly useful tool.
Posix is fine on Unices but well I doubt it's that great on windows, besides we do not have any stuff for portable GUIs there.
I also second the recommendation to separate code for different platforms into different modules/trees instead of ifdefs.
Also I recommend to check beforehand what are the differences in you platforms and how you could abstract them. E.g. this is some OS related stuff (e.g. the annoying CR,CRLF,LF in text files), or hardware stuff. E.g. the previous mentioned posix compability doesnt stop you from
int c;
fread(&c, sizeof(int), 1, file);
But on different hardware platforms the internal memory layout can be complete different (endianess), forcing you to use conversion functions on some of the target platforms.
You can use NAppGUI for both console and desktop apps. The SDK uses ANSI-C and your code will work on Windows/macOS/Linux.
https://www.nappgui.com
It's free and OpenSource.

Resources