【问题标题】:Overwrite variables in recursive make覆盖递归make中的变量
【发布时间】:2022-06-11 10:09:15
【问题描述】:

我正在开发一个国际象棋引擎,最近决定重写我们的 makefile。我决定使用递归生成文件,它具有一组编译选项:

NAMING   ?= 1
STATIC   ?= 0
NATIVE   ?= 0
DETECT   ?= 1
PGO      ?= 0
DEBUG    ?= 0
LTO      ?= 0
PEXT     ?= 0

根据上面的标志,我生成了 FLAGS 来构建我的程序。我的makefile 的主要目标是build。我的 makefile 使用上面的标志并生成所有选项。从理论上讲,如果我将它称为make build PGO=1 NATIVE=1 ...,makefile 可以正常工作。现在这是我想要的行为。此外,我想到了做一个递归的 makefile,它预先定义了一些选项,例如:

native:
    $(_MAKE) build DEBUG=0 NATIVE=1 PGO=0 LTO=1 DETECT=1 NAMING=$(NAMING) STATIC=$(STATIC) EXE_NAME=$(EXE_NAME)

pgo:
    $(_MAKE) build DEBUG=0 NATIVE=1 PGO=1 LTO=1 DETECT=1 NAMING=$(NAMING) STATIC=$(STATIC) EXE_NAME=$(EXE_NAME)

问题是我无法覆盖递归生成文件中的那些指定变量。假设我打电话给make pgo,它会进入递归make和调用

$(_MAKE) build DEBUG=0 NATIVE=1 PGO=1 LTO=1 DETECT=1 NAMING=$(NAMING) STATIC=$(STATIC) EXE_NAME=$(EXE_NAME)

当我尝试在 makefile 中指定 PGO := 0 时,它似乎对 PGO 变量没有影响。似乎我无法以我的方式调用它时覆盖它。完整的makefile如下:

_THIS     := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
_ROOT     := $(_THIS)/..
_SRC      := $(_ROOT)/src_files
_BIN      := $(_ROOT)/bin
_MAKE     := $(MAKE) --no-print-directory -C $(_THIS) -e

# compiler and sources
CXX        = g++
_LIBS_WL  := -Wl,--whole-archive -lpthread -Wl,--no-whole-archive
_LIBS     := -pthread
_CXXSRCS  := $(_SRC)/*.cpp
_CSRCS    := $(_SRC)/syzygy/tbprobe.c
_SRCS     := $(_CSRCS) $(_CXXSRCS)

# engine name and version
NAME       = Koivisto
MINOR      = 11
MAJOR      = 8
MAKROS     = -DMINOR_VERSION=$(MINOR) -DMAJOR_VERSION=$(MAJOR)
EXE_NAME   = $(NAME)_$(MAJOR).$(MINOR)
EXE_DIR    = $(_ROOT)/bin
EXE        = $(EXE_DIR)/$(EXE_NAME)
EVALFILE   = $(_ROOT)/networks/default.net
EXE_INFO   =


# compilation flags
FLAGS          = -std=c++17 -Wall -Wextra -Wshadow -DEVALFILE=\"$(EVALFILE)\"
MARCH_FLAG     = -march=native
PGO_PRE_FLAGS  = -fprofile-generate -lgcov
PGO_POST_FLAGS = -fprofile-use -fno-peel-loops -fno-tracer

# ---------------------------------------------------------------------------------------------------------------------
# COMPILATION OPTIONS AND NAME ADJUSTMENT
# ---------------------------------------------------------------------------------------------------------------------

# options
NAMING   ?= 1
STATIC   ?= 0
NATIVE   ?= 0
DETECT   ?= 1
PGO      ?= 0
DEBUG    ?= 0
LTO      ?= 0
PEXT     ?= 0
# vector instructions
AVX512   ?= 0
AVX2     ?= $(AVX512)
AVX      ?= $(AVX2)
POPCNT   ?= $(AVX)
SSE42    ?= $(POPCNT)
SSE41    ?= $(SSE42)
SSE3     ?= $(SSE41)
SSE2     ?= $(SSE3)
SSE      ?= $(SSE2)

# adjust the exe name as well as the FLAGS
ifeq ($(PGO),1)
    EXE_INFO := $(EXE_INFO)-pgo
endif

ifeq ($(DEBUG),1)
    EXE_INFO := $(EXE_INFO)-debug
else
    FLAGS    += -DNDEBUG -O3
endif

ifeq ($(PEXT),1)
    EXE_INFO := $(EXE_INFO)-pext
    FLAGS    += -DUSE_PEXT -mbmi2
endif

ifeq ($(LTO),1)
    FLAGS    += -flto
endif

ifeq ($(STATIC),1)
    FLAGS    += -static -static-libgcc -static-libstdc++
endif

# toggle avx options based on the highest one
ifeq ($(AVX512),1)
    FLAGS += -mavx512f -mavx512bw -mavx512dq
endif
ifeq ($(AVX2),1)
    FLAGS += -mavx2
endif
ifeq ($(AVX),1)
    FLAGS += -mavx
endif
ifeq ($(POPCNT),1)
    FLAGS += -DUSE_POPCNT -mpopcnt
endif
ifeq ($(SSE42),1)
    FLAGS += -msse4.2
endif
ifeq ($(SSE41),1)
    FLAGS += -msse4.1
endif
ifeq ($(SSE3),1)
    FLAGS += -msse3
endif
ifeq ($(SSE2),1)
    FLAGS += -msse2
endif
ifeq ($(SSE),1)
    FLAGS += -msse
endif

# set name based on highest vector extension
ifeq ($(AVX512),1)
    EXE_INFO := $(EXE_INFO)-avx512
else ifeq ($(AVX2),1)
    EXE_INFO := $(EXE_INFO)-avx2
else ifeq ($(AVX),1)
    EXE_INFO := $(EXE_INFO)-avx
else ifeq ($(POPCNT),1)
    EXE_INFO := $(EXE_INFO)-popcnt
else ifeq ($(SSE42),1)
    EXE_INFO := $(EXE_INFO)-sse42
else ifeq ($(SSE41),1)
    EXE_INFO := $(EXE_INFO)-sse41
else ifeq ($(SSE3),1)
    EXE_INFO := $(EXE_INFO)-msse3
else ifeq ($(SSE2),1)
    EXE_INFO := $(EXE_INFO)-sse2
else ifeq ($(SSE),1)
    EXE_INFO := $(EXE_INFO)-sse
endif

# ---------------------------------------------------------------------------------------------------------------------
# HOST DETECTION AND NAME ADJUSTMENT IF NAMING IS ACTIVE
# ---------------------------------------------------------------------------------------------------------------------
ifeq ($(OS),Windows_NT)
    PREFIX     := windows
    SUFFIX     := .exe
    _LIBS      += $(_LIBS_WL)
else
UNAME    := $(shell uname -s)
ifeq ($(UNAME),Linux)
    PREFIX     := linux
    SUFFIX     :=
    _LIBS      += $(_LIBS_WL)
else
ifeq ($(UNAME),Darwin)
    PREFIX     := darwin
    SUFFIX     :=
    MARCH_FLAG := -mcpu=apple-a14
else
$(warning incompatible host, this might fail)
    PREFIX     := _
    SUFFIX     :=
endif
endif
endif
ifeq ($(NAMING),1)
    EXE := $(EXE_DIR)/$(EXE_NAME)-$(PREFIX)$(EXE_INFO)$(SUFFIX)
endif
EXE_FULL   := $(abspath $(EXE))

FLAGS      += $(MARCH_FLAG)

# auto detect certain flags
ifeq ($(DETECT),1)
    PROPS = $(shell echo | $(CC) $(MARCH_FLAG) -E -dM -)
    ifneq ($(findstring __BMI2__, $(PROPS)),)
        ifeq ($(findstring __znver1, $(PROPS)),)
            ifeq ($(findstring __znver2, $(PROPS)),)
                FLAGS += $(PEXTFLAGS)
            endif
        endif
    endif
endif


# ---------------------------------------------------------------------------------------------------------------------
# RULES
# ---------------------------------------------------------------------------------------------------------------------

ifeq ($(UNAME),Darwin)
openbench:
    $(_MAKE) build DEBUG=0 NATIVE=1 PGO=0 LTO=1 DETECT=1 EVALFILE=$(EVALFILE) NAMING=0 EXE=$(EXE)
else
openbench:
    $(_MAKE) build DEBUG=0 NATIVE=1 PGO=1 LTO=1 DETECT=1 EVALFILE=$(EVALFILE) NAMING=0 EXE=$(EXE)
endif

native:
    $(_MAKE) build DEBUG=0 NATIVE=1 PGO=0 LTO=1 DETECT=1 NAMING=$(NAMING) STATIC=$(STATIC) EXE_NAME=$(EXE_NAME)

pgo:
    $(_MAKE) build DEBUG=0 NATIVE=1 PGO=1 LTO=1 DETECT=1 NAMING=$(NAMING) STATIC=$(STATIC) EXE_NAME=$(EXE_NAME)


overview:
    $(info NAME      : $(NAME))
    $(info EXE       : $(EXE))
    $(info FULL NAME : $(EXE_FULL))
    $(info NAMING    : $(NAMING))
    $(info FLAGS     : $(FLAGS))
    $(info NATIVE    : $(NATIVE))
    $(info STATIC    : $(STATIC))
    $(info PEXT      : $(PEXT))
    $(info PGO       : $(PGO))
    $(info DEBUG     : $(DEBUG))
    $(info AVX512    : $(AVX512))
    $(info AVX2      : $(AVX2))
    $(info AVX       : $(AVX))
    $(info POPCNT    : $(POPCNT))
    $(info SSE42     : $(SSE42))
    $(info SSE41     : $(SSE41))
    $(info SSE3      : $(SSE3))
    $(info SSE2      : $(SSE2))
    $(info SSE       : $(SSE))

build: updateNetwork overview
    mkdir -p $(EXE_DIR)
    ifeq ($(PGO),1)
        $(CXX) $(PGO_PRE_FLAGS)  $(FLAGS) $(_SRCS) $(MAKROS) $(_LIBS) -o $(EXE)
        $(EXE_FULL) bench
        $(CXX) $(PGO_POST_FLAGS) $(FLAGS) $(_SRCS) $(MAKROS) $(_LIBS) -o $(EXE)
        @rm -f *.gcda
    else
        $(CXX) $(FLAGS) $(_SRCS) $(MAKROS) $(_LIBS) -o $(EXE)
    endif

release:
    #$(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 AVX512=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 AVX2=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 POPCNT=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE42=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE41=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE3=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE2=1
    $(_MAKE) build DEBUG=0 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE=1

    #$(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 AVX512=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 AVX2=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 POPCNT=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE42=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE41=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE3=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE2=1
    $(_MAKE) build DEBUG=0 PEXT=1 PGO=1 LTO=1 DETECT=0 NAMING=1 STATIC=1 SSE=1

# update the network
updateNetwork:
    ifeq ($(EVALFILE),$(_ROOT)/networks/default.net)
        git -C .. submodule update --init
    endif

有谁知道我可以如何覆盖递归 makefile 中的变量?我很高兴得到任何帮助!

【问题讨论】:

  • 那个makefile是very large, and most of it has no bearing on the question。我的猜测是当你make pgo时,Make的主实例(其中目标是pgo)中PGO的值是0,而第二个实例中PGO的值(即由主实例调用,其中目标是其他东西)是1。并且您想修改此生成文件,以便第二个实例可以更改该值。如果这就是你想要的,那么问题就很简单了。是你想要的吗?
  • 是的,这正是我想要的。我希望第二个实例编辑第一个实例传递的变量。

标签: makefile


【解决方案1】:

来自the manual

如果一个变量已经设置了一个命令参数,那么普通 makefile 中的分配被忽略。如果你想设置 makefile 中的变量,即使它是用命令设置的 参数,您可以使用override 指令...

像这样:

override PGO := 0

【讨论】:

    猜你喜欢
    • 2020-11-26
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    相关资源
    最近更新 更多