1

I want to compile my c code (in kernel) which needs to include some header files from another directory.

Instead of specifying the complete path to header files in c file, I would like to specify the include path in Makefile.

My c file gets complied when the config option CONFIG_FEATURE_X is enabled. I have written the following in Makefile:

obj-$(CONFIG_FEATURE_X) += my_file.o

ccflags-$(CONFIG_FEATURE_X) += -I$(obj)/../../path
  1. When the CONFIG_FEATURE_X is enabled (Y) in .config using make menuconfig, it works fine.

  2. But when the CONFIG_FEATURE_X is enabled as module (m) in .config, this does not include the header files from the path specified and gives the file not found error.

How can I do this?

sawdust
  • 16,103
  • 3
  • 40
  • 50
Udit Agarwal
  • 15
  • 1
  • 9
  • How can I add ccflags option in MAKEFILE based on CONFIG_FEATURE_X or CONFIG_FEATURE_X_MODULE ? Is it acceptable upstream to have both the configs in Makefile ? – Udit Agarwal Jul 21 '18 at 11:37

2 Answers2

3

When the CONFIG_FEATURE_X is enabled (Y) in .config using make menuconfig, it works fine.

That's because

ccflags-$(CONFIG_FEATURE_X) += -I$(obj)/../../path  

would evaluate to

ccflags-y += -I$(obj)/../../path

According to Documentation/kbuild/makefiles.txt:

--- 3.7 Compilation flags

    ccflags-y, asflags-y and ldflags-y
        These three flags apply only to the kbuild makefile in which they
        are assigned. They are used for all the normal cc, as and ld
        invocations happening during a recursive build.
        Note: Flags with the same behaviour were previously named:
        EXTRA_CFLAGS, EXTRA_AFLAGS and EXTRA_LDFLAGS.
        They are still supported but their usage is deprecated.

        ccflags-y specifies options for compiling with $(CC).

So you have defined a valid compilation flag for the built-in case.


But when the CONFIG_FEATURE_X is enabled as module (m) in .config, this does not include the header files from the path specified and gives the file not found error.

That's because

ccflags-$(CONFIG_FEATURE_X) += -I$(obj)/../../path  

would evaluate to

ccflags-m += -I$(obj)/../../path

According to the current version of Documentation/kbuild/makefiles.txt, there is no such compilation flag as "ccflags-m".
So the path specification is never used for the loadable module.


How can I do this?

Instead of the ccflags-$() flag, you could try to use CFLAGS_$@, a per-file options for $(CC).

CFLAGS_$@, AFLAGS_$@

    CFLAGS_$@ and AFLAGS_$@ only apply to commands in current
    kbuild makefile.

    $(CFLAGS_$@) specifies per-file options for $(CC).  The $@
    part has a literal value which specifies the file that it is for.

    Example:
        # drivers/scsi/Makefile
        CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF
        CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ \
                 -DGDTH_STATISTICS

    These two lines specify compilation flags for aha152x.o and gdth.o.

    $(AFLAGS_$@) is a similar feature for source files in assembly
    languages.

    Example:
        # arch/arm/kernel/Makefile
        AFLAGS_head.o        := -DTEXT_OFFSET=$(TEXT_OFFSET)
        AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
        AFLAGS_iwmmxt.o      := -Wa,-mcpu=iwmmxt

So in your Makefile:

CFLAGS_my_file.o =   -I$(obj)/../../path
sawdust
  • 16,103
  • 3
  • 40
  • 50
  • While documentation notes only `ccflags-y`, googling for `ccflags-m` reveals [LWN article](https://lwn.net/Articles/434278/) with changelog for 2.6.39 kernel, which notes about such flags too. However, I am not sure whether `ccflags-m` should work for newest kernel. – Tsyvarev Jul 22 '18 at 17:20
  • @Tsyvarev *"I am not sure whether ccflags-m should work for newest kernel."* -- Regardless, the OP has provided some evidence that it doesn't seem to work for the kernel version he's using. – sawdust Jul 23 '18 at 02:36
  • Will this CFLAGS_my_file.o = -I$(obj)/../../path work, if the my_file.c compilation depends on the include path? – Udit Agarwal Jul 23 '18 at 04:41
  • @UditAgarwal *"Will this CFLAGS_my_file.o = -I$(obj)/../../path work"* -- The kernel documentation suggests that it would, but you're the only one with the makefile and source code. So you're the person that has to test it. – sawdust Jul 23 '18 at 05:24
  • Also you can use `subst` to convert **m** to **y**. – 0andriy Jul 27 '18 at 22:22
2

As noted by the @sawdust answer, it seems (according to documentation) that only ccflags-y variable is supported, not a ccflags-m one.

However, for make things work you may use a "trick":

ccflags-y += ${ccflags-m}

Complete code:

obj-$(CONFIG_FEATURE_X) += my_file.o

ccflags-$(CONFIG_FEATURE_X) += -I$(obj)/../../path

# After all, add content of 'ccflags-m' variable to 'ccflags-y' one.
ccflags-y += ${ccflags-m}
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Why resort to using a two-line *"trick"* when there is a one-line conventional solution? – sawdust Jul 23 '18 at 02:39
  • Will this CFLAGS_my_file.o = -I$(obj)/../../path work, if the my_file.c compilation depends on the include path? – Udit Agarwal Jul 23 '18 at 04:45
  • 1
    @sawdust: Variable `CFLAGS_$@` is applied to the single *source file*. So, if optional component, which depends on some option, consists from 10 files, you need 10 lines for assign CCFLAGS variables. The "trick" requires **single additional line** *regardless* from the **number of files** in an optional component, and even *regardless* from the **number of optional components**. So it can be useful in some cases. – Tsyvarev Jul 23 '18 at 07:30
  • @UditAgarwal: Your [comment](https://stackoverflow.com/questions/51453193/ccflag-option-in-makefile/51467604?noredirect=1#comment89911643_51467604) seems to address the other answer. Could you remove the comment from here (as you have already added it for the other answer)? – Tsyvarev Jul 23 '18 at 07:34
  • @Tsyvarev -- Good, for other situations, there could be an advantage to this approach. – sawdust Jul 23 '18 at 07:49