如何编写一个makefile,其中已编译的目标文件位于另一个具有不同名称的目录中? [英] How to write a makefile where the compiled object files are in a different directory with a different name?

查看:55
本文介绍了如何编写一个makefile,其中已编译的目标文件位于另一个具有不同名称的目录中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在尝试编写一个用于QuestaSim和systemverilog文件的Makefile.如果您不知道那是什么(大多数人不会),请不要担心,这与我的问题无关.

So I'm trying to write a Makefile to use with QuestaSim and systemverilog files. If you don't know what that is (and most people won't) then don't worry, it's not that relevant to my problem.

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

I have a project director containing: src/ work/ Makefile

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

the src/ directory contains several directories which each contain source files.

work/目录最初并不存在,而是由makefile创建的.

the work/ directory doesn't initially exist, and is created by the makefile.

当我将我的编译器"称为vlog时,在.sv文件上会在工作文件夹中创建一个目录,该目录的名称与.sv文件相同,但没有后缀.在该目录中有三个文件,我将用作目标"文件的一个文件是_primary.dat.

when I call my "compiler" which is called vlog, on a .sv file a directory gets created in the work folder with the same name as the .sv file without the suffix. In that directory are three files the one that I'll use as my "object' file is _primary.dat.

例如,调用"vlog src/interface/my_interface.sv"会创建(如果成功)work/my_interface/_primary.dat

So for example, calling "vlog src/interface/my_interface.sv" creates (if it succeeds) work/my_interface/_primary.dat

我的.sv文件也需要按照特定的顺序进行编译,并且我只想在源文件或其依赖项之一已更改的情况下进行编译.

My .sv files also need to be compiled in a specific order, and I only want to compile them if the source file or one of their dependencies has changed.

我可以使用"$(addsuffix/_primary.dat,$(addprefix $(VLIB_DIR)/,$(basename $(notdir $(SRC)))))",但是相反,因为我们失去了目录结构,所以是不可能的.

I can turn the path to the .sv file into the path to the relevant _primary.dat file using "$(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR)/, $(basename $(notdir $(SRC)))))" however the reverse is impossible, as we loose the directory structure.

所以我想我想要的是某种来自对象-> src的地图.这样,在我的$(OBJ):目标中,我可以执行"vlog $(getsrc $ @)".

So I think what I want is some sort of map from object -> src. So that in my $(OBJ): target, I can do "vlog $(getsrc $@)".

此后,我必须处理编译顺序和依赖项,但我可能可以解决.

After that I have to deal with the compile order and dependencies, but I can probably work that out.

有什么建议吗?

推荐答案

我找到了可行的解决方案.我不确定这是最干净的,但是我会将其发布在这里,以帮助遇到此问题的其他人.

I found a solution that works. I'm not sure it's the neatest, but I'll post it here to help anyone else who has this problem.

基本上,我创建一个带有两个参数的宏:.sv源文件的路径和名称以及依赖项列表.这会将源文件路径转换为目标文件路径,并将其创建为目标.具有对源文件的依赖关系以及任何传入的依赖关系.然后,我创建一个包含所有源列表的变量.最后我做了:$(foreach src,$(SRCS),$(eval $(call create_target_for,$(src)))))创建我的所有目标.

Basically I create a macro that takes two arguments: the .sv source file path and name, and a list of dependencies. This turns the source file path into the object file path and creates that as a target. With a dependency on the source file and any passed in dependencies. I then create a variable containing a list of all my sources. Finally I do: $(foreach src,$(SRCS),$(eval $(call create_target_for, $(src)))) which creates all my targets.

此外,我还把每个子目录作为伪目标,并带有相关的依存关系,使我能够在目录上获得正确的编译顺序.

Additionally I have each subdirectory as a phony target, with the relevant dependencies, allowing me to get the correct compile order on directories.

唯一缺少的是是否需要确保单个目录中的文件具有正确的编译顺序.

The only thing missing is if I need to ensure files in a single directory have the correct compile order.

我的Makefile:

My Makefile:

# 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,其中已编译的目标文件位于另一个具有不同名称的目录中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