as you say, it works.
But can I build -in some way- the string for the include directive ?
Something like
in .login
setenv REPO "/tmp"
compile
# gcc -D"REPO=${REPO}" source.c
in source.c
#ifdef REPO
#include ${REPO}/my_dir/my_file.h
#endif
thanks
As Joachim writes, in GCC you can use the -D flag to #define things from the command-line:
gcc -DTEST source.c
// in source.c
#include <stdio.h>
int main() {
#ifdef TEST
printf("TEST macro is #defined!\n"); // only runs if -DTEST
#endif
return 0;
}
You can easily plug in environment variables (at compile-time) via this
mechanism:
gcc "-DTEST=$MY_ENV_VAR" source.c
If you need to use the run-time value of the environment variable, then the macro preprocessor (#define, #ifdef, ...) can't help you. Use getenv() instead, and forget about macros.
More to the point:
#include TEST
int main() {
printf("Hello world!\n");
return 0;
}
Will work fine only if compiled with "-DTEST=<stdio.h>" (note the quotes).
Related
I'm working on a small open source project in C where I'm trying to use a test framework with C (the framework is min_unit).
I have a foo.h file with prototypes, and foo.c, with the implementation.
In my test file, tests.c, I have
#include "../test_framework/min_unit.h"
#include "foo.c"
... test cases ...
the problem is, because I have a main() function in foo.c (which I need to compile it), I can't compile tests.c because I get an error that states
note: previous definition of ‘main’ was here
int main() {
My question is, is there a way to make it so that the main() function in foo.c is conditional, so that it does not compile when I'm running tests.c? It's just annoying to have to remove and add main over and over.
The easiest way to use conditional compilation is to use #ifdef statements. E.g., in foo.c you have:
#ifdef NOT_TESTING //if a macro NOT_TESTING was defined
int main() {
//main function here
}
#endif
While in test.c, you put:
#ifndef NOT_TESTING //if NOT_TESTING was NOT defined
int main() {
//main function here
}
#endif
When you want to compile the main function in foo.c, you simply add the option -DNOT_TESTING to your compile command. If you want to compile the main function in test.c, don't add that option.
Haven't you try the use of pre-processor compiler conditions? May be you've tried but it doesn't work, hum?
Anyway, you probably should:
1- Define a token at top of "tests.c" class file like:
#defined foo_MIN_UNIT_TEST
2- Surround your "main() { ... } " method in "foo.c" class file with #ifndef / #endif like:
#ifndef foo_MIN_UNIT_TEST //consider using #ifndef not #ifdef!!!
int main()
{ ... }
#endif
3- This way, when you compile your unit test files, the main() method of foo.c will not be included in compile time and the only main() method of tests will be available to compiler.
For further reading: http://www.cprogramming.com/
Regards.
I have following code in C:
int do_something(void);
#ifdef SOMETHING
#define DO_SOMETHING() do_something()
#else
#define DO_SOMETHING() 0
#endif
This code produced warning "statement with no effect" when compiled without SOMETHING defined. I am trying to fix it, but there is one problem - code which uses this macro sometimes checks that "return value" and sometimes ignores it. Because of this I cannot use the easiest solution - casting to void in macro itself.
Is it possible to write macro which allows to compare "returned value" and does not produce this warning when it is ignored?
I use gcc to compile my code.
Three possible solutions:
Define a do_nothing function, which will get optimized out by gcc:
int do_something(void);
int do_nothing(void) { return 0; }
#ifdef SOMETHING
#define DO_SOMETHING() do_something()
#else
#define DO_SOMETHING() do_nothing()
#endif
Or, modify the do_something implementation to move the #ifdef check there
int do_something(void)
{
#ifndef SOMETHING
return 0;
#endif
// Your implementation here
}
You can also ignore the warning using #pragma directives.
By the way, which version of gcc and with which flags are you compiling? gcc -Wall -pedantic with GCC 4.9 doesn't produce the warning.
#include <stdio.h>
int do_something(void);
#ifdef SOMETHING
#define DO_SOMETHING() do_something()
#define DO_SOMETHING_ASSIGN() do_something()
#else
#define DO_SOMETHING()
#define DO_SOMETHING_ASSIGN() 0
#endif
int do_something(void)
{
static int cnt=0;
/* code for do something here */
++cnt;
printf("do_something has been called %d %s!\n",cnt,
(cnt==1)?"time":"times");
return cnt;
}
void main(void)
{
int x;
DO_SOMETHING();
x=DO_SOMETHING_ASSIGN();
printf("%d %d\n",x,DO_SOMETHING_ASSIGN());
puts("end!!!");
}
I hope this is usefull to you!
If you save this code as main.c, you may compile it with:
gcc main.c -o main
when you run main, you obtain the following output:
0 0
end!!!
If you compile it with:
gcc main.c -DSOMETHING -o main
When you run main, you obtain the following output:
do_something has been called 1 time!
do_something has been called 2 times!
do_something has been called 3 times!
2 3
end!!!
Which result does return this construct? I mean the result variable in main-function, and why?
I know, that the example is very strange ;)
header1.h file:
extern const int clf_1;
header2.c file:
#include "header1.h"
const int clf_1 = 2;
test.h file:
#include <header1.h>
#define xyz clf_1
#define NC_CON 2
#if (xyz== NC_CON)
#define test 40
#else
#define test 41
#endif
C file
#include <header1.h>
#include <test.h>
int main(int argc,char *argv[])
{
int result = 0:
if (test == 40)
{
result = 40;
}
}
Read the wikipage on the C preprocessor and the documentation of GNU cpp (the preprocessor inside GCC, i.e run by gcc or g++ etc...). It is a textual thing, and it is run before the definition const int clf_1 = 2; has been processed by the compiler. A #if directive only makes sense if all the names appearing in it are preprocessor symbols (defined with #define or with -D passed on the command line of the GCC or Clang/LLVM compiler)
Use gcc -C -E yoursource.c > yoursource.i (with some other options after gcc, probably -I. is needed ... you should #include "header1.h"
etc...) then look with an editor or a pager into the generated yoursource.i (the preprocessed form)
The world would be very different if the C preprocessor transformed ASTs; for historical reasons, the first C preprocessors were textual filters (run as a different program).
I am making a small, library, and I want to give the user the option to disable the parts they do not require.
lib.h
#ifndef ONLY_BASICS
void complexFunction(void);
#endif
lib.c
#ifndef ONLY_BASICS
void complexFunction(void) {
printf("damn, this is complex alright!\n");
}
#endif
main.c
#define ONLY_BASICS
#include "lib.h"
I have seen this being done in other libraries, what am I missing?
You can make users control the build using the prepossessing macros from the compiler without editing the code. If you use GCC use the switch -D followed by the macro name. On Microsoft compiler use the /D option.
For example using GCC, I have:
#include <stdio.h>
int main(int argc, char **argv) {
#ifdef SAYHI
#ifdef CAPITAL
printf("HI\n");
#else
printf("hi\n");
#endif
#elif SAYHELLO
#ifdef CAPITAL
printf("HELLO\n");
#else
printf("hello\n");
#endif
#else
#ifdef CAPITAL
printf("SAY SOMETHING\n");
#else
printf("say something\n");
#endif
#endif
return 0;
}
The user can enable and disable what he want via -DMACRO without editing the code, example:
$ gcc main.c
$ a.exe
say something
$
$ gcc main.c -DCAPITAL
$ a.exe
SAY SOMETHING
$
$ gcc main.c -DSAYHI -DCAPITAL
$ a.exe
HI
$
$ gcc main.c -DSAYHELLO
$ a.exe
hello
$
It seems you're misunderstanding what a library is and what it's used for. Most (all?) linkers already do what you're trying by not including unreferenced symbols from libraries - it's why with gcc, for instance, you need to put the libraries at the end of the command line after the list of source files that contain references to library functions.
What you're doing seems to be confusing this behaviour with compile-time options for the library itself. In that case, you can use the #ifndef blocks as you have in lib.h and lib.c, but you shouldn't need to do anything in main.c - the library will already have been built without complexFunction. You may want to have your library build process generate a header that describes which functionality is available.
I'm doing some test to learn how to create shared library.
The template for shared libraries in Code::Blocks is this
library.c
// The functions contained in this file are pretty dummy
// and are included only as a placeholder. Nevertheless,
// they *will* get included in the shared library if you
// don't remove them :)
//
// Obviously, you 'll have to write yourself the super-duper
// functions to include in the resulting library...
// Also, it's not necessary to write every function in this file.
// Feel free to add more files in this project. They will be
// included in the resulting library.
// A function adding two integers and returning the result
int SampleAddInt(int i1, int i2)
{
return i1 + i2;
}
// A function doing nothing ;)
void SampleFunction1()
{
// insert code here
}
// A function always returning zero
int SampleFunction2()
{
// insert code here
return 0;
}
I tried to compile it, and it compiled without any error or warning. But when i tried to use it with the ctyped.cdll.LoadLibrary("library path.dll") in python 3(that actually should work like the C function), it said that it wasn't a valid win32 application. Both python and code::blocks are 32 bit (code:blocks compile with gcc, and i tryed to use an installed version of mingw on my system, but it gives some error about a missing library) while i'm working on win 7 64bit
Do you know what the problem can be, or if i'm doing something wrong?
EDIT1:
i'm on windows 7 64bit, in the specs file of the compiler is wrote: "Thread model: win32, gcc version 3.4.5 (mingw-vista special r3)"
and i used as command
gcc.exe -shared -o library.dll library.c
in python i used
from ctypes import *
lib = cdll.LoadLibrary("C:\\Users\\Francesco\\Desktop\\C programmi\\Python\\Ctypes DLL\\library.dll")
and the error was
WindowsError: [Error 193] %1 is not a valid Win32 application
i installed both python3.1 and mingw from the binary package and not compiling them on my system
EDIT2:
After reading Marc answer.
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
DLL_EXPORT int MySimpleSum(int A, int B);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
main.c
#include "main.h"
// a sample exported function
DLL_EXPORT int MySimpleSum(int A, int B)
{
return A+B;
}
compiling options
gcc -c _DBUILD_DLL main.c
gcc -shared -o library.dll main.o -Wl,--out-implib,liblibrary.a
with gcc 4.5.2
still get the same error..
I believe in the windows environment you need to use the __declspec annotation. How to create a shared library and the use of __declspec is described here: DLL Creation in MingW.