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]
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.
Comentários muito úteis
Não tenho certeza de quais documentos dizem isso, mas o seguinte está errado:
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:
ou
Esses exemplos são mínimos no sentido de que, se algo for ignorado nas linhas de comando f2py acima, é esperada uma falha.