gpt4 book ai didi

c++ - 生成文件 : How to link object files from different subdirectory and include different search paths

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:56:14 24 4
gpt4 key购买 nike

我想更改我的测试代码 ( tsnnls_test_DKU.c ) 的位置,但我无法在 makefile 中进行更改以正确反射(reflect)此文件夹更改。一些帮助将不胜感激。

我有两个问题:
1) 如何链接来自不同子目录的目标文件
2) 包括不同的搜索路径(在我的示例中为 3 个搜索路径)。

在我的原始设置中,makefile 工作正常,我放置了我的测试代码 tsnnls_test_DKU.c在以下位置(在第三方库内):

Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls

我链接到的所有目标文件都位于
OBJDir = /home/dkumar/libtsnnls-2.3.3/tsnnls

此外,一些包含在 tsnnls_test_DKU.c 中的包含文件位于以下三个位置( 三个搜索路径 ):
Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls  
Dir2 = /home/dkumar/libtsnnls-2.3.3
Dir3 = /home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic

我的 makefile 工作正常。

但是,我想将测试代码的位置更改为:
Dir4 = /home/dkumar/CPP_ExampleCodes_DKU/Using_tsnnls_DKU/

这是我的 makefile 的样子(在其他用户输入后更新:
# A sample Makefile

VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls
INC_PATH = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/

# Here is a simple Make Macro.
LINK_TARGET = tsnnls_test_DKU
OBJS_LOC = tsnnls_test_DKU.o

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS = libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o \
$(OBJS_LOC)

REBUILDABLES = $(LINK_TARGET)

all : $(LINK_TARGET)
echo All done

clean :
rm -f $(REBUILDABLES)
echo Clean done

#Inclusion of all libraries
RANLIB = ranlib
STATICLIB= /usr/local/lib/taucs_full/lib/linux/libtaucs.a

tsnnls_test_LDADD = $(LDADD)
LIBS = -largtable2 -llapack -lblas -lquadmath -lm

$(LINK_TARGET) : $(OBJS) $(tsnnls_test_LDADD) $(LIBS) $(STATICLIB)
gcc -g ${INC_PATH} -o $@ $^

尝试运行“$make”时遇到的错误
make: *** No rule to make target `libtsnnls_la-taucs_malloc.o', needed by `tsnnls_test_DKU'.  Stop.

显然,我无法正确使用 VPATH。

更新:
感谢 Mike Kinghan 回答我的问题。

最佳答案

Q1:如何从不同的子目录链接目标文件?

假设您的程序 prog是一个将从对象 file0.o 链接的 C 程序, file1.o哪一个
被编译到子目录obj .这是您通常需要的东西
makefile 来执行该链接。

$(OBJS) = $(patsubst %.o,obj/%.o,file0.o file1.o)

prog: $(OBJS)
gcc -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)

这使得 $(OBJS) = obj/file0.o, obj/file1.o你只需传递对象
像这样的文件到链接命令。 Documentation of patsubst

注意这不足以创建 obj子目录,如果它不存在,当你想要
将目标文件编译到其中。您必须自己创建它或学习如何制作 make做吧。

Q2:如何包含不同的搜索路径?

这是一个模棱两可的问题-模棱两可让您感到困惑-我们必须将其分解为 Q2.a、Q2.b、Q2.c :

Q2.a:如何指定不同的搜索路径,预处理器将在其中查找 #include 的头文件-ed 在源代码中?

默认情况下,预处理器将使用内置的标准搜索路径列表查找头文件。你可以看到他们
以详细模式运行预处理器,例如 cpp -v (CTRL-C 终止)。输出将包含如下内容:
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/4.8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.

假设您在子目录中有一些自己的头文件 incinc/foo/bar并希望预处理器搜索这些目录
以及。然后你需要传递预处理器选项:
-I inc -I inc/foo/bar

