makefile:如何链接来自不同子目录的目标文件并包括不同的搜索路径 [英] makefile : How to link object files from different subdirectory and include different search paths
问题描述
我想更改测试代码(tsnnls_test_DKU.c
)的位置,但无法在makefile中进行更改以正确反映此文件夹更改.一些帮助,将不胜感激.
I want to change the location of my test code (tsnnls_test_DKU.c
) and I am unable to make change in makefile to reflect this folder change properly. Some help would be appreciated.
我有两个问题: 1)如何链接来自不同子目录的目标文件 2)包括不同的搜索路径(在我的示例中为3个搜索路径).
I have two questions: 1) How to link object files from different subdirectory 2) include different search paths (3 search paths in my example).
在我的常规设置中,makefile可以正常工作,我将测试代码tsnnls_test_DKU.c
放在以下位置(在第三方库中):
In my orinal setup, where makefile works fine, I put my test code tsnnls_test_DKU.c
at following location (inside the third party libraries):
Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls
我链接到的所有目标文件都位于
All object files, that I am linking to, are at
OBJDir = /home/dkumar/libtsnnls-2.3.3/tsnnls
此外,tsnnls_test_DKU.c
中包含的某些包含文件位于以下三个位置(三个搜索路径):
Also, some include file contained in tsnnls_test_DKU.c
are at following three locations (three search paths):
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正常工作.
and my makefile works fine.
但是,我想将测试代码的位置更改为:
However, I would like to change the location of test code to:
Dir4 = /home/dkumar/CPP_ExampleCodes_DKU/Using_tsnnls_DKU/
这是我的makefile的样子(在其他用户输入后更新:
Here is how my makefile looks like (Updated after inputs from other user:
# 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"时出现的错误
The error that I get when trying to run "$make"
make: *** No rule to make target `libtsnnls_la-taucs_malloc.o', needed by `tsnnls_test_DKU'. Stop.
很明显,我无法正确使用VPATH.
Obviously, I have not been able to use VPATH properly.
更新: 感谢Mike Kinghan回答了我的问题.
UPDATE: Thanks to Mike Kinghan for answering my question.
推荐答案
问题1:如何从其他子目录链接目标文件?
比方说,您的程序prog
是C语言程序,它将与对象file0.o
,file1.o
链接,
将被编译到子目录obj
中.这是您通常需要的东西
makefile来执行该链接.
Let's say your program prog
is a C program that will be linked from object file0.o
, file1.o
which
are to be compiled into subdirectory obj
. Here is the sort of thing you typically need in your
makefile to perform that linkage.
$(OBJS) = $(patsubst %.o,obj/%.o,file0.o file1.o)
prog: $(OBJS)
gcc -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
这使得$(OBJS)
= obj/file0.o, obj/file1.o
,您只需传递对象
链接命令之类的文件. patsubst
This makes $(OBJS)
= obj/file0.o, obj/file1.o
and you simply pass the object
files like that to the link command. Documentation of patsubst
N.B.如果要在obj
子目录中不存在make
做到这一点.
N.B. This is not sufficient to create the obj
subdirectory if it doesn't exist when you want to
compile an object file into it. You'll have to create it yourself or study how to make make
do it.
第二季度:如何包括不同的搜索路径?
这是一个模棱两可的问题-模糊性使您感到困惑-我们必须将其分解为 Q2.a,Q2.b,Q2.c :
This is an ambiguous question - the ambiguity is confusing you - and we must break it down into Q2.a, Q2.b, Q2.c:
Q2.a:如何指定预处理器将在源代码中查找#include
-ed的头文件的不同搜索路径?
Q2.a: How to specify different search paths where the preprocessor will look for header files that are #include
-ed in the source code?
默认情况下,预处理器将使用内置的标准搜索路径列表来查找头文件.您可以通过以下方式看到它们
在详细模式下运行预处理器,例如cpp -v
(CTRL-C终止).输出将包含以下内容:
By default, the preprocessor will look for header files using a built-in a list of standard search paths. You can see them by
running the preprocessor in verbose mode, e.g.cpp -v
(CTRL-C to terminate). The output will contain something like:
#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.
让我们假设您在子目录中有一些自己的头文件
inc
和inc/foo/bar
并希望预处理器搜索这些目录
也一样然后,您需要传递预处理器选项:
Let's suppose you have some header files of your own in subdirectories
inc
and inc/foo/bar
and want the preprocessor to search these directories
as well. Then you need to pass the preprocessor options:
-I inc -I inc/foo/bar
到您的编译命令.预处理器选项通常分配给
make变量CPPFLAGS
,例如
to your compile command. Preprocessor options are conventionally assigned to
the make variable CPPFLAGS
, e.g.
CPPFLAGS = -I inc -I inc/foo/bar
(以及您需要的其他任何预处理程序选项),并通过此方法传递 编译命令配方中的变量,例如
(along with any other preprocessor options you require), and passed via this variable in the compile command recipe, e.g.
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
N.B.一个普遍的错误是认为CPPFLAGS
是C ++编译器标志的常规make变量.
C ++编译器标志的常规make变量为CXXFLAGS
.
N.B. It is a common mistake to think that CPPFLAGS
is the conventional make variable for C++ compiler flags.
The conventional make variable for C++ compiler flags is CXXFLAGS
.
您可以通过运行以下命令来查看-I
选项的效果:
You can see the effect of the -I
option by running:
mkdir -p inc/foo/bar # Just to create the path
cpp -v -I inc -I inc/foo/bar
(CTRL-C终止).现在输出将包含以下内容:
(CTRL-C to terminate). Now the output will contain the like of:
#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级.然后你
需要通过链接器选项:
Let's suppose you are have a library, libfoobar.a
that you need to link with prog
and
that it resides in a directory lib
that is 2 levels up from your makefile. Then you
need to pass the linker options:
-L ../../lib
和
-lfoobar
链接命令.其中的第一个将告诉链接器../../lib
是要查找的地方之一
用于图书馆.按照惯例,您可以通过LDFLAGS
在链接器命令配方中传递此选项.第二个告诉
链接器搜索称为libfoobar.a
(静态库)或libfoobar.so
的某些库
(动态库).按照惯例,您可以通过LDLIBS
to your link command. The first of these will tell the linker that ../../lib
is one of the places to look
for libraries. Conventionally, you pass this option in the linker command recipe via LDFLAGS
. The second tells
the linker to search for some library called libfoobar.a
(a static library) or libfoobar.so
(a dynamic library). Conventionally, you pass this option in the linker command recipe via LDLIBS
就像预处理器的搜索路径有默认列表一样,默认设置也有 链接程序的搜索路径列表.您可以通过运行以下命令来查看它们:
Just as there is a default list of search paths for the preprocessor, there is a default list of search paths for the linker. You can see them by running:
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/
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
即可.
When you need to link one of the standard libraries, e.g. libm
(the math library), that resides in one of the
the default library search paths, you don't need to pass any -L
option. -lm
alone will do.
Q2.c:如何在make
查找先决条件的地方指定不同的搜索路径
的目标?
Q2.c: How to specify different search paths where make
will look for the prerequisites
of targets?
N.B.这是有关make
的问题,而不是有关预处理器,编译器或
链接器.
N.B. This is a question about make
, not a question about the preprocessor, compiler, or
linker.
我们假设您的所有目标文件都将被编译到子目录obj
中.
为了使它们在那里编译,只需要使用模式规则就可以了:
We have assumed that all of your object files will be compiled into the subdirectory obj
.
To get them compiled there, it would be nice and simple just to use the pattern rule:
obj/%.o:%.c
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
告诉make
的
obj/file0.o
由file0.c
由以下配方制成:
which tell make
that, e.g. obj/file0.o
is made from file0.c
by the recipe:
gcc -c -o obj/file0.o $(CPPFLAGS) $(CFLAGS) file0.c
,并且类似地适用于任何文件obj/*.o
和匹配的文件*.c
and similarly for any file obj/*.o
and matching file *.c
这很好,只要file0.c
与makefile驻留在同一目录中,但是
假设您的*.c
文件在其他位置?说您的源文件井井有条
在子目录foo/file0.c
和bar/file1.c
中.然后make
将无法
满足该模式规则,并会说没有规则可以使目标obj/file0.o",
等
This is fine as long file0.c
resides in the same directory as the makefile, but
suppose you have your *.c
files somewhere else? Say your source files are organised
in subdirectories, foo/file0.c
and bar/file1.c
. Then make
will be unable to
satisfy that pattern rule and will say there is "no rule to make target obj/file0.o",
etc.
要解决此问题,请使用VPATH
,这是一个具有特殊含义的make
变量.
如果您为VPATH
分配了一个目录名称列表,并用':'进行了标点,则
make
会在每个列出的目录中搜索前提条件
它在当前目录中找不到它.所以:
To solve this problem use VPATH
, a make
variable that has a special meaning.
If you assign a list of directory names, punctuated by ':', to VPATH
, then
make
will search for a prerequisite in each of the listed directories whenever
it can't find it in the current directory. So:
VPATH = foo:bar
将导致make
在当前目录中查找,然后在foo
和bar
中查找
它尝试查找.c
文件以匹配该模式规则.它将成功满足
规则,并将编译必要的源文件.
will cause make
to look in the current directory, and then foo
and bar
when
it tries to find .c
files to match that pattern rule. It will succeed in satisfying
the rule and will compile the necessary source files.
N.B.您在发布的代码中错误地使用了VPATH
:
N.B. You have used VPATH
wrongly in your posted code:
VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls
您已经为它分配了一个 linker 搜索路径,并带有链接器选项-L
,该选项没有
在那里做生意.
You have asigned a linker search path to it, with the linker option -L
, which has no
business there.
底线:
-
用于查找头文件的前驱搜索路径指定为 预处理器的
-I<dirname>
选项.将这些选项传递给CPPFLAGS
The preprecessor search paths, for locating header files, are specified with the preprocessor's
-I<dirname>
option. Pass these options to the compile recipe inCPPFLAGS
用于查找库的链接程序搜索路径是通过
链接器的-L<dirname>
选项.将这些选项传递给LDFLAGS
The linker search paths, for locating libraries, are specified with the
linker's -L<dirname>
option. Pass these options to the linkage recipe in LDFLAGS
make
规则的前提条件的搜索路径在
make
变量VPATH
,作为目录名称的':-标点符号列表.
The search paths for the preprequisities of make
rules are specified in
the make
variable VPATH
, as a ':-punctuated list of directory names.
这篇关于makefile:如何链接来自不同子目录的目标文件并包括不同的搜索路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!