Why might need include a source file that? - c

I am to port h264 codec in an embedded device. The ffmpeg source code uses the following construction:
#undef CHROMA_IDC
#define CHROMA_IDC 3
#include "h264_mc_template.c"
static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceContext *sl)
{
...
}
Why do I need to include such a source file? Isn't that used only for the header?

the "template" suffix hints at the fact that the code depends on some preprocessor directives.
I checked the source and at the beginning there's
#if CHROMA_IDC == 1
# define MCFUNC(n) FUNC(n ## _420)
#elif CHROMA_IDC == 2
# define MCFUNC(n) FUNC(n ## _422)
#elif CHROMA_IDC == 3
# define MCFUNC(n) FUNC(n ## _444)
#endif
note that you have #define CHROMA_IDC 3 before including this file.
This tells the preprocessor to use define MCFUNC(n) FUNC(n ## _444) in the included file.
the source could have been left alone in the makefile but with a -DCHROMA_IDC=3 directive, and in that case, the template cannot be reused for other source files because of multiple redefinition (the functions in this source file are static to avoid multiple redefinition if the template is instanciated more than once)
Why using a template? probably for performance issues, to avoid a call chain and some tests to branch on the required behaviour. ffmpeg cannot afford to be slow on the encoding functions.

Related

CMake : different configure_file() for each target

I'm not very familiar with cmake but as the title says what i'd like to do is the following:
I've an header file of configuration (eg config.h.in), in which I'd like to specify all my parameters depending on which target I'm currently calling. So my header file is something like:
#cmakedefine TEST #TEST#
#cmakedefine PINK #PINK#
#ifndef TEST
#define MY_A 10
#endif
#ifdef PINK
#define MY_A 20
#endif
Now, in my CMakeLists.txt I would like to have multiple targets, so for example (actually the config.hfile is just included from other .c files)
add_executable(FirstTarget
something.c
somethingelse.c
config.h
)
add_executable(SecondTarget
something.c
somethingother.c
config.h
)
And what i would really like to do is that FirstTarget And SecondTarget have different configuration file, so what I'm asking is if it possible to run something like
set(TEST Test)
configure_file(config.h.in config.h)
just for target FirstTarget, and then someway running for SecondTarget
set(PINK Test2)
configure_file(config.h.in config.h)
so that if i call make FirstTarget and make SecondTarget they've different configuration parameters each.
Thanks!
The command configure_file creates a "real" file: it has the same content for each target.
However, the created file may contain #ifdef (or other conditional statements), so its interpretation may differ for different target.
Following example uses target_compile_definitions command for "assign" compile definitions for a specific target.
config.h:
#ifndef TEST
#define MY_A 10
#endif
#ifdef PINK
#define MY_A 20
#endif
CMakeLists.txt:
add_executable(FirstTarget ...)
# When "config.h" will be included into this target, it will use "PINK" branch.
target_compile_definitions(FirstTarget PRIVATE PINK)
add_executable(SecondTarget ...)
# When "config.h" will be included into this target, it will use "TEST" branch.
target_compile_definitions(FirstTarget PRIVATE TEST)

Prevent inclusion of headers into same file in C

I'm looking for a way to enforce that certain headers cannot be included into the same file.
To explain the situation further, assume I have the headers
a_1.h, b_1.h
and
a_2.h, b_2.h
I want to prevent the inclusion of _1 and _2 files into the same file, regardless of if they were
a_ or b_
Assuming that mixing the _1 and _2 headers is a mistake that needs to be caught, a simple way of catching it is to define and check guard macros to check for mixed usage of these headers and use the #error directive to report errors.
For example, the a_1.h header can include this code:
#ifndef A_1_H__INCLUDED
#define A_1_H__INCLUDED
/* Define header set as 1 if not already defined. */
#ifndef HEADER_SET
#define HEADER_SET 1
#endif
/* Check for consistent header set usage. */
#if HEADER_SET != 1
#error "Inconsistent header sets"
#endif
/* Other header stuff ... */
#endif /* A_1_H__INCLUDED */
The other headers will be similar but the _2 headers will have #define HEADER_SET 2 and #if HEADER_SET != 2.
Remember that ANY other file in the build process can include a header. With the typical include guard: #ifndef MYHEADER \n #include MYHEADER, the header code is only inserted on the first instance. After that, the compiler has eaten it and remembers and doesn't need to include it again. Think of compiling as putting ALL the source code into one file and turning that into a binary. (you know, "compiling" as in putting it all in a pile). So it's not "into the same file" it's "into the same build".
You want a header file to be mutually exclusive with another header file. (Like, say, if you've got code that targets specific hardware via includes, and you obviously can't build towards two chips at the same time.) First off, if that's an issue, you should really have a single place where such things are defined (like the build script) so that's not a problem. But if you want a simple safeguard:
#ifndef PPC_e6500
#define PPC_e6500
#ifdef LINUX
#error This processor ain't big enough for the both of us, Tux. This here's 8548 territory!
#endif
That will fail to build and you can figure out who did whatever horrible thing that tried to build towards two targets at once.

Documenting conditional exclusive code in Doxygen

Consider
// EXTERNAL_MACRO is an external macro defined to some value by build system
#if EXTERNAL_MACRO == 1
# define EXCLUSIVE_MACRO_ONE
#elif EXTERNAL_MACRO == 2
# define EXCLUSIVE_MACRO_TWO
#else
# define EXCLUSIVE_MACRO_OTHER
#endif
At built time, only one of the EXCLUSIVE_MACRO_... macros is defined.
How can one document all three EXCLUSIVE_MACRO_... macros in Doxygen?
PREDEFINED configuration setting is not helpful for this because it allows to define EXTERNAL_MACRO to only a single value (and therefore document only a single EXCLUSIVE_MACRO_...).
This SO answer offers a work-around solution that does the job but it requires an additional logic. I am looking for a simpler answer, one that uses Doxygen configuration (if possible) rather than modifying the original code (though some modification is of course fine).
See related question and answer:
Document a config macro with doxygen
Basically:
In the doxygen configuration file, add:
PREDEFINED = IN_DOXYGEN
Somewhere in the source code, add:
/*
Exporting build configuration macros to doxygen,
so they get documented.
*/
#ifdef IN_DOXYGEN
# define EXCLUSIVE_MACRO_ONE
# define EXCLUSIVE_MACRO_TWO
# define EXCLUSIVE_MACRO_THREE
#endif /* IN_DOXYGEN */
Then the documentation for these macros is picked up properly.
If you don't want to change the source, you can add EXCLUSIVE_MACRO_ONE and friends in PREDEFINED, instead of setting EXTERNAL_MACRO.
Inspired by answer.
PROBLEM: We have an existing header that, based on an external macro (provided by build system), defines one of several exclusive macros during compilation. Since only one of the compile-time macros is defined (for each individual build), it is difficult to add Doxygen documentation to all of the exclusive options.
// DEFINED_EXTERNALLY is a macro provided by the build system (e.g. via -D). It is defined as 1, 2, or some other natural number.
// Based on DEFINED_EXTERNALLY we want to define one of several exclusive DEFINED_HERE_... macros (e.g. DEFINED_HERE_1, DEFINED_HERE_2, and DEFINED_HERE_OTHER).
// First, we check that none of the DEFINED_HERE_... macros is defined yet.
#if defined(DEFINED_HERE_1) || defined(DEFINED_HERE_2) || defined(DEFINED_HERE_OTHER)
# error "Conflict: macro DEFINED_HERE_... is already defined!"
#endif
// Then, we define one, and only one, of the DEFINED_HERE_... macros.
#if DEFINED_EXTERNALLY == 1
# define DEFINED_HERE_1
#elif DEFINED_EXTERNALLY == 2
# define DEFINED_HERE_2
#else
# define DEFINED_HERE_OTHER
#endif
SOLUTION: We temporarily define all variants of the DEFINED_HERE_... macros, together with their documentation. This will cause Doxygen to generate documentation for all of them. We then undefine all of the variants and resume normal macro definition logic.
As a result, we will have documentation for all variants yet only one of them will be defined during compilation as was the case before adding the documentation.
Original code
// DEFINED_EXTERNALLY is a macro provided by the build system (e.g. via -D). It is defined as 1, 2, or some other natural number.
// Based on DEFINED_EXTERNALLY we want to define one of several DEFINED_HERE_... macros (e.g. DEFINED_HERE_1, DEFINED_HERE_2, and DEFINED_HERE_OTHER).
// First, we check that none of the DEFINED_HERE_... macros is defined yet.
#if defined(DEFINED_HERE_1) || defined(DEFINED_HERE_2) || defined(DEFINED_HERE_OTHER)
# error "Conflict: macro DEFINED_HERE_... is already defined!"
#endif
New inserted code to generate documentation
/// \brief Value 1.
/// \details It does the following...
#define DEFINED_HERE_1
#undef DEFINED_HERE_1
/// \brief Value 2.
/// \details It does the following...
#define DEFINED_HERE_2
#undef DEFINED_HERE_2
/// \brief Other value.
/// \details It does the following...
#define DEFINED_HERE_OTHER
#undef DEFINED_HERE_OTHER
Original code
// Then, we define one, and only one, of the DEFINED_HERE_... macros.
#if DEFINED_EXTERNALLY == 1
# define DEFINED_HERE_1
#elif DEFINED_EXTERNALLY == 2
# define DEFINED_HERE_2
#else
# define DEFINED_HERE_OTHER
#endif
NB no change to the default Doxygen settings is required
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
PREDEFINED =
EXPAND_AS_DEFINED =

Can I use libopencm3 to write an i2c program on my STM32L0?

I am trying to create a very simple i2c test program to run on my STM32L0 (discovery kit). I have modified the miniblink program in libopencm3-examples/examples/stm32/l0/stm32l0538-disco.
But if I just include the i2c header file:
#include <libopencm3/stm32/i2c.h>
And run make I get the error:
../../../../../libopencm3//include/libopencm3/stm32/i2c.h:36:9: error: #error "stm32 family not defined."
Upon investigating this file it appears that there are rules defined for each of the other models but not for the l0, why is this? Does libopencm3 not support i2c on the STM32L0 series?
#if defined(STM32F0)
# include <libopencm3/stm32/f0/i2c.h>
#elif defined(STM32F1)
# include <libopencm3/stm32/f1/i2c.h>
#elif defined(STM32F2)
# include <libopencm3/stm32/f2/i2c.h>
#elif defined(STM32F3)
# include <libopencm3/stm32/f3/i2c.h>
#elif defined(STM32F4)
# include <libopencm3/stm32/f4/i2c.h>
#elif defined(STM32L1)
# include <libopencm3/stm32/l1/i2c.h>
#else
# error "stm32 family not defined."
#endif
I had a look at libopencm3/stm32/l1/i2c.h and all it seems to do is import the common i2c library anyway. Is there any way I can just use the i2c library for the l1?
Thanks
STM32L0 specific header need to be added.
though (i2c common header file can probebly be used).
the common header's are not intended to be directly included (for safty and less headache). (it has includer check)
solution:
you should check "i2c_common_all.h" if it is has correct register defination for l0 (probebly yes), then copy stm32/l1/i2c.h to stm32/l0/i2c.h and added (the last two lines) to stm32/i2c.h
#elif defined(STM32L1)
# include <libopencm3/stm32/l1/i2c.h>
#elif defined(STM32L0)
# include <libopencm3/stm32/l0/i2c.h>
and make modification to lib/stm32/l0/Makefile OBJS += i2c_common_all.o
if you want, send a pull request
hack: (not recommended)
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/memorymap.h>
#define LIBOPENCM3_I2C_H
#include <libopencm3/stm32/i2c_common_all.h>
and include the source file lib/stm32/common/i2c_common_all.c manually.

What is the purpose of "__SRCVERSION" function at the end of each C file?

I am working on the source code of a Unix-based kernel. I noticed that the last line of each source code file (.c or .h) is a specific line with the following format:
__SRCVERSION( "$URL: ... $ $Rev: 219996 $" )
The URL points to the web address of the same file. I'm wondering what does that mean, and what is it actually for? Would it be any problem if I delete this line from all of my source code files?
Macros like this are often used to embed versioning information into binaries when they are compiled. They can be updated automatically when fetched out of a source control system with appropriate rules. Removing them shouldn't cause any harm, but you will lose the benefit of being able to search a binary to identify which versions of your source files were used to compile it.
As #Keith Thompson says below, it may also be possible to configure your build to not embed the information. Below is an example of the macro definition taken from here (different systems are likely to have different definitions). You can see that it uses the __USESRCVERSION definition to decide which version of the __SRCVERSION macro is used:
#ifndef __USESRCVERSION
#define __SRCVERSION(id)
#else /* __USESRCVERSION */
#ifdef __QNXNTO__
#if defined __SRCVERSION
#undef __SRCVERSION
#endif /*__SRCVERSION */
#define __SRCVERSION(id) \
__asm__(".section .ident,\"SM\",#progbits,1"); \
__asm__(".asciz " #id); \
__asm__(".previous");
#endif /* __QNXNTO__ */
#endif /* __USESRCVERSION */

Resources