Makefile在另一个目录中编译库,如果它不';t不存在或目录已被修改

Makefile在另一个目录中编译库,如果它不';t不存在或目录已被修改,makefile,directory,shared-libraries,Makefile,Directory,Shared Libraries,嗨,我有一个makefile,它编译我的库,然后编译程序。我想做的是,makefile重新编译总是修改我的库文件,因为我在本文中考虑到了这一点 ifneq ("$(wildcard $(PATH_LIB.A)","") FILE_EXIST = 1 else FILE_EXIST = 0 endif $(MAIN_PROCESS): $(PATH_LIB.A) check_lib ...thing to do... $(PATH_LIB.a): FILE_EXIST = 0 check_l

嗨,我有一个makefile,它编译我的库,然后编译程序。我想做的是,makefile重新编译总是修改我的库文件,因为我在本文中考虑到了这一点

ifneq ("$(wildcard $(PATH_LIB.A)","")
FILE_EXIST = 1
else
FILE_EXIST = 0
endif

$(MAIN_PROCESS): $(PATH_LIB.A) check_lib
...thing to do...

$(PATH_LIB.a):
FILE_EXIST = 0

check_lib:
ifeq("$(FILE_EXIST)","0")
    $(MAKE) -C $(PATH_MAKEFILE_LIB.A)
endif

我的问题是,当我编译它时,它会一直重新链接“…thins to do…”,因为正在将所有时间的check_lib检查为可更新,您建议我做什么?

Make不是bash或python之类的脚本语言。它需要的是对目标和先决条件之间的相互依赖关系的描述,以及构建它们的方法。在您的情况下(但我不确定我是否了解所有细节),您可以尝试:

$(MAIN_PROCESS): $(PATH_LIB.A)
    ...thing to do...

$(PATH_LIB.A):
    $(MAKE) -C $(PATH_MAKEFILE_LIB.A)
仅此而已(但继续阅读,还有更多需要理解)。这告诉我们:

  • $(主进程)
    取决于
    $(路径库A)
    ,如果它不存在或比
    $(路径库A)
    旧,还需要做些什么来构建
    $(主进程)
  • $(PATH_LIB.A)
    不依赖于任何东西,以及如果它不存在该怎么办
  • 它几乎起作用了。这几乎仅仅是因为如果
    $(PATH_LIB.A)
    已经存在,但已经过期(相对于它自己的源文件),它将不会被重建。一种解决方法是将其声明为虚假:

    这样make将始终尝试重建它,即使它已经存在。如果需要,sub make会这样做,否则它只会告诉您它是最新的。但这并不是全部的故事:因为make总是试图重建<代码> $(PATHOLIB。A),它会考虑<代码> $(MIN进程)< /C>也必须重建,即使子make没有做任何事情,因为<代码> $(PATHOLIB .A)< /C> >是最新的。 如果这是一个问题,可以使用更棘手的解决方案,如使用一个或多个子品牌。其思路如下:

  • 使用make条件为
    $(主进程)
    目标创建两个不同的调用上下文,并使用两个不同的规则
  • 在第一次调用make时,使用第一个上下文,其中
    $(主进程)
    依赖于虚假的
    $(路径库A)
    ,但是它的配方,而不是
    …要做的事情…
    是另一个上下文中对make的第二次调用
  • 对于第二次调用,
    $(主进程)
    依赖于非虚假的
    $(路径库A)
    ,并将有其正常的配方
  • 由于专用的make变量(
    SECONDPASS
    ,在下面的代码中),这两个上下文得以区分

    例如:

    host> cat lib/Makefile
    foo.a: foo.c
        touch $@
    
    host> cat Makefile
    ifeq ($(SECONDPASS),)
    $(MAIN_PROCESS): $(PATH_LIB.A)
        $(MAKE) SECONDPASS=1
    
    .PHONY: $(PATH_LIB.A)
    
    $(PATH_LIB.A):
        $(MAKE) -C $(dir $@)
    else
    $(MAIN_PROCESS): $(PATH_LIB.A)
        touch $@
    endif
    
    host> make --no-print-directory
    make -C lib/
    touch foo.a
    make SECONDPASS=1
    touch bar
    
    host> make --no-print-directory
    make[1]: 'foo.a' is up to date.
    make SECONDPASS=1
    make[1]: 'bar' is up to date.
    
    host> touch lib/foo.c
    
    host> make --no-print-directory
    make -C lib/
    touch foo.a
    make SECONDPASS=1
    touch bar
    
    host> touch lib/foo.a
    
    host> make --no-print-directory
    make -C lib/
    make[1]: 'foo.a' is up to date.
    make SECONDPASS=1
    touch bar
    

    嗯,我明白你的意思,但例如,如果我的
    lib.a
    有一个名为
    foo.c
    的文件,并且我修改
    foo.c
    (在lib.a目录中),当我要做的时候,它将检查
    $(主进程)
    $(路径库a)
    ,并且它们将匹配,尽管
    lib.a
    应该更新。也许我应该检查库目录中的所有文件?但是,在这种情况下,我是否必须为我的库使用的每个函数创建另一个宏?@JaumeGarciaSanchez:不,因为它是假的,make将始终尝试重建
    $(PATH_lib.A)
    。要做到这一点,它将启动子make,负责
    $(PATH_LIB.A)
    的源文件。请注意,我忘了提到这种方法的一个缺点:
    $(主进程)
    也将始终重建,即使sub make最终决定
    $(PATH\u LIB.a)
    是最新的。这是一个问题吗?哦,看起来像是
    .PHONY
    的东西还不够,但直到现在我一直在Makefile的最顶端使用
    .PHONY
    之类的东西,但没有正常工作,当我看到你的例子时,我试着在规则之前编写
    。PHONY:$(PATH_LIB.a)
    ,这很有效。现在我意识到,在声明之前,我说过要将Makefile转换成假的$(PATH_LIB.A),这可能是因为它不起作用。非常感谢你。我用了这个棘手的部分来解决问题。如果你把它贴出来,我会打勾表示正确。非常感谢。
    host> cat lib/Makefile
    foo.a: foo.c
        touch $@
    
    host> cat Makefile
    ifeq ($(SECONDPASS),)
    $(MAIN_PROCESS): $(PATH_LIB.A)
        $(MAKE) SECONDPASS=1
    
    .PHONY: $(PATH_LIB.A)
    
    $(PATH_LIB.A):
        $(MAKE) -C $(dir $@)
    else
    $(MAIN_PROCESS): $(PATH_LIB.A)
        touch $@
    endif
    
    host> make --no-print-directory
    make -C lib/
    touch foo.a
    make SECONDPASS=1
    touch bar
    
    host> make --no-print-directory
    make[1]: 'foo.a' is up to date.
    make SECONDPASS=1
    make[1]: 'bar' is up to date.
    
    host> touch lib/foo.c
    
    host> make --no-print-directory
    make -C lib/
    touch foo.a
    make SECONDPASS=1
    touch bar
    
    host> touch lib/foo.a
    
    host> make --no-print-directory
    make -C lib/
    make[1]: 'foo.a' is up to date.
    make SECONDPASS=1
    touch bar