diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/win32build/README.txt | 9 | ||||
-rw-r--r-- | tools/win32build/cpuid/SConstruct | 5 | ||||
-rw-r--r-- | tools/win32build/cpuid/cpuid.c | 169 | ||||
-rw-r--r-- | tools/win32build/cpuid/cpuid.h | 20 | ||||
-rw-r--r-- | tools/win32build/cpuid/test.c | 44 | ||||
-rw-r--r-- | tools/win32build/nsis_scripts/numpy-superinstaller-2.4.nsi | 120 | ||||
-rw-r--r-- | tools/win32build/nsis_scripts/numpy-superinstaller-2.5.nsi | 120 |
7 files changed, 487 insertions, 0 deletions
diff --git a/tools/win32build/README.txt b/tools/win32build/README.txt new file mode 100644 index 000000000..54989182f --- /dev/null +++ b/tools/win32build/README.txt @@ -0,0 +1,9 @@ +This directory contains various scripts and code to build installers for
+windows
+ - cpuid: contains a mini lib to detect SSE.
+ - cpucaps: nsis plugin to add the ability to detect SSE for installers.
+ - *nsi scripts: actual nsis scripts to build the installer
+ - build.py: script to build various versions of python binaries
+ (several archs, several python versions)
+
+To build the binaries, you need blas/lapack/atlas for all architectures.
diff --git a/tools/win32build/cpuid/SConstruct b/tools/win32build/cpuid/SConstruct new file mode 100644 index 000000000..3b491deb1 --- /dev/null +++ b/tools/win32build/cpuid/SConstruct @@ -0,0 +1,5 @@ +env = Environment(tools = ['mingw']) + +#libcpuid = env.SharedLibrary('cpuid', source = ['cpuid.c']) +#test = env.Program('test', source = ['test.c'], LIBS = libcpuid, RPATH = ['.']) +test = env.Program('test', source = ['test.c', 'cpuid.c']) diff --git a/tools/win32build/cpuid/cpuid.c b/tools/win32build/cpuid/cpuid.c new file mode 100644 index 000000000..d30d00de8 --- /dev/null +++ b/tools/win32build/cpuid/cpuid.c @@ -0,0 +1,169 @@ +/* + * TODO: + * - test for cpuid availability + * - test for OS support (tricky) + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "cpuid.h" + +#ifndef __GNUC__ +#error "Sorry, this code can only be compiled with gcc for now" +#endif + +/* + * SIMD: SSE 1, 2 and 3, MMX + */ +#define CPUID_FLAG_MMX 1 << 23 /* in edx */ +#define CPUID_FLAG_SSE 1 << 25 /* in edx */ +#define CPUID_FLAG_SSE2 1 << 26 /* in edx */ +#define CPUID_FLAG_SSE3 1 << 0 /* in ecx */ + +/* + * long mode (AMD64 instruction set) + */ +#define CPUID_FLAGS_LONG_MODE 1 << 29 /* in edx */ + +/* + * struct reprensenting the cpuid flags as put in the register + */ +typedef struct { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +} cpuid_t; + +/* + * Union to read bytes in 32 (intel) bits registers + */ +union _le_reg { + uint8_t ccnt[4]; + uint32_t reg; +} __attribute__ ((packed)); +typedef union _le_reg le_reg_t ; + +/* + * can_cpuid and read_cpuid are the two only functions using asm + */ +static int can_cpuid(void) +{ + int has_cpuid = 0 ; + + /* + * See intel doc on cpuid (pdf) + */ + asm volatile ( + "pushfl \n\t" + "popl %%eax \n\t" + "movl %%eax, %%ecx \n\t" + "xorl $0x200000, %%eax \n\t" + "pushl %%eax \n\t" + "popfl \n\t" + "pushfl \n\t" + "popl %%eax \n\t" + "xorl %%ecx, %%eax \n\t" + "andl $0x200000, %%eax \n\t" + "movl %%eax,%0 \n\t" + :"=m" (has_cpuid) + : /*no input*/ + : "eax","ecx","cc"); + + return (has_cpuid != 0) ; +} + +/* + * func is the "level" of cpuid. See for cpuid.txt + */ +static cpuid_t read_cpuid(unsigned int func) +{ + cpuid_t res; + + /* we save ebx because it is used when compiled by -fPIC */ + asm volatile( + "pushl %%ebx \n\t" /* save %ebx */ + "cpuid \n\t" + "movl %%ebx, %1 \n\t" /* save what cpuid just put in %ebx */ + "popl %%ebx \n\t" /* restore the old %ebx */ + : "=a"(res.eax), "=r"(res.ebx), + "=c"(res.ecx), "=d"(res.edx) + : "a"(func) + : "cc"); + + return res; +} + +static uint32_t get_max_func() +{ + cpuid_t cpuid; + + cpuid = read_cpuid(0); + return cpuid.eax; +} + +/* + * vendor should have at least CPUID_VENDOR_STRING_LEN characters + */ +static int get_vendor_string(cpuid_t cpuid, char vendor[]) +{ + int i; + le_reg_t treg; + + treg.reg = cpuid.ebx; + for (i = 0; i < 4; ++i) { + vendor[i] = treg.ccnt[i]; + } + + treg.reg = cpuid.edx; + for (i = 0; i < 4; ++i) { + vendor[i+4] = treg.ccnt[i]; + } + + treg.reg = cpuid.ecx; + for (i = 0; i < 4; ++i) { + vendor[i+8] = treg.ccnt[i]; + } + vendor[12] = '\0'; + return 0; +} + +int cpuid_get_caps(cpu_caps_t *cpu) +{ + cpuid_t cpuid; + int max; + + memset(cpu, 0, sizeof(*cpu)); + + if (!can_cpuid()) { + return 0; + } + + max = get_max_func(); + + /* Read vendor string */ + cpuid = read_cpuid(0); + get_vendor_string(cpuid, cpu->vendor); + + if (max < 0x00000001) { + return 0; + } + cpuid = read_cpuid(0x00000001); + + /* We can read mmx, sse 1 2 and 3 when cpuid level >= 0x00000001 */ + if (cpuid.edx & CPUID_FLAG_MMX) { + cpu->has_mmx = 1; + } + if (cpuid.edx & CPUID_FLAG_SSE) { + cpu->has_sse = 1; + } + if (cpuid.edx & CPUID_FLAG_SSE2) { + cpu->has_sse2 = 1; + } + if (cpuid.ecx & CPUID_FLAG_SSE3) { + cpu->has_sse3 = 1; + } + return 0; +} diff --git a/tools/win32build/cpuid/cpuid.h b/tools/win32build/cpuid/cpuid.h new file mode 100644 index 000000000..dc6d2933c --- /dev/null +++ b/tools/win32build/cpuid/cpuid.h @@ -0,0 +1,20 @@ +#ifndef _GABOU_CPUID_H +#define _GABOU_CPUID_H + +#include <stdlib.h> + +#define CPUID_VENDOR_STRING_LEN 12 + +struct _cpu_caps { + int has_cpuid; + int has_mmx; + int has_sse; + int has_sse2; + int has_sse3; + char vendor[CPUID_VENDOR_STRING_LEN+1]; +}; +typedef struct _cpu_caps cpu_caps_t; + +int cpuid_get_caps(cpu_caps_t *cpuinfo); + +#endif diff --git a/tools/win32build/cpuid/test.c b/tools/win32build/cpuid/test.c new file mode 100644 index 000000000..31f9a7f11 --- /dev/null +++ b/tools/win32build/cpuid/test.c @@ -0,0 +1,44 @@ +#include <stdio.h> + +#include "cpuid.h" + +int main() +{ + cpu_caps_t *cpuinfo; + + cpuinfo = malloc(sizeof(*cpuinfo)); + + if (cpuinfo == NULL) { + fprintf(stderr, "Error allocating\n"); + } + + cpuid_get_caps(cpuinfo); + printf("This cpu string is %s\n", cpuinfo->vendor); + + if (cpuinfo->has_mmx) { + printf("This cpu has mmx instruction set\n"); + } else { + printf("This cpu does NOT have mmx instruction set\n"); + } + + if (cpuinfo->has_sse) { + printf("This cpu has sse instruction set\n"); + } else { + printf("This cpu does NOT have sse instruction set\n"); + } + + if (cpuinfo->has_sse2) { + printf("This cpu has sse2 instruction set\n"); + } else { + printf("This cpu does NOT have sse2 instruction set\n"); + } + + if (cpuinfo->has_sse3) { + printf("This cpu has sse3 instruction set\n"); + } else { + printf("This cpu does NOT have sse3 instruction set\n"); + } + + free(cpuinfo); + return 0; +} diff --git a/tools/win32build/nsis_scripts/numpy-superinstaller-2.4.nsi b/tools/win32build/nsis_scripts/numpy-superinstaller-2.4.nsi new file mode 100644 index 000000000..78e5c842e --- /dev/null +++ b/tools/win32build/nsis_scripts/numpy-superinstaller-2.4.nsi @@ -0,0 +1,120 @@ +;--------------------------------
+;Include Modern UI
+
+!include "MUI2.nsh"
+
+;SetCompress off ; Useful to disable compression under development
+
+;--------------------------------
+;General
+
+;Name and file
+Name "Numpy super installer"
+OutFile "numpy-1.1.0-win32-superpack-python2.4.exe"
+
+;Default installation folder
+InstallDir "$TEMP"
+
+;--------------------------------
+;Interface Settings
+
+!define MUI_ABORTWARNING
+
+;--------------------------------
+;Pages
+
+;!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Docs\Modern UI\License.txt"
+;!insertmacro MUI_PAGE_COMPONENTS
+;!insertmacro MUI_PAGE_DIRECTORY
+;!insertmacro MUI_PAGE_INSTFILES
+
+;!insertmacro MUI_UNPAGE_CONFIRM
+;!insertmacro MUI_UNPAGE_INSTFILES
+
+;--------------------------------
+;Languages
+
+!insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Component Sections
+
+!include 'Sections.nsh'
+!include LogicLib.nsh
+
+Var HasSSE2
+Var HasSSE3
+Var CPUSSE
+
+Section "Core" SecCore
+
+ ;SectionIn RO
+ SetOutPath "$INSTDIR"
+
+ ;Create uninstaller
+ ;WriteUninstaller "$INSTDIR\Uninstall.exe"
+
+ DetailPrint "Install dir for actual installers is $INSTDIR"
+
+ StrCpy $CPUSSE "0"
+ CpuCaps::hasSSE2
+ Pop $0
+ StrCpy $HasSSE2 $0
+
+ CpuCaps::hasSSE3
+ Pop $0
+ StrCpy $HasSSE3 $0
+
+ ; Debug
+ StrCmp $HasSSE2 "Y" include_sse2 no_include_sse2
+ include_sse2:
+ DetailPrint '"Target CPU handles SSE2"'
+ StrCpy $CPUSSE "2"
+ goto done_sse2
+ no_include_sse2:
+ DetailPrint '"Target CPU does NOT handle SSE2"'
+ goto done_sse2
+ done_sse2:
+
+ StrCmp $HasSSE3 "Y" include_sse3 no_include_sse3
+ include_sse3:
+ DetailPrint '"Target CPU handles SSE3"'
+ StrCpy $CPUSSE "3"
+ goto done_sse3
+ no_include_sse3:
+ DetailPrint '"Target CPU does NOT handle SSE3"'
+ goto done_sse3
+ done_sse3:
+
+ ClearErrors
+
+ ; Install files conditionaly on detected cpu
+ ${Switch} $CPUSSE
+ ${Case} "3"
+ DetailPrint '"Install SSE 3"'
+ File "numpy-1.1.0-sse3.exe"
+ ExecWait '"$INSTDIR\numpy-1.1.0-sse3.exe"'
+ ${Break}
+ ${Case} "2"
+ DetailPrint '"Install SSE 2"'
+ File "numpy-1.1.0-sse2.exe"
+ ExecWait '"$INSTDIR\numpy-1.1.0-sse2.exe"'
+ ${Break}
+ ${Default}
+ DetailPrint '"Install NO SSE"'
+ File "numpy-1.1.0-nosse.exe"
+ ExecWait '"$INSTDIR\numpy-1.1.0-nosse.exe"'
+ ${Break}
+ ${EndSwitch}
+
+ ; Handle errors when executing installers
+ IfErrors error no_error
+
+ error:
+ messageBox MB_OK "Executing numpy installer failed"
+ goto done
+ no_error:
+ goto done
+ done:
+
+SectionEnd
diff --git a/tools/win32build/nsis_scripts/numpy-superinstaller-2.5.nsi b/tools/win32build/nsis_scripts/numpy-superinstaller-2.5.nsi new file mode 100644 index 000000000..f7592b824 --- /dev/null +++ b/tools/win32build/nsis_scripts/numpy-superinstaller-2.5.nsi @@ -0,0 +1,120 @@ +;--------------------------------
+;Include Modern UI
+
+!include "MUI2.nsh"
+
+;SetCompress off ; Useful to disable compression under development
+
+;--------------------------------
+;General
+
+;Name and file
+Name "Numpy super installer"
+OutFile "numpy-1.1.0-win32-superpack-python2.5.exe"
+
+;Default installation folder
+InstallDir "$TEMP"
+
+;--------------------------------
+;Interface Settings
+
+!define MUI_ABORTWARNING
+
+;--------------------------------
+;Pages
+
+;!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Docs\Modern UI\License.txt"
+;!insertmacro MUI_PAGE_COMPONENTS
+;!insertmacro MUI_PAGE_DIRECTORY
+;!insertmacro MUI_PAGE_INSTFILES
+
+;!insertmacro MUI_UNPAGE_CONFIRM
+;!insertmacro MUI_UNPAGE_INSTFILES
+
+;--------------------------------
+;Languages
+
+!insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Component Sections
+
+!include 'Sections.nsh'
+!include LogicLib.nsh
+
+Var HasSSE2
+Var HasSSE3
+Var CPUSSE
+
+Section "Core" SecCore
+
+ ;SectionIn RO
+ SetOutPath "$INSTDIR"
+
+ ;Create uninstaller
+ ;WriteUninstaller "$INSTDIR\Uninstall.exe"
+
+ DetailPrint "Install dir for actual installers is $INSTDIR"
+
+ StrCpy $CPUSSE "0"
+ CpuCaps::hasSSE2
+ Pop $0
+ StrCpy $HasSSE2 $0
+
+ CpuCaps::hasSSE3
+ Pop $0
+ StrCpy $HasSSE3 $0
+
+ ; Debug
+ StrCmp $HasSSE2 "Y" include_sse2 no_include_sse2
+ include_sse2:
+ DetailPrint '"Target CPU handles SSE2"'
+ StrCpy $CPUSSE "2"
+ goto done_sse2
+ no_include_sse2:
+ DetailPrint '"Target CPU does NOT handle SSE2"'
+ goto done_sse2
+ done_sse2:
+
+ StrCmp $HasSSE3 "Y" include_sse3 no_include_sse3
+ include_sse3:
+ DetailPrint '"Target CPU handles SSE3"'
+ StrCpy $CPUSSE "3"
+ goto done_sse3
+ no_include_sse3:
+ DetailPrint '"Target CPU does NOT handle SSE3"'
+ goto done_sse3
+ done_sse3:
+
+ ClearErrors
+
+ ; Install files conditionaly on detected cpu
+ ${Switch} $CPUSSE
+ ${Case} "3"
+ DetailPrint '"Install SSE 3"'
+ File "numpy-1.1.0-sse3.exe"
+ ExecWait '"$INSTDIR\numpy-1.1.0-sse3.exe"'
+ ${Break}
+ ${Case} "2"
+ DetailPrint '"Install SSE 2"'
+ File "numpy-1.1.0-sse2.exe"
+ ExecWait '"$INSTDIR\numpy-1.1.0-sse2.exe"'
+ ${Break}
+ ${Default}
+ DetailPrint '"Install NO SSE"'
+ File "numpy-1.1.0-nosse.exe"
+ ExecWait '"$INSTDIR\numpy-1.1.0-nosse.exe"'
+ ${Break}
+ ${EndSwitch}
+
+ ; Handle errors when executing installers
+ IfErrors error no_error
+
+ error:
+ messageBox MB_OK "Executing numpy installer failed"
+ goto done
+ no_error:
+ goto done
+ done:
+
+SectionEnd
|