13

I have an assembly file (asm.S) which needs a constant #define'd in a C header file (c_decls.h). The header file contains C function declarations in addition to the #define I want. Unfortunately, gcc barfs when trying to compile the assembly file. For example,

c_decls.h

#ifndef __c_decls_h__
#define __c_decls_h__

#define I_NEED_THIS 0xBEEF
int foo(int bar);

#endif

asm.S

#include "c_decls.h"

.globl main
main:
    pushl %ebp
    movl %esp, %ebp
    movl $I_NEED_THIS, %eax
    leave
    ret

Output

> gcc -m32 asm.S
c_decls.h: Assembler messages:
c_decls.h:6: Error: junk '(int bar)' after expression
c_decls.h:6: Error: suffix or operands invalid for 'int'

Is there a way to #include a C header file that contains function declarations in an assembly file? (Changing the header or moving/redefining the #define is not an option.)

Andrew Keeton
  • 22,195
  • 6
  • 45
  • 72
  • (Changing the header or moving/redefining the #define is not an option.) Seeing as you've disqualified the most reasonable option, I'd say you're out of luck. :-) – asveikau Feb 08 '11 at 00:14
  • Considering that the header is invoking undefined behavior (by using a name that begins with double-underscore as its multiple-inclusion guard), I think you should reconsider the requirement of not changing it. :-) – R.. GitHub STOP HELPING ICE Feb 08 '11 at 00:32

2 Answers2

14

Use the -dM option for cpp to get just the #defines out of your header files, and include that file instead.

cpp -dM c_decls.h > bare_c_decls.h

Now include bare_c_decls.h in your .S file. And if you can't change the #include in the .S file, generate the bare header files in another directory, and put that include path on your compiler/assembler command line, ahead of everything else.

And finally, you can wrap this all up in a makefile so your "bare" header files are generated automatically.

payne
  • 13,833
  • 5
  • 42
  • 49
  • 2
    Simple `-dM` doesn't work for me. It returns nothing. `-E -dM` dumps all defines, including one which is defined in a header. There only inconvenience that there are more than 700 defines in the list. – user3124812 Mar 03 '17 at 04:50
  • What version of cpp are you using? (Note the question is related to gcc) – payne Mar 04 '17 at 14:10
  • It's GNU GCC, `arm-none-eabi-g++ (GNU Tools for ARM Embedded Processors) 4.9.3 20150529 (release)` – user3124812 Mar 05 '17 at 22:59
  • @user3124812: You probably ran `gcc -dM` rather than `cpp -dM`. You *should* use `gcc -E -dM` with all other compile options you normally use, to make sure all `#ifdef`s in your headers get the same pre-defined macros. (e.g. maybe you have `#ifdef __AVX__` in a header, and define something differently if building on an x86 target with `-mavx` vs. without.) So I'd recommend not using `cpp` directly. – Peter Cordes Nov 16 '17 at 21:47
10

That's simle: In your .S file use

#define __ASSEMBLY__

In your .C file use

#undef __ASSEMBLY__

Then in .h file place condition

       #ifdef __ASSEMBLY__
                  // here declarations only for assembler
       #else
                  // here only for C
       #endif
                  // and here - defines suitable for both
Andre
  • 109
  • 1
  • 2
  • 1
    Header should be included with 'C' like include, `#include my_defs.h`, not 'ASM' like `.include my_defs.h`. In last case `#ifdef`, `#else`, `#endif` will be ignored by asm parser. Just stumble over this... – user3124812 Mar 03 '17 at 03:22
  • 5
    `gcc foo.S` already pre-defines `__ASSEMBLER__` to 1. So you can just protect all your C-only stuff with `#ifndef __ASSEMBLER__` – Peter Cordes Nov 16 '17 at 21:50