使用 Makefile 中的头文件编译 Pybind (不使用 cmake)

Compile Pybind with header files in Makefile (not using cmake)

本文关键字:cmake Pybind 编译 Makefile 文件 使用      更新时间:2023-10-16

我正在尝试用C++编译一个Pybind11模块,该模块调用(.h)顶部的多个头文件。由于我有很多头文件,我决定做一个Makefile,除了创建目标共享对象文件(s.o)之外,它可以正常工作。我需要这个共享对象文件才能在 Python 中调用 Pybind 模块。

但是,在编译时,我得到:

g++ -shared -fPIC neat.o network.o nnode.o link.o trait.o gene.o innovation.o organism.o species.o genome.o population.o example.o -o example.so
/usr/bin/ld: example.o: relocation R_X86_64_PC32 against symbol `_ZTI3Pet' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'example.so' failed
make: *** [example.so] Error 1

我的问题基本上是:编译目标文件以创建目标时我做错了什么?

生成文件

example.so: neat.o network.o nnode.o link.o trait.o gene.o innovation.o organism.o species.o genome.o population.o example.o
g++ neat.o network.o nnode.o link.o trait.o gene.o innovation.o organism.o species.o genome.o population.o example.o -shared -o example.so
neat.o: neat.cpp neat.h
g++ -c -O3 -Wall -fPIC neat.cpp
network.o: network.cpp network.h
g++ -c -O3 -Wall -fPIC network.cpp
nnode.o: nnode.cpp nnode.h
g++ -c -O3 -Wall -fPIC nnode.cpp
link.o: link.cpp link.h
g++ -c -O3 -Wall -fPIC link.cpp
trait.o: trait.cpp trait.h
g++ -c -O3 -Wall -fPIC trait.cpp
gene.o: gene.cpp gene.h
g++ -c -O3 -Wall -fPIC gene.cpp
innovation.o: innovation.cpp innovation.h
g++ -c -O3 -Wall -fPIC innovation.cpp
organism.o: organism.cpp organism.h genome.h genome.cpp species.h species.cpp
g++ -c -O3 -Wall -fPIC organism.cpp
species.o: species.h species.cpp organism.cpp organism.h genome.h genome.cpp
g++ -c -O3 -Wall -fPIC species.cpp
genome.o: genome.cpp genome.h
g++ -c -O3 -Wall -fPIC genome.cpp
population.o: population.cpp population.h organism.h
g++ -c -O3 -Wall -fPIC population.cpp
experiments.o: experiments.cpp experiments.h
g++ -c -O3 -Wall -fPIC experiments.cpp
example.o:
g++ -O3 -Wall -std=c++11 -fopenmp -I -fPIC `python3 -m pybind11 --includes` -c example.cpp
clean:
rm *.o *.so

示例.cpp

#include <pybind11/pybind11.h>
#include <iostream>
#include <string>
#include "population.h"
namespace py = pybind11;
int create_neat(){
Population *the_pop=0;
return 0;
}
PYBIND11_MODULE(example, m){
m.def("create_neat", &create_neat, "create a pop object");
}

该标准没有完全定义#include "..."#include <...>之间的区别,但在我熟悉的所有编译器中,包括的<>语法通常意味着"这是一个系统类型的头文件",""语法意味着"这是一个本地类型的头文件"。

实际上,这通常意味着在工作目录中查找"",然后在编译器的-I选项指定的目录中查找,最后在系统默认目录中查找,而<>是相同的,只是它不在工作目录中查找。

因此,您需要更改代码以使用:

#include "population.h"

否则,您需要将-I.添加到编译行中,以便编译器知道查找当前目录:

population.o: population.cpp population.h organism.h
g++ -I. -c population.cpp

就我个人而言,我会同时做这两件事,因为将您需要的目录添加到编译行中是一种很好的卫生习惯,并且因为将""用于本地标头是一种很好的做法,这样阅读代码的人就会立即理解这是您的标头而不是系统标头。

对于您的第二个问题,编译是否为了使具有对象文件的共享对象文件正确,我很抱歉,但我不明白您在问什么。

如果您询问的是 makefile 中定义的目标的顺序,那么它们可以是任何顺序,除了第一个目标将是默认目标(如果您运行没有目标名称的make则 make 将构建第一个目标 - 以及第一个目标所需的任何先决条件(。

伊塔

好的,现在我们可以看到实际的错误是example.o不存在。 为什么它不存在? 同样,因为您已经从问题中的示例中删除了重要细节,所以我们无法确定。 当你在问题中写下:

example.so: //some .o files which are not important// HERE IS THE PROBLEM

作为example.so先决条件出现的.o文件究竟是什么?

如果要在尝试构建example.so之前生成example.o,则必须将文件example.o列为example.so的先决条件。 您需要列出创建共享库所需的所有对象文件。 所以这应该是:

example.so: population.o example.o neat.o network.o nnode.o link.o trait.o gene.o innovation.o organism.o species.o genome.o

它们在先决条件列表中的显示顺序并不重要,但它们都必须都在那里。

经过几个小时的阅读,尝试,也感谢MadScientist的提示,我让它工作了,但原因尚不清楚。我只是更改了目标编译中先决条件的顺序,将-shared -o example.so放在前面而不是行尾,它奏效了。 整个文件如下:

example.so: neat.o network.o nnode.o link.o trait.o gene.o innovation.o organism.o species.o genome.o population.o example.o
g++ -shared -o example.so neat.o network.o nnode.o link.o trait.o gene.o innovation.o organism.o species.o genome.o population.o example.o
neat.o: neat.cpp neat.h
g++ -c -O3 -Wall -fPIC neat.cpp
network.o: network.cpp network.h
g++ -c -O3 -Wall -fPIC network.cpp
nnode.o: nnode.cpp nnode.h
g++ -c -O3 -Wall -fPIC nnode.cpp
link.o: link.cpp link.h
g++ -c -O3 -Wall -fPIC link.cpp
trait.o: trait.cpp trait.h
g++ -c -O3 -Wall -fPIC trait.cpp
gene.o: gene.cpp gene.h
g++ -c -O3 -Wall -fPIC gene.cpp
innovation.o: innovation.cpp innovation.h
g++ -c -O3 -Wall -fPIC innovation.cpp
organism.o: organism.cpp organism.h genome.h genome.cpp species.h species.cpp
g++ -c -O3 -Wall -fPIC organism.cpp
species.o: species.h species.cpp organism.cpp organism.h genome.h genome.cpp
g++ -c -O3 -Wall -fPIC species.cpp
genome.o: genome.cpp genome.h
g++ -c -O3 -Wall -fPIC genome.cpp
population.o: population.cpp population.h organism.h
g++ -c -O3 -Wall -fPIC population.cpp
experiments.o: experiments.cpp experiments.h
g++ -c -O3 -Wall -fPIC experiments.cpp
example.o:
g++ -O3 -Wall -std=c++11 -fopenmp `python3 -m pybind11 --includes` -fPIC -c example.cpp
clean:
rm *.o *.so