1

For simplicity, let's say I have the following C project structure:

src/
  utils/
    logger.c
    logger.h
   main.c
   secondary_component.c

main.c starts with:

#include "utils/logger.h"

I would like to keep the code and its structure as-is, but stub out logger.c, logger.h and avoid compiling secondary_component.c (i.e. only use the subset of main and logger). For instance, instead of the regular logger.c writing to a file, the stubbed version would include a simple printf.

My attempted solution: create an extra folder stubbed_src/utils and place my new logger.c, logger.h inside that folder. Then, I perform:

clang -iquote stubbed_src -iquote src -o main_proj main.c stubbed_src/utils/logger.c

The goal is that when clang sees the #include logger.h in main.c, it will first look at the stubbed_src folder and find it (and thereby ignore the original src/utils/logger.h). Unfortunately, clang always looks at the current folder first (i.e. it looks for utils/logger.h starting at src, where main.c is located) and only if it doesn't find it will it then looks at the iquote folders. In which case, it will always stop when it finds the implementation in src/utils.

There used to be a clang command line workaround which disabled this current working directory behavior, but it has since been deprecated.

If I were willing to change main.c's #include to be an angle bracketed #include, then using -I would also solve the problem since -I has no such restriction regarding the current directory. But this would be an improper usage of angle brackets, and also I'm unable to change main.c in this case.

Ideally, my stubbed versions of logger.c, logger.h would be much reduced in size and only implement functions used in main.c. For instance, I would like to discard any logger functions called by secondary_component.c since I only want to compile main.c. In addition, those extraneous functions called by secondary_component.c introduce their own #include requirements into the original logger files and I'm trying to avoid compiling those extra #includes. I would like to be able to simply compile main.c and have it work with stubbed logger functions and be able to avoid compiling any extra files.

Any other suggestions on how to use an alternative/stubbed out implementation of logger.c, logger.h?

  • Change the current folder to stubbed_src before invoking Clang? – Robert Harvey May 21 at 19:04
  • 2
    Is the stubbed-out version of logger.h different from the original? In what way? Usually header files only contain function prototypes, forward declarations, and other "parts of the API contract," so you would not normally want to stub out a header. What part of the header are you trying to stub out, and why? – Kevin May 21 at 19:38
  • Good point. In other words, the header file is not likely to change. Your implementation (.c file) will, however. – Robert Harvey May 21 at 20:08
  • @Kevin For instance, logger.h has a function not used by main.c (but used by some other file). That extra function results in extra #include's in the header file (for instance, if the function prototype includes named structs specified elsewhere). One of my primary goals is to avoid compiling a long chain of #include's if they're not at all needed for simply compiling main.c. – ChaimKut May 21 at 20:09
  • @RobertHarvey The idea of 'current working directory' for purposes of clang compilation is relative the file currently being compiled (and not relative to where clang is being executed on the command line). So no matter where clang is invoked, as long as main.c is inside of src, then src will always be the current working directory for main.c compilation. – ChaimKut May 21 at 20:11
4

The normal practice when mocking functions in C (or otherwise using different implementations) is to use different .c source files in your build process. Normally, header files are not replaced.

If header files really must be replaced, then the #include "header.h" include directive must not refer to a file that can be found directly from the current source's directory. The C standard specifies that the #include "..." form must always first look in the current directory before starting to look into other paths.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.