Build C++ unit tests for C89 code - c++

I'm hoping this won't turn to a dead end, but here's what I would like to do. Please let me know if this is even remotely possible, or if you have another good (or better) approach.
I'm working on a legacy code base that's C89 standard (what year is it again?) and I would like to build unit tests for some parts of the software. The C unit test frameworks I've found do not seem nearly as useful and easy as the Catch framework in C++, or really most other C++ unit test framework for obvious reasons. Thus, I would like to build these unit tests in C++.
There exists some homebrew build process that will build whatever application you're working on, all using the C89 standard. The system was built because there are a lot of shared dependencies among projects, and this was made before better alternatives existed. What I would like to do is use the artifacts built from that process to be linked in to a C++ unit test application. I could, alternatively, try to find all the dependencies and build them in to the unit test, but that's 1. redundant to rebuild, 2. cumbersome, and 3. removes the C89 compiledness of them, which I'd like to maintain to ensure the code I'm testing will be exactly as it runs for the end user (compiled in C89, not C++).
Using the same compiler (gcc), is this possible to accomplish, or am I stuck with C unit test frameworks? Some technical explanation either way would be very helpful, since I'm not too familiar with the differences among the different language and standard library artifacts (other than the library itself is different). Also, note that at this point changing the build process is (unfortunately) not feasible (read: in the budget).

Converting comments into an answer
In my view, it should be doable provided that you have suitable headers for all the parts of the system that will be exploited by the C++ unit test code. Those headers should be usable by the C++ compiler, and will need to be wrapped inside extern "C" { and a matching }. This might be done inside the unit test code or in the main (C) headers (based on #if defined(__cplusplus)). If you don't have headers that can be compiled by C++, then it is not going to be possible until you do have appropriate headers.
Can I link my C++ unit test executable directly with the C89 objects? No worries about potential conflicts using different versions of the standard library in the same application?
You will be linking with the C++ compiler. You might need to add -lc to the link line, but probably won't. The C library will be the same as you used anyway — there isn't a separate C89 library and C99 library and C11 library. So, although your code under test is written to C89 and your code testing it is in C++11, the C code will be using the current C library and test code will be using the C++ library. The C++ code will be using facilities in the C++ std namespace, so you shouldn't run into any troubles there. That said, I've not validated this, but it is the sort of thing that compilers get right.
There's a book Test Driven Development for Embedded C which recommends C++ unit test frameworks for testing (embedded) C code.

Code is easily included in a C++ project simply by linking in your C object files (.o, .a). C header files are included in the C++ project wrapped with extern "C", e.g.
extern "C" {
#include "my_c_header.h"
}
You might get weird compile- and run-time issues. Look out for some C legacy code gotchas like #defining bool and replacing allocators with custom memory management schemes. -_-'

Related

Use multiple different implementations of library in one program (unit tests)

During writing of unit tests I found that I need to implement "dummy" version of some library in one of unit tests. However the same library is used in its standard version in other unit tests. The obvious way how to solve this issue is to compile unit tests as two (or more) standalone programs (executables).
However, this solution does not satisfy my ambition ;-). I think that there should be a way how to compile one library against another library "statically" (in sense of "static function"). In other words: some used libraries are encapsulated in my library but the rest of program uses another implementation of used libraries.
Any ideas how to achieve that?
Our tests are build on unity and compiled with gcc and cmake.

Mix C and C++ with CMake

I have a project written in C (on Linux) and now want to use a third-party C ++ library that provides .h and .c source files.
I renamed the .c file to .cpp and then include this library in the C project. However, the following error appears when compiled:
unknown type name ‘class’
Added: The third-party library is here https://github.com/0xmalloc/c-log
The author say it's friendly to both C and C++
There are two options here:
you make your whole project a C++ one - this doesn't mean you need to convert your C code to C++ but rather that you will probably have to touch this and that part of it and also go for a C++ and not C-only compiler
provide wrappers - usually if you write C++ code in C style (no classes etc.) you will only have to do that extern "C" void foo() routine for your C++ functions. However the moment you start working with features that C doesn't support you will have to provide wrappers for your C++ functionality so that it can be exposed to the C part of your application. Such procedure can be from very easy to incredibly complex. For example many modern C/C++ API also provide Python API. In order to do that without having to rewrite everything in Python the authors create wrappers that translate the C/C++ functionality to Python. Depending on how well this is done features of the target language (Python in case we go from C/C++ to Python) can be used to allow better error handling, type checking, readability, native (to the target language) data containers etc.
I do believe that the author of the library misled you since the library is clearly for C++ (the classes in the header are definitely the most obvious thing that just screams C++).

