Numpy: [BUG] f2py incapaz de compilar o módulo de extensão se as fontes C forem geradas primeiro

Criado em 22 nov. 2019  ·  7Comentários  ·  Fonte: numpy/numpy

Seguindo os docs / Guia do Usuário de f2py, se alguém deseja gerar um arquivo .c com o módulo de extensão, deve-se fazer

$ f2py -m fib1 fib1.f

para gerar um arquivo fib1module.c . Isso funciona. No entanto, a próxima etapa para construir o módulo de extensão para ser importável em Python, de acordo com a documentação, é

$ f2py -c fib1module.c

No entanto, isso falha para mim com as seguintes mensagens:

$ f2py -c fib1module.c --verbose
running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "untitled" sources
build_src: building npy-pkg config files
running build_ext
new_compiler returns <class 'distutils.unixccompiler.UnixCCompiler'>
customize UnixCCompiler
customize UnixCCompiler using build_ext
********************************************************************************
<class 'distutils.unixccompiler.UnixCCompiler'>
preprocessor  = ['gcc', '-pthread', '-B', '/opt/miniconda/envs/numpy-dev/compiler_compat', '-Wl,--sysroot=/', '-E']
compiler      = ['gcc', '-pthread', '-B', '/opt/miniconda/envs/numpy-dev/compiler_compat', '-Wl,--sysroot=/', '-Wsign-compare', '-DNDEBUG', '-g', '-fwrapv', '-O3', '-Wall', '-Wstrict-prototypes', '-std=c99']
compiler_so   = ['gcc', '-pthread', '-B', '/opt/miniconda/envs/numpy-dev/compiler_compat', '-Wl,--sysroot=/', '-Wsign-compare', '-DNDEBUG', '-g', '-fwrapv', '-O3', '-Wall', '-Wstrict-prototypes', '-fPIC', '-std=c99']
compiler_cxx  = ['g++', '-pthread', '-B', '/opt/miniconda/envs/numpy-dev/compiler_compat', '-Wl,--sysroot=/']
linker_so     = ['gcc', '-pthread', '-shared', '-B', '/opt/miniconda/envs/numpy-dev/compiler_compat', '-L/opt/miniconda/envs/numpy-dev/lib', '-Wl,-rpath=/opt/miniconda/envs/numpy-dev/lib', '-Wl,--no-as-needed', '-Wl,--sysroot=/']
linker_exe    = ['gcc', '-pthread', '-B', '/opt/miniconda/envs/numpy-dev/compiler_compat', '-Wl,--sysroot=/']
archiver      = ['ar', 'rc']
ranlib        = None
libraries     = []
library_dirs  = []
include_dirs  = ['/opt/miniconda/envs/numpy-dev/include/python3.6m']
********************************************************************************
building 'untitled' extension
compiling C sources
C compiler: gcc -pthread -B /opt/miniconda/envs/numpy-dev/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -std=c99

compile options: '-I/home/melissa/projects/numpy/numpy/core/include -I/opt/miniconda/envs/numpy-dev/include/python3.6m -c'
gcc: fib1module.c
fib1module.c:16:10: fatal error: fortranobject.h: Arquivo ou diretório inexistente
   16 | #include "fortranobject.h"
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.
error: Command "gcc -pthread -B /opt/miniconda/envs/numpy-dev/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -std=c99 -I/home/melissa/projects/numpy/numpy/core/include -I/opt/miniconda/envs/numpy-dev/include/python3.6m -c fib1module.c -o /tmp/tmpyjgu4iq5/fib1module.o -MMD -MF /tmp/tmpyjgu4iq5/fib1module.o.d" failed with exit status 1

Fazendo

$ f2py -c fib1module.c -I/home/melissa/projects/numpy/numpy/f2py/src -m fib1module

parece funcionar (este é o local do meu arquivo fortranobject.h ), mas o módulo não é importável:

>>> import fib1module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /home/melissa/projects/numpy/doc/source/f2py/fib1module.cpython-36m-x86_64-linux-gnu.so: undefined symbol: PyFortran_Type

TL; DR: Isso é um bug ou algo que não devemos fazer (gerar .c fontes e, em seguida, construir o módulo de extensão em uma etapa separada)?

>>> import sys, numpy; print(numpy.__version__, sys.version)
1.18.0.dev0+8d217b0 3.6.7 | packaged by conda-forge | (default, Jul  2 2019, 02:18:42) 
[GCC 7.3.0]
00 - Bug numpy.f2py

Comentários muito úteis

Não tenho certeza de quais documentos dizem isso, mas o seguinte está errado:

$ f2py -c fib1module.c

f2py -c ... deve ser aplicado ao arquivo .pyf (mais os arquivos de origem / objeto / biblioteca) ou deve-se especificar a opção -m <modulename> (mais os arquivos de origem / objeto / biblioteca) . f2py -c não se destina a compilar os módulos de extensão C / API gerados diretamente (embora seja provável que seja capaz de fazer isso com sinalizadores de diretório de inclusão adequados e as entradas de arquivo de origem / objeto).

