#!/usr/bin/python # # A simple Python script that mimics autoconf # import os import sys import platform # Project name PROJ = "MirrorCity" # Version number (major.minor.release) VERSION = "0.0.1" # Default values PREFIX = "/usr/local" DATADIR = None SYSCONFDIR = None VERBOSE = 0 MODE = "release" COMPILER = os.getenv ("COMPILER", "gcc") CFLAGS = os.getenv ("CFLAGS", "") CXXFLAGS = os.getenv ("CXXFLAGS", "") LDFLAGS = os.getenv ("LDFLAGS", "") CONFIG_H = ["/* This file has been automatically generated, do not modify", " as it will be overwritten next time you run configure! */", ""] CONFIG_MAK=["# This file has been automatically generated, do not modify", "# as it will be overwritten next time you run configure!", ""] DEFS = "" LIBS = "" def help (): print """ This script helps you to configure this project to build on your operating system The following switches are available: --prefix=DIR Set the base prefix for installation/execution --sysconfdir=DIR Set the system-wide directory for configuration files --datadir=DIR Set the system-wide directory for data files --verbose Display verbosely the detection process --mode=MODE Use given compilation mode by default (debug, release) --compiler=COMPILER Use the respective compiler (supported: gcc, cl) --cflags=CFLAGS Additional compiler flags for C --cxxflags=CXXFLAGS Additional compiler flags for C++ --ldflags=LDFLAGS Additional linker flags The following environment variables affect the configure process: COMPILER The compiler suite to use (default: $COMPILER) NOTE: a file named build/mak/\$COMPILER.mak must exist! CFLAGS Additional compilation flags for C CXXFLAGS Additional compilation flags for C++ LDFLAGS Additional linker flags """ sys.exit (1) def remove (filename): try: os.remove (filename) except: pass def add_config_h (macro, val = "1"): global CONFIG_H CONFIG_H.append ("#define %s %s" % (macro, val)) def add_config_mak (macro, val = "1"): global CONFIG_MAK CONFIG_MAK.append ("%s=%s" % (macro, val)) def check_started (text): print text.ljust (42), "...", def check_finished (res): print res def check_compile (srcf, outf, cflags = ""): global COMPILER,VERBOSE, DEVNULL cmd = COMPILER + " -c " + srcf + " -o " + outf + " " + cflags suffix = " >&" + DEVNULL if VERBOSE == 1: suffix = "" print cmd fd = os.popen (cmd + suffix) return fd.close () == None def check_compile_and_link (srcf, outf, cflags = "", ldflags = ""): global COMPILER,VERBOSE, DEVNULL cmd = COMPILER + " " + srcf + " -o " + outf + " " + cflags + " " + ldflags suffix = " >&" + DEVNULL if VERBOSE == 1: suffix = "" print cmd fd = os.popen (cmd + suffix) return fd.close () == None def write_to_file (filename, content): fd = open (filename, "w") fd.write (content) fd.close () def check_cflags (cflags): global DEFS check_started ("Checking if compiler supports " + cflags) write_to_file ("conftest.c", "int main () { }"); if check_compile ("conftest.c", "conftest" + OBJ, cflags = ""): check_finished ("Yes") if DEFS != "": DEFS = DEFS + " " DEFS = DEFS + cflags elif requiredtxt: check_finished ("No") remove ("conftest.c") remove ("conftest" + OBJ) def check_library (lib, funcname, cflags = "", libs = None, requiredtxt = None): global PROJ, EXE, DEFS, LIBS check_started ("Checking for library " + lib) if not libs: libs = "-l" + lib write_to_file ("conftest.c", """ extern void %s (); int main () { void (*x) () = %s; return 0; } """ % (funcname, funcname)); if check_compile_and_link ("conftest.c", "conftest" + EXE, cflags, libs): check_finished ("OK") add_config_h ("HAVE_LIB" + lib.upper ()) if cflags != "": if DEFS != "": DEFS = DEFS + " " DEFS = DEFS + cflags if LIBS != "": LIBS = LIBS + " " LIBS = LIBS + libs rc = True elif requiredtxt: check_finished ("FAILED") print """ This library is required to build %s, since %s Aborting""" % (PROJ, requiredtxt) remove ("conftest.c") remove ("conftest" + EXE) sys.exit (1) else: check_finished ("NOT FOUND") rc = False remove ("conftest.c") remove ("conftest" + EXE) return rc def check_header (hdr, cflags = "", requiredtxt = None): global DEFS, OBJ check_started ("Checking for header file " + hdr) write_to_file ("conftest.c", """ #include <%s> """ % hdr); if check_compile ("conftest.c", "conftest" + OBJ, cflags): check_finished ("OK") add_config_h ("HAVE_" + hdr.replace (".", "_").upper ()) if cflags != "": if DEFS != "": DEFS = DEFS + " " DEFS = DEFS + cflags rc = True elif requiredtxt: check_finished ("FAILED") print """ This header file is required to build %s, since %s Aborting """ % (PROJ, requiredtxt) remove ("conftest.c") remove ("conftest" + OBJ) sys.exit (1) else: check_finished ("NOT FOUND") rc = False remove ("conftest.c") remove ("conftest" + OBJ) return rc def check_gmake (req_maj, req_min): global DEVNULL check_started ("Checking the version of GNU Make") try: fd = os.popen ("make --version 2>" + DEVNULL) line = fd.readline () fd.close () # transform the string to an array like ['3', '80'] line = line.split () [-1].split ('.') if line[0] < req_maj or (line[0] == req_maj and line [1] < req_min): check_finished ("FAILED") print "GNU Make version %s.%s or later is required!" % (req_maj, req_min) sys.exit (1) check_finished ("%s.%s, OK" % (line [0], line [1])) except: check_finished ("FAILED") print "GNU Make is required to build this project" sys.exit (1) def update_file (filename, content): try: fd = open (filename, "r") old_content = fd.read () fd.close () except: old_content = None if content != old_content: write_to_file (filename, content) pass def pkgconfig (prog, args, lib = None): global DEF_PKGCONFIG cmd = prog; if lib: cmd = cmd + " " + lib cmd = cmd + " --" + args + " 2>" + DEVNULL fd = os.popen (cmd) line = " ".join (fd.readlines ()).strip () if fd.close () == None: return line if not lib: lib = prog.replace ("_config", "").replace ("-config", "") if lib in DEF_PKGCONFIG: pkg = DEF_PKGCONFIG [lib] if args in pkg: return args [pkg] return "" def link_lib (path, library): global COMPILER if COMPILER == "cl": return "-libpath:" + path + " " + ".lib".join (library) + ".lib" # gcc: -L ../.. -lblah return "-L" + path + " -l" + " -l".join (library) #------------------------------------------------------------------------------# OBJ = ".o" if os.name == "posix": PLATFORM = "posix" DEVNULL = "/dev/null" EXE = "" elif os.name == "nt" or os.name == "nt": PLATFORM = "windows" DEVNULL = "nul" EXE = ".exe" OBJ = ".o" else: print "Unknown operating system: " + os.name sys.exit (1) add_config_h ("PLATFORM_" + PLATFORM.upper ()) add_config_mak ("PLATFORM", PLATFORM) ARCH = platform.machine () if ARCH [0] == "i" and ARCH [2:4] == "86": ARCH="x86" elif ARCH [:6] == "x86_64": ARCH="x86_64" else: print "Unsupported architecture: " + ARCH add_config_h ("ARCH_" + ARCH.upper ()) add_config_mak ("ARCH", ARCH) for opt in sys.argv [1:]: if opt == "--help" or opt == "-h": help () elif opt [:9] == "--prefix=": PREFIX = opt [9:].strip () elif opt [:13] == "--sysconfdir=": SYSCONFDIR = opt [13:].strip () elif opt [:10] == "--datadir=": DATADIR = opt [10:].strip () elif opt == "--verbose" or opt == "-v": VERBOSE = 1 elif opt [:7] == "--mode=": MODE = opt[7:].strip () elif opt [:11] == "--compiler=": COMPILER = opt[11:].strip () elif opt [:9] == "--cflags=": CFLAGS = opt[9:].strip () elif opt [:11] == "--cxxflags=": CXXFLAGS = opt[11:].strip () elif opt [:10] == "--ldflags=": LDFLAGS = opt[10:].strip () else: print "Unrecognized command-line argument:", opt sys.exit (1) if not SYSCONFDIR: SYSCONFDIR = PREFIX + "/etc/" + PROJ if not DATADIR: DATADIR = PREFIX + "/share/" + PROJ add_config_h ("CONF_PREFIX", '"' + PREFIX + '"') add_config_mak ("CONF_PREFIX", PREFIX + '/') add_config_h ("CONF_SYSCONFDIR", '"' + SYSCONFDIR + '"') add_config_mak ("CONF_SYSCONFDIR", SYSCONFDIR + '/') add_config_h ("CONF_DATADIR", '"' + DATADIR + '"') add_config_mak ("CONF_DATADIR", DATADIR + '/') add_config_h ("CONF_VERSION", '"' + VERSION + '"') add_config_mak ("CONF_VERSION", VERSION) check_gmake (3, 80) # Default library cflags/locations DEF_PKGCONFIG = {} if PLATFORM == "windows": DEF_PKGCONFIG = { "OGRE": { "cflags": "-I../../OgreSDK/include", "ldflags": link_lib ("../../OgreSDK/lib", ["OgreMain"]) }, "sdl": { "cflags": "-I../../SDL/include", "ldflags": link_lib ("../../SDL/lib", ["SDL"]) }, "mysql": { "cflags": "-I../../MySQL/include", "ldflags": link_lib ("../../MySQL/lib", ["mysqlclient", "z", "crypt", "nsl"]) }, "zziplib": { "cflags": "-I../../ZZipLib/include", "ldflags": link_lib ("../../ZZipLib/lib", ["zzip", "z"]) } } if COMPILER == "cl": ogre_func = "" cegui_func = "" OBJ = ".obj" else: ogre_func = "_ZN4Ogre4Root10saveConfigEv" cegui_func = "_ZTSN5CEGUI6WindowE" check_cflags ("-Wno-non-virtual-dtor") check_library ("OGRE", ogre_func, pkgconfig ("pkg-config", "cflags", "OGRE"), pkgconfig ("pkg-config", "libs", "OGRE"), "this is the 3D engine") check_library ("CEGUI", cegui_func, pkgconfig ("pkg-config", "cflags", "CEGUI"), pkgconfig ("pkg-config", "libs", "CEGUI"), "this is the windowing library") check_library ("SDL", "SDL_Init", pkgconfig ("sdl-config", "cflags"), pkgconfig ("sdl-config", "libs"), "it handles input and sound") check_library ("MySQL", "mysql_query", pkgconfig ("mysql_config", "cflags"), pkgconfig ("mysql_config", "libs"), "it handles database management") check_library ("zlib", "compress", "", "-lz", "it handles data compression and decompression") check_library ("pthread", "pthread_create", "", "-lpthread", PROJ + " uses threads") check_library ("zziplib", "zzip_open", pkgconfig ("pkg-config", "cflags", "zziplib"), pkgconfig ("pkg-config", "libs", "zziplib"), "it handles ZIP archive management") #check_library ("ssl", "BN_cmp") check_library ("compat", "ftime") if not check_library ("ncurses", "tgetent"): check_library ("termcap", "tgetent") check_header ("endian.h") add_config_mak ("COMPILER", COMPILER) add_config_mak ("DEFS", DEFS) add_config_mak ("CFLAGS", CFLAGS + ' $(DEFS)') add_config_mak ("CXXFLAGS", CXXFLAGS + ' $(DEFS)') add_config_mak ("LDFLAGS", LDFLAGS) add_config_mak ("LDLIBS", LIBS) add_config_mak ("MODE", MODE) update_file ("include/" + PLATFORM + "/config.h", "\n".join (CONFIG_H) + "\n") update_file ("config.mak", "\n".join (CONFIG_MAK) + "\n")