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

4xrmg8kj  于 2023-01-06  发布在  其他
关注(0)|答案(2)|浏览(177)

我试图在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");

}
oalqel3c

oalqel3c1#

这个标准并没有完全定义#include "..."#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文件究竟是什么?
如果你想让make在编译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

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

jei2mxaa

jei2mxaa2#

经过几个小时的阅读和尝试,也多亏了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

相关问题