Setting pre-processor definitions with extconf.rb - c

I'm writing a C extension for Ruby, and I have something like this in the extconf.rb file:
if(not have_library('z'))
$stderr << "Error, could not locate zlib.\n"
abort "Missing zlib"
end
So the installation process aborts if zlib is missing. Instead, since my extension can work with AND without zlib, I would like to do something like the following;
if(have_library('z'))
# do something so that -DHAVE_ZLIB is passed to the compiler
# when compiling the extension.
end
How can I do that?
EDIT: The question is on the comment in the if...end statement: how to add the -DHAVE_ZLIB definition for the compiler?

If you can rely on checking for a header file then have_header will define a HAVE_HEADER_H macro for you. For example:
have_header('zlib.h')
will define HAVE_ZLIB_H, which you can then refer to in your code.
If this isn’t enough or you need to define a macro for some other reason you can use the $defs global:
if(have_library('z'))
$defs << '-DHAVE_ZLIB'
# Now HAVE_ZLIB will be defined for you to check in your code
end

I would do it as the following your in extconf.rb file
$libs = ["-lliba", "-llibb"]
if have_library('z')
# where $libs is your array of libraries defined
$libs << "-llibz"
end
As you can see in the api docs for have_library, the method have_library returns either true or false

Related

Ignore macro if it is not defined

I am using the following macro in some C files:
DBGL_LOG_INFO(DBGL_UART_LOG_ENABLED, "UART is initialized");
The macro calls my logging module, if the define LOG_UART_ENABLED is true.
If the define is false, the logging code will not be compiled and so does not influence my regular program code in release build.
But now, I have the following Problem:
The C files, which does contain this macro call should be also used in another project, where the log module does not exist. So the define DBGL_UART_LOG_ENABLED also does not exist in this other Project.
Of course, when I compile the file with this code in the project, i get the following error:
'DBGL_UART_LOG_ENABLED' undeclared (first use in this function); did you mean '...'?
Is it possible, to tell the compiler, that this code should be ignored, if the macro and the defines are missing?
Thank you in advance.
Conditionally define the macro. For instance, the following is a common pattern:
#ifndef DBGL_UART_LOG_ENABLED
# define DBGL_UART_LOG_ENABLED 0
#endfif
And you probably also need to handle DBGL_LOG_INFO:
#ifndef DBGL_LOG_INFO
# define DBGL_LOG_INFO(...) do {} while (false)
#endif
This defines the macro as an empty block that swallows its arguments. That way, you can continue to use the macro in code without it affecting the output.
This would be why such code is commonly written as
#ifdef DBGL_UART_LOG_ENABLED
/* do stuff with DBGL_UART_LOG_ENABLED */
#endif

How to use SSH support in libgit2?

As i see from this question, libgit2 is now supporting use of ssh repository urls.
But how to force it to work? as i understood from CMakeLists file, SSH support will be enabled automatically if libssh2 library will be detected.
IF(NOT LIBSSH2_LIBRARY)
FIND_PACKAGE(LIBSSH2 QUIET)
ENDIF()
IF (LIBSSH2_FOUND)
MESSAGE("libssh2 was detected!")
ADD_DEFINITIONS(-DGIT_SSH)
INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIR})
SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
ENDIF()
As it has to be, i saw the "libssh2 was detected" message.
However, the macro GIT_SSH after cmake work is still undefined, and all of SSH stuff is unavailable.
For example, code git_cred_ssh_keyfile_passphrase kf_pass; does not compile.
I get such error:
'git_cred_ssh_keyfile_passphrase' was not declared in this scope,
i.e. GIT_SSH is undefined because this structure is declared in #ifdef GIT_SSH ... #endif block.
Maybe i'm do something in a wrong way?

Include a header file for parsing of all other files with Doxygen preprocessor

