Makefile с несколькими результатами - PullRequest
0 голосов
/ 30 апреля 2018

Это моя первая попытка написать make-файл, и поэтому есть много возможностей для улучшений. Мне нужно сгенерировать несколько функций mex для matlab на mac, используя пакет sedumi и студию компилятора intel.

Вот файл makefile

# define matlab dir
MDIR = /Applications/MATLAB_R2017b.app

# compiles mex files using g++
#CC = gcc

# compiler flags for g++
#CCFLAGS = -O3 -fpic

# to use the intel compiler instead, uncomment CC and CCFLAGS below:

# compiles mex file using the intel compiler
CC = icc

# compiler flags for intel compiler
CCFLAGS = -O3 -fPIC -D__amd64

# Figure out which platform we're on
UNAME = $(shell uname -s)

# Linux
ifeq ($(findstring Linux,${UNAME}), Linux)
    # define which files to be included
    CINCLUDE = -I$(MDIR)/extern/include -Ic++ -shared
    # define extension
    EXT = mexa64
endif

# Mac OS X
ifeq ($(findstring Darwin,${UNAME}), Darwin)
    # define which files to be included
    CINCLUDE = -L$(MDIR)/bin/maci64 -Ic++ -shared -lmx -lmex -lmat -lmwblas
    # define extension
    EXT = mexmaci64
    # CCFLAGS += -std=c++11 
endif

SRC:=$(wildcard *.c)

*.o: $(SRC)
    for i in $(SRC) ; do \
    $(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $$i -o $${i%.c}.o; \
    done

OBJ0:=bwblkslv.o sdmauxFill.o sdmauxRdot.o
OBJ1:=choltmpsiz.o


all: 
    $(CC) $(CCFLAGS) $(CINCLUDE) $(OBJ0) -o bwblkslv.$(EXT)
    $(CC) $(CCFLAGS) $(CINCLUDE) $(OBJ1) -o choltmpsiz.$(EXT)

# clean up
clean:
    rm -f *.o *.$(EXT)

Как есть, Makefile работает просто отлично. make, а затем make все возвращают mex-функции, необходимые в matlab.

У меня OBJ0 к OBJ37, и хотя добавление строк решает проблему, мне интересно, есть ли более простой способ добиться тех же результатов.

Большое спасибо.

Ed

PS. Спасибо автору https://github.com/jtilly/mex за части make-файла.

1 Ответ

0 голосов
/ 01 мая 2018

Есть несколько аспектов, которые вы можете улучшить:

  1. Использовать автоматические переменные make ($@, $<, $^ ...)

  2. Используйте более ориентированный на создание стиль для своих компиляций C, благодаря правилу make pattern :

    SRC := $(wildcard *.c)
    OBJ := $(patsubst %.c,%.o,$(SRC))
    
    %.o: %.c
        $(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $< -o $@
    

    Это имеет несколько преимуществ перед вашей оболочкой. Наиболее важным является то, что только одна компиляция запускается, когда изменяется только один файл C. С вашим решением все файлы C перекомпилируются, когда изменяется только одно. Более того, *.o - это шаблон, который распространяется на существующие объектные файлы. Обычно не то, что вы хотите. Обратите внимание, что в вашем случае вы также можете использовать статическое шаблонное правило :

    $(OBJ): %.o: %.c
        $(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $< -o $@
    

    , который выглядит почти так же, но ограничивает правило указанным списком целей $(OBJ).

  3. Используйте макрос и foreach-eval-call для создания правил компоновщика:

    .PHONY: all clean
    
    EXTS :=
    
    # $(1): variable name
    define MY_rule
    $(1)_EXT := $$(patsubst %.o,%.$$(EXT),$$(firstword $$($(1))))
    
    EXTS += $$($(1)_EXT)
    
    $$($(1)_EXT): $$($(1))
        $$(CC) $$(CCFLAGS) $$(CINCLUDE) $$^ -o $$@
    endef
    
    OBJVARS := OBJ0 OBJ1 ... OBJ37
    
    OBJ0 := bwblkslv.o sdmauxFill.o sdmauxRdot.o
    OBJ1 := choltmpsiz.o
    
    $(foreach v,$(OBJVARS),$(eval $(call MY_rule,$(v))))
    
    all: $(EXTS)
    
    clean:
        rm -f $(OBJ) $(EXTS)
    

    Обратите внимание на $$, чтобы избежать первого расширения, добавленного eval. Например, первая итерация foreach создает следующее правило:

    OBJ1_EXT := $(patsubst %.o,%.$(EXT),$(firstword $(OBJ1))
    
    EXTS += $(OBJ1_EXT)
    
    $(OBJ1_EXT): $(OBJ1)
        $(CC) $(CCFLAGS) $(CINCLUDE) $^ -o $@
    

    Простой способ создания макроса состоит в том, чтобы сначала записать то, что вы хотите, например, переменной OBJ1, заменить каждый $ на $$ и, наконец, заменить OBJ1 на $(1).

...