简体   繁体   中英

Is there a portable way to make portable optionnal dependency in Makefile?

Working on Lua-i18n , I'm trying to change the Makefile so user can compile the project with the facilities they are interested in, that is the Makefile define some C macro that will disable the corresponding code. Defining that in the Makefile is straight forward, but getting rid of unnecessary compilation dependencies linked to the feature thus defined is less trivial when portability is targeted. Indeed, the project aims at modifying the original code as few as possible, and add as few dependencies as possible (possibly none).

So here are some relevant links found in the process

Here is a solution which seems to work on a Fedora 24 desktop with GNU Make. However I would like to know if such a solution would work with any (reasonably modern) make implementation out there.

cflag= -D CODE_SWITCH
resolved_conditional_cflag!= test -n "$(cflag)" && echo "$(cflag)"
conditional_dep= additional_dep.c
mandatory_dep= dep0.c dep1.c
resolved_conditional_dep!= test -n "$(cflag)" && echo "$(conditional_dep)"
all_dep= $(mandatory_dep) $(resolved_conditional_dep)
all: target
    @echo building code with flag $(resolved_conditional_cflag) 
    @echo ${SHELL}
target: $(all_dep)
    @echo building $@ which depends on $(all_dep)
dep0.c:
    @echo building dep0.c
dep1.c:
    @echo building dep1.c
additional_dep.c:
    @echo building $@

The idea is that the user comment the line cflag= -D CODE_SWITCH , and that's all, the compiler won't treat related dependencies. So, would such a solution be portable? It relies on the shell expansion != and the test command. I think the last one might be POSIX, but I may be wrong. More generally, their might be portability issues I'm not aware here.

Note that for this specific demand, "using CMake, autotools or other" is not an desired answer.

!= is only available in GNU make 4.0 and above. Also it's not POSIX; it was added to GNU make for portability with BSD make and it was proposed for inclusion in the POSIX spec, but it's not been accepted as of now.

I'm not aware of any way using only purely portable make (POSIX) to change the prerequisites of a target based on the contents of a make macro.

If you're willing to assume GNU make, then (at least for now) it's more portable to use $(shell ...) than != . Although if you assume GNU make there are better ways to handle this that don't require the shell at all. If you want to use != to get portability with BSD make, be sure to add a note to your docs that you require GNU make 4.0 or above.

NB, it's usually a really bad idea to not put whitespace between the variable name and the assignment operator in a makefile; eg it's better to write FOO != bar , instead of FOO!=bar or FOO!= bar .

EDIT

One option as discussed by Chrono Kitsune would be to use a bit of recursion; it would look something like this:

cflag= -D CODE_SWITCH

conditional_dep= additional_dep.c
mandatory_dep= dep0.c dep1.c

all_dep= $(mandatory_dep)
all: target
        @echo building code with flag $(cflag) 
        @echo ${SHELL}
target: $(mandatory_dep)
        @all_dep='$^'; if test -n "$(cflag)"; then \
            all_dep='$^ $(conditional_dep)'; \
            $(MAKE) $(conditional_dep); \
         fi; \
        echo building $@ which depends on $$all_dep
dep0.c:
        @echo building dep0.c
dep1.c:
        @echo building dep1.c
additional_dep.c:
        @echo building $@

Another alternative, if you don't have to have things depend on commenting out cflag itself, would be to use recursive variable naming; that would look something like this:

SWITCH = enabled

enabled_cflag = -D CODE_SWITCH
enabled_dep = additional_dep.c

mandatory_dep = dep0.c dep1.c

cflag = $($(SWITCH)_cflag)
all_dep = $(mandatory_dep) $($(SWITCH)_dep)

all: target
        @echo building code with flag $(cflag) 
        @echo ${SHELL}
target: $(all_dep)
        echo building $@ which depends on $(all_dep)
dep0.c:
        @echo building dep0.c
dep1.c:
        @echo building dep1.c
additional_dep.c:
        @echo building $@

Now if you comment out the SWITCH setting, or set it to empty on the make command line, then those elements will be turned off (because $($(SWITCH)_cflag) will expand the non-existent/empty variable _cflag not enabled_cflag ). Recursive variable naming is supported by most versions of make (but not all).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM