如何编写一个生成文件,其中已编译的目标文件位于具有不同名称的不同目录中?
How to write a makefile where the compiled object files are in a different directory with a different name?
所以我正在尝试编写一个 Makefile 以与 QuestaSim 和 systemverilog 文件一起使用。如果您不知道那是什么(大多数人不知道),请不要担心,这与我的问题无关。
我有一个项目主管包含:src/work/Makefile
src/ 目录包含几个目录,每个目录都包含源文件。
work/ 目录最初并不存在,是由 makefile 创建的。
当我调用名为 vlog 的 "compiler" 时,在 .sv 文件上会在工作文件夹中创建一个与 .sv 文件同名但没有后缀的目录。在该目录中有三个文件,我将用作我的“对象”文件的文件是 _primary.dat.
因此,例如,调用 "vlog src/interface/my_interface.sv" 创建(如果成功)work/my_interface/_primary.dat
我的 .sv 文件也需要按特定顺序编译,我只想在源文件或其依赖项之一发生更改时编译它们。
我可以使用“$(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR) /, $(basename $(notdir $(SRC)))))" 但是反过来是不可能的,因为我们松散了目录结构。
所以我想我想要的是来自对象 -> src 的某种映射。这样在我的 $(OBJ): 目标中,我可以做 "vlog $(getsrc $@)".
之后我必须处理编译顺序和依赖关系,但我可能会解决这个问题。
有什么建议吗?
我找到了一个有效的解决方案。我不确定它是否最简洁,但我会 post 在这里帮助遇到此问题的其他人。
基本上我创建了一个带有两个参数的宏:.sv 源文件路径和名称,以及依赖项列表。这会将源文件路径转换为目标文件路径并将其创建为目标。依赖于源文件和任何传入的依赖项。然后我创建一个变量,其中包含我所有来源的列表。最后我做了: $(foreach src,$(SRCS),$(eval $(call create_target_for, $(src)))) 它创建了我所有的目标。
此外,我将每个子目录作为一个虚假目标,具有相关的依赖关系,使我能够在目录上获得正确的编译顺序。
唯一缺少的是我是否需要确保单个目录中的文件具有正确的编译顺序。
我的生成文件:
# Makefile for use in building all my UVM components
# ----------------------------------------------------------------------------------
# Requirements:
# QuestaSim - We use the vlog compiler packaged with QuestaSim.
# ModelSim also comes with vlog, but doesn't really support UVM.
# UVM_INCLUDE_DIR environment var - This should point to the UVM src directory.
# For me this is: C:\questasim_10.0b\verilog_src\uvm-1.0p1\src
# ----------------------------------------------------------------------------------
# Notes:
# The vlog compiler creates an output folder in the VLIB_DIR directors
# per package/module/interface with the same name as the entity
# Any capitals are replace with @ followed by the lower case letter
# IE. FooBar -> @foo@bar
# This makefile requires that:
# All interfaces end in _if
# All packages end in _pkg
# Each file can only contain a single interface, package or module
# No capitals in package/module/interface naems
# The package/module/interface has the same name as the file
# some variabls to use later
VLIB_DIR = ./work
VLOG_FLAGS = +incdir+$(UVM_INCLUDE_DIR)
# src files - per directory for use with compile orders
# ie. transactions have to be compiled before drivers
INTERFACE_SRCS = $(wildcard src/interfaces/*.sv)
CONFIG_SRCS = $(wildcard src/configs/*.sv)
TRANSACTION_SRCS = $(wildcard src/transactions/*.sv)
SEQUENCE_SRCS = $(wildcard src/sequences/*.sv)
DRIVER_SRCS = $(wildcard src/drivers/*.sv)
MONITOR_SRCS = $(wildcard src/monitors/*.sv)
AGENT_SRCS = $(wildcard src/agents/*.sv)
SCOREBOARD_SRCS = $(wildcard src/scoreboards/*.sv)
# all source files - for use with creating makefile targets
SRCS = $(INTERFACE_SRCS) \
$(CONFIG_SRCS) \
$(TRANSACTION_SRCS) \
$(SEQUENCE_SRCS) \
$(DRIVER_SRCS) \
$(MONITOR_SRCS) \
$(AGENT_SRCS) \
$(SCOREBOARD_SRCS)
# list of all the components
COMPONENTS = interfaces \
configs \
transactions \
sequences \
drivers \
monitors \
agents \
scoreboards
# colours for use in echo commands for highlighting
COLOUR_NONE = \x1b[0m
COLOUR_RED = \x1b[31;01m
COLOUR_BLUE = \x1b[34;01m
COLOUR_GREEN = \x1b[32;01m
# macros to turn a .sv file into the compiled file in the relevant VLIB_DIR subdirectory
# src/abc/def.sv -> $(VLIB_DIR)/def/_primary.dat
src2obj = $(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR)/, $(basename $(notdir $(1)))))
# macro to create a target for a given source file
# it takes two arguments:
# 1) the path and name of the source file
# 2) any dependencies
# It then creates a traget on the relevant _primary.dat (questaSim created object)
# with a dependency on the source file, and any other passed in dependencies
define create_target_for
$$(info $COLOUR_GREEN create_target_for called on $(1))
$$(info creating target $(call src2obj, $(1)))
$$(info with dependencies $(VLIB_DIR) $(1) $(2))
$$(info )
$(call src2obj, $(1)): $(1) $(2)
@echo -e "$(COLOUR_BLUE)compiling $(1) because of changes in: $$? $(COLOUR_NONE)\n"
vlog $(VLOG_FLAGS) $(1)
endef
# default rule is to create the library, compile the UVM pkg and all the components
all: $(VLIB_DIR) UVM $(COMPONENTS)
# create the questaSim library if it's not already there
$(VLIB_DIR):
vlib $(VLIB_DIR)
@echo -e "$(COLOUR_GREEN)Created the $(VLIB_DIR) library$(COLOUR_NONE)\n"
# compile the UVM library
$(VLIB_DIR)/uvm_pkg/_primary.dat:
vlog +incdir+$(UVM_INCLUDE_DIR) $(UVM_INCLUDE_DIR)/uvm.sv
@echo -e "$(COLOUR_GREEN)Compiled the UVM package$(COLOUR_NONE)\n"
# simple alias
UVM: $(VLIB_DIR) $(VLIB_DIR)/uvm_pkg/_primary.dat
# create targets for all our sources
# note with this method we can't set dependencies within a single directory
$(foreach src,$(SRCS),$(eval $(call create_target_for, $(src))))
# define a phony target per directory so we can specify compile order
interfaces: $(VLIB_DIR) UVM \
$(call src2obj, $(INTERFACE_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
configs: $(VLIB_DIR) UVM \
$(call src2obj, $(CONFIG_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
transactions: $(VLIB_DIR) UVM \
$(call src2obj, $(TRANSACTION_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
sequences: $(VLIB_DIR) UVM \
transactions \
$(call src2obj, $(SEQUENCE_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
drivers: $(VLIB_DIR) UVM \
transactions interfaces \
$(call src2obj, $(DRIVER_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
monitors: $(VLIB_DIR) UVM \
transactions interfaces \
$(call src2obj, $(MONITOR_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
agents: $(VLIB_DIR) UVM \
drivers monitors transactions configs interfaces \
$(call src2obj, $(AGENT_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
scoreboards: $(call src2obj, $(SCOREBOARD_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
# delete the library and all compiled files
clean:
if [ -d $(VLIB_DIR) ]; then vdel -lib $(VLIB_DIR) -all; fi;
.PHONY: clean UVM $(COMPONENTS)
所以我正在尝试编写一个 Makefile 以与 QuestaSim 和 systemverilog 文件一起使用。如果您不知道那是什么(大多数人不知道),请不要担心,这与我的问题无关。
我有一个项目主管包含:src/work/Makefile
src/ 目录包含几个目录,每个目录都包含源文件。
work/ 目录最初并不存在,是由 makefile 创建的。
当我调用名为 vlog 的 "compiler" 时,在 .sv 文件上会在工作文件夹中创建一个与 .sv 文件同名但没有后缀的目录。在该目录中有三个文件,我将用作我的“对象”文件的文件是 _primary.dat.
因此,例如,调用 "vlog src/interface/my_interface.sv" 创建(如果成功)work/my_interface/_primary.dat
我的 .sv 文件也需要按特定顺序编译,我只想在源文件或其依赖项之一发生更改时编译它们。
我可以使用“$(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR) /, $(basename $(notdir $(SRC)))))" 但是反过来是不可能的,因为我们松散了目录结构。
所以我想我想要的是来自对象 -> src 的某种映射。这样在我的 $(OBJ): 目标中,我可以做 "vlog $(getsrc $@)".
之后我必须处理编译顺序和依赖关系,但我可能会解决这个问题。
有什么建议吗?
我找到了一个有效的解决方案。我不确定它是否最简洁,但我会 post 在这里帮助遇到此问题的其他人。
基本上我创建了一个带有两个参数的宏:.sv 源文件路径和名称,以及依赖项列表。这会将源文件路径转换为目标文件路径并将其创建为目标。依赖于源文件和任何传入的依赖项。然后我创建一个变量,其中包含我所有来源的列表。最后我做了: $(foreach src,$(SRCS),$(eval $(call create_target_for, $(src)))) 它创建了我所有的目标。
此外,我将每个子目录作为一个虚假目标,具有相关的依赖关系,使我能够在目录上获得正确的编译顺序。
唯一缺少的是我是否需要确保单个目录中的文件具有正确的编译顺序。
我的生成文件:
# Makefile for use in building all my UVM components
# ----------------------------------------------------------------------------------
# Requirements:
# QuestaSim - We use the vlog compiler packaged with QuestaSim.
# ModelSim also comes with vlog, but doesn't really support UVM.
# UVM_INCLUDE_DIR environment var - This should point to the UVM src directory.
# For me this is: C:\questasim_10.0b\verilog_src\uvm-1.0p1\src
# ----------------------------------------------------------------------------------
# Notes:
# The vlog compiler creates an output folder in the VLIB_DIR directors
# per package/module/interface with the same name as the entity
# Any capitals are replace with @ followed by the lower case letter
# IE. FooBar -> @foo@bar
# This makefile requires that:
# All interfaces end in _if
# All packages end in _pkg
# Each file can only contain a single interface, package or module
# No capitals in package/module/interface naems
# The package/module/interface has the same name as the file
# some variabls to use later
VLIB_DIR = ./work
VLOG_FLAGS = +incdir+$(UVM_INCLUDE_DIR)
# src files - per directory for use with compile orders
# ie. transactions have to be compiled before drivers
INTERFACE_SRCS = $(wildcard src/interfaces/*.sv)
CONFIG_SRCS = $(wildcard src/configs/*.sv)
TRANSACTION_SRCS = $(wildcard src/transactions/*.sv)
SEQUENCE_SRCS = $(wildcard src/sequences/*.sv)
DRIVER_SRCS = $(wildcard src/drivers/*.sv)
MONITOR_SRCS = $(wildcard src/monitors/*.sv)
AGENT_SRCS = $(wildcard src/agents/*.sv)
SCOREBOARD_SRCS = $(wildcard src/scoreboards/*.sv)
# all source files - for use with creating makefile targets
SRCS = $(INTERFACE_SRCS) \
$(CONFIG_SRCS) \
$(TRANSACTION_SRCS) \
$(SEQUENCE_SRCS) \
$(DRIVER_SRCS) \
$(MONITOR_SRCS) \
$(AGENT_SRCS) \
$(SCOREBOARD_SRCS)
# list of all the components
COMPONENTS = interfaces \
configs \
transactions \
sequences \
drivers \
monitors \
agents \
scoreboards
# colours for use in echo commands for highlighting
COLOUR_NONE = \x1b[0m
COLOUR_RED = \x1b[31;01m
COLOUR_BLUE = \x1b[34;01m
COLOUR_GREEN = \x1b[32;01m
# macros to turn a .sv file into the compiled file in the relevant VLIB_DIR subdirectory
# src/abc/def.sv -> $(VLIB_DIR)/def/_primary.dat
src2obj = $(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR)/, $(basename $(notdir $(1)))))
# macro to create a target for a given source file
# it takes two arguments:
# 1) the path and name of the source file
# 2) any dependencies
# It then creates a traget on the relevant _primary.dat (questaSim created object)
# with a dependency on the source file, and any other passed in dependencies
define create_target_for
$$(info $COLOUR_GREEN create_target_for called on $(1))
$$(info creating target $(call src2obj, $(1)))
$$(info with dependencies $(VLIB_DIR) $(1) $(2))
$$(info )
$(call src2obj, $(1)): $(1) $(2)
@echo -e "$(COLOUR_BLUE)compiling $(1) because of changes in: $$? $(COLOUR_NONE)\n"
vlog $(VLOG_FLAGS) $(1)
endef
# default rule is to create the library, compile the UVM pkg and all the components
all: $(VLIB_DIR) UVM $(COMPONENTS)
# create the questaSim library if it's not already there
$(VLIB_DIR):
vlib $(VLIB_DIR)
@echo -e "$(COLOUR_GREEN)Created the $(VLIB_DIR) library$(COLOUR_NONE)\n"
# compile the UVM library
$(VLIB_DIR)/uvm_pkg/_primary.dat:
vlog +incdir+$(UVM_INCLUDE_DIR) $(UVM_INCLUDE_DIR)/uvm.sv
@echo -e "$(COLOUR_GREEN)Compiled the UVM package$(COLOUR_NONE)\n"
# simple alias
UVM: $(VLIB_DIR) $(VLIB_DIR)/uvm_pkg/_primary.dat
# create targets for all our sources
# note with this method we can't set dependencies within a single directory
$(foreach src,$(SRCS),$(eval $(call create_target_for, $(src))))
# define a phony target per directory so we can specify compile order
interfaces: $(VLIB_DIR) UVM \
$(call src2obj, $(INTERFACE_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
configs: $(VLIB_DIR) UVM \
$(call src2obj, $(CONFIG_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
transactions: $(VLIB_DIR) UVM \
$(call src2obj, $(TRANSACTION_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
sequences: $(VLIB_DIR) UVM \
transactions \
$(call src2obj, $(SEQUENCE_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
drivers: $(VLIB_DIR) UVM \
transactions interfaces \
$(call src2obj, $(DRIVER_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
monitors: $(VLIB_DIR) UVM \
transactions interfaces \
$(call src2obj, $(MONITOR_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
agents: $(VLIB_DIR) UVM \
drivers monitors transactions configs interfaces \
$(call src2obj, $(AGENT_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
scoreboards: $(call src2obj, $(SCOREBOARD_SRCS))
@echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"
# delete the library and all compiled files
clean:
if [ -d $(VLIB_DIR) ]; then vdel -lib $(VLIB_DIR) -all; fi;
.PHONY: clean UVM $(COMPONENTS)