2002-04-03 18:45:09 -07:00
#! /usr/bin/env python
2009-08-03 15:14:44 -04:00
#
# setup.py : Distutils setup script
#
# Part of the Python Cryptography Toolkit
#
# ===================================================================
# Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation;
# All Rights Reserved
#
# This file contains code from the Python 2.2 setup.py module (the
# "Original Code"), with modifications made after it was incorporated
# into PyCrypto (the "Modifications").
#
# To the best of our knowledge, the Python Software Foundation is the
# copyright holder of the Original Code, and has licensed it under the
# Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for
# details.
#
# The Modifications to this file are dedicated to the public domain.
# To the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever. No rights are
# reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
2002-07-11 14:31:19 -07:00
2008-08-06 21:27:50 -04:00
__revision__ = " $Id$ "
2002-07-11 14:31:19 -07:00
2010-12-28 16:26:52 -05:00
from distutils import core , fancy_getopt
2008-11-21 13:04:18 -05:00
from distutils . core import Extension , Command
2003-02-28 17:38:29 -07:00
from distutils . command . build_ext import build_ext
import os , sys
2008-09-15 21:32:58 -04:00
import struct
2002-04-03 18:45:09 -07:00
2002-07-18 13:05:37 -07:00
if sys . version [ 0 : 1 ] == ' 1 ' :
2010-12-28 16:26:52 -05:00
raise RuntimeError ( " The Python Cryptography Toolkit requires "
" Python 2.x or 3.x to build. " )
2002-07-18 13:05:37 -07:00
2002-06-19 13:07:12 -07:00
if sys . platform == ' win32 ' :
HTONS_LIBS = [ ' ws2_32 ' ]
2002-10-23 04:52:20 -07:00
plat_ext = [
2008-09-17 11:00:45 -04:00
Extension ( " Crypto.Random.OSRNG.winrandom " ,
2002-10-23 04:52:20 -07:00
libraries = HTONS_LIBS + [ ' advapi32 ' ] ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/winrand.c " ] )
]
2002-06-19 13:07:12 -07:00
else :
HTONS_LIBS = [ ]
2002-10-23 04:52:20 -07:00
plat_ext = [ ]
2003-02-28 17:38:29 -07:00
2009-10-11 02:04:38 -04:00
# For test development: Set this to 1 to build with gcov support.
# Use "gcov -p -o build/temp.*/src build/temp.*/src/*.gcda" to build the .gcov files
USE_GCOV = 0
2010-12-28 16:26:52 -05:00
try :
# Python 3
from distutils . command . build_py import build_py_2to3 as build_py
except ImportError :
# Python 2
from distutils . command . build_py import build_py
2008-08-13 23:11:05 -04:00
# List of pure Python modules that will be excluded from the binary packages.
# The list consists of (package, module_name) tuples
2010-12-28 16:26:52 -05:00
if sys . version_info [ 0 ] is 2 :
EXCLUDE_PY = [
( ' Crypto.Hash ' ) , # Included for your amusement, but the C version is much faster.
]
else :
EXCLUDE_PY = [
( ' Crypto.Hash ' , ' Crypto.Util.python_compat ' ) , # Included for your amusement, but the C version is much faster. Also, we don't want Py3k to choke on the 2.x compat code
]
# Work around the print / print() issue with Python 2.x and 3.x. We only need to print at one point of the code, which makes this easy
def PrintErr ( * args , * * kwd ) :
fout = kwd . get ( " file " , sys . stderr )
w = fout . write
if args :
w ( str ( args [ 0 ] ) )
sep = kwd . get ( " sep " , " " )
for a in args [ 1 : ] :
w ( sep )
w ( str ( a ) )
w ( kwd . get ( " end " , " \n " ) )
2008-08-13 23:11:05 -04:00
2003-02-28 17:38:29 -07:00
# Functions for finding libraries and files, copied from Python's setup.py.
def find_file ( filename , std_dirs , paths ) :
""" Searches for the directory where a given file is located,
and returns a possibly - empty list of additional directories , or None
if the file couldn ' t be found at all.
' filename ' is the name of a file , such as readline . h or libcrypto . a .
' std_dirs ' is the list of standard system directories ; if the
file is found in one of them , no additional directives are needed .
' paths ' is a list of additional locations to check ; if the file is
found in one of them , the resulting list will contain the directory .
"""
# Check the standard locations
for dir in std_dirs :
f = os . path . join ( dir , filename )
if os . path . exists ( f ) : return [ ]
# Check the additional directories
for dir in paths :
f = os . path . join ( dir , filename )
if os . path . exists ( f ) :
return [ dir ]
# Not found anywhere
return None
def find_library_file ( compiler , libname , std_dirs , paths ) :
filename = compiler . library_filename ( libname , lib_type = ' shared ' )
result = find_file ( filename , std_dirs , paths )
if result is not None : return result
filename = compiler . library_filename ( libname , lib_type = ' static ' )
result = find_file ( filename , std_dirs , paths )
return result
2008-09-15 21:32:58 -04:00
def endianness_macro ( ) :
2008-09-16 12:48:24 -04:00
s = struct . pack ( " @I " , 0x33221100 )
2010-12-28 16:26:52 -05:00
if s == " \x00 \x11 \x22 \x33 " . encode ( ) : # little endian
2008-09-15 21:32:58 -04:00
return ( ' PCT_LITTLE_ENDIAN ' , 1 )
2010-12-28 16:26:52 -05:00
elif s == " \x33 \x22 \x11 \x00 " . encode ( ) : # big endian
2008-09-15 21:32:58 -04:00
return ( ' PCT_BIG_ENDIAN ' , 1 )
raise AssertionError ( " Machine is neither little-endian nor big-endian " )
2003-02-28 17:38:29 -07:00
class PCTBuildExt ( build_ext ) :
def build_extensions ( self ) :
# Detect which modules should be compiled
self . detect_modules ( )
2009-03-10 23:40:47 -04:00
2009-10-10 15:05:36 -04:00
# Tweak compiler options
if self . compiler . compiler_type in ( ' unix ' , ' cygwin ' , ' mingw32 ' ) :
2010-05-29 10:13:54 -04:00
# Tell GCC to compile using the C99 standard.
self . __add_compiler_option ( " -std=c99 " )
2009-10-10 15:05:36 -04:00
# Make assert() statements always work
self . __remove_compiler_option ( " -DNDEBUG " )
# Choose our own optimization options
for opt in [ " -O " , " -O0 " , " -O1 " , " -O2 " , " -O3 " , " -Os " ] :
self . __remove_compiler_option ( opt )
if self . debug :
# Basic optimization is still needed when debugging to compile
# the libtomcrypt code.
self . __add_compiler_option ( " -O " )
else :
# Speed up execution by tweaking compiler options. This
# especially helps the DES modules.
self . __add_compiler_option ( " -O3 " )
self . __add_compiler_option ( " -fomit-frame-pointer " )
# Don't include debug symbols unless debugging
self . __remove_compiler_option ( " -g " )
2010-08-02 16:38:42 -04:00
# Don't include profiling information (incompatible with -fomit-frame-pointer)
self . __remove_compiler_option ( " -pg " )
2009-10-11 02:04:38 -04:00
if USE_GCOV :
self . __add_compiler_option ( " -fprofile-arcs " )
self . __add_compiler_option ( " -ftest-coverage " )
self . compiler . libraries + = [ ' gcov ' ]
2009-03-10 23:40:47 -04:00
# Call the superclass's build_extensions method
2003-02-28 17:38:29 -07:00
build_ext . build_extensions ( self )
def detect_modules ( self ) :
2009-08-18 19:57:08 -04:00
# Add special include directory for MSVC (because MSVC is special)
2008-11-16 11:39:38 -05:00
if self . compiler . compiler_type == ' msvc ' :
self . compiler . include_dirs . insert ( 0 , " src/inc-msvc/ " )
2009-08-18 19:57:08 -04:00
2010-12-23 02:41:02 -05:00
# Detect libgmp or libmpir and don't build _fastmath if both are missing.
2003-02-28 17:38:29 -07:00
lib_dirs = self . compiler . library_dirs + [ ' /lib ' , ' /usr/lib ' ]
2010-12-23 02:41:02 -05:00
if not ( self . compiler . find_library_file ( lib_dirs , ' gmp ' ) or self . compiler . find_library_file ( lib_dirs , ' mpir ' ) ) :
2010-12-28 16:26:52 -05:00
PrintErr ( " warning: GMP or MPIR library not found; Not building Crypto.PublicKey._fastmath. " )
2009-08-18 19:57:08 -04:00
self . __remove_extensions ( [ " Crypto.PublicKey._fastmath " ] )
2010-12-23 02:41:02 -05:00
# Change library to libmpir if libgmp is missing
elif not ( self . compiler . find_library_file ( lib_dirs , ' gmp ' ) ) :
self . __change_extension_lib ( [ " Crypto.PublicKey._fastmath " ] , [ ' mpir ' ] )
def __change_extension_lib ( self , names , libs ) :
""" Change the libraries to be used for the specified extension(s) """
i = 0
while i < len ( self . extensions ) :
if self . extensions [ i ] . name in names :
self . extensions [ i ] . libraries = libs
i + = 1
2009-08-18 19:57:08 -04:00
def __remove_extensions ( self , names ) :
2010-12-23 02:41:02 -05:00
""" Remove the specified extension(s) from the list of extensions to build """
2009-08-18 19:57:08 -04:00
i = 0
while i < len ( self . extensions ) :
if self . extensions [ i ] . name in names :
del self . extensions [ i ]
continue
i + = 1
2003-02-28 17:38:29 -07:00
2009-03-10 23:40:47 -04:00
def __remove_compiler_option ( self , option ) :
""" Remove the specified compiler option.
Return true if the option was found . Return false otherwise .
"""
found = 0
for attrname in ( ' compiler ' , ' compiler_so ' ) :
compiler = getattr ( self . compiler , attrname , None )
if compiler is not None :
while option in compiler :
compiler . remove ( option )
found + = 1
return found
def __add_compiler_option ( self , option ) :
for attrname in ( ' compiler ' , ' compiler_so ' ) :
compiler = getattr ( self . compiler , attrname , None )
if compiler is not None :
compiler . append ( option )
2008-08-13 23:11:05 -04:00
class PCTBuildPy ( build_py ) :
def find_package_modules ( self , package , package_dir , * args , * * kwargs ) :
modules = build_py . find_package_modules ( self , package , package_dir , * args , * * kwargs )
# Exclude certain modules
2008-09-15 18:16:11 -04:00
retval = [ ]
for item in modules :
pkg , module = item [ : 2 ]
2008-08-13 23:11:05 -04:00
if ( pkg , module ) in EXCLUDE_PY :
continue
2008-09-15 18:16:11 -04:00
retval . append ( item )
return retval
2008-08-13 23:11:05 -04:00
2010-12-23 02:41:02 -05:00
2008-11-21 13:04:18 -05:00
class TestCommand ( Command ) :
description = " Run self-test "
user_options = [
( ' skip-slow-tests ' , None ,
' Skip slow tests ' )
]
def initialize_options ( self ) :
self . build_dir = None
self . skip_slow_tests = None
def finalize_options ( self ) :
self . set_undefined_options ( ' install ' , ( ' build_lib ' , ' build_dir ' ) )
self . config = { ' slow_tests ' : not self . skip_slow_tests }
def run ( self ) :
# Run SelfTest
self . announce ( " running self-tests " )
old_path = sys . path [ : ]
try :
sys . path . insert ( 0 , self . build_dir )
from Crypto import SelfTest
SelfTest . run ( verbosity = self . verbose , stream = sys . stdout , config = self . config )
finally :
# Restore sys.path
sys . path [ : ] = old_path
# Run slower self-tests
self . announce ( " running extended self-tests " )
2003-02-28 17:55:21 -07:00
kw = { ' name ' : " pycrypto " ,
2010-08-27 00:20:06 -04:00
' version ' : " 2.3 " , # See also: lib/Crypto/__init__.py
2003-02-28 17:55:21 -07:00
' description ' : " Cryptographic modules for Python. " ,
2009-08-03 21:46:28 -04:00
' author ' : " Dwayne C. Litzenberger " ,
' author_email ' : " dlitz@dlitz.net " ,
' url ' : " http://www.pycrypto.org/ " ,
2003-02-28 17:38:29 -07:00
2008-11-21 13:04:18 -05:00
' cmdclass ' : { ' build_ext ' : PCTBuildExt , ' build_py ' : PCTBuildPy , ' test ' : TestCommand } ,
2010-12-28 16:26:52 -05:00
' packages ' : [ " Crypto " , " Crypto.Hash " , " Crypto.Cipher " , " Crypto.Util " ,
2008-09-17 11:00:45 -04:00
" Crypto.Random " ,
2008-09-20 12:04:40 -04:00
" Crypto.Random.Fortuna " ,
2008-09-17 11:00:45 -04:00
" Crypto.Random.OSRNG " ,
2008-09-12 15:26:24 -04:00
" Crypto.SelfTest " ,
2008-09-13 00:13:29 -04:00
" Crypto.SelfTest.Cipher " ,
2008-09-12 15:26:24 -04:00
" Crypto.SelfTest.Hash " ,
2008-11-21 13:05:35 -05:00
" Crypto.SelfTest.Protocol " ,
2008-09-18 23:48:38 -04:00
" Crypto.SelfTest.PublicKey " ,
2008-09-17 13:35:25 -04:00
" Crypto.SelfTest.Random " ,
2008-09-20 12:04:40 -04:00
" Crypto.SelfTest.Random.Fortuna " ,
2008-09-17 13:35:25 -04:00
" Crypto.SelfTest.Random.OSRNG " ,
2008-09-15 18:59:25 -04:00
" Crypto.SelfTest.Util " ,
2002-05-23 13:22:04 -07:00
" Crypto.Protocol " , " Crypto.PublicKey " ] ,
2009-02-28 13:17:31 -05:00
' package_dir ' : { " Crypto " : " lib/Crypto " } ,
2009-08-18 19:57:08 -04:00
' ext_modules ' : plat_ext + [
# _fastmath (uses GNU mp library)
Extension ( " Crypto.PublicKey._fastmath " ,
include_dirs = [ ' src/ ' ] ,
libraries = [ ' gmp ' ] ,
sources = [ " src/_fastmath.c " ] ) ,
# Hash functions
Extension ( " Crypto.Hash.MD2 " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/MD2.c " ] ) ,
Extension ( " Crypto.Hash.MD4 " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/MD4.c " ] ) ,
Extension ( " Crypto.Hash.SHA256 " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/SHA256.c " ] ) ,
Extension ( " Crypto.Hash.RIPEMD160 " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/RIPEMD160.c " ] ,
define_macros = [ endianness_macro ( ) ] ) ,
# Block encryption algorithms
Extension ( " Crypto.Cipher.AES " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/AES.c " ] ) ,
Extension ( " Crypto.Cipher.ARC2 " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/ARC2.c " ] ) ,
Extension ( " Crypto.Cipher.Blowfish " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/Blowfish.c " ] ) ,
Extension ( " Crypto.Cipher.CAST " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/CAST.c " ] ) ,
Extension ( " Crypto.Cipher.DES " ,
include_dirs = [ ' src/ ' , ' src/libtom/ ' ] ,
sources = [ " src/DES.c " ] ) ,
Extension ( " Crypto.Cipher.DES3 " ,
include_dirs = [ ' src/ ' , ' src/libtom/ ' ] ,
sources = [ " src/DES3.c " ] ) ,
# Stream ciphers
Extension ( " Crypto.Cipher.ARC4 " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/ARC4.c " ] ) ,
Extension ( " Crypto.Cipher.XOR " ,
include_dirs = [ ' src/ ' ] ,
sources = [ " src/XOR.c " ] ) ,
# Utility modules
Extension ( " Crypto.Util.strxor " ,
include_dirs = [ ' src/ ' ] ,
sources = [ ' src/strxor.c ' ] ) ,
# Counter modules
Extension ( " Crypto.Util._counter " ,
include_dirs = [ ' src/ ' ] ,
sources = [ ' src/_counter.c ' ] ) ,
]
}
2010-12-28 16:26:52 -05:00
def touch ( path ) :
import os , time
now = time . time ( )
try :
# assume it's there
os . utime ( path , ( now , now ) )
except os . error :
PrintErr ( " Failed to update timestamp of " + path )
2003-02-28 17:55:21 -07:00
# If we're running Python 2.3, add extra information
if hasattr ( core , ' setup_keywords ' ) :
if ' classifiers ' in core . setup_keywords :
kw [ ' classifiers ' ] = [
' Development Status :: 4 - Beta ' ,
' License :: Public Domain ' ,
' Intended Audience :: Developers ' ,
' Operating System :: Unix ' ,
' Operating System :: Microsoft :: Windows ' ,
' Operating System :: MacOS :: MacOS X ' ,
' Topic :: Security :: Cryptography ' ,
]
if ' download_url ' in core . setup_keywords :
2009-08-18 21:33:29 -04:00
kw [ ' download_url ' ] = ( ' http://www.pycrypto.org/files/ '
2003-02-28 17:55:21 -07:00
' %s - %s .tar.gz ' % ( kw [ ' name ' ] , kw [ ' version ' ] ) )
core . setup ( * * kw )
2010-12-28 16:26:52 -05:00
#PY3K: Workaround for winrandom.pyd not existing during the first pass.
# It needs to be there for 2to3 to fix the import in nt.py
if sys . platform == ' win32 ' and sys . version_info [ 0 ] is 3 and ' build ' in sys . argv [ 1 : ] :
PrintErr ( " Second pass to allow 2to3 to fix nt.py. No cause for alarm. " )
touch ( " ./lib/Crypto/Random/OSRNG/nt.py " )
core . setup ( * * kw )