Files
ogdf/makeMakefile.py
2015-12-19 03:26:49 +01:00

474 lines
15 KiB
Python

#!/usr/bin/env python
# Make Makefile
#
# October 2012
# Markus Chimani, [email protected]
# Carsten Gutwenger, [email protected]
#########################################################
# use Python 3 print function on both Python 2.x and Python 3.x
from __future__ import print_function
import os, sys, fnmatch, posixpath, shutil, subprocess
# Simple hack for using "configparser" on both Python 2 and 3
if sys.hexversion > 0x03000000:
import configparser
else:
import ConfigParser
configparser = ConfigParser
class versionclass:
def call(self):
return '$(' + self.var + ')'
def library(self):
return self.call() + '/' + libName
def sharedLibrary(self):
return self.call() + '/' + sharedlibName
def objects(self):
return '$(' +self.var + '_OBJS)'
def path(self):
return '_' + self.var
def coinLibrary(self):
return self.call() + '/' + coinLibName
def coinSharedLibrary(self):
return self.call() + '/' + coinSharedLibName
def coinName(self):
return coinLibName[3:coinLibName.find('.')]
def coinSharedName(self):
return coinSharedLibName[3:coinSharedLibName.find('.')]
def coinObjects(self):
return '$(' +self.var + '_COIN_OBJS)'
def bailout(msg):
print(msg)
print('Please use the original makeMakefile.config as a template')
sys.exit()
def loadConfig(sect, key, noError = False):
if config.has_option(sect, key):
v = config.get(sect, key)
print(' [', sect, ']', key, '=', v)
return v
else:
if noError:
return None
else:
bailout('Option "' + key + '" in section "' + sect + '" is missing')
def checkSolver(name, defSolver, extSolvers):
if(name == defSolver):
return True
for s in extSolvers:
s = s.strip()
if(name == s):
return True
return False
#########################################################
# LOAD CONFIGURATION
config = configparser.ConfigParser()
print('Loading makeMakefile.config...')
try:
config.readfp(open('makeMakefile.config'))
except IOError:
bailout('makeMakefile.config not found')
if not config.has_section('GENERAL'):
bailout('Section "GENERAL" is missing')
if not config.has_section('OGDF'):
bailout('Section "OGDF" is missing')
if not config.has_section('VERSIONS'):
bailout('Section "VERSIONS" is missing')
if not config.has_section('COIN'):
bailout('Section "COIN" is missing')
compilerCommand = loadConfig('GENERAL', 'compilerCommand')
compilerFlags = loadConfig('GENERAL', 'compilerParams')
libCommand = loadConfig('GENERAL', 'libCommand')
sharedlibCommand = loadConfig('GENERAL', 'sharedlibCommand')
rmCommand = loadConfig('GENERAL', 'rmCommand')
mkdirCommand = loadConfig('GENERAL', 'mkdirCommand')
ranlibCommand = loadConfig('GENERAL', 'ranlibCommand', True)
installPrefix = loadConfig('GENERAL', 'installPrefix', True)
sharedLib = loadConfig('GENERAL', 'sharedLib').startswith('t')
libName = loadConfig('OGDF', 'libName')
sharedlibName = loadConfig('OGDF', 'sharedlibName')
includeLegacyCode = loadConfig('OGDF', 'includeLegacyCode').startswith('t')
memoryManager = loadConfig('OGDF', 'memoryManager', True)
# defines for auto generated config_autogen.h header file
config_defines = ''
gccMessageLength = loadConfig('GENERAL', 'gccMessageLength', True)
if gccMessageLength:
compilerFlags = '-fmessage-length=' + gccMessageLength + ' ' + compilerFlags
libs = ''
if sharedLib:
config_defines += '#define OGDF_DLL\n'
if sys.platform == 'win32' or sys.platform == 'cygwin':
libs += ' -lpsapi'
else:
compilerFlags += ' -fPIC'
if memoryManager:
config_defines += '#define ' + memoryManager + '\n'
addIncludes = ''
useCoin = loadConfig('COIN', 'useCoin').startswith('t')
addOsiCpx = False
addOsiGrb = False
if useCoin:
shutil.copyfile('config/coinstuff/config.h', 'include/coin/config.h')
coinLibName = loadConfig('COIN', 'libName')
coinSharedLibName = loadConfig('COIN', 'sharedlibName')
defaultSolver = loadConfig('COIN', 'defaultSolver')
externalSolvers = loadConfig('COIN', 'externalSolvers').split(';')
solverIncludes = loadConfig('COIN', 'solverIncludes').split(';')
solverLDFlags = loadConfig('COIN', 'solverLDFlags')
addOsiCpx = checkSolver('CPX', defaultSolver, externalSolvers)
addOsiGrb = checkSolver('GRB', defaultSolver, externalSolvers)
config_defines += '#define USE_COIN\n'
config_defines += '#define COIN_OSI_' + defaultSolver + '\n'
for s in externalSolvers:
s = s.strip();
if s != '':
config_defines += '#define OSI_' + s.strip() + '\n'
for p in solverIncludes:
p = p.strip()
if p != '':
addIncludes += '-I' + p + ' '
if sharedLib and (sys.platform == 'win32' or sys.platform == 'cygwin'):
libs += ' -l' + v.coinSharedName()
ogdfFlags = '-I./include ' + addIncludes
coinFlags = '$(COIN_INSTALL_DEFINES) -I./include/coin ' + addIncludes
if sharedLib:
ogdfFlags += ' -DOGDF_INSTALL'
versions = []
V = config.items('VERSIONS')
if len(V) == 0:
bailout('Versions missing')
else:
for ve in V:
v = versionclass()
v.var, v.params = ve
print(' [ VERSIONS ] Name:', v.var, ', Cmd:',v.params)
versions.append(v)
print('Resulting compiler call (OGDF):', ' '.join([compilerCommand, compilerFlags, ogdfFlags]))
if useCoin:
print('Resulting compiler call (COIN):', ' '.join([compilerCommand, compilerFlags, coinFlags]))
print('Finished loading makeMakefile.config')
#########################################################
# ANALYZE & GENERATE
print('Generating config_autogen.h ...')
config_autogen = open('include/ogdf/internal/config_autogen.h','w')
config_autogen.write('//\n')
config_autogen.write('// This file has been automatically generated by makeMakefile.py\n')
config_autogen.write('//\n')
config_autogen.write('// Do not change this file manually, instead reconfigure OGDF!\n')
config_autogen.write('\n')
config_autogen.write(config_defines)
config_autogen.close()
if installPrefix:
print('Generating ogdf.pc ...')
pc = open('ogdf.pc', 'w')
pc.write('prefix=' + installPrefix + '\n')
pc.write('exec_prefix=${prefix}\n')
pc.write('includedir=${prefix}/include\n')
pc.write('libdir=${exec_prefix}/lib\n\n')
pc.write('Name: OGDF\n')
pc.write('Description: Open Graph Drawing Framework\n')
pc.write('URL: http://ogdf.net/\n')
pc.write('Version: ')
version_h = open('include/ogdf/internal/version.h')
for line in version_h:
if line.startswith('#define OGDF_VERSION '):
pc.write(line[22:line.find('"', 22)])
version_h.close()
pc.write('\n')
pc.write('Cflags: -I${includedir}\n')
pc.write('Libs: -L${libdir} -lOGDF')
if useCoin:
if sharedLib:
pc.write(' -l' + v.coinSharedName())
else:
pc.write(' -l' + v.coinName())
pc.write('\n')
pc.close()
print('Analyzing sources & generating Makefile...')
makefile = open('Makefile','w')
# add header
header = open('Makefile.header')
headercontent = header.read()
header.close()
makefile.write(headercontent)
# define general variables
makefile.write('CC = ' + compilerCommand + '\n')
makefile.write('CXXFLAGS = ' + compilerFlags + '\n')
makefile.write('OGDFFLAGS = ' + ogdfFlags + '\n')
makefile.write('COINFLAGS = ' + coinFlags + '\n')
if ranlibCommand:
makefile.write('RANLIB = ' + ranlibCommand + '\n')
makefile.write('RM = ' + rmCommand + '\n')
makefile.write('AR = ' + libCommand + '\n')
makefile.write('LD = ' + sharedlibCommand + '\n')
makefile.write('MKDIR = ' + mkdirCommand + '\n')
# define release & debug
for v in versions:
makefile.write(v.var + ' = ' + v.path() + '\n')
makefile.write('CXXFLAGS_' + v.var + ' = ' + v.params + '\n')
makefile.write('\n');
# just the def. nothing happens yet
def Walk(curdir):
objs = []
names = os.listdir(curdir)
names.sort()
for name in names:
# OGDF ignores
if name.startswith('.') or name.startswith('_') or (name=='legacy' and not includeLegacyCode):
continue
# COIN ignores
if (name == 'OsiCpxSolverInterface.cpp' or name == 'OsiCpxSolverInterface.hpp') and not addOsiCpx:
continue
if (name == 'OsiGrbSolverInterface.cpp' or name == 'OsiGrbSolverInterface.hpp') and not addOsiGrb:
continue
fullname = posixpath.normpath(posixpath.join(curdir, name))
if os.path.isdir(fullname) and not os.path.islink(fullname):
if name != 'abacus' or useCoin == True:
objs = objs + Walk(fullname)
else:
for pat in [ '*.c', '*.cpp' ]:
if fnmatch.fnmatch(name, pat):
objfullname = fullname[:-len(pat)+2] + 'o'
objs.append(objfullname)
targetAndDepend = subprocess.check_output(' '.join([compilerCommand, compilerFlags, ogdfFlags, '-MM', fullname]), shell=True)
for v in versions:
# print target&depend: add full path spec, incl. version & ignore extra line
path = v.call() + '/' +fullname[:-len(name)]
makefile.write(path + targetAndDepend[:-1] + '\n')
# ensure folder
makefile.write('\t$(MKDIR) ' + v.call() + '/' + fullname[:-len(name)-1] + '\n')
# what to do: call the compiler
makefile.write('\t$(CC) $(CXXFLAGS) $(OGDFFLAGS) $(CXXFLAGS_' + v.var + ') -o $@ -c ' + fullname + '\n\n')
# pattern found: don't try other suffix
break
return objs
def WalkCoin(curdir):
objs = []
names = os.listdir(curdir)
names.sort()
for name in names:
# OGDF ignores
if name.startswith('.') or name.startswith('_') or (name=='legacy' and not includeLegacyCode):
continue
# COIN ignores
if (name == 'OsiCpxSolverInterface.cpp' or name == 'OsiCpxSolverInterface.hpp') and not addOsiCpx:
continue
if (name == 'OsiGrbSolverInterface.cpp' or name == 'OsiGrbSolverInterface.hpp') and not addOsiGrb:
continue
fullname = posixpath.normpath(posixpath.join(curdir, name))
if os.path.isdir(fullname) and not os.path.islink(fullname):
if name != 'abacus' or useCoin == True:
objs = objs + WalkCoin(fullname)
else:
for pat in [ '*.c', '*.cpp' ]:
if fnmatch.fnmatch(name, pat):
objfullname = fullname[:-len(pat)+2] + 'o'
if not name.startswith('unitTest'): #conflict if in library!
objs.append(objfullname)
# skip .h dependency check here
for v in versions:
path = v.call() + '/' +objfullname
makefile.write(path + ': ' + fullname + '\n')
# ensure folder
makefile.write('\t$(MKDIR) ' + v.call() + '/' + fullname[:-len(name)-1] + '\n')
# what to do: call the compiler
makefile.write('\t$(CC) $(CXXFLAGS) $(COINFLAGS) $(CXXFLAGS_' + v.var + ') -o $@ -c ' + fullname + '\n\n')
# pattern found: don't try other suffix
break
return objs
# OGDF
objs = Walk('./src/ogdf')
# List all Objs for use in lib-generation and clear
for v in versions:
makefile.write(v.objects()[2:-1] + ' = \\\n')
for o in objs:
makefile.write('\t' + v.call() + '/' + o + ' \\\n')
makefile.write('\n')
# Coin
if useCoin:
objsCoin = WalkCoin('./src/coin')
# List all Objs for use in lib-generation and clear
for v in versions:
makefile.write(v.coinObjects()[2:-1] + ' = \\\n')
for o in objsCoin:
makefile.write('\t' + v.call() + '/' + o + ' \\\n')
makefile.write('\n')
# generate test binary targets
makefile.write('\n#######################################################')
makefile.write('\n# test binary targets\n\n')
objsTest = Walk('./test')
for v in versions:
libdependencies = ''
if sharedLib:
if useCoin:
libdependencies += ' ' + v.coinSharedLibrary()
libdependencies += ' ' + v.sharedLibrary()
else:
if useCoin:
libdependencies += ' ' + v.coinLibrary()
libdependencies += ' ' + v.library()
makefile.write('test/test-' + v.var + ': ' + ' '.join([v.call() + '/' + x for x in objsTest]) + libdependencies + '\n')
makefile.write('\t$(CC) -o $@ $^ -pthread -L' + v.call() + ' -lOGDF')
if useCoin:
if sharedLib:
makefile.write(' -l' + v.coinSharedName() + ' ' + solverLDFlags)
else:
makefile.write(' -l' + v.coinName() + ' ' + solverLDFlags)
makefile.write('\n\n')
# generate alls and cleans etc...
for v in versions:
makefile.write('\n#######################################################')
makefile.write('\n# all, clean, etc. for ' + v.var + '\n\n')
makefile.write('.PHONY: ' + v.var + ' install' + v.var + ' clean' + v.var + ' clean' + v.var + '-coin\n\n')
if sharedLib:
if useCoin:
makefile.write(v.coinSharedLibrary() + ': ' + v.coinObjects() + '\n')
makefile.write('\t$(LD) -shared -o ' + v.coinSharedLibrary() + ' ' + v.coinObjects() + '\n\n')
makefile.write(v.sharedLibrary() + ': ' + v.objects() + '\n')
makefile.write('\t$(LD) -shared -o ' + v.sharedLibrary() + ' ' + v.objects() + ' ' + libs + ' $(LIBS)\n\n')
makefile.write(v.var + ': ' + v.sharedLibrary())
if useCoin:
makefile.write(' ' + v.coinSharedLibrary())
makefile.write(' test/test-' + v.var + '\n\n')
else:
if useCoin:
makefile.write(v.coinLibrary() + ': ' + v.coinObjects() + '\n')
makefile.write('\t$(AR) -r ' + v.coinLibrary() + ' ' + v.coinObjects() + '\n')
if ranlibCommand:
makefile.write('\t$(RANLIB) ' + v.coinLibrary() + '\n')
makefile.write('\n')
makefile.write(v.library() + ': ' + v.objects() + '\n')
makefile.write('\t$(AR) -r ' + v.library() + ' ' + v.objects() + ' $(LIBS)\n')
if ranlibCommand:
makefile.write('\t$(RANLIB) ' + v.library() + '\n')
makefile.write('\n')
makefile.write(v.var + ': ' + v.library())
if useCoin:
makefile.write(' ' + v.coinLibrary())
makefile.write(' test/test-' + v.var + '\n\n')
makefile.write('clean' + v.var + ':\n')
# makefile.write('\t$(RM) ' + v.objects() + ' ' + v.library() + '\n\n')
makefile.write('\t$(RM) ' + v.call() + ' test/test-' + v.var + '\n\n')
if useCoin:
makefile.write('clean' + v.var + '-coin:\n')
makefile.write('\t$(RM) ' + v.coinLibrary() + ' ' + v.coinSharedLibrary() + ' ' + v.call() +'/src/coin\n\n')
if installPrefix:
makefile.write('install' + v.var + ':\n')
makefile.write('\tinstall -d $(DESTDIR)' + installPrefix + '/lib\n')
if sharedLib:
makefile.write('\tinstall -m 0644 ' + v.sharedLibrary() + ' $(DESTDIR)' + installPrefix + '/lib/\n')
else:
makefile.write('\tinstall -m 0644 ' + v.library() + ' $(DESTDIR)' + installPrefix + '/lib/\n')
if useCoin:
if sharedLib:
makefile.write('\tinstall -m 0644 ' + v.coinSharedLibrary() + ' $(DESTDIR)' + installPrefix + '/lib/\n')
else:
makefile.write('\tinstall -m 0644 ' + v.coinLibrary() + ' $(DESTDIR)' + installPrefix + '/lib/\n')
makefile.write('\n')
def InstallHeaders(curdir, makefile, installPrefix):
makefile.write('\tinstall -d $(DESTDIR)' + installPrefix + '/' + curdir + '\n')
names = os.listdir(curdir)
for name in names:
filename = curdir + '/' + name
if (os.path.isdir(filename)):
InstallHeaders(filename, makefile, installPrefix)
elif name.endswith('.h') or name.endswith('.hpp'):
makefile.write('\tinstall -m 0644 ' + filename + ' $(DESTDIR)' + installPrefix + '/' + curdir + '\n')
if installPrefix:
makefile.write('.PHONY: install-headers install-pkgconfig\n')
makefile.write('install: installrelease install-headers install-pkgconfig\n\n')
makefile.write('install-headers:\n')
InstallHeaders('include/ogdf', makefile, installPrefix)
if useCoin:
InstallHeaders('include/coin', makefile, installPrefix)
makefile.write('\ninstall-pkgconfig: ogdf.pc\n')
makefile.write('\tinstall -d $(DESTDIR)' + installPrefix + '/lib/pkgconfig\n')
makefile.write('\tinstall -m 0644 ogdf.pc $(DESTDIR)' + installPrefix + '/lib/pkgconfig\n')
makefile.write('\ndistclean: clean-doc')
for v in versions:
makefile.write(' clean' + v.var)
makefile.write('\n\t$(RM) Makefile ogdf.pc include/ogdf/internal/config_autogen.h include/coin/config.h\n')
makefile.close()
print('Makefile generated')