forked from bartvdbraak/blender
bdad961ce3
development of ode at http://q12.org and periodically copy the q12.org ODE sourcecode into this tree to update the Blender ODE. This ODE has not been changed from q12.org and is provided here merely as a convenience to Blender developers.
438 lines
13 KiB
C
438 lines
13 KiB
C
/*************************************************************************
|
|
* *
|
|
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
|
|
* All rights reserved. Email: russ@q12.org Web: www.q12.org *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of EITHER: *
|
|
* (1) The GNU Lesser General Public License as published by the Free *
|
|
* Software Foundation; either version 2.1 of the License, or (at *
|
|
* your option) any later version. The text of the GNU Lesser *
|
|
* General Public License is included with this library in the *
|
|
* file LICENSE.TXT. *
|
|
* (2) The BSD-style license that is included with this library in *
|
|
* the file LICENSE-BSD.TXT. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
|
|
* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
|
|
* *
|
|
*************************************************************************/
|
|
|
|
/*
|
|
|
|
this program discovers some system configuration stuff, prior to compiling
|
|
ODE. the usage is:
|
|
|
|
configurator <config.h-file-to-generate> <compiler-command-line>
|
|
<delete-command-line> <THIS_DIR-variable>
|
|
|
|
this program looks long, but it really has an extremely simple structure and
|
|
should be very easy for anyone to modify. it should be very portable as it
|
|
is written in straight ANSI C and only uses the following library functions:
|
|
* printf
|
|
* fopen (assumes 0 returned on failure)
|
|
* fclose
|
|
* fprintf
|
|
* system
|
|
* exit
|
|
except where stated, we do not assume anything about the return codes from
|
|
these functions.
|
|
|
|
why didn't i just use GNU autoconf? :
|
|
* autoconf needs a bourne shell and a bunch of other tools that windows
|
|
users may not have.
|
|
* i like reinventing the wheel.
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
/****************************************************************************/
|
|
/* project constants */
|
|
|
|
#define SETUP_SHLIB_DEFS \
|
|
"#ifndef SHAREDLIBIMPORT\n" \
|
|
"#define SHAREDLIBIMPORT\n" \
|
|
"#endif\n" \
|
|
"#ifndef SHAREDLIBEXPORT\n" \
|
|
"#define SHAREDLIBEXPORT\n" \
|
|
"#endif\n"
|
|
|
|
/* the config.h header */
|
|
char *config_h_part1 =
|
|
"/* per-machine configuration. this file is automatically generated. */\n"
|
|
"\n"
|
|
"#ifndef _ODE_CONFIG_H_\n"
|
|
"#define _ODE_CONFIG_H_\n"
|
|
"\n"
|
|
"/* shared lib definitions */\n"
|
|
SETUP_SHLIB_DEFS
|
|
"\n"
|
|
"/* standard system headers */\n";
|
|
|
|
|
|
char *config_h_part2 =
|
|
"\n"
|
|
"#ifdef __cplusplus\n"
|
|
"extern \"C\" {\n"
|
|
"#endif\n"
|
|
"\n";
|
|
|
|
/* the config.h footer */
|
|
char *config_h_footer =
|
|
"#ifdef __cplusplus\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#endif\n";
|
|
|
|
/****************************************************************************/
|
|
/* implementations of some string functions. these are prefixed with 'x'
|
|
* to prevent any conflicts with built-in functions.
|
|
*/
|
|
|
|
#define strcpy xstrcpy
|
|
void xstrcpy (char *dest, char *src)
|
|
{
|
|
while (*src) *dest++ = *src++;
|
|
*dest = 0;
|
|
}
|
|
|
|
|
|
#define strcat xstrcat
|
|
void xstrcat (char *dest, char *src)
|
|
{
|
|
while (*dest) dest++;
|
|
while (*src) *dest++ = *src++;
|
|
*dest = 0;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* utility functions */
|
|
|
|
/* print an error message and exit */
|
|
|
|
void fatal_error (char *message)
|
|
{
|
|
printf ("\n*** configurator failed: %s.\n\n"
|
|
"please fix your configuration and try again.\n"
|
|
"if you have to fix the configurator program or the makefiles, "
|
|
"please email\n"
|
|
"your changes to the ODE mailing list (ode@q12.org).\n\n", message);
|
|
exit (0);
|
|
}
|
|
|
|
|
|
/* open a file, generate an error if it can't be done */
|
|
|
|
FILE * xfopen (char *filename, char *mode)
|
|
{
|
|
FILE *f;
|
|
f = fopen (filename,mode);
|
|
if (!f) fatal_error ("can not open a file");
|
|
return f;
|
|
}
|
|
|
|
|
|
/* return 1 if the file exists or 0 if not */
|
|
|
|
int file_exists (char *filename)
|
|
{
|
|
FILE *f;
|
|
f = fopen (filename,"rb");
|
|
if (f) fclose (f);
|
|
return (f != 0);
|
|
}
|
|
|
|
|
|
/* write a string to a new file */
|
|
|
|
void write_to_file (char *filename, char *s)
|
|
{
|
|
FILE *f = xfopen (filename,"wt");
|
|
fprintf (f,"%s",s);
|
|
fclose (f);
|
|
}
|
|
|
|
|
|
/* write a comment to a header file */
|
|
|
|
void write_header_comment (FILE *file, char *description)
|
|
{
|
|
fprintf (file,"/* %s */\n",description);
|
|
printf ("%s ...\n",description);
|
|
}
|
|
|
|
|
|
/* delete a file */
|
|
|
|
char *delete_cmd_line = 0;
|
|
void delete_file (char *filename)
|
|
{
|
|
char cmd[1000];
|
|
strcpy (cmd,delete_cmd_line);
|
|
strcat (cmd," ");
|
|
strcat (cmd,filename);
|
|
printf ("%s\n",cmd);
|
|
system (cmd);
|
|
}
|
|
|
|
|
|
/* run a compile command */
|
|
|
|
char *compile_cmd_line = 0;
|
|
void compile (char *output, char *input)
|
|
{
|
|
char cmd[1000];
|
|
strcpy (cmd,compile_cmd_line);
|
|
strcat (cmd,output);
|
|
strcat (cmd," ");
|
|
strcat (cmd,input);
|
|
printf ("%s\n",cmd);
|
|
system (cmd);
|
|
}
|
|
|
|
|
|
/* run a program we've just compiled */
|
|
|
|
char *run_prefix = "";
|
|
void run (char *filename)
|
|
{
|
|
char cmd[1000];
|
|
strcpy (cmd,run_prefix);
|
|
strcat (cmd,filename);
|
|
printf ("%s\n",cmd);
|
|
system (cmd);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* system tests */
|
|
|
|
void check_if_this_is_a_pentium (FILE *file)
|
|
{
|
|
write_header_comment (file,"is this a pentium on a gcc-based platform?");
|
|
write_to_file ("ctest.c",
|
|
"int main() {\n"
|
|
" asm (\"mov $0,%%eax\\n cpuid\\n\" : : : \"%eax\");\n"
|
|
" return 0;\n"
|
|
"}\n");
|
|
delete_file ("ctest.exe");
|
|
compile ("ctest.exe","ctest.c");
|
|
if (file_exists ("ctest.exe")) {
|
|
fprintf (file,"#define PENTIUM 1\n\n");
|
|
}
|
|
else {
|
|
fprintf (file,"/* #define PENTIUM 1 -- not a pentium */\n\n");
|
|
}
|
|
|
|
delete_file ("ctest.c");
|
|
delete_file ("ctest.exe");
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* tests: standard headers */
|
|
|
|
void get_all_standard_headers (FILE *file)
|
|
{
|
|
int i;
|
|
FILE *f;
|
|
char *header[7] = {"stdio.h", "stdlib.h", "math.h", "string.h",
|
|
"stdarg.h", "malloc.h", "alloca.h"};
|
|
|
|
for (i=0; i < sizeof(header)/sizeof(char*); i++) {
|
|
FILE *f = xfopen ("ctest.c","wt");
|
|
fprintf (f,"#include <%s>\nint main() { return 0; }\n",header[i]);
|
|
fclose (f);
|
|
delete_file ("ctest.exe");
|
|
compile ("ctest.exe","ctest.c");
|
|
if (file_exists ("ctest.exe")) {
|
|
fprintf (file,"#include <%s>\n",header[i]);
|
|
}
|
|
}
|
|
|
|
delete_file ("ctest.c");
|
|
delete_file ("ctest.exe");
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* tests: typedefs and constants for ODE */
|
|
|
|
void get_ODE_integer_typedefs (FILE *file)
|
|
{
|
|
write_header_comment (file,"integer types (we assume int >= 32 bits)");
|
|
if (sizeof(char) != 1) fatal_error ("expecting sizeof(char) == 1");
|
|
if (sizeof(int) < 4) fatal_error ("expecting sizeof(int) >= 4");
|
|
fprintf (file,"typedef char int8;\ntypedef unsigned char uint8;\n");
|
|
if (sizeof(short) == 4) {
|
|
fprintf (file,"typedef short int32;\ntypedef unsigned short uint32;\n");
|
|
}
|
|
else if (sizeof(int) == 4) {
|
|
fprintf (file,"typedef int int32;\ntypedef unsigned int uint32;\n");
|
|
}
|
|
else {
|
|
fatal_error ("can not find 4 byte integer type");
|
|
}
|
|
fprintf (file,"\n"
|
|
"/* an integer type that we can safely cast a pointer to and\n"
|
|
" * from without loss of bits.\n"
|
|
" */\n");
|
|
if (sizeof(short) == sizeof(void*)) {
|
|
fprintf (file,"typedef unsigned short intP;\n");
|
|
}
|
|
else if (sizeof(int) == sizeof(void*)) {
|
|
fprintf (file,"typedef unsigned int intP;\n");
|
|
}
|
|
else if (sizeof(long int) == sizeof(void*)) {
|
|
fprintf (file,"typedef unsigned long int intP;\n");
|
|
}
|
|
fprintf (file,"\n");
|
|
}
|
|
|
|
|
|
void get_ODE_float_stuff (FILE *file)
|
|
{
|
|
char *suffix,*type;
|
|
int i;
|
|
FILE *f;
|
|
|
|
#define SHARED_LIB_SPEC_DECISION \
|
|
"#if defined SHARED_CONFIG_H_INCLUDED_FROM_DEFINING_FILE\n" \
|
|
" #define GLOBAL_SHAREDLIB_SPEC SHAREDLIBEXPORT\n" \
|
|
"#else \n" \
|
|
" #define GLOBAL_SHAREDLIB_SPEC SHAREDLIBIMPORT\n" \
|
|
"#endif\n"
|
|
|
|
#define UNDEF_SHAREDLIB_SPEC "\n#undef GLOBAL_SHAREDLIB_SPEC\n"
|
|
|
|
#ifdef dSINGLE
|
|
|
|
#define INFBYTES SHARED_LIB_SPEC_DECISION "union dInfBytes { unsigned char c[4]; float f; };\nextern GLOBAL_SHAREDLIB_SPEC union dInfBytes dInfinityValue;\n#define dInfinity (dInfinityValue.f)"
|
|
|
|
char *inc[6] = {"#include <math.h>",
|
|
"#include <math.h>",
|
|
"",
|
|
"",
|
|
"",
|
|
""};
|
|
char *decl[6] = {
|
|
"SHAREDLIBEXPORT double dInfinityValue = HUGE_VALF;",
|
|
"SHAREDLIBEXPORT double dInfinityValue = HUGE_VAL;",
|
|
"SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0x7f,0x80,0,0}};",
|
|
"SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0,0,0x80,0x7f}};",
|
|
"SHAREDLIBEXPORT double dInfinityValue = 1.0f/0.0f;",
|
|
"SHAREDLIBEXPORT double dInfinityValue = 1e20f;"};
|
|
char *inf[6] = {
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
|
|
INFBYTES UNDEF_SHAREDLIB_SPEC,
|
|
INFBYTES UNDEF_SHAREDLIB_SPEC,
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC};
|
|
|
|
#else /* not dSINGLE, must be dDOUBLE */
|
|
|
|
#define INFBYTES SHARED_LIB_SPEC_DECISION "union dInfBytes { unsigned char c[8]; double d; };\nextern GLOBAL_SHAREDLIB_SPEC union dInfBytes dInfinityValue;\n#define dInfinity (dInfinityValue.d)"
|
|
|
|
char *inc[5] = {
|
|
"#include <math.h>",
|
|
"",
|
|
"",
|
|
"",
|
|
""};
|
|
char *decl[5] = {
|
|
"SHAREDLIBEXPORT double dInfinityValue = HUGE_VAL;",
|
|
"SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0x7f,0xf0,0,0,0,0,0,0}};",
|
|
"SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0,0,0,0,0,0,0xf0,0x7f}};",
|
|
"SHAREDLIBEXPORT double dInfinityValue = 1.0/0.0;",
|
|
"SHAREDLIBEXPORT double dInfinityValue = 1e20;"};
|
|
char *inf[5] = {
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
|
|
INFBYTES UNDEF_SHAREDLIB_SPEC,
|
|
INFBYTES UNDEF_SHAREDLIB_SPEC,
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
|
|
SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC};
|
|
#endif
|
|
|
|
write_header_comment (file,"select the base floating point type");
|
|
#ifdef dSINGLE
|
|
fprintf (file,"#define dSINGLE 1\n\n");
|
|
type = "float";
|
|
suffix = "f";
|
|
#else
|
|
fprintf (file,"#define dDOUBLE 1\n\n");
|
|
type = "double";
|
|
suffix = "";
|
|
#endif
|
|
|
|
/* infinity */
|
|
write_header_comment (file,"the floating point infinity");
|
|
|
|
/* try the different infinity constants until one works */
|
|
for (i=0; i < sizeof(inf)/sizeof(char*); i++) {
|
|
f = xfopen ("ctest.c","wt");
|
|
fprintf (f,
|
|
"#include <stdio.h>\n"
|
|
"#define SHARED_CONFIG_H_INCLUDED_FROM_DEFINING_FILE 1\n"
|
|
SETUP_SHLIB_DEFS
|
|
"%s\n"
|
|
"%s\n"
|
|
"%s\n"
|
|
"int main() {\n"
|
|
" if (dInfinity > 1e10%s && -dInfinity < -1e10%s &&\n"
|
|
" -dInfinity < dInfinity) {\n"
|
|
" FILE *f = fopen (\"data\",\"wt\");\n"
|
|
" fprintf (f,\"foo\\n\");\n"
|
|
" fclose (f);\n"
|
|
" }\n"
|
|
" return 0;\n"
|
|
"}\n"
|
|
,inc[i],inf[i],decl[i],suffix,suffix);
|
|
fclose (f);
|
|
delete_file ("data");
|
|
compile ("ctest.exe","ctest.c");
|
|
run ("ctest.exe");
|
|
if (file_exists ("data")) {
|
|
fprintf (file,"#define DINFINITY_DECL %s\n",decl[i]);
|
|
fprintf (file,"%s\n\n",inf[i]);
|
|
delete_file ("ctest.c");
|
|
delete_file ("ctest.exe");
|
|
delete_file ("data");
|
|
return;
|
|
}
|
|
}
|
|
|
|
fatal_error ("can't determine dInfinity constant");
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
FILE *file;
|
|
|
|
if (argc < 4 || argc > 5)
|
|
fatal_error ("configurator expects 3 or 4 arguments");
|
|
compile_cmd_line = argv[2];
|
|
delete_cmd_line = argv[3];
|
|
if (argc >= 5) run_prefix = argv[4];
|
|
|
|
/* check some defines we should have been compiled with */
|
|
#if !defined(dSINGLE) && !defined(dDOUBLE)
|
|
fatal_error ("you must set PRECISION to either SINGLE or DOUBLE");
|
|
#endif
|
|
|
|
file = xfopen (argv[1],"wt");
|
|
fprintf (file,config_h_part1);
|
|
get_all_standard_headers (file);
|
|
fprintf (file,config_h_part2);
|
|
check_if_this_is_a_pentium (file);
|
|
get_ODE_integer_typedefs (file);
|
|
get_ODE_float_stuff (file);
|
|
fprintf (file,config_h_footer);
|
|
fclose (file);
|
|
|
|
printf ("\n*** configurator succeeded ***\n\n");
|
|
return 0;
|
|
}
|