如何编写一个makefile,其中编译的对象文件位于具有不同名称的不同目录中?

如何编写一个makefile,其中编译的对象文件位于具有不同名称的不同目录中?,makefile,system-verilog,questasim,Makefile,System Verilog,Questasim,因此,我试图编写一个Makefile,用于QuestaSim和systemverilog文件。如果你不知道那是什么(大多数人都不知道),那么别担心,这与我的问题无关 我有一个项目主管,其中包含:src/work/Makefile src/目录包含多个目录,每个目录都包含源文件 工作/目录最初不存在,由makefile创建 当我调用名为vlog的“编译器”时,在一个.sv文件上,会在工作文件夹中创建一个目录,该目录与没有后缀的.sv文件同名。在该目录中有三个文件,我将用作“对象”文件的文件是_pr

因此,我试图编写一个Makefile,用于QuestaSim和systemverilog文件。如果你不知道那是什么(大多数人都不知道),那么别担心,这与我的问题无关

我有一个项目主管,其中包含:src/work/Makefile

src/目录包含多个目录,每个目录都包含源文件

工作/目录最初不存在,由makefile创建

当我调用名为vlog的“编译器”时,在一个.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‘‘‘‘‘‘‘‘‘)将.sv文件的路径转换为相关的_primary.dat文件的路径”,但是,由于我们放松了目录结构,不可能实现相反的操作

所以我想我想要的是object->src中的某种映射。这样,在我的$(OBJ):target中,我可以执行“vlog$(getsrc$@)”

在这之后,我必须处理编译顺序和依赖关系,但我可能可以解决这个问题


有什么建议吗?

我找到了一个有效的解决方案。我不确定这是最简单的解决方案,但我会把它贴在这里,以帮助其他有这个问题的人

基本上,我创建了一个包含两个参数的宏:.sv源文件路径和名称,以及依赖项列表。这将源文件路径转换为目标文件路径,并将其创建为目标。使用源文件的依赖项和传入的任何依赖项。然后,我创建了一个包含所有源文件列表的变量。最后,我o:$(foreach src,$(src),$(eval$(调用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)

1) 是否存在源名称冲突的危险?也就是说,如果存在
src/interface/foo.sv
,是否也存在
src/engine/foo.sv
?2)可以
src/
超过两个级别?也就是说,是否存在
src/foo/bar/baz.sv
?我要求包/接口/模块与因此,任何冲突都会导致编译错误。目前目录只有两个级别很深,但我可以考虑稍后添加更多的级别。您是否看过与Questa一起出现的 VGuest实用程序?我不知道这一点。我看了一下,它看起来并不是很好。用我的MaMfile解决方案和然后运行vmake work>test。然后删除工作库并重新创建它。最后运行make-f test,我得到了一系列错误。查看测试文件,所有内容的顺序都不正确,出于某种原因,我的UVM include dir周围有{},这使它停止工作。