如何检测包含链中的第一个Makefile?

如何检测包含链中的第一个Makefile?,makefile,gnu-make,Makefile,Gnu Make,假设我有一个目录~/dir1/dir2/dir3/和一个包含内容的文件Makefile include../Makefile ~/dir1/dir2/Makefile的内容与~/dir1/dir2/dir3/Makefile 如果允许我控制~/dir1/Makefile的内容,并且~/dir1/dir2/dir3/中调用了make,那么如何获取字符串~/dir1/dir2/dir3/Makefile(第一个包含文件)作为~/dir1/Makefile中的变量 可复制示例(根据MADSCUSTO

假设我有一个目录
~/dir1/dir2/dir3/
和一个包含内容的文件
Makefile

include../Makefile
~/dir1/dir2/Makefile
的内容与
~/dir1/dir2/dir3/Makefile

如果允许我控制
~/dir1/Makefile
的内容,并且
~/dir1/dir2/dir3/
中调用了
make
,那么如何获取字符串
~/dir1/dir2/dir3/Makefile
(第一个包含文件)作为
~/dir1/Makefile
中的变量

可复制示例(根据MADSCUSTOMENT的要求):

  • 任何unix系统
  • mkdir-p~/dir1/dir2/dir3
  • cd~/dir1/dir2/dir3
  • echo'包括../Makefile'>Makefile
  • cp./Makefile../Makefile
  • 现在,我们在
    ~/dir1/dir2/dir3/
    ~/dir1/dir2/
    中有一个具有相同声明的Makefile,即包含父目录中的Makefile的include声明

    如果在
    ~/dir1/dir2/dir3
    中调用了
    make
    ,则包含链最终停止在
    ~/dir1/Makefile


    如何找到此包含链中第一个文件的路径,即用作
    ~/dir1/dir2/dir3/Makefile
    中变量的
    ~/dir1/Makefile

    获取从CLI调用的第一个make文件的完整路径:

    make_path_called_from_cli:=$(firstword $(foreach mk,${MAKEFILE_LIST},$(abspath ${mk})))
    
    $(info Using GNUmake Special variable to obtain Every make file used...)
    
    $(info ${MAKEFILE_LIST})
    
    $(info Compute the full path for all of those make files...)
    all_make_file_full_path:=$(foreach mk,${MAKEFILE_LIST},$(abspath ${mk}))
    
    $(info ${all_make_file_full_path})
    
    $(info The last one from the list is the current make file...)
    
    current_make_file_path:=$(lastword ${all_make_file_full_path})
    $(info ${current_make_file_path})
    
    $(info Now we remove the current make file from the list of make...)
    all_make_file_path_except_current:=$(filter-out ${current_make_file_path}, ${all_make_file_full_path})
    
    $(info ${all_make_file_path_except_current})
    
    # Now the last one from the list is the make file which included the current one
    parent_make_file_path:=$(lastword ${all_make_file_path_except_current})
    
    $(info We finally have the answer...)
    $(info ${parent_make_file_path})
    

    获取包含当前make文件的make文件的完整路径:

    make_path_called_from_cli:=$(firstword $(foreach mk,${MAKEFILE_LIST},$(abspath ${mk})))
    
    $(info Using GNUmake Special variable to obtain Every make file used...)
    
    $(info ${MAKEFILE_LIST})
    
    $(info Compute the full path for all of those make files...)
    all_make_file_full_path:=$(foreach mk,${MAKEFILE_LIST},$(abspath ${mk}))
    
    $(info ${all_make_file_full_path})
    
    $(info The last one from the list is the current make file...)
    
    current_make_file_path:=$(lastword ${all_make_file_full_path})
    $(info ${current_make_file_path})
    
    $(info Now we remove the current make file from the list of make...)
    all_make_file_path_except_current:=$(filter-out ${current_make_file_path}, ${all_make_file_full_path})
    
    $(info ${all_make_file_path_except_current})
    
    # Now the last one from the list is the make file which included the current one
    parent_make_file_path:=$(lastword ${all_make_file_path_except_current})
    
    $(info We finally have the answer...)
    $(info ${parent_make_file_path})
    

    如果目录的名称不尽相同,那么这个问题就更容易理解了。我不知道你是如何从
    ~/test/test/test/Makefile
    ~/test/Makefile
    的。。。还有其他的吗?无论如何,我认为您可以通过适当使用
    MAKEFILE_LIST
    获得您想要的东西,但如果没有,您可以澄清这个问题,希望通过MCVE,我建议您使用
    include
    仅合并专门为该目的设计和专门用于该目的的MAKEFILE片段。否则,如果要使用在其他makefile中定义的规则,请使用recursive
    make
    。这会帮你省去很多麻烦。其中之一就是不确定是否有任何给定的文件是包含树的根。@Madscitist我已经按照你的建议重构了这篇文章
    MAKEFILE_LIST
    确实为我做了这项工作,但在重构帖子之后,我发现了另一个错误。不知何故,包含父目录中的Makefile意味着您不能包含包含的Makefile(包含的Makefile)的父目录中存在的另一个Makefile,我编写的示例在make中返回了一个错误的地址错误,原因是dir2 makefile包括
    。/makefile
    您新发现的错误是下面两个makefile中的错误;您可以修复它,但不能从顶级makefile中修复。至于主要问题,您是否需要波浪线(“~”)?绝对路径(例如,
    /users/monke/dir1/dir2/dir3/Makefile
    )更容易构建。我相信OP要求调用的第一个Makefile(来自命令行的一个),简单地说就是
    $(firstword$(Makefile\u LIST))