到您的编译命令。预处理器选项通常分配给
make 变量 CPPFLAGS ,例如
CPPFLAGS = -I inc -I inc/foo/bar

(以及您需要的任何其他预处理器选项),并通过此传递
编译命令配方中的变量,例如
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<

注意认为 CPPFLAGS 是一个常见的错误。是 C++ 编译器标志的常规 make 变量。
C++ 编译器标志的常规 make 变量是 CXXFLAGS .

可以看到 -I的效果通过运行选项:
mkdir -p inc/foo/bar # Just to create the path
cpp -v -I inc -I inc/foo/bar

(CTRL-C 终止)。现在输出将包含以下内容:
#include "..." search starts here:
#include <...> search starts here:
inc
inc/foo/bar
/usr/lib/gcc/x86_64-linux-gnu/4.8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.

Q2.b:如何指定链接器查找库的不同搜索路径?

假设您有一个图书馆, libfoobar.a您需要与 prog 链接和
它驻留在目录 lib 中比您的 makefile 高 2 个级别。那么你
需要传递链接器选项:
-L ../../lib


-lfoobar

到您的链接命令。第一个将告诉链接器 ../../lib是值得一看的地方之一
为图书馆。通常,您可以通过 LDFLAGS 在链接器命令配方中传递此选项。 .第二个告诉
用于搜索名为 libfoobar.a 的某个库的链接器(静态库)或 libfoobar.so(一个动态库)。通常,您可以通过 LDLIBS 在链接器命令配方中传递此选项。

正如预处理器有一个默认的搜索路径列表一样,也有一个默认的
链接器的搜索路径列表。您可以通过运行来查看它们:
gcc -v -Wl,--verbose 2>&1 | grep 'LIBRARY_PATH'

输出将类似于:

LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/: /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/: /usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/



当您需要链接标准库之一时,例如 libm (数学库),位于其中之一
默认库搜索路径,您不需要传递任何 -L选项。 -lm一个人就行。

Q2.c:如何指定不同的搜索路径,其中make将寻找先决条件
目标?


注意这是一个关于 make的问题,不是关于预处理器、编译器或
链接器。

我们假设您的所有目标文件都将编译到子目录 obj 中。 .
要在那里编译它们,只需使用模式规则即可:
obj/%.o:%.c
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<

告诉 make那个,例如 obj/file0.ofile0.c 制成按食谱:
gcc -c -o obj/file0.o $(CPPFLAGS) $(CFLAGS) file0.c

对于任何文件 obj/*.o 也类似和匹配文件 *.c
只要 file0.c 就可以了与 makefile 位于同一目录中,但
假设你有你的 *.c其他地方的文件?假设你的源文件是有组织的
在子目录中, foo/file0.cbar/file1.c .然后 make将无法
满足该模式规则并会说“没有规则可以制作目标 obj/file0.o”,
等等。

要解决此问题,请使用 VPATH , make具有特殊意义的变量。
如果您将目录名称列表(以“:”标点)分配给 VPATH , 然后 make将在每个列出的目录中搜索先决条件
它在当前目录中找不到它。所以:
VPATH = foo:bar

会引起 make查看当前目录,然后 foobar什么时候
它试图找到 .c文件以匹配该模式规则。它会成功满足
规则并将编译必要的源文件。

注意您已使用 VPATH在您发布的代码中错误地:
VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls

您已为其分配了链接器搜索路径,并带有链接器选项 -L ,其中没有
在那里做生意。

底线:
  • 用于定位头文件的前置搜索路径指定为
    预处理器的 -I<dirname>选项。将这些选项传递给 CPPFLAGS 中的编译配方
  • 用于定位库的链接器搜索路径用
    链接器 -L<dirname>选项。将这些选项传递给 LDFLAGS 中的链接配方
  • make先决条件的搜索路径规则在make变量 VPATH , 作为目录名称的 ':-标点列表。
  • 关于c++ - 生成文件 : How to link object files from different subdirectory and include different search paths,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28153873/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com