I want to include the #defines from a h file for parsing of all other files with Doxygen.
Project background:
My C project includes a header file config.h on it's the build command.
It also defines a target MODEL_A on the same build command.
config.h creates defines depending on the target being built (not the same lists of defines for MODEL_A as for MODEL_B):
#if defined(MODEL_A)
#define HAS_FUNCTIONALITY_1
#define HAS_FUNCTIONALITY_2
#elif defined(MODEL_B)
#define HAS_FUNCTIONALITY_3
#define HAS_FUNCTIONALITY_4
#endif
My issue with Doxygen:
I try to generate documentation with Doxygen. I have in the Doxyfile:
# including of config.h to INPUT seems necessary.
INPUT = ./source/config.h \
./source
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
INCLUDE_PATH = ./source
INCLUDE_FILE_PATTERNS = ./source/config.h
PREDEFINED = MODEL_A
The code that is dependent on the defines HAS_FUNCTIONALITY_x is not included in the documentation, as if the preprocessor did not get the defines in config.h.
My findings so far:
I inspected the preprocessor output with help of doxygen -d Preprocessor, and could see that:
./source/config.h was parsed first, and correctly according to MODEL_A (I can see the correct #defines in the preprocessor output). #define HAS_FUNCTIONALITY_1 figures in the preprocessor output.
the preprocessing of C files which depend on HAS_FUNCTIONALITY_1 act as if it was not defined.
Defining HAS_FUNCTIONALITY_1 in the field PREDEFINED of the Doxyfile works as expected. This is not a practical solution, but still interesting.
How do I make sure that the #define rows that are preprocessed first from config.h stay defined when the preprocessor works on all subsequent C files?
It would probably be beneficial for you to show the C code itself. In general, Doxygen runs a standard preprocessor - i.e. the rendered code should be the same as if the compiler preprocessed it. In order to achieve the equivalent of #define HAS_FUNCTIONALITY_1 in the code - it has to be defined.
I understand from your reluctance to add it to the doxygen configuration that it is defined somewhere else in the project (or perhaps the Makefile) and that that is the reason that the actual code acts as though it was defined.
If this is the case, I don't see a plausible workaround other than more preprocessor trickery or simply adding it in the doxygen config file.
I ran into a very similar issue.
My headers were in a different directory from my source, e.g.:
doxy_input_dir/
|
+ src/
|
+ inc/
I had RECURSIVE input file option set to YES. I assumed the preprocessor would correctly find my headers. However, when I viewed the preprocessor output by running doxygen -d Predefined <doxyfile> I saw a lot of #include foo.h: not found! skipping....
The solution was to specify all of the header directories explicitly using the INCLUDE_PATH tag.

gcc check if file is main (#if __BASE_FILE__ == __FILE__)

In ruby there's very common idiom to check if current file is "main" file:
if __FILE__ == $0
# do something here (usually run unit tests)
end
I'd like to do something similar in C after reading gcc documentation I've figured that it should work like this:
#if __FILE__ == __BASE_FILE__
// Do stuff
#endif
the only problem is after I try this:
$ gcc src/bitmap_index.c -std=c99 -lm && ./a.out
src/bitmap_index.c:173:1: error: token ""src/bitmap_index.c"" is not valid in preprocessor expressions
Am I using #if wrong?
As summary for future guests:
You cannot compare string using #if
BASE_FILE is the name of file that is being compiled (that Is actually what I wanted).
Best way to do this is to set flag during compilation with -D
in gcc you can use:
#if __INCLUDE_LEVEL__ == 0
or:
if(!__INCLUDE_LEVEL__)
to check if your inside the __BASE_FILE__
Yes, you are misusing #if. It only works on integer constant expressions. But even if you were using if, comparing pointers for equality is never a valid way to compare strings in C.
It seems you can't.
Alternatively, it works perfectly fine on a regular if condition, and gcc can optimize this nicely.
if (!strcmp(__BASE_FILE__, __FILE__)) {
// works.
}
but you can't define new main functions or use other preprocessor tricks. but you could short-circuit main by using static methods, but that's harsh and dirty.
But maybe you shouldn't do it. in Ruby/python, this works because usage of files is done at runtime. in C, all files are to be compiled to be used.
Keep in mind that most build system will build one file at a time, building them as object files, and rebuilding them only when necessary. So
__BASE_FILE__ and __FILE__
will be equals most of the time in sources files, if not always. And i would strongly discourage you to do this in header files.
It's easier to just put your tests in separate files, only linking them when needed.
Yup, as others say, you're misusing it since you can't compare strings that way in C, and especially not in the preprocessor.
The file that defines int main(int argc, char* argv[]) is the main file. There can be only one such function in an executable.
In addition to what others have said (you can't have the C preprocessor compare strings), be careful with __BASE_FILE__ because it may not correspond to your definition of "main" file. __BASE_FILE__ is the name of the file being compiled, so it's always equal to __FILE__ in source files, and only differs in headers and other included files.
In particular, __BASE_FILE__ is not the name of the file which contains the main() function.

Pre-preprocessor

I want to have a C pre-preprocessor which is filtering some #define statements from the sourcecode without changing anything else.
Why? This should be used to remove some client specific code from the sources if the source is handed out to another client.
Does anyone know of an existing solution?
Thanks!
Simon
You can use something like awk instead of CPP ? Add some flags in your code surrounding the piece of code to be removed. For example:
(...)
//BEGIN_REMOVE_THIS_CODE
printf("secret code");
//END_REMOVE_THIS_CODE
(...)
then write a awk script to remove this code, something like...
BEGIN { write=1;}
/^\/\/BEGIN_REMOVE_THIS_CODE/ { write=0; next;}
/^\/\/END_REMOVE_THIS_CODE/ { write=1; next;}
{
if(write==1) print $0;
}
I recommend using an additional macro language layer for code filtering, like filepp. You may use a C preprocessor friendly syntax to express which parts belongs to which clients.
//%ifdef CLIENT_A
code for client A
//%endif
//%ifdef CLIENT_B
code for client B
//%endif
//%if "CLIENT_A" || "CLIENT_B"
code for client A and B
//%endif
The '//%' prefix enables You to compile the code unmodified. You may run filepp before You giving out the code to a client.
This sounds like what I asked about in Is there a C pre-processor which eliminates ifdef blocks based on values defined. The best answer I got was sunifdef, or 'Son of unifdef', which has worked reliably for me on some excessively contorted conditional code (the accumulated crud from over 20 years of development on a wide variety of platforms with an inadequate theory of how to do platform-specific compilation).
I don't think you need a preprocessor for this. If you don't have nested #ifdef's in your code, any regex engine can remove anything that is located between #ifdef CLIENT and #endif (use non-greedy matching to match first #endif, not last).
I would put the client specific code in a separate directory or possibly part of a different project that would need to be checked out of the source control.
Put a function call that would be stubbed out or (I forget the proper term) loosely linked so that another function can be put in its place.
If you're using gcc, then you can use:
gcc <insert files here> -E
The -E option tells gcc to only preprocess the sources, and not to compile them.
Or, you could use grep to filter out specific files and let the preprocessor loose on them only.
grep -r '#define CLIENT_CODE' ./*.h
You can also try unifdef which is rather simpler than sunifdef.
Why don't you do something like:
client_a_specific_functions_definition.c
double discount_for_paying_upfront() { return 0.1; };
// ...
client_b_specific_functions_definition.c
double discount_for_paying_upfront() { return 0.05; };
// ...
When you hand out the code it is just a matter of selecting the right file with their specific definitions.
Then you would create a header file to include it where you need to access the client specific code with something like:
client_functions.h
#pragma once
double discount_for_paying_upfront();
#define stringify(x) #x
#define FILE2(a) stringify(client_##a##_specific_functions_definition.c)
#define FILE(a) FILE2(a)
#include FILE(CLIENT_NAME)
#undef stringify
#undef FILE2
#undef FILE
Then say you #include "client_functions.h" in your main.c. You could compile it with:
gcc -DCLIENT_NAME=a main.c -o a.exe
gcc -DCLIENT_NAME=b main.c -o b.exe
as far as I know... the preprocessor can be run as a separate step (using the correct compiler optios) . This way you can do whatever you want with the processed code.

Resources