I'm writing a C program and would like to write a function so that, if a certain macro is used at least once, the function is compiled in the object file exactly once.
I was thinking of something in these lines:
#define CERTAIN_MACRO \
...some code here... \
#include "myfunction.h"
(adding my function code in myfunction.h, with suitable include guards in order to prevent multiple inclusion), or
#define CERTAIN_MACRO \
...some code here... \
#define USE_MY_FUNCTION
#ifdef USE_MY_FUNCTION
my function code
#endif
But neither works, because #define and #include are not allowed in macro-expanded code. Any suggestions?
Let the linker do the job it's meant to.
Place the function into its own source file and then build that into a library, say liboptional.a.
When it comes time to create the executable, use that library, for example:
gcc -o execfile file1.o file2.o -loptional
At the time the linker sees the -l optional, it will use the objects within that library to satisfy undefined references. Hence, if you're used the function in file1.o or file2.o, it will be included.
Related
I was trying to build a C project which has a rather unfamiliar way to define namespaces, eg. in file root.h
#define eval CRYPTO_NAMESPACE(eval)
And in the Makefile the following appears (rule for make all):
gcc -O3 -g -march=native -mtune=native -Wall -I. -Isubroutines -DKAT -DKATNUM='cat KATNUM' "-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x" -o kat nist/kat_kem.c nist/rng.c benes.c bm.c controlbits.c decrypt.c encrypt.c gf.c operations.c pk_gen.c root.c sk_gen.c synd.c transpose.c util.c -I${PWD}/subroutines -L${PWD}/libs/ -lXKCP -lcrypto -ldl
What do these options do:
"-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x"
I know that -DXXX=YYY is the same as #define XXX YYY. Now, why is it in double-quotes? Why it looks like a macro (may be it is)? Lastly, what does _##x mean?
The macro in the header:
#define eval CRYPTO_NAMESPACE(eval)
Replaces every token eval with CRYPTO_NAMESPACE(eval). So if the code contains
void eval(char *expr) {
...
the preprocessor output - without any other definition - would be
void CRYPTO_NAMESPACE(eval)(char *expr) {
...
The -D parameters effectively add two more definitions:
#define DCRYPTO_NAMESPACE(x) x
#define _CRYPTO_NAMESPACE(x) _##x
In our example, the first define causes the normal result to be re-written one more time:
void eval(char *expr) {
...
so we're back where we started. A different definition could be used to change the compiled name of the function. This definition makes the header definition a no-op.
The second macro uses the token concatenation operator ##. It adds a prefix underscore _ to the macro argument. E.g. if the code contained something like:
void _CRYPTO_NAMESPACE(foo)(int x) {
then the result is
void _foo(int x) {
At a higher level, these macros allow names of things (in the first case anything named eval and in the second, any name at all) to be transformed uniformly throughout the program. This is a fairly standard workaround for name collisions in big C programs. If you have two source code bases that have both defined the same public function name, macros like this can be used to add a prefix or suffix that changes one or both names in the compiled code without modifying either original code. This is an important capability for long-term configuration management where manually editing externally furnished code bases isn't a serious option.
A wild guess is that this treatment is given to eval because the likelihood of some other chunk of C also defining a function named eval is extremely high.
I have a program which, depending on the user input, #includes one header headerA.h or another headerB.h I expect the header to be there till the end of the program.
headerA and headerB define structures with the same names but with different fields, and I'm not able to merge both files in one, and neither able to change anything else from the libraries that headerA and headerB are using.
Is there a way to solve this problem?
Preprocessor macros:
#if defined(USE_HEADERA)
# include "headerA.h"
#elif defined(USE_HEADERB)
# include "headerB.h"
#else
# error must define USE_HEADERA or USE_HEADERB
#endif
If you have GCC then you tell the preprocessor which to select using the GCC -D option:
$ gcc -DUSE_HEADERA myfile.c -o myprogram
However, if you want to do it runtime during execution that's impossible. #include is a preprocessor directive, and the preprocessor only runs as part of the compilation.
Although it is possible to conditionally include files, it does not seem to be possible to have this change during runtime. See this answer about it. The if statements only work before runtime.
I don't think it is possible as your #includes are resolved before compilation i.e during preprocessing. So it is not possible to change them during runtime.
But you can try conditional compilation by defining a macro during compiletime.
#ifdef HEADERA
#include <headerA>
#ifdef HEADERB
#include <headerA>
While compilinging gcc
$ gcc prog.c -DHEADERA to include headerA or vice versa
I have a main file like so:
main_a.c:
#define MAIN_A
#include <stdio.h>
#include "shared.h"
extern int i;
int main() {
printf("i is: %d\n", i);
return 0;
}
I want to use the define in shared.h like this:
shared.h
#if defined(MAIN_A)
# define A
#endif
So I can declare a variable according to whether the main file is present or not, like this:
shared.c
#include "shared.h"
#if defined(A)
int i = 1;
#else
int i = 0;
#endif
I build it using a makefile which looks like this:
Makefile:
all : a
./a
a : main_a.o shared.o
gcc -o $# $^
%.o : %.c
gcc -c $<
However this prints
i is: 0
Now my question is: Why is it that the define seems to be lost when I compile the shared module? I know the main module is compiled first, so the define should have been resolved by the time shared.c is compiled.
One suspicion I have is that the preprocessor might get run at the start of each module build and not just at the start of the project. If this is correct is there a way of compiling more than a single module at a time to use the preprocessor as I attempt above?
Preprocessor is run for each file before it is compiled, i.e. once for main_a.c and then again independently for shared.c. When shared.c is compiled MAIN_A is undefined.
Preprocessor can't be used the way you're attempting, i.e. remembering state across compilation units.
What you can do is define a name (for example MAIN_A) using the -Dcompiler option in your Makefile and test this name using preprocessor the same way you're doing it now. This way the definition takes place on the project level (in the Makefile) rather than on a compilation unit level (in a .c file).
Let me do the preprocessor's work here and expand all your macros. In main.c, MAIN_A is defined, so A is defined. Nothing depends on A in main.c, and i is extern.
In shared.c, MAIN_A and thereby A are undefined, and i is 0.
In short, the preprocessor cannot transport information between compilation units. That's good practice, because otherwise programs would quickly become unreadable and you would have to recompile all compilation units when one unit changes (because symbols might have changed). Resolve the issue by setting i explicitly in main:
int main() {
i = 1;
}
It is more verbose, but is also much clearer to the reader. If you want to encapsulate, define a function InitializeShared. If you truly want to compile some code as a single compilation unit, make one of the files a header file and #include it into the other.
Yes you are right, they are completely separate compilation units.
MAIN_A is only defined in main_a.c
One thought that comes to mind is to cat the files together to make one compilation unit?
Global define A
gcc main_a.c shared.c -DA
Defines almost work the same as any variable. If you want to share a variable across modules, you put it in a header. Same goes for #defines.
However, it is strange to use the #ifdef as you are always going to have main.c. You don't want to change the code each time you compile. Instead, use the method described by Adam Zalcman
I'm a C newbie and I was just trying to write a console application with Code::Blocks. Here's the (simplified) code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks
int main()
{
//t = test(); // calling of method also not necessary
return 0;
}
test.c:
void test() {}
When I try to build this program, it gives the following errors:
*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|
There is no way that I'm multiply defining test (although I don't know where the underscore is coming from) and it seems highly unlikely that the definition is somehow included twice. This is all the code there is.
I've ruled out that this error is due to some naming conflict with other functions or files being called test or test.c. Note that the multiple and the first definition are on the same line in the same file.
Does anyone know what is causing this and what I can do about it? Thanks!
You actually compile the source code of test.c twice:
The first time when compiling test.c itself,
The second time when compiling main.c which includes all the test.c source.
What you need in your main.c in order to use the test() function is a simple declaration, not its definition. This is achieved by including a test.h header file which contains something like:
void test(void);
This informs the compiler that such a function with input parameters and return type exists. What this function does ( everything inside { and } ) is left in your test.c file.
In main.c, replace #include "test.c" by #include "test.h".
A last point: with your programs being more complex, you will be faced to situations when header files may be included several times. To prevent this, header sources are sometimes enclosed by specific macro definitions, like:
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
void test(void);
#endif
The underscore is put there by the compiler and used by the linker. The basic path is:
main.c
test.h ---> [compiler] ---> main.o --+
|
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe
So, your main program should include the header file for the test module which should consist only of declarations, such as the function prototype:
void test(void);
This lets the compiler know that it exists when main.c is being compiled but the actual code is in test.c, then test.o.
It's the linking phase that joins together the two modules.
By including test.c into main.c, you're defining the test() function in main.o. Presumably, you're then linking main.o and test.o, both of which contain the function test().
You shouldn't include other source files (*.c) in .c files. I think you want to have a header (.h) file with the DECLARATION of test function, and have it's DEFINITION in a separate .c file.
The error is caused by multiple definitions of the test function (one in test.c and other in main.c)
I had similar problem and i solved it following way.
Solve as follows:
Function prototype declarations and global variable should be in test.h file and you can not initialize global variable in header file.
Function definition and use of global variable in test.c file
if you initialize global variables in header it will have following error
multiple definition of `_ test'|
obj\Debug\main.o:path\test.c|1|first defined here|
Just declarations of global variables in Header file no initialization should work.
Hope it helps
Cheers
Including the implementation file (test.c) causes it to be prepended to your main.c and complied there and then again separately. So, the function test has two definitions -- one in the object code of main.c and once in that of test.c, which gives you a ODR violation. You need to create a header file containing the declaration of test and include it in main.c:
/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */
If you have added test.c to your Code::Blocks project, the definition will be seen twice - once via the #include and once by the linker. You need to:
remove the #include "test.c"
create a file test.h which contains the declaration:
void test();
include the file test.h in main.c
If you're using Visual Studio you could also do "#pragma once" at the top of the headerfile to achieve the same thing as the "#ifndef ..."-wrapping. Some other compilers probably support it as well ..
.. However, don't do this :D Stick with the #ifndef-wrapping to achieve cross-compiler compatibility. I just wanted to let you know that you could also do #pragma once, since you'll probably meet this statement quite a bit when reading other peoples code.
Good luck with it
Ages after this I found another problem that causes the same error and did not find the answer anywhere. I thought to put it here for reference to other people experiencing the same problem.
I defined a function in a header file and it kept throwing this error. (I know it is not the right way, but I thought I would quickly test it that way.)
The solution was to ONLY put a declaration in the header file and the definition in the cpp file.
The reason is that header files are not compiled, they only provide definitions.
I use a parser generator here, that unfortunately insists on putting a
#include <some/file.h>
at the top of every generated source file. The header has since long been renamed. While it is no problem forcing the compiler (gcc) to use the new header with -include new/header.h, removing the above directive from every generated file complicates the build-process.
Is there a way to tell gcc to simply ignore some/file.h?
No. You can post-process your generated file - I say: NO!!!
Or you can just add '.' to your system include directories (or whatever your local include path is - make sure it's also a <> system include path).
Then make a 'some' directory and stick your own permanent 'file.h' in there that has 1 line for #include and get rid of your -include.
I'm guess there's some reason that might not work - cause it seems like the more straight forward and understandable thing to do before using -include. Especially since you can comment the pass-through file to explain what's going on.
Replace some/file.h with an empty file.
Why not make a symlink from some/file.h to new/header.h, and remove the -include directive?
Try using preprocessor directives like #if and #ifdef and gcc -DSYMBOL=value command line flag.
In example, if you compile using gcc -DREQUIRE_STDC=1 -o myfile.o myfile.c, and your .c file contains:
#if defined(REQUIRE_STDC) && defined(__STDC__)
#include "some/file.h"
#else
#include "another/file.h"
#endif /* defined(REQUIRE_STDC) && defined(__STDC__) */
It will compile using "some/file.h" if have both STDC and REQUIRE_STDC symbols defined. Also your header may include the proper directive to avoid multiple inclusions of the same file:
#ifndef MY_HEADER_FILE
#define MY_HEADER_FILE 1
/* your C declarations here */
#endif /* MY_HEADER_FILE */
Also, you could the gcc preprocessor manual.
#include <some/file.h>
may start as something like
#ifndef _FILE_H_
#define _FILE_H_
If so, just add #define _FILE_H_ before the #include command and it should ignore it.
I'm not sure whether this is the best solution, though.