Makefile conditional include
Asked Answered
S

2

23

I'm trying to write an application that needs either ALSA or OSS headers. Basically, I want to pass a define to the compiler if /etc/oss.conf does not exist, since that probably means the soundcard.h header doesn't exist (feel free to correct me on that one, I'm still new to working with OSS). Per the OSS documentation, you would use the include directive like so:

include /etc/oss.conf
CFLAGS := -I$(OSSLIBDIR)/include/sys

One problem. OSS support is optional, so I'd want to check if the header exists, and if does, pass a define to the compiler. The problem is, AFAIK there is no way to check if a file exists outside of a makefile rule. Inside the rule, if I use an if statement, for some reason, trying to set CFLAGS doesn't alter it:

test: $(objects)
    @if [ -f ${OSS_CONFIG} ]; then \
    . ${OSS_CONFIG}; \
    CFLAGS+=" -I${OSSLIBDIR} -DUSE_OSS"; \
    fi
    @echo ${CFLAGS}

(The above just outputs the original value of CFLAGS, even if ${OSS_CONFIG} exists.) This is, of course, extremely ugly, and I'm wondering if there's a cleaner way to do it. Or is the way I'm going about this going to trigger a worldwide cataclysmic event involving the genocide of kittens?

Oh, and please don't tell me to use autoconf.

Symbology answered 11/10, 2010 at 21:19 Comment(2)
Unfortunately, this kind of thing is why the abominable system known as "autoconf" got created in the first place. Before autoconf, you would hand-craft a config script which is easy enough to do if you are fluent in the common-subset dialect of /bin/sh that works on every unix-like platform where your code might run. Lots of people still swear by hand-crafting your own config script... I've also heard that CMAKE is another way out, but don't know enough about it to base an answer on that.Defroster
I can strongly recommend CMake. Good stuff.Jud
I
30

One suggest: use -include (then it won't warn + quit on failure). I don't know if I ever quite got this syntax to work myself, though.

Another hack could be something along the lines of: DUMMY_VAR := $(shell ... ) to execute arbitrary code. I think this is even less likely to work.

Other than that, I don' think this is possible. When I looked into a similar problem recently, I found that I can't get make to run arbitrary shell commands during the makefile creation process.

Immedicable answered 11/10, 2010 at 21:27 Comment(1)
Wow, I was completely unaware of -include. Thank you very much for that, that pretty much solved my problem. I can just use an ifdef OSSLIBDIR after the include and then assign CFLAGS accordingly. Kudos.Symbology
S
14

Yes, there is a cleaner way. You can test for the existence of a file with the wildcard function, and then use ifeq/endif to set up the appropriate CFLAGS. If you stick the audio-related flags into something like AUDIO_CFLAGS then you can automatically include the correct set of flags throughout the Makefile.

It'll look something like this:

OSS_CONF_FILE := $(strip $(wildcard /etc/oss.conf))

ifeq ($OSS_CONF_FILE,)
    AUDIO_CFLAGS = "-I${ALSALIBDIR} -DUSE_ALSA"
else 
    AUDIO_CFLAGS = "-I${OSSLIBDIR} -DUSE_OSS"
endif


sample_build_rule:
    $(CC) $(CFLAGS) $(AUDIO_CFLAGS) ...
Starstudded answered 11/10, 2010 at 21:41 Comment(3)
That works as well, although I think I'll stick with -include and using ifdef just for the sake of clarity. Good point about using a separate variable for the library-specific CFLAGS, I think I'll use that.Symbology
Thats neat, that almost solves my problem too. Out of curiosity, do you know if there is a way to use a foreach loop in makefiles? Specifically, I'm looking to do something like: foreach DIR in ( ls ) -include DIR/Rules.mkImmedicable
include will take multiple files and expand wildcards. Does -include */Rules.mk not work for you?Starstudded

© 2022 - 2024 — McMap. All rights reserved.