Mixing C and C++ on an embedded system

So I'm having the following problem:
I have an MEMS board that runs on FreeRTOS and includes gyro, accelerometer and magnetometer.
I cannot change any existing code (All in C).
Now I have a basic motion detection library written in C++ and I extended this library with some functions (All in C++).
I thought I can just use a C++ compiler and compile everything but I'm getting hundreds of errors.
I found some solution how to use C functions inside C++ but I don't know how to use C++ functions (or libraries) inside C.
Is there a feasible way? Can I somehow wrap all my C++ code in an easy way?
I'm using Keil uvision to compile the code for my embedded system in case that is important.
There are a few differences between C and C++ that may make a compiler stumble over some of the code. See for example the wikipedia page on this topic.
I'd suggest that you split your project into two projects, one being the RTOS and application in C, the other being the motion detection library. Then you have to write a C wrapper around your C++ library API. Here's a good SO post on writing a C wrapper for C++ code.
Then you would have to link your RTOS + application project to your library, which you compiled in your other uVision project.

Where is the standard library?

I have searched Google but haven't found quite a direct answer to my queries.
I have been reading C++ Primer and I'm still quite new to the language, but despite how good the book is it discusses the use of the standard library but doesn't really describe where it is or where it comes from (it hasn't yet anyway). So, where is the standard library? Where are the header files that let me access it? When I downloaded CodeBlocks, did the STL come with it? Or does it automatically come with my OS?
Somewhat related, but what exactly is MinGW that came with Cobeblocks? Here it says
MinGW is a C/C++ compiler suite which allows you to create Windows executables without dependency on such DLLs
So at the most basic level is it just a collection of "things" needed to let me make C++ programs?
Apologies for the quite basic question.
"When I downloaded CodeBlocks, did the STL come with it?"
Despite it's not called the STL, but the C++ standard library, it comes with your c++ compiler implementation (and optionally packaged with the CodeBlocks IDE).
You have to differentiate IDE and compiler toolchain. CodeBlocks (the Integrated Development Environment) can be configured to use a number of different compiler toolchains (e.g. Clang or MSVC).
"Or does it automatically come with my OS?"
No, usually not. Especially not for Windows OS
"So, where is the standard library? Where are the header files that let me access it?"
They come with the compiler toolchain you're currently using for your CodeBlocks project.
Supposed this is the MinGW GCC toolchain and it's installed in the default directory, you'll find the libraries under a directory like (that's what I have)
C:\MinGW\lib\gcc\mingw32\4.8.1
and the header files at
C:\MinGW\lib\gcc\mingw32\4.8.1\include\c++
"So at the most basic level is it just a collection of "things" needed to let me make C++ programs?"
It's the Minimalist GNU toolchain for Windows. It usually comes along with the GCC (GNU C/C++ compiler toolchain), plus the MSYS minimalist GNU tools environment (including GNU make, shell, etc.).
When you have installed a C++ implementation you'll have something which implements everything necessary to use C++ source files and turn them into something running. How that is done exactly depends on the specific C++ implementation. Most often, there is a compiler which processes individual source file and translates them into object files which are then combined by a linker to produce an actual running program. That is by no means required and, e.g., cling directly interprets C++ code without compiling.
All this is just to clarify that there is no one way how C++ is implemented although the majority of contemporary C++ implementations follow the approach of compiler/linker and provide libraries as a collection of files with declarations and library files providing implementations of these declarations.
Where the C++ standard library is located and where its declarations are to be found entirely depends on the C++ implementations. Oddly, all C++ implementations I have encountered so far except cling do use a compiler and all these compilers support a -E option (although it is spelled /E for MSVC++) which preprocesses a C++ file. The typically quite large output shows locations of included files pointing at the location of the declarations. That is, something like this executed on a command line yields a file with the information about the locations:
compiler -E input.cpp > input.ii
How the compiler compiler is actually named entirely depends on the C++ implementation and is something like g++, clang++, etc. The file input.cpp is supposed to contain a suitable include directive for one of the standard C++ library headers, e.g.
#include <iostream>
Searching in the output input.ii should reveal the location of this header. Of course, it is possible that the declarations are made available by the compiler without actually including a file but just making declarations visible. There used to be a compiler like this (TenDRA) but I'm not aware of any contemporary compiler doing this (with modules being considered for standardization these may come back in the future, though).
Where the actual library file with the objects implementing the various declarations is located is an entirely different question and locating these tends to be a bit more involved.
The C++ implementation is probably installed somehow when installing CodeBlocks. I think it is just one package. On systems with a package management system like dpkg on some Linuxes it would be quite reasonable to just have the IDE have a dependency on the compiler (e.g., gcc for CodeBlocks) and have the compiler have a dependency on the standard C++ library (libstdc++ for gcc) and have the package management system sort out how things are installed.
There are several implementations of the C++ standard library. Some of the more popular ones are libstdc++, which comes packaged with GCC, libc++, which can be used with Clang, or Visual Studio's implementation by Microsoft. They use a licensed version of Dinkumware's implementation. MinGW contains a port of GCC. CodeBlocks, an IDE, allows you to choose a setup which comes packaged with a version of MinGW, or one without. Either way, you can still set up the IDE to use a different compiler if you choose. Part of the standard library implementation will also be header files, not just binaries, because a lot of it is template code (which can only be implemented in header files.)
I recommend you read the documentation for the respective technologies because they contain a lot of information, more than a tutorial or book would:
libstdc++ faq
MinGW faq
MSDN

Building C++ source code as a library - where to start?

Over the months I've written some nice generic enough functionality that I want to build as a library and link dynamically against rather than importing 50-odd header/source files.
The project is maintained in Xcode and Dev-C++ (I do understand that I might have to go command line to do what I want) and have to link against OpenGL and SDL (dynamically in SDL's case). Target platforms are Windows and OS X.
What am I looking at at all?
What will be the entry point of my
library if it needs one?
What do I have to change in my code?
(calling conventions?)
How do I release it? My understanding
is that headers and the compiled
library (.dll, .dylib(, .framework),
whatever it'll be) need to be
available for the project -
especially as template functionality
can not be included in the library by
nature.
What else I need to be aware of?
I'd recommend building as a statc library rather than a DLL. A lot of the issues of exporting C++ functions and classes go away if you do this, provided you only intend to link with code produced by the same compiler you built the library with.
Building a static library is very easy as it is just an collection of .o/.obj files - a bit like a ZIP file but without compression. There is no need to export anything - just include the library in the list of files that your application links with. To access specific functions or classes, just include the relevant header file. Note you can't get rid of header files - the C++ compilation model, particularly for templates, depends on them.
It can be problematic to export a C++ class library from a dynamic library, but it is possible.
You need to mark each function to be exported from the DLL (syntax depends on the compiler). I'm poking around to see if I can find how to do this from xcode. In VC it's __declspec(dllexport) and in CodeWarrior it's #pragma export on/#pragma export off.
This is perfectly reasonable if you are only using your binary in-house. However, one issue is that C++ methods are named differently by different compilers. This means that nobody who uses a different compiler will be able to use your DLL, unless you are only exporting C functions.
Also, you need to make sure the calling conventions match in the DLL and the DLL's client. This either means you should have the same default calling convention flag passed to the compiler for both the DLL or the client, or better, explicitly set the calling convention on each exported function in the DLL, so that it won't matter what the default is for the client.
This article explains the naming issue:
http://en.wikipedia.org/wiki/Name_decoration
The C++ standard doesn't define a standard ABI, and that's bad news for people trying to build C++ libraries. This means that you get different behavior from your compiled code depending on which flags were used to compile it, and that can lead to mysterious bugs in code that compiles and links just fine.
This extends beyond just different calling conventions - C++ code can be compiled to support or not support RTTI, exception handling, and with various optimizations that can affect the the memory layout of class instances, which C++ code relies on.
So, what can you do? I would build C++ libraries inside my source tree, and make sure that they're built as part of my project's build, and that all the libraries and the code that links to them use the same compiler flags.
Note that name mangling, which was supposed to at least prevent you from linking object files that were compiled with different compilers/compiler flags only mostly works, and there are certain things you can do, especially with GCC, that will result in code that links just fine and fails at runtime.
You have to be extra careful with vendor supplied dynamic C++ libraries (QT on most Linux distributions, for example.) I've seen instances of vendor supplied libraries that were compiled in ways that prevented certain things from working properly. For example, some Redhat Linux releases (maybe all of them) disabled exceptions in QT, which made it impossible to catch exceptions in main() if the exceptions were thrown in a QT callback. Fun.