Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile 是否存在目标特定变量的非传递版本?_Makefile_Gnu Make - Fatal编程技术网

Makefile 是否存在目标特定变量的非传递版本?

Makefile 是否存在目标特定变量的非传递版本?,makefile,gnu-make,Makefile,Gnu Make,我使用特定于目标的变量传递特定于对象的标志已经有一段时间了。例如,如果我需要将可执行文件与某个库链接,我可能会执行以下操作: bin/foo: LDFLAGS += -lbar 而bin/%规则将拾取-lbar。这对系统库非常有效,但当我链接的库也是项目的一部分时,会出现问题。在这种情况下,我将有一个类似 bin/foo: lib/libbar.so 我应用于bin/foo的特定于目标的规则在构建lib/libbar时也会被传递!这不起作用,因为libbar。因此无法链接到自身。正如《圣经》

我使用特定于目标的变量传递特定于对象的标志已经有一段时间了。例如,如果我需要将可执行文件与某个库链接,我可能会执行以下操作:

bin/foo: LDFLAGS += -lbar
bin/%
规则将拾取
-lbar
。这对系统库非常有效,但当我链接的库也是项目的一部分时,会出现问题。在这种情况下,我将有一个类似

bin/foo: lib/libbar.so
我应用于
bin/foo
的特定于目标的规则在构建
lib/libbar时也会被传递!这不起作用,因为
libbar。因此
无法链接到自身。正如《圣经》所说

目标特定变量还有一个特殊特性:定义目标特定变量时,该变量值对该目标的所有先决条件及其所有先决条件都有效(除非这些先决条件使用其自身的目标特定变量值覆盖该变量)

我如何才能只为
bin/foo
添加该标志,而不为其先决条件添加该标志?上面的引语暗示了类似的情况

lib/libbar.so: LDFLAGS :=
但这并不理想,因为我真正的项目在全局范围内设置了其他我想要保留的LDFLAGS

这是一台复制机:

生成文件

bin/%:
  @mkdir -p $(@D)
  gcc $(LDFLAGS) $(filter %.o,$^) -o $@

lib/%:
  @mkdir -p $(@D)
  gcc $(LDFLAGS) -shared $(filter %.o,$^) -o $@

obj/%.o: src/%.c
  @mkdir -p $(@D)
  gcc $(CFLAGS) -c $< -o $@

bin/foo: obj/foo.o lib/libbar.so
bin/foo: LDFLAGS := -Wl,-rpath='$$ORIGIN/../lib' -Llib -lbar

lib/libbar.so: obj/bar.o

clean:
  rm -rf bin lib obj

.PHONY: clean
src/bar.c

int bar() {
  return 42;
}
这是坏的:

$ make bin/foo
gcc  -c src/foo.c -o obj/foo.o
gcc  -c src/bar.c -o obj/bar.o
gcc -Wl,-rpath='$ORIGIN/../lib' -Llib -lbar -shared obj/bar.o -o lib/libbar.so
/bin/ld: lib/libbar.so: file not recognized: file truncated
collect2: error: ld returned 1 exit status
make: *** [Makefile:7: lib/libbar.so] Error 1
但如果我先构建lib,它就会工作:

$ make lib/libbar.so
gcc  -c src/bar.c -o obj/bar.o
gcc  -shared obj/bar.o -o lib/libbar.so
$ make bin/foo
gcc  -c src/foo.c -o obj/foo.o
gcc -Wl,-rpath='$ORIGIN/../lib' -Llib -lbar obj/foo.o -o bin/foo
$ ./bin/foo; echo $?
42

您可以使用构造的变量名,而不是特定于目标的变量。这是一种不同的语法,但允许特定的目标设置

比如:

LDFLAGS += $($@_FLAGS)

bin/foo_FLAGS = -lbar
更多细节可以找到


简而言之,如果没有可用的继承特性,就没有特定于目标的特性。如果不想继承,就必须使用不同的方法。

我认为问题在于Unix中(老式的,很抱歉)编译和链接方法的传统。或者,也许是我不知道某些背景。我发现很难理解为什么库名在链接器调用中被破坏,以隐藏这样一个事实,即实际上我们是针对一个接口而不是一个实际的文件进行链接的——尽管我们需要这个文件来提取对所述接口的微不足道的描述。哦,好吧。无论真正的原因是什么,
make
对这些隐藏和扭曲的依赖性信息不满意,因此您遇到了问题,因为对于
make
,您提供的信息既非鱼也非肉。可能是一个像变量这样的函数

LIBSWITCHES = $(patsubst lib%,-l%,$(basename $(notdir $(filter %.so,$^))))
可能会有所帮助,因为它试图重建与链接库的依赖关系。它从依赖项列表中获取所有共享对象,并从中创建一个
-l
+库名称开关。由于您的库本身不是依赖项,因此它不会显示在此列表中,因此不应混淆链接器。只需取出所有的
-l
开关,您实际上正在从
$(LDFLAGS)
重建哪些名称库:


谢谢虽然我接受了疯狂科学家的答案,因为它回答了一般性的问题。@TavianBarnes如果你的解决方案中有一些巧妙的转折,那么访客会很乐意阅读它们!没有什么太聪明的,它是类似于
$(foreach so,$(filter%.so,$^),-L$(dir$(so))-L$(patsubst lib%.so,%,$(notdir$(so)))
LIBSWITCHES = $(patsubst lib%,-l%,$(basename $(notdir $(filter %.so,$^))))
bin/%:
    @mkdir -p $(@D)
    gcc $(LDFLAGS) $(LIBSWITCHES) $(filter %.o,$^) -o $@

lib/%:
    @mkdir -p $(@D)
    gcc $(LDFLAGS) $(LIBSWITCHES) -shared $(filter %.o,$^) -o $@

bin/foo: LDFLAGS := -Wl,-rpath='$$ORIGIN/../lib' -Llib