Скомпилируйте Pybind с заголовочными файлами в Makefile (не используя cmake) - PullRequest
0 голосов
/ 11 февраля 2020

Я пытаюсь скомпилировать модуль Pybind11 в C++, который вызывает несколько заголовочных файлов (.h) сверху. Поскольку у меня много заголовочных файлов, я решил создать Makefile, который без проблем работает, КРОМЕ для создания целевого общего объектного файла (s.o). Мне нужен этот общий объектный файл, чтобы иметь возможность вызывать модуль Pybind в Python.

Однако при компиляции я получаю:

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

Мой вопрос в основном: что я делаю неправильно при компиляции объектных файлов для создания цели?

Любая помощь будет чрезвычайно признательна. Заранее спасибо за ваш ответ.

Makefile

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");

}

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Стандарт не полностью определяет разницу между #include "..." и #include <...>, но во всех компиляторах я знаком с синтаксисом <> для include, который обычно означает «это заголовочный файл системного типа» а синтаксис "" означает «это заголовочный файл локального типа».

На практике это обычно означает, что "" ищется в рабочем каталоге, а затем в каталогах, указанных параметрами -I в компилятор и, наконец, в системные каталоги по умолчанию, в то время как <> то же самое, за исключением того, что он не выглядит в рабочем каталоге.

Итак, вам нужно либо изменить код для использования:

#include "population.h"

или же вам нужно добавить -I. в строку компиляции, чтобы компилятор знал, как искать в текущем каталоге:

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

Лично я бы сделал и то и другое, потому что добавить гигиену - это хорошая гигиена каталоги, которые вам нужны для вашей строки компиляции, и потому что это хорошая практика - использовать "" для локальных заголовков, чтобы люди, читающие код, сразу поняли, что это ваша голова и не системный заголовок.

По второму вопросу: Является ли компиляция для того, чтобы сделать общий объектный файл с объектными файлами правильными Извините, но я не понимаю то, что вы спрашиваете.

Если вы спрашиваете о порядке целей, определенных в make-файле, то они могут быть в любом порядке на всех , за исключением , что первой целью будет цель по умолчанию (если вы запускаете make без имени цели, make создаст первую цель - и все необходимые условия для первой цели).

ETA

ОК, теперь мы видим, что фактическая ошибка в том, что example.o не существует. Почему этого не существует? Опять же, поскольку вы удалили важные детали из примера в своем вопросе, мы не можем сказать наверняка. Когда вы пишете в своем вопросе:

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

, что именно являются .o файлами, которые появляются как предварительные условия для example.so?

Вы должны перечислить файл example.o как предварительное условие example.so, если вы хотите, чтобы make собрал 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

Неважно, в каком порядке они появляются в списке предварительных условий, но все они должны быть там.

0 голосов
/ 12 февраля 2020

После нескольких часов чтения, попыток, а также благодаря подсказкам 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
...