diff --git a/build.vc10/mpir_config.py b/build.vc10/mpir_config.py new file mode 100644 index 00000000..142bd44e --- /dev/null +++ b/build.vc10/mpir_config.py @@ -0,0 +1,807 @@ +''' +Set up Visual Sudio 2010 to build a specified MPIR configuration + +Copyright (C) 2011, Brian Gladman + +32-bit: +x86w: x86, i386, i486, i586, pentium, pentiummmx, k6, k62, k63, k7, athlon, viac3, viac32, x86_64 +p6: pentiumpro, i686 +mmx: pentium2 +sse2: pentium4, prescott, core, netburst, netburstlahf +p3mmx: pentium3, k8, k10, k102, k103, bulldozer, bobcat, core2, penryn, nehalem, westmere, sandybridge, atom, nano + +64-bit: +x86_64: x86_64w +netburst: netburst, netburstlahf +k8only: k8, nano +k10: k10 +k102: k102, k103, bulldozer +bobcat: bobcat +core2: core2 +penryn: penryn +nehalem: nehalem +westmere: westmere +sandybridge: sandybridge +atom atom +''' + +from __future__ import print_function +from operator import itemgetter +from os import listdir, walk, unlink, makedirs +from os.path import split, splitext, isdir, relpath, join, exists +from copy import deepcopy +from sys import exit +from filecmp import cmp +from shutil import copy +from re import search + +is_DLL = False +is_debug = False + +lib_type = 'dll' if is_DLL else 'lib' + +# The path to the mpir root directory +mpir_dir = 'C:/Users/Brian Gladman/Documents/Visual Studio 2010/Projects/mpir/' +vc10_dir = mpir_dir + 'build.vc10/' +out_dir = vc10_dir + 'dll/' if is_DLL else 'lib/' + +# paths that might incsrc_listude source filesv(*.c, *.h, *.asm) +c_directories = ( '', 'build.vc10', 'mpf', 'mpq', 'mpz', 'printf', 'scanf' ) + +# files that are to be excluded from the build +exclude_file_list = ('config.guess', 'cfg', 'getopt', 'getrusage', 'gettimeofday', 'cpuid', + 'obsolete', 'win_timing', 'gmp-mparam', 'tal-debug', 'tal-notreent', + 'new_fft', 'new_fft_with_flint', 'compat', 'udiv_w_sdiv' ) + +# copy from file ipath to file opath but avoid copying if +# opath exists and is the same as ipath (this is to avoid +# triggering an unecessary rebuild). + +def write_f(ipath, opath): + if exists(ipath) and not isdir(ipath): + if exists(opath): + if isdir(opath) or cmp(ipath, opath): + return + copy(ipath, opath) + +# append a file (ipath) to an existing file (opath) + +def append_f(ipath, opath): + try: + with open(opath, 'ab') as out_file: + try: + with open(ipath, 'rb') as in_file: + buf = in_file.read(8192) + while buf: + out_file.write(buf) + buf = in_file.read(8192) + except IOError: + print('error reading {0:s} for input'.format(f)) + return + except IOError: + print('error opening {0:s} for output'.format(opath)) + +# copy files in a list from in_dir to out_dir +def copy_files(file_list, in_dir, out_dir): + makedirs(out_dir, exist_ok=True) + for f in file_list: + copy(join(in_dir, f), out_dir) + +# Recursively search a given directory tree to find header, +# C and assembler code files that either replace or augment +# the generic C source files in the input list 'cf_list'. +# As the directory tree is searched, files in each directory +# become the source code files for the current directory and +# the default source code files for its child directories. +# +# Lists of default header, C and assembler source code files +# are maintained as the tree is traversed and if a file in +# the current directory matches the name of a file in the +# default file list (name matches ignore file extensions), +# the name in the list is removed and is replaced by the new +# file found. On return each directory in the tree had an +# entry in the returned dictionary that contains: +# +# 1. The list of header files +# +# 2. The list of C source code files for the directory +# +# 3. The list of assembler code files that replace C files +# +# 4. The list of assembler files that are not C replacements +# + +def find_asm(path, cf_list): + d = dict() + for root, dirs, files in walk(path): + if '.svn' in dirs: # ignore SVN directories + dirs.remove('.svn') + relp = relpath(root, path) # path from asm root + relr = relpath(root, mpir_dir) # path from MPIR root + if relp == '.': # set C files as default + relp = h = t = '' + d[''] = [ [], deepcopy(cf_list), [], [] ] + else: + h, t = split(relp) # h = parent, t = this directory + hh, h = split(h) + # copy defaults from this directories parent + d[t] = [ deepcopy(d[h][0]), deepcopy(d[h][1]), + deepcopy(d[h][2]), deepcopy(d[h][3]) ] + for f in files: # for the files in this directory + n, x = splitext(f) + if x == '.h': # if it is a header file, remove + for cf in reversed(d[t][0]): # any matching default + if cf[0] == n: + d[t][0].remove(cf) + d[t][0] += [(n, x, relr)] # and add the local header file + if x == '.c': # if it is a C file, remove + for cf in reversed(d[t][1]): # any matching default + if cf[0] == n: + d[t][1].remove(cf) + d[t][1] += [(n, x, relr)] # and add the local C file + if x == '.asm': # if it is an assembler file + match = False + for cf in reversed(d[t][1]): # remove any matching C file + if cf[0] == n: + d[t][1].remove(cf) + match = True + break + for cf in reversed(d[t][2]): # and remove any matching + if cf[0] == n: # assembler file + d[t][2].remove(cf) + match = True + break + if match: # if a match was found, put the + d[t][2] += [(n, x, relr)] # file in the replacement list + else: # otherwise look for it in the + for cf in reversed(d[t][3]): # additional files list + if cf[0] == n: + d[t][3].remove(cf) + break + d[t][3] += [(n, x, relr)] + for k in d: # additional assembler list + for i in range(4): + d[k][i].sort(key=itemgetter(0)) # sort the four file lists + return d + +# create 4 lists of c, h, cc (or cpp) and asm (or as) in a directory + +def find_src(dir_list): + # list number from file extension + di = { '.h': 0, '.c': 1, '.cc': 2, '.cpp': 2, '.asm': 3, '.as': 3 } + list = [ [], [], [], [] ] + for d in dir_list: + for f in listdir(join(mpir_dir, d)): + if f == '.svn': + continue # ignore SVN directories + if not isdir(f): + n, x = splitext(f) # split into name + extension + if x in di and not n in exclude_file_list: + list[di[x]] += [(n, x, d)] # if of the right type and is + for x in list: # not in the exclude list + x.sort(key=itemgetter(2, 0, 1)) # add it to appropriaate list + return list + +# generate VIsual Studio 2010 IDE Filter + +def filter_folders(cf_list, af_list, outf): + + f1 = r''' + + +''' + f2 = r''' +''' + f3 = r''' +''' + c_dirs = set(i[2] for i in cf_list) + a_dirs = set(i[2] for i in af_list) + if a_dirs: + c_dirs |= set(('mpn\yasm',)) + outf.write(f1) + for d in sorted(c_dirs): + if d: + t = d if d != 'mpn\generic' else 'mpn' + outf.write(f2.format(t)) + outf.write(f3) + +filter_hdr_item = ' \n Header Files\n \n' + +def filter_headers(hdr_list, outf): + + f1 = r''' +''' + f2 = r''' + Header Files + +''' + f3 = r''' +''' + outf.write(f1) + for h in hdr_list: + outf.write(f2.format(h)) + outf.write(f3) + +def filter_csrc(cf_list, outf): + + f1 = r''' +''' + f2 = r''' + Source Files\{2:s} + +''' + f3 = r''' +''' + outf.write(f1) + for i in cf_list: + t = 'mpn' if i[2].endswith('generic') else i[2] + outf.write(f2.format(i[0] + i[1], i[2], t)) + outf.write(f3) + +def filter_asrc(af_list, outf): + + f1 = r''' +''' + f2 = r''' + Source Files\mpn\yasm + +''' + f3 = r''' +''' + outf.write(f1) + for i in af_list: + outf.write(f2.format(i[0] + i[1], i[2], i[2])) + outf.write(f3) + + +def gen_filter(name, hf_list, cf_list, af_list): + + f1 = r''' + +''' + f2 = r''' +''' + fn = join(vc10_dir, name) + makedirs(split(fn)[0], exist_ok=True) + with open(fn, 'w') as outf: + + outf.write(f1) + filter_folders(cf_list, af_list, outf) + filter_headers(hf_list, outf) + filter_csrc(cf_list, outf) + filter_asrc(af_list, outf) + outf.write(f2) + +# generate vcxproj file + +def vcx_proj_cfg(plat, outf): + + f1 = r''' +''' + f2 = r''' + {1:s} + {0:s} + +''' + f3 = r''' +''' + outf.write(f1) + for conf in ('Release', 'Debug'): + outf.write(f2.format(plat, conf)) + outf.write(f3) + +def vcx_globals(name, outf): + + f1 = r''' + {0:s} + Win32Proj + +''' + outf.write(f1.format(name)) + +def vcx_default_cpp_props(outf): + + f1 = r''' +''' + outf.write(f1) + +def vcx_library_type(plat, is_dll, outf): + + f1 = r''' + {2:s}Library + MultiByte + +''' + for conf in ('Release', 'Debug'): + outf.write(f1.format(plat, conf, 'Dynamic' if is_dll else 'Static' )) + +def vcx_cpp_props(outf): + + f1 = r''' +''' + outf.write(f1) + +def vcx_extensions(outf): + + f1 = r''' + + +''' + outf.write(f1) + +def vcx_user_props(plat, outf): + + f1 = r''' + + +''' + for conf in ('Release', 'Debug'): + outf.write(f1.format(plat, conf)) + +def vcx_target_name_and_dirs(name, plat, is_dll, outf): + + f1 = r''' + <_ProjectFileVersion>10.0.21006.1 +''' + f2 = r''' {2:s} + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ +''' + f3 = r''' +''' + outf.write(f1) + for conf in ('Release', 'Debug'): + outf.write(f2.format(plat, conf, name)) + outf.write(f3) + +def yasm_options(is_dll, outf): + + f1 = r''' + {0:s} + ..\..\mpn\x86_64w\ + true + $(IntDir)mpn\ + $(IntDir)mpn\ + +''' + + outf.write(f1.format('DLL' if is_dll else '')) + +def compiler_options(is_dll, is_debug, outf): + + f1 = r''' + {0:s} + true + ..\..\ + {1:s}%(PreprocessorDefinitions) + MultiThreaded{2:s} + $(TargetDir)$(TargetName).pdb + ProgramDatabase + +''' + + if is_dll: + s1 = 'DEBUG;HAVE_CONFIG_H;__GMP_LIBGMP_DLL;__GMP_WITHIN_GMP;__GMP_WITHIN_GMPXX;' + s2 = 'DLL' + else: + s1 = 'DEBUG;_LIB;HAVE_CONFIG_H;' + s2 = '' + if is_debug: + opt, defines, crt = 'Disabled', '_' + s1, 'Debug' + s2 + else: + opt, defines, crt = 'Full', 'N' + s1, s2 + outf.write(f1.format(opt, defines, crt)) + +def linker_options(outf): + + f1 = r''' + true + true + +''' + outf.write(f1) + +def vcx_post_build(outf): + + f1 = ''' + cd ..\ +postbuild "$(TargetPath)" + +''' + outf.write(f1) + +def vcx_tool_options(plat, is_dll, outf): + + f1 = r''' +''' + f2 = r''' +''' + for is_debug in (False, True): + outf.write(f1.format(plat, 'Debug' if is_debug else 'Release')) + yasm_options(is_dll, outf) + compiler_options(is_dll, is_debug, outf) + if is_dll: + linker_options(outf) + vcx_post_build(outf) + outf.write(f2) + +def vcx_hdr_items(hdr_list, outf): + + f1 = r''' +''' + f2 = r''' +''' + f3 = r''' +''' + outf.write(f1) + for i in hdr_list: + outf.write(f2.format(i)) + outf.write(f3) + +def vcx_c_items(cf_list, plat, outf): + + f1 = r''' +''' + f2 = r''' +''' + f3 = r''' + $(IntDir){2:s}\ + $(IntDir){2:s}\ + +''' + f4 = r''' +''' + outf.write(f1) + for nxd in cf_list: + if nxd[2] == '': + outf.write(f2.format(nxd)) + else: + outf.write(f3.format(nxd, plat, 'mpn' if nxd[2].endswith('generic') else nxd[2])) + outf.write(f4) + +def vcx_a_items(af_list, outf): + + f1 = r''' +''' + f2 = r''' +''' + f3 = r''' +''' + outf.write(f1) + for nxd in af_list: + outf.write(f2.format(nxd)) + outf.write(f3) + +def gen_vcxproj(proj_name, file_name, plat, is_dll, hf_list, cf_list, af_list): + + f1 = r''' + +''' + f2 = r''' +''' + f3 = r''' +''' + f4 = r''' + + +''' + f5 = ''' +''' + + with open(join(vc10_dir, file_name), 'w') as outf: + outf.write(f1) + vcx_proj_cfg(plat, outf) + vcx_globals(proj_name, outf) + vcx_default_cpp_props(outf) + vcx_library_type(plat, is_dll, outf) + vcx_cpp_props(outf) + vcx_extensions(outf) + vcx_user_props(plat, outf) + outf.write(f2) + vcx_target_name_and_dirs(proj_name, plat, is_dll, outf) + vcx_tool_options(plat, is_dll, outf) + vcx_hdr_items(hf_list, outf) + vcx_c_items(cf_list, plat, outf) + vcx_a_items(af_list, outf) + outf.write(f3) + outf.write(f4) + outf.write(f5) + +t = find_src(c_directories) +c_hdr_list = t[0] +c_src_list = t[1] +if t[2] or t[3]: + print('found C++ and/or assembler file(s) in a C directory') +for f in c_hdr_list: + print(f) +print() +for f in c_src_list: + print(f) +print() + +t = find_src(['cxx']) +cc_hdr_list = t[0] +cc_src_list = t[2] +if t[1] or t[3]: + print('found C+ and/or assembler file(s) in a C++ directory') +for f in cc_hdr_list: + print(f) +print() +for f in cc_src_list: + print(f) +print() + +t = find_src([r'mpn\generic']) +gc_hdr_list = t[0] +gc_src_list = t[1] +if t[1] or t[3]: + print('found C++ and/or assembler file(s) in a C directory') +for f in gc_hdr_list: + print(f) +print() +for f in gc_src_list: + print(f) +print() + +mpn_32 = find_asm(mpir_dir + 'mpn/x86w', gc_src_list) +mpn_32['gc-win32'] = [ gc_hdr_list, gc_src_list, [], [] ] +del mpn_32[''] +mpn_64 = find_asm(mpir_dir + 'mpn/x86_64w', gc_src_list) +mpn_64['gc-x64'] = [ gc_hdr_list, gc_src_list, [], [] ] +del mpn_64[''] + +err = False +config = '' +mode = '' +while True: + cnt = 0 + for v in sorted(mpn_32): + cnt += 1 + print('{0:2d}. {1:12s} (win32)'.format(cnt, v)) + for v in sorted(mpn_64): + cnt += 1 + print('{0:2d}. {1:12s} (x64)'.format(cnt, v)) + if err: + s = input('please enter a number <= {0:d} (0 to exit)? '.format(cnt)) + err = False + else: + s = input('Number of configuation to build (0 to exit)? ') + try: + n = int(s) + if n < 1: + n = 0 + break + if n <= len(mpn_32): + config = sorted(mpn_32)[n - 1] + mode = 'win32' + mpn_f = mpn_32[config] + break + elif n <= len(mpn_32) + len(mpn_64): + config = sorted(mpn_64)[n - len(mpn_32) - 1] + mode = 'x64' + mpn_f = mpn_64[config] + break + except: + pass + err = True +if n == 0: + exit() + +if mode == 'x64': + for l in mpn_f[1:]: + for t in l: + if t[0].startswith('preinv_'): + if (mode == 'x64' and t[0] == 'preinv_divrem_1' or + mode == 'win32' and t[0] == 'preinv_mod_1'): + l.remove(t) + +print(config, mode) + +# generate mpir.h and gmp.h from gmp_h.in +gmp_h_32 = ''' +#define __GMP_BITS_PER_MP_LIMB 32 +#define GMP_LIMB_BITS 32 +#if defined _LONG_LONG_LIMB +# undef _LONG_LONG_LIMB 1 +#endif +#if defined _WIN64 +# undef _WIN64 +#endif +#define GMP_NAIL_BITS 0 +#define SIZEOF_MP_LIMB_T (GMP_LIMB_BITS >> 3) +''' +gmp_h_64 = ''' +#define __GMP_BITS_PER_MP_LIMB 64 +#define GMP_LIMB_BITS 64 +#if !defined _LONG_LONG_LIMB +# define _LONG_LONG_LIMB 1 +#endif +#if !defined _WIN64 +#define _WIN64 +#endif +#define GMP_NAIL_BITS 0 +#define SIZEOF_MP_LIMB_T (GMP_LIMB_BITS >> 3) +''' + +try: + lines = open(join(mpir_dir, 'gmp-h.in'), 'r').readlines() +except IOError: + print('error attempting to read from gmp_h.in') + exit() +try: + tfile = join(mpir_dir, 'tmp.h') + with open(tfile, 'w') as outf: + first = True + for line in lines: + if search('@\w+@', line): + if first: + first = False + outf.writelines(gmp_h_32 if mode == 'win32' else gmp_h_64) + else: + outf.writelines([line]) + + # write result to mpir.h but only overwrite the existing + # version if this version is different (don't trigger an + # unnecessary rebuild) + write_f(tfile, join(mpir_dir, 'mpir.h')) + write_f(tfile, join(mpir_dir, 'gmp.h')) + unlink(tfile) +except IOError: + print('error attempting to create mpir.h from gmp-h.in') + exit() + +# generate config.h + +try: + tfile = join(mpir_dir, 'tmp.h') + with open(tfile, 'w') as outf: + for i in mpn_f[3]: + outf.writelines(['#define HAVE_NATIVE_{0:s} 1\n'.format(i[0])]) + + append_f(join(vc10_dir, 'cfg.h'), tfile) + write_f(tfile, join(mpir_dir, 'config.h')) + unlink(tfile) +except IOError: + print('error attempting to write to {0:s}'.format(tfile)) + exit() + +# generate longlong.h and copy gmp-mparam.h + +try: + li_file = None + for i in mpn_f[0]: + if i[0] == 'longlong_inc': + li_file = join(mpir_dir, join(i[2], r'longlong_inc.h')) + if i[0] == 'gmp-mparam': + write_f(join(mpir_dir, join(i[2], 'gmp-mparam.h')), join(mpir_dir, 'gmp-mparam.h')) + + if not li_file or not exists(li_file): + print('error attempting to read {0:s}'.format(li_file)) + exit() + + tfile = join(mpir_dir, 'tmp.h') + write_f(join(mpir_dir, 'longlong_pre.h'), tfile) + append_f(li_file, tfile) + append_f(join(mpir_dir, 'longlong_post.h'), tfile) + write_f(tfile, join(mpir_dir, 'longlong.h')) + unlink(tfile) +except IOError: + print('error attempting to generate longlong.h') + exit() + +# generate vcxproj filter + +hf_list = ('config.h', 'gmp-impl.h', 'longlong.h', 'mpir.h', 'gmp-mparam.h') +af_list = sorted(mpn_f[2] + mpn_f[3]) + +# set up DLL build +is_DLL = True +proj_name = 'mpir' +vcx_name = 'dll_mpir_' + config + '\\dll_mpir_' + config + '.2.vcxproj' +gen_filter(vcx_name + '.filters', hf_list, c_src_list + cc_src_list + mpn_f[1], af_list) +gen_vcxproj(proj_name, vcx_name, mode, is_DLL, hf_list, c_src_list + cc_src_list + mpn_f[1], af_list) + +# set up LIB build +is_DLL = False +proj_name = 'mpir' +vcx_name = 'lib_mpir_' + config + '\\lib_mpir_' + config + '.2.vcxproj' +gen_filter(vcx_name + '.filters', hf_list, c_src_list + mpn_f[1], af_list) +gen_vcxproj(proj_name, vcx_name, mode, is_DLL, hf_list, c_src_list + mpn_f[1], af_list) + +exit() + +for x in sorted(mpn_f[0] + mpn_f[1]): + print(x) +print() +for x in sorted(mpn_f[2] + mpn_f[3]): + print(x) +print() +exit() + +# mpn_files = dict() +# mpn_files.update(mpn_32) +# mpn_files.update(mpn_64) +for x in mpn_f[config]: + print(x) + if False: + print('1:') + for y in mpn_files[x][0]: + print(y) + print('2:') + for y in mpn_files[x][1]: + print(y) + print('3:') + for y in mpn_files[x][2]: + print(y) + print('4:') + for y in mpn_files[x][3]: + print(y) + print() + for y in sorted(x[2] + x[3]): + print(y) + print() + print() + +exit() + + +mpn_dirs = ('mpn/generic', 'mpn/x86_64w', 'mpn/x86w' ) + +# compile a list of files in directories in 'dl' under root 'r' with extension 'p' +def findf(r, dl, p): + l = [] + for d in dl: + for root, dirs, files in os.walk(r + d): + relp = os.path.relpath(root, r) # path relative to mpir root directory + if '.svn' in dirs: + dirs.remove('.svn') # ignore SVN directories + if d == '' or root.endswith('build.vc10'): + for d in reversed(dirs): # don't scan build.vc10 subdirectories + dirs.remove(d) + for f in files: + if f.endswith(p): + l += [(tuple(relp.split('\\')), f)] + return sorted(l) + +hdr_list = findf(dpath, c_dirs, '.h') +for x in hdr_list: + print(x) +print() + +src_list = findf(dpath, c_dirs, '.c') +for x in src_list: + print(x) +print() + +cpp_list = findf(dpath, ['cpp'], '.cc') +for x in cpp_list: + print(x) +print() + +gnc_list = findf(dpath + 'mpn/', ['generic'], '.c') +for x in gnc_list: + print(x) +print() + +w32_list = findf(dpath + 'mpn/', ['x86w'], '.asm') +for x in w32_list: + print(x) +print() + +x64_list = findf(dpath + 'mpn/', ['x86_64w'], '.asm') +for x in x64_list: + print(x) +print() + +nd = dict([]) +for d, f in gnc_list: + n, x = os.path.splitext(f) + nd[n] = nd.get(n, []) + [(d, 'c')] +for d, f in x64_list: + n, x = os.path.splitext(f) + nd[n] = nd.get(n, []) + [(d, 'asm')] +for d, f in w32_list: + n, x = os.path.splitext(f) + nd[n] = nd.get(n, []) + [(d, 'asm')] +for x in nd: + print(x, nd[x]) diff --git a/build.vc10/readme.txt b/build.vc10/readme.txt index 141c3fb8..e6b3f313 100644 --- a/build.vc10/readme.txt +++ b/build.vc10/readme.txt @@ -7,7 +7,7 @@ A Note On Licensing Files in this distribution that have been created by me for use in building MPIR with Microsoft Visual Studio 2010 are provided under -the LGPL v2.1+ license terms. +the terms of the LGPL v2.1+ license. The MPIR library uses numerous files which are LGPL v3+ and so the overall license of the library distribution is LGPL v3+. Some of @@ -18,8 +18,8 @@ Using the Assembler Based Build Projects If you wish to use the assembler files you will need VSYASM, a version of YASM x86/x64 assembler tailored specifically for use with -Microsoft Visual Studio 2010. You will need a -recent revision of YASM from: +Microsoft Visual Studio 2010. You will need a recent revision of +YASM from: http://www.tortall.net/projects/yasm/ @@ -111,11 +111,11 @@ of their build project in the IDE and exclude all the files in this subdirectory from the build process. All the DLLs and static libraries are multi-threaded and are linked to -the multi-threaded Microsoft run-time libraries (DLLs are linked to DLL +the multi-threaded Microsoft run-time libraries (DLLs are linked to DLL run time libraries and static libraries are linked to run time static libraries). -Within the 'dll' and 'lib' sub-directories used for output the structure +Within the 'dll' and 'lib' sub-directories used for output, the layout is: DLL or LIB @@ -126,11 +126,11 @@ is: Release Debug -in order to enable the appropriate library for the desired target -platform to be easily located. The individual project sub- -directories also contain the libraries once they have been built (the -'dll' and 'lib' directories are just used to hold the latest built -versions for linking the tests that are described later). +so that the appropriate library for the desired target platform can be +easily located. The individual project sub-directories also contain the +libraries once they have been built (as indicaated earlier, the 'dll' +and 'lib' directories are used to hold the latest built versions for +linking the tests). C++ Interface ============= @@ -144,23 +144,42 @@ DLL) that has been built. To build the MPIR C+ library wrapper use: The DLL projects include the C++ functions so an additional library is not needed when they are used. +Python Build File Generator +=========================== + +Only a limited number of build configurations are supported in the +VC++ IDE build. If another build is needed, other configurations +can be created using the program mpir_build.py (Python 2.6 or later +needs to be installed). + +When this program is run, it outputs a list of all available MPIR +configurations and allows the user to select one of them. It then +creates VC++ IDE build projects for both a static library and DLL +build for this configuaration. + +These can then be added to a VC++ solution using the facilities of +the IDE in the normal way. The project and fillter files are named +with the extensions *.2.vcxproj and *.2.vcxproj.filters to avoid +interfering with the conflict project files already provided for +VC++. + The Tests ========= There is a separate solution for the MPIR tests: mpir-tests.sln. In Visual Studio 2010 this is in build.vc10 folder. -The tests are configured to always test the last version of MPIR that is -built. But this is controlled by the file lastbuild.txt in the mpir-tests -directory whose contents are typically: +The tests are configured to always test the last version of MPIR that +has been built. This is automatic but it can be changed by editing +the file lastbuild.txt in the mpir-tests directory whose content +controls the tests by setting the 'library type', the 'platform', +the 'configuration' and the 'MPIR binary directory' relative to the +mpir-tests' directory. Its content is typically: dll Win32 Release "..\dll\Win32\Release" -giving the 'library type', the 'platform', the 'configuration' and the -'MPIR binary directory' relative to the mpir-tests' directory. - -This file can be edited to test a different version of MPIR but it is also -necessary to copy either: +If this file can be edited to test a different version of MPIR, it +is also necessary to copy either: mpir\build.vc10\mpir-tests\lib-test-config.props @@ -172,8 +191,7 @@ into: mpir\build.vc10\mpir-tests\test-config.props -depending on whether a static or DLL build of MPIR is to be tested -respectively. +depending on whether a static or DLL build of MPIR is to be tested. The tests also use the C++ library functions so for testing MPIR static libraries both the desired version of MPIR and the C++ library must be @@ -183,17 +201,17 @@ MPIR DLLs as they contain the C++ routines. Test Automation =============== -After they have been built the tests cn be run using the Python script +After they have been built the tests can be run using the Python script run-tests.py in the build.vc10\mpir-tests directory. To see the test output the python script should be run in a command window from within these sub-directories: - cmd>run-tests.py - + cmd>run-tests.py + and the output can be directed to a file: - cmd>run-tests.py >out.txt - + cmd>run-tests.py >out.txt + When an MPIR library is built the file 'last_build.txt' is written to the buid.vc10 subdirectory giving details of the build configuration. These details are then used to run the MPIR tests and this means that @@ -282,8 +300,8 @@ In Windows the different C runtime libraries each have their own stream input/output tables, which means that FILE* pointers cannot be passed from one to another. In consequence, if an application that is built with one library attempts to pass FILE parameters to a DLL that is built with -another, the FILE parameters will not be recognised and the program will -fail. +another library, the FILE parameters will not be recognised and the +program will fail. It is hence important to build a MPIR application using the same run time library as that used to build any DLL that is used - in this case the @@ -305,7 +323,7 @@ that provides a _stdcall interface to the normal _cdecl MPIR DLLs. Prebuild -------- -It is not necessary to read this unless you wnat to change the buiild +It is not necessary to read this unless you want to change the build process. The first step in an MPIR build is managed by the batch file prebuilld.bat which has the following steps: @@ -363,10 +381,10 @@ file postbuild.bat which has the following steps: for a DLL, mpir.lib and mpir.pdb for a static library) are then copied into the output directory. -6. In the sub-directory mpir-tests, either dll-test-config.props (for - a DLL) or lib-test-config.props (for a static library) is copied - into test-config.props to set up the tests for the version of MPIR - being built. +6. In the sub-directory mpir-tests, either dll-test-config.props (for + a DLL) or lib-test-config.props (for a static library) is copied + into test-config.props to set up the tests for the version of MPIR + being built. ACKNOWLEDGEMENTS ================ @@ -381,4 +399,4 @@ My thanks to: 4. Jeff Gilchrist for his help in testing, debugging and improving the readme giving the VC++ build instructions - Brian Gladman, August 2010 + Brian Gladman, September 2011