Use uma das seguintes opções:

f2py -c -m fib1 fib1.f

ou

f2py -m fib1 fib1.f -h fib1.pyf
f2py -c fib1.pyf fib1.f

Esses exemplos são mínimos no sentido de que, se algo for ignorado nas linhas de comando f2py acima, é esperada uma falha.

Todos 7 comentários

Obrigado pelo relatório @melissawm. Estamos falando sobre esta página certa: https://numpy.org/devdocs/f2py/getting-started.html?

Posso confirmar o que você está vendo:

$ f2py -m fib1 fib1.f
$ f2py -c fib1module.c
...
fib1module.c:16:10: fatal error: 'fortranobject.h' file not found
#include "fortranobject.h"

No entanto, a página de doc faz $ f2py -c -m fib1 fib1.f vez disso (gera código e compila-o de uma vez), e isso funciona como esperado para mim. Não tenho certeza se a separação de -m e -c já foi suportada. Deve ser possível fazer -c -somente funcionar, adicionando automaticamente o caminho de inclusão correto - provavelmente não é difícil, mas não tenho certeza se ele é necessário.

@pearu alguma opinião?

Não tenho certeza de quais documentos dizem isso, mas o seguinte está errado:

$ f2py -c fib1module.c

f2py -c ... deve ser aplicado ao arquivo .pyf (mais os arquivos de origem / objeto / biblioteca) ou deve-se especificar a opção -m <modulename> (mais os arquivos de origem / objeto / biblioteca) . f2py -c não se destina a compilar os módulos de extensão C / API gerados diretamente (embora seja provável que seja capaz de fazer isso com sinalizadores de diretório de inclusão adequados e as entradas de arquivo de origem / objeto).

Use uma das seguintes opções:

f2py -c -m fib1 fib1.f

ou

f2py -m fib1 fib1.f -h fib1.pyf
f2py -c fib1.pyf fib1.f

Esses exemplos são mínimos no sentido de que, se algo for ignorado nas linhas de comando f2py acima, é esperada uma falha.

Na verdade, estou falando sobre esta página: https://numpy.org/devdocs/f2py/usage.html

Lá, nos itens 2 e 3, temos o seguinte: O item 2 deve executar f2py sem as opções -m ou -c , o que aparentemente não funciona. Item 3 diz

Para construir um módulo de extensão, use

f2py -c <options> <fortran files>       \
  [[ only: <fortran functions>  : ]     \
   [ skip: <fortran functions>  : ]]... \
  [ <fortran/c source files> ] [ <.o, .a, .so files> ]

Se <fortran files> contém um arquivo de assinatura, então uma fonte para um módulo de extensão é construída,
todas as fontes Fortran e C são compiladas e, finalmente, todos os arquivos de objetos e bibliotecas são vinculados ao
módulo de extensão <modulename>.so que é salvo no diretório atual.

Se <fortran files> não contém um arquivo de assinatura, então um módulo de extensão é construído por
digitalizando todos os códigos-fonte Fortran para assinaturas de rotina.

Pelo que você disse, entendo que não devemos usar as fontes .c diretamente, certo? Se gerarmos um arquivo .c , ele ficará inutilizável posteriormente?

Obrigado pela contribuição!

Na verdade, estou falando sobre esta página: https://numpy.org/devdocs/f2py/usage.html

Esta página descreve as f2py opções de linha de comando e os diferentes modos. Ele pressupõe que se entenda como os módulos de extensão Python podem ser construídos, consulte, por exemplo, https://docs.python.org/3.8/extending/index.html

Enquanto f2py pode ser usado para criar módulos de extensão que envolvem também funções C (contidas em .c arquivos) e, portanto, a declaração "não devemos usar as fontes .c diretamente" é imprecisa.

Deve-se distinguir os arquivos .c que o f2py gera e os .c arquivos que contêm implementações de funções C do usuário. O arquivo .c que f2py gera é útil apenas quando é necessário ter controle total de como o módulo de extensão é construído ou para depurar f2py. Em todos os outros casos, não é necessário gerar o módulo de extensão, pois ele será gerado automaticamente no processo de construção.

Estou adicionando a explicação de @pearu acima aos documentos, se você tiver alguma outra ideia, me avise. Obrigado a todos por seus comentários!

Sinta-se à vontade para encerrar o problema (ou devo fazê-lo somente depois que o PR for aceito?)

Sugiro encerrar quando o PR que aborda esse problema for aceito.

Sugiro encerrar quando o PR que aborda esse problema for aceito.

+1

@melissawm você também pode adicionar closes gh-14960 a uma de suas mensagens de commit, então o problema será fechado automaticamente quando o PR for mesclado.

Esta página foi útil?
0 / 5 - 0 avaliações