编写makefile来构建动态库

发布于 2024-10-30 17:42:24 字数 1246 浏览 6 评论 0原文

我的 src 目录中有一个 makefile。 makefile 应该构建位于 DataStructures/ 中的数据结构,然后迭代calculations/ 中的所有 cpp 文件并在 ../bin/calculations 中创建相应的 .so 文件

我尝试了以下语法:

DAST = DataStructures/ 
COMPS = computations/ 
BIN = ../bin/ 
OBJECTS = ${DAST}Atom.o ${DAST}Molecule.o
COMPILE = g++ -Wall -g -c -std=c++0x -I/usr/local/include/openbabel-2.0 LINK = g++ -Wall -g -std=c++0x ${OBJECTS} -lopenbabel -I/usr/local/include/openbabel-2.0

all: ${BIN}main ${DAST}Molecule.o ${DAST}Atom.o ${BIN}${COMPS}%.so

${BIN}main: ${OBJECTS} main.cpp
    ${LINK} main.cpp -o ${BIN}main

${DAST}Molecule.o: ${DAST}Molecule.h ${DAST}Molecule.cpp    
    ${COMPILE} ${DAST}Molecule.cpp -o ${DAST}Molecule.o

${DAST}Atom.o: ${DAST}Atom.h ${DAST}Atom.cpp
    ${COMPILE} ${DAST}Atom.cpp -o ${DAST}Atom.o

${BIN}${COMPS}%.o: ${COMPS}%.cpp
    gcc -Wall -fPIC -c -lopenbabel $< -I/usr/local/include/openbabel-2.0 -std=c++0x

${BIN}${COMPS}%.so: ${COMPS}%.o
    gcc -shared -Wl,-soname,libcsmtest.so.1 -o libcsmtest.so $@

clean:
    rm -rf ${OBJECTS}

.PHONY: all clean

但它显然没有工作,因为我得到以下输出:

shai@ubuntu:~/csm/csm2/src$ make all
make: *** No rule to make target `../bin/computations/%.so', needed by 'all'.  Stop.

谢谢

I have a makefile in my src directory.
The makefile should build the data structures, which are in DataStructures/, and then iterate over all cpp files in calculations/ and create a corresponding .so file in ../bin/calculations

I tried the following syntax:

DAST = DataStructures/ 
COMPS = computations/ 
BIN = ../bin/ 
OBJECTS = ${DAST}Atom.o ${DAST}Molecule.o
COMPILE = g++ -Wall -g -c -std=c++0x -I/usr/local/include/openbabel-2.0 LINK = g++ -Wall -g -std=c++0x ${OBJECTS} -lopenbabel -I/usr/local/include/openbabel-2.0

all: ${BIN}main ${DAST}Molecule.o ${DAST}Atom.o ${BIN}${COMPS}%.so

${BIN}main: ${OBJECTS} main.cpp
    ${LINK} main.cpp -o ${BIN}main

${DAST}Molecule.o: ${DAST}Molecule.h ${DAST}Molecule.cpp    
    ${COMPILE} ${DAST}Molecule.cpp -o ${DAST}Molecule.o

${DAST}Atom.o: ${DAST}Atom.h ${DAST}Atom.cpp
    ${COMPILE} ${DAST}Atom.cpp -o ${DAST}Atom.o

${BIN}${COMPS}%.o: ${COMPS}%.cpp
    gcc -Wall -fPIC -c -lopenbabel 
lt; -I/usr/local/include/openbabel-2.0 -std=c++0x

${BIN}${COMPS}%.so: ${COMPS}%.o
    gcc -shared -Wl,-soname,libcsmtest.so.1 -o libcsmtest.so $@

clean:
    rm -rf ${OBJECTS}

.PHONY: all clean

But it obviously doesn't work, as I get the following output:

shai@ubuntu:~/csm/csm2/src$ make all
make: *** No rule to make target `../bin/computations/%.so', needed by 'all'.  Stop.

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

靖瑶 2024-11-06 17:42:24

您需要在 all: 目标中明确指定先决条件。

在 Makefile 中,% 是一个通配符,可以在自动规则中使用。但是,all: 目标是一个没有此类通配符的简单目标,因此 ${BIN}${COMPS}%.so 在该上下文中是错误的。

请注意,当我在这种情况下说“通配符”时,该通配符将目标与先决条件进行匹配,而不是像 glob 表达式中的 * 那样与文件系统匹配。


另外,虽然你的心处于正确的位置,但从风格上来说,你的 Makefile 可以更好:

  • 中间对象不应该是 all 目标的先决条件,而只是你希望的最终目标船。
  • 有自动和简单规则的混合来指定对象的创建。
  • 通常,人们不会为 %.so 编写自动规则,因为库通常是由多个对象构建的。
  • 对象和头文件之间的依赖关系是一个复杂的问题。简而言之,您需要指定生成的对象依赖于 *.cpp (或 .c)以及 < 包含的所有标头(直接和间接)代码>*.cpp 文件。
  • 按照惯例,GNU make 很好地支持这一点,而不是像您那样使用 ${COMPILE} ,而应该为您的 C++ 编译器使用 $(CXX) ,并且 < code>$(CXXFLAGS) 表示您希望传递给该编译器的标准标志。

You need to specify in the all: target, the prerequisites explicitly.

In Makefile parlance, % is a wildcard that can be used in automatic rules. However, the all: target is a simple target with no such wildcard, thus ${BIN}${COMPS}%.so is wrong in that context.

Please note that when I say 'wildcard' in this context, this wildcard matches the target against the prerequisites, not against the filesystem like * do in glob expressions.


Also, while your hart is in the right place, as a matter of style, your Makefile can be better:

  • Intermediary objects, should not be prerequisites of the all target, but only the final targets you wish to ship.
  • There is a mix of automatic and simple rules to specify the creation of objects.
  • Typically one doesn't write an automatic rule for %.so, because a library is often constructed from more than one object.
  • The dependencies between an object and header files is a complex issue. In short you need to specify that the resulting object depends on the *.cpp (or .c) as well as all the headers included (directly and indirectly) by the *.cpp file.
  • By convention, that is well supported by GNU make, instead of using ${COMPILE} as you do, one should use $(CXX) for your C++ compiler, and $(CXXFLAGS) for the standard flags you wish to pass to that compiler.
世界等同你 2024-11-06 17:42:24

您需要类似的东西

SOBJECTS = ...

all: ${BIN}main ${SOBJECTS}
     ...

您需要一种方法来收集变量 SOBJECTS 中的所有 *.so 名称。您可以手动执行此操作,或使用 make 的一些内部函数来扫描源目录。

另请注意,我从 all 目标中删除了两个作为依赖项的 *.o 文件。它们不是构建的最终目标(我认为),因此您不需要在那里提及它们。

除此之外,还有其他风格点,我会采取不同的做法,但目前它们不会造成直接问题,所以我不会离题,但我建议您看一些教程,了解一般情况下是如何完成的。
对于初学者,请查看 Paul 的 Makefile 规则如何不使用 VPATH

You need something like

SOBJECTS = ...

all: ${BIN}main ${SOBJECTS}
     ...

You need a way to gather all the *.so names in the variable SOBJECTS. You can do this manually, or use some of make's internal functions to scan the source directory.

Also notice that I removed the two *.o files as dependencies from the all target. They are not final goals of the build (I assume), so you don't need to mention them there.

Besides this there are other stylistic points which I would do differently, but at the moment they are not causing immediate problems, so I won't digress, but I advise you to have a look at some tutorials to see how things are done generally.
For starters, look at Paul's Rules of Makefiles, and How Not to Use VPATH.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文