Error C1083 al compilar extensiones con Visual Studio 2015

En Microsoft Windows, al compilar una extensión de Python (a partir de la versión 3.5) escrita en C o C++ o bien intentar instalar un paquete que requiere ser compilado utilizando Microsoft Visual C++ 14.0 (Visual Studio 2015), se obtiene el siguiente error.

pyconfig.h(68): fatal error C1083: No se puede abrir el archivo incluir: ‘io.h’: No such file or directory

Explicación

A partir de la versión 14.0 de Microsoft Visual C++ (distribuido en Visual Studio 2015) se incorpora el llamado Universal CRT, un conjunto de componentes que incluye, entre otros, la librería estándar de C. El objetivo de esta implementación es la unificación y compatibilidad entre las distintas versiones del compilador, en lugar de mantener diferentes CRT (C Runtime) para cada una de ellas, como se hacía hasta el momento (desde Visual Studio 2002 hasta 2013).

Al ser cada CRT específico de una versión del compilador, las librerías y los archivos de cabecera se incluian dentro de la carpeta de instalación, por ejemplo, C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib y C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include. Con la introducción del Universal CRT, estos componentes se encuentran en un SDK independiente, instalado junto con Visual Studio pero en una ubicación diferente (por defecto C:\Program Files (x86)\Windows Kits\10). En mi caso, los archivos de cabecera se encuentran en C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt y las librerías en C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10150.0\ucrt\x86 (32 bit) y C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10150.0\ucrt\x64 (64 bit).

El archivo io.h y tantos otros pertenecen al CRT y, al no ser encontrados en los directorios anteriores, el compilador se queja imprimiendo el error anterior.

Solución

Simplemente hay que indicarle al compilador (vía los parámetros include_dirs y library_dirs de distutils.core.Extension) los directorios en donde debe buscar los archivos del Universal CRT en el archivo setup.py de tu extensión o el paquete que deseas compilar e instalar.

Considerando el siguiente fichero de ejemplo.

from distutils.core import setup, Extension

setup(name='foo',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'])],
      )

Especificamos los directorios del UCRT (para una extensión de 64 bit).

from distutils.core import setup, Extension

ucrt_include = r'C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt'
ucrt_lib = r'C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10150.0\ucrt\x64'

setup(name='foo',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'],
                             include_dirs=[ucrt_include],
                             library_dirs=[ucrt_lib])],
      )

Y para una de 32 bit:

ucrt_lib = r'C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10150.0\ucrt\x86'

¡Ya podés compilar tu extensión sin problemas!

Para usuarios de Cython, considerando el siguiente setup.py.

from distutils.core import setup
from Cython.Build import cythonize

setup(
  name = 'Hello world app',
  ext_modules = cythonize("helloword.pyx")
)

Deben crear manualmente una instancia de la clase Extension.

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

ucrt_include = r'C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt'
ucrt_lib = r'C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10150.0\ucrt\x64'

ext = Extension("helloworld", ["helloword.pyx"],
                include_dirs=[ucrt_include], library_dirs=[ucrt_lib])

setup(
  name = 'Hello world app',
  ext_modules = cythonize([ext])
)



Deja una respuesta