Reputation: 10393
// common.h
// This is foo function. It has a body.
__inline void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
I would like to inline the foo function only when I build for release. I don't want to inline functions for Debug
build.
I tried it but linker errors annoyed me.
In this case, foo
function's body is defined in common.h header file.
so if I just do
//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
It will be met a link error in DEBUG
build. Because two modules try to include common.h.
I have no idea to solve it.
Is it possible?
Upvotes: 3
Views: 2088
Reputation: 3448
#ifdef RELEASE
#define INLINE __inline
#else
#define INLINE
#endif
Then
// common.h
INLINE void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
then define RELEASE
for the release version. of course you can see from this there are lots of ways to do it.
Upvotes: 3
Reputation: 58087
Use compiler conditionals and define a compile time flag.
Example:
#ifdef RELEASE_BUILD_FLAG
//Run inline function
#else
//some alternative
#endif
Upvotes: 0
Reputation: 340218
The fundamental thing to realize is that the inline
keyword (or Microsoft's __inline
extension for C - since MSVC doesn't support C99) is essentially a pass to violate the one definition rule. If you think about it - that's all it really is, since the compiler is under no obligation to actually perform any inlining.
So, when you have an inline
function you're allowed to have the function defined in more than one module. In fact, you're obligated to have it defined in any module that actually uses the function.
However, if you don't declare the function as inline
, you have to ensure that you have no more than one definition (exactly one if it actually gets used). For non-member functions (all function in C), there are a few ways around this:
static
to change it's linkage to internal (note that you can have static inline
functions to begin with).Basically, what you need to do is have an implementation of the function in a separate .c file, just like if you were following the tradition of a-single-function-per-module coding standard (actually you can do this just as well putting several inline functions in the .c module - but they should all be inline or not inline as a group to keep things from getting too out of hand). The implementation of the function needs to arrange to be able to be included in a header - so it needs include guards, just like any other header. Then you use the preprocessor to conditionally include the implementation as part of the header when you want inline functions (so the implementation will be available to all modules), but don't include it if you're not inlining (so you follow the one definition rule in that case):
The common.h
header:
// common.h
#ifndef COMMON_H
#define COMMON_H
#ifdef RELEASE
#define USE_INLINE
#define INLINE __inline
#else
#define INLINE
#endif
INLINE void foo(void);
#ifdef USE_INLINE
#include "foo.c"
#endif
#endif /* COMMON_H */
The implementation of foo()
:
// foo.c
#ifndef FOO_C
#define FOO_C
#include <stdio.h>
#include "common.h"
INLINE void foo()
{
printf("foo\n");
}
#endif /* FOO_C */
And an example program:
// main.c
#include<stdio.h>
#include "common.h"
int main()
{
foo();
return 0;
}
Now if you compile for release:
cl /DRELEASE main.c foo.c
foo()
will be inline
(or __inline
as the case may be).
If you compile for non-release:
cl test.c foo.c
you have a non-inline foo()
.
And both the compiler and linker are happy in either case.
All that said, I kind of like the suggestion to maybe redefine INLINE
to be static
for debugging purposes.
However, ultimately I'm not sure I see the point to any of this really - modern debuggers are able to step through functions that are inline
, and the debugger probably won't inline function calls if you disable optimizations. So you can set breakpoints inside the inline function as well and have it work fine in non-optimized builds.
I'm not sure exactly what you're end-goal in this really is. What's the drawback to leaving the functions as inline
in debug/non-optimized builds?
Upvotes: 5
Reputation: 2045
You can't declare header only functions as non-inline. You could declare them as static (a.k.a. C-style static), but that will generate a copy of the function (including local static variables, if any) in each translation unit. A better solution is to leave it as inline. In debug mode when optimizations are disabled compilers usually don't inline any functions.
Upvotes: 3
Reputation: 25657
The "easy" solution would be this:
#if !defined(_DEBUG) || defined(NDEBUG)
#define INLINE inline
#else
#define INLINE static
#endif
static
is necessary to silence linking errors and get around the One Definition Rule.
A better solution would be to simply disable inlining project wide for debugging. GCC supports the -wno-inline-functions
and -fno-inline-small-functions
options to counteract those optimizations, and it also does not enable inlining for -O1
or lower (and probably -Os
as well). Most compilers have similar options.
I call the latter a better solution because it should instruct the compiler to ignore the inline
hint, eliminating the need for pesky preprocessor directives.
Upvotes: 8
Reputation: 9431
In most cases release flags are not defined. Typically debug flags are defined. _DEBUG is defined by most compilers, so there is no need to define a release flag:
More practical:
#ifndef _DEBUG
__inline void foo() { /* something */ }
#else
//some alternative
#endif
Upvotes: 1