0% found this document useful (0 votes)
70 views30 pages

CDN Uwsgi

This document describes the build system used for uWSGI. It defines variables for the operating system, CPU, and version being built. It also defines functions for compiling code, checking features, and building the uWSGI binary using multiple threads to improve compilation speed when multiple CPU cores are available. The build system collects information about the configuration and features that were detected or enabled during compilation.

Uploaded by

Suhail Ahmad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
70 views30 pages

CDN Uwsgi

This document describes the build system used for uWSGI. It defines variables for the operating system, CPU, and version being built. It also defines functions for compiling code, checking features, and building the uWSGI binary using multiple threads to improve compilation speed when multiple CPU cores are available. The build system collects information about the configuration and features that were detected or enabled during compilation.

Uploaded by

Suhail Ahmad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 30

# uWSGI build system

uwsgi_version = '2.0.19.1'
import platform
import os
import re
import time
uwsgi_os = platform.uname()[0]
uwsgi_os_k = re.split('[-+_]', platform.uname()[2])[0]
uwsgi_os_v = platform.uname()[3]
uwsgi_cpu = platform.uname()[4]

import sys
import subprocess
from threading import Thread,Lock
from optparse import OptionParser

try:
from queue import Queue
except:
from Queue import Queue

from distutils import sysconfig

try:
import ConfigParser
except:
import configparser as ConfigParser

try:
from shlex import quote
except ImportError:
from pipes import quote

PY3 = sys.version_info[0] == 3

if uwsgi_os == 'Darwin':
GCC = os.environ.get('CC', 'clang')
else:
GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
if not GCC:
GCC = 'gcc'

def get_preprocessor():
if 'clang' in GCC:
return 'clang -xc core/clang_fake.c'
return 'cpp'

CPP = os.environ.get('CPP', get_preprocessor())

try:
CPUCOUNT = int(os.environ.get('CPUCOUNT', -1))
except:
CPUCOUNT = -1

if CPUCOUNT < 1:
try:
import multiprocessing
CPUCOUNT = multiprocessing.cpu_count()
except:
try:
CPUCOUNT = int(os.sysconf('SC_NPROCESSORS_ONLN'))
except:
CPUCOUNT = 1

# force single cpu in cygwin mode


if uwsgi_os.startswith('CYGWIN'):
CPUCOUNT=1

binary_list = []

started_at = time.time()

# this is used for reporting (at the end of the build)


# the server configuration
report = {
'kernel': False,
'execinfo': False,
'ifaddrs': False,
'locking': False,
'event': False,
'timer': False,
'filemonitor': False,
'pcre': False,
'routing': False,
'capabilities': False,
'yaml': False,
'json': False,
'ssl': False,
'xml': False,
'debug': False,
'plugin_dir': False,
'zlib': False,
'ucontext': False,
}

verbose_build = False

def print_compilation_output(default_str, verbose_str):


if verbose_build:
print(verbose_str)
elif default_str is not None:
print(default_str)

compile_queue = None
print_lock = None
thread_compilers = []

def thread_compiler(num):
while True:
(objfile, cmdline) = compile_queue.get()
if objfile:
print_lock.acquire()
print_compilation_output("[thread %d][%s] %s" % (num, GCC, objfile),
"[thread %d] %s" % (num, cmdline))
print_lock.release()
ret = os.system(cmdline)
if ret != 0:
os._exit(1)
elif cmdline:
print_lock.acquire()
print(cmdline)
print_lock.release()
else:
return

def binarize(name):
return name.replace('/', '_').replace('.','_').replace('-','_')

def spcall(cmd):
p = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,stderr=open('uwsgibuild.log','w'))

if p.wait() == 0:
if sys.version_info[0] > 2:
return p.stdout.read().rstrip().decode()
return p.stdout.read().rstrip()
else:
return None

# commodity function to remove -W* duplicates


def uniq_warnings(elements):
new_elements = []
for element in elements:
if element.startswith('-W'):
if not element in new_elements:
new_elements.append(element)
else:
new_elements.append(element)

return new_elements

if uwsgi_version.endswith('-dev') and os.path.exists('%s/.git' %


os.path.dirname(os.path.abspath( __file__ ))):
try:
uwsgi_version += '-%s' % spcall('git rev-parse --short HEAD')
except:
pass

def spcall2(cmd):
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)

if p.wait() == 0:
if sys.version_info[0] > 2:
return p.stderr.read().rstrip().decode()
return p.stderr.read().rstrip()
else:
return None

def test_snippet(snippet):
"""Compile a C snippet to see if features are available at build / link
time."""
if sys.version_info[0] >= 3 or (sys.version_info[0] == 2 and
sys.version_info[1] > 5):
if not isinstance(snippet, bytes):
if PY3:
snippet = bytes(snippet, sys.getdefaultencoding())
else:
snippet = bytes(snippet)
cmd = "{0} -xc - -o /dev/null".format(GCC)
else:
cmd = GCC + " -xc - -o /dev/null"
p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
p.communicate(snippet)
return p.returncode == 0

def has_usable_ucontext():
if uwsgi_os in ('OpenBSD', 'Haiku'):
return False
if uwsgi_os.startswith('CYGWIN'):
return False
if uwsgi_os == 'Darwin' and uwsgi_os_k.startswith('8'):
return False
if uwsgi_cpu[0:3] == 'arm':
return False
# check for ucontext.h functions definitions, musl has only declarations
return test_snippet("""#include <ucontext.h>
int main()
{
ucontext_t uc;
getcontext(&uc);
return 0;
}""")

def spcall3(cmd):
p = subprocess.Popen(cmd, shell=True, stdin=open('/dev/null'),
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
(out, err) = p.communicate()

if p.returncode == 0:
if sys.version_info[0] > 2:
return err.rstrip().decode()
return err.rstrip()
else:
return None

def add_o(x):
if x == 'uwsgi':
x = 'main'
elif x.endswith('.a') or x.endswith('.o'):
return x
x = x + '.o'
return x

def push_print(msg):
if not compile_queue:
print(msg)
else:
compile_queue.put((None, msg))

def push_command(objfile, cmdline):


if not compile_queue:
print_compilation_output("[%s] %s" % (GCC, objfile), cmdline)
ret = os.system(cmdline)
if ret != 0:
sys.exit(1)
else:
compile_queue.put((objfile, cmdline))

def compile(cflags, last_cflags_ts, objfile, srcfile):


source_stat = os.stat(srcfile)
header_stat = os.stat('uwsgi.h')
try:
if os.environ.get('UWSGI_FORCE_REBUILD', None):
raise
if source_stat[8] >= last_cflags_ts:
raise
if header_stat[8] >= last_cflags_ts:
raise
object_stat = os.stat(objfile)
if object_stat[8] <= source_stat[8]:
raise
if object_stat[8] <= header_stat[8]:
raise
for profile in os.listdir('buildconf'):
profile_stat = os.stat('buildconf/%s' % profile)
if object_stat[8] <= profile_stat[8]:
raise
print("%s is up to date" % objfile)
return
except:
pass
cmdline = "%s -c %s -o %s %s" % (GCC, cflags, objfile, srcfile)
push_command(objfile, cmdline)

def build_uwsgi(uc, print_only=False, gcll=None):

global print_lock, compile_queue, thread_compilers

if CPUCOUNT > 1:
print_lock = Lock()
compile_queue = Queue(maxsize=CPUCOUNT)
for i in range(0,CPUCOUNT):
t = Thread(target=thread_compiler,args=(i,))
t.daemon = True
t.start()
thread_compilers.append(t)

if not gcll:
gcc_list, cflags, ldflags, libs = uc.get_gcll()
else:
gcc_list, cflags, ldflags, libs = gcll
if 'UWSGI_EMBED_PLUGINS' in os.environ:
ep = uc.get('embedded_plugins')
if ep:
uc.set('embedded_plugins', ep + ',' +
os.environ['UWSGI_EMBED_PLUGINS'])
else:
uc.set('embedded_plugins', os.environ['UWSGI_EMBED_PLUGINS'])

if uc.get('embedded_plugins'):
ep = uc.get('embedded_plugins').split(',')
epc = "-DUWSGI_DECLARE_EMBEDDED_PLUGINS=\""
eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\""
for item in ep:
# allow name=path syntax
kv = item.split('=')
p = kv[0]
p = p.strip()
if not p or p == 'None':
continue
if p == 'ugreen':
if not report['ucontext']:
continue
epc += "UDEP(%s);" % p
eplc += "ULEP(%s);" % p
epc += "\""
eplc += "\""

cflags.append(epc)
cflags.append(eplc)

if print_only:
print(' '.join(cflags))
sys.exit(0)

if 'APPEND_CFLAGS' in os.environ:
cflags += os.environ['APPEND_CFLAGS'].split()

print("detected CPU cores: %d" % CPUCOUNT)


print("configured CFLAGS: %s" % ' '.join(cflags))

if sys.version_info[0] >= 3:
import binascii
uwsgi_cflags = binascii.b2a_hex('
'.join(cflags).encode('ascii')).decode('ascii')
else:
uwsgi_cflags = ' '.join(cflags).encode('hex')

last_cflags_ts = 0

if os.path.exists('uwsgibuild.lastcflags'):
ulc = open('uwsgibuild.lastcflags','r')
last_cflags = ulc.read()
ulc.close()
if uwsgi_cflags != last_cflags:
os.environ['UWSGI_FORCE_REBUILD'] = '1'
else:
last_cflags_ts = os.stat('uwsgibuild.lastcflags')[8]
ulc = open('uwsgibuild.lastcflags','w')
ulc.write(uwsgi_cflags)
ulc.close()

# embed uwsgi.h in the server binary. It increases the binary size, but will be
very useful
# for various tricks (like cffi integration)
# if possibile, the blob is compressed
if sys.version_info[0] >= 3:
uwsgi_dot_h_content = open('uwsgi.h', 'rb').read()
else:
uwsgi_dot_h_content = open('uwsgi.h').read()
if report['zlib']:
import zlib
# maximum level of compression
uwsgi_dot_h_content = zlib.compress(uwsgi_dot_h_content, 9)
if sys.version_info[0] >= 3:
import binascii
uwsgi_dot_h = binascii.b2a_hex(uwsgi_dot_h_content).decode('ascii')
else:
uwsgi_dot_h = uwsgi_dot_h_content.encode('hex')
open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h);
gcc_list.append('core/dot_h')

# embed uwsgiconfig.py in the server binary. It increases the binary size, but
will be very useful
# if possibile, the blob is compressed
if sys.version_info[0] >= 3:
uwsgi_config_py_content = open('uwsgiconfig.py', 'rb').read()
else:
uwsgi_config_py_content = open('uwsgiconfig.py').read()
if report['zlib']:
import zlib
# maximum level of compression
uwsgi_config_py_content = zlib.compress(uwsgi_config_py_content, 9)
if sys.version_info[0] >= 3:
import binascii
uwsgi_config_py = binascii.b2a_hex(uwsgi_config_py_content).decode('ascii')
else:
uwsgi_config_py = uwsgi_config_py_content.encode('hex')
open('core/config_py.c', 'w').write('char *uwsgi_config_py = "%s";\n' %
uwsgi_config_py);
gcc_list.append('core/config_py')

additional_sources = os.environ.get('UWSGI_ADDITIONAL_SOURCES')
if not additional_sources:
additional_sources = uc.get('additional_sources')
if additional_sources:
for item in additional_sources.split(','):
gcc_list.append(item)

if uc.filename.endswith('coverity.ini'):
cflags.append('-DUWSGI_CFLAGS=\\"\\"')
else:
cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags)
build_date = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:
%S", time.gmtime(build_date)))
post_build = []

push_print("*** uWSGI compiling server core ***")


for file in gcc_list:
objfile = file
if objfile == 'uwsgi':
objfile = 'main'
if not objfile.endswith('.a') and not objfile.endswith('.o'):
if objfile.endswith('.c') or objfile.endswith('.cc') or
objfile.endswith('.m') or objfile.endswith('.go'):
if objfile.endswith('.go'):
cflags.append('-Wno-error')
compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file)
if objfile.endswith('.go'):
cflags.pop()
else:
if objfile == 'core/dot_h':
cflags.append('-g')
compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file +
'.c')
if objfile == 'core/dot_h':
cflags.pop()

if uc.get('embedded_plugins'):
ep = uc.get('embedded_plugins').split(',')

if len(ep) > 0:
push_print("*** uWSGI compiling embedded plugins ***")
for item in ep:
# allows name=path syntax
kv = item.split('=')
if len(kv) > 1:
p = kv[1]
p = p.strip()
if p.startswith('http://') or p.startswith('https://') or
p.startswith('git://') or p.startswith('ssh://'):
git_dir = p.split('/').pop()
if not os.path.isdir(git_dir):
if os.system('git clone %s' % p) != 0:
sys.exit(1)
else:
if os.system('cd %s ; git pull' % git_dir) != 0:
sys.exit(1)
p = git_dir
path = os.path.abspath(p)
else:
p = kv[0]
p = p.strip()
path = 'plugins/%s' % p

if not p or p == 'None':
continue

if p == 'ugreen':
if not report['ucontext']:
continue

path = path.rstrip('/')
up = {}

if os.path.isfile(path):
bname = os.path.basename(path)
# override path
path = os.path.dirname(path)
up['GCC_LIST'] = [bname]
up['NAME'] = bname.split('.')[0]
if not path: path = '.'
elif os.path.isdir(path):
try:
execfile('%s/uwsgiplugin.py' % path, up)
except:
f = open('%s/uwsgiplugin.py' % path)
exec(f.read(), up)
f.close()
else:
print("Error: plugin '%s' not found" % p)
sys.exit(1)

p_cflags = cflags[:]
try:
p_cflags += up['CFLAGS']
except:
pass

if uwsgi_os.startswith('CYGWIN'):
try:
p_cflags.remove('-fstack-protector')
except:
pass

if GCC in ('clang',):
try:
p_cflags.remove('-fno-fast-math')
p_cflags.remove('-ggdb3')
except:
pass

try:
p_cflags.remove('-Wdeclaration-after-statement')
except:
pass

try:
p_cflags.remove('-Werror=declaration-after-statement')
except:
pass

try:
p_cflags.remove('-Wwrite-strings')
except:
pass

try:
p_cflags.remove('-Werror=write-strings')
except:
pass
try:
if up['post_build']:
post_build.append(up['post_build'])
except:
pass

for cfile in up['GCC_LIST']:


if cfile.endswith('.a'):
gcc_list.append(cfile)
elif cfile.endswith('.o'):
gcc_list.append('%s/%s' % (path, cfile))
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and
not cfile.endswith('.go') and not cfile.endswith('.m'):
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile + '.c')
gcc_list.append('%s/%s' % (path, cfile))
else:
if cfile.endswith('.go'):
p_cflags.append('-Wno-error')
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile)
gcc_list.append('%s/%s' % (path, cfile))
for bfile in up.get('BINARY_LIST', []):
try:
binary_link_cmd = "ld -r -b binary -o %s/%s.o %s/%s" %
(path, bfile[1], path, bfile[1])
print(binary_link_cmd)
if os.system(binary_link_cmd) != 0:
raise Exception('unable to link binary file')
for kind in ('start','end'):
objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=%s_
%s %s/%s.o" % (binarize('%s/%s' % (path, bfile[1])), kind, bfile[0], kind, path,
bfile[1])
print(objcopy_cmd)
if os.system(objcopy_cmd) != 0:
raise Exception('unable to link binary file')
gcc_list.append('%s/%s.o' % (path, bfile[1]))
except:
pass

try:
libs += up['LIBS']
except:
pass

if not 'LDFLAGS' in up:


up['LDFLAGS'] = []

if uwsgi_os == 'Darwin':
found_arch = False
sanitized_ldflags = []
for flag in up['LDFLAGS']:
if flag == '-arch':
found_arch = True
continue
if found_arch:
found_arch = False
continue
sanitized_ldflags.append(flag)
ldflags += sanitized_ldflags
else:
ldflags += up['LDFLAGS']

if uc.get('plugins'):

plugins = uc.get('plugins').split(',')
if len(plugins) > 0:
push_print("*** uWSGI building plugins ***")

for p in plugins:
p = p.strip()
push_print("*** building plugin: %s ***" % p)
build_plugin("plugins/%s" % p, uc, cflags, ldflags, libs)

bin_name = os.environ.get('UWSGI_BIN_NAME', uc.get('bin_name'))

if uc.embed_config:
gcc_list.append("%s.o" % binarize(uc.embed_config))
for ef in binary_list:
gcc_list.append("%s.o" % ef)

if compile_queue:
for t in thread_compilers:
compile_queue.put((None, None))
for t in thread_compilers:
t.join()

print("*** uWSGI linking ***")


ldline = "%s -o %s %s %s %s" % (GCC, quote(bin_name), '
'.join(uniq_warnings(ldflags)),
' '.join(map(add_o, gcc_list)), ' '.join(uniq_warnings(libs)))
print(ldline)
ret = os.system(ldline)
if ret != 0:
print("*** error linking uWSGI ***")
sys.exit(1)

print("################# uWSGI configuration #################")


print("")
for report_key in report:
print("%s = %s" % (report_key, report[report_key]))
print("")
print("############## end of uWSGI configuration #############")

print("total build time: %d seconds" % (time.time() - started_at))

if bin_name.find("/") < 0:
bin_name = './' + bin_name
if uc.get('as_shared_library'):
print("*** uWSGI shared library (%s) is ready, move it to a library
directory ***" % bin_name)
else:
print("*** uWSGI is ready, launch it with %s ***" % bin_name)

for pb in post_build:
pb(uc)

def open_profile(filename):
if filename.startswith('http://') or filename.startswith('https://') or
filename.startswith('ftp://'):
wrapped = False
try:
import urllib2
except:
import urllib.request
wrapped = True

if wrapped:
import io
return io.TextIOWrapper(urllib.request.urlopen(filename),
encoding='utf-8')
return urllib2.urlopen(filename)
return open(filename)

class uConf(object):

def __init__(self, filename, mute=False):


global GCC

self.filename = filename
self.config = ConfigParser.ConfigParser()
if not mute:
print("using profile: %s" % filename)

if os.path.exists('uwsgibuild.lastprofile'):
ulp = open('uwsgibuild.lastprofile','r')
last_profile = ulp.read()
ulp.close()
if last_profile != filename:
os.environ['UWSGI_FORCE_REBUILD'] = '1'

ulp = open('uwsgibuild.lastprofile', 'w')


ulp.write(filename)
ulp.close()

if hasattr(self.config, 'read_file'):
self.config.read_file(open_profile(filename))
else:
self.config.readfp(open_profile(filename))
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket',
'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
'core/notify', 'core/mule', 'core/subscription', 'core/stats',
'core/sendfile', 'core/async', 'core/master_checks', 'core/fifo',
'core/offload', 'core/io', 'core/static', 'core/websockets',
'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer',
'core/reader', 'core/writer', 'core/alarm', 'core/cron', 'core/hooks',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons',
'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
'core/queue', 'core/event', 'core/signal', 'core/strings',
'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon', 'core/mount',
'core/metrics', 'core/plugins_builder', 'core/sharedarea',
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie',
'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')
self.gcc_list.append('proto/http')
self.gcc_list.append('proto/fastcgi')
self.gcc_list.append('proto/scgi')
self.gcc_list.append('proto/puwsgi')
self.include_path = []

if 'UWSGI_INCLUDES' in os.environ:
self.include_path += os.environ['UWSGI_INCLUDES'].split(',')

self.cflags = ['-O2', '-I.', '-Wall', '-D_LARGEFILE_SOURCE', '-


D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split() +
self.get('cflags','').split()

report['kernel'] = uwsgi_os

if uwsgi_os == 'Linux':
if uwsgi_cpu != 'ia64':
self.gcc_list.append('lib/linux_ns')
try:
lk_ver = uwsgi_os_k.split('.')
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2])
<= 9:
self.cflags.append('-DOBSOLETE_LINUX_KERNEL')

report['kernel'] = 'Old Linux'


except:
pass

if uwsgi_os == 'GNU':
self.cflags.append('-D__HURD__')

gcc_version = spcall("%s -dumpversion" % GCC)


if not gcc_version and GCC.startswith('gcc'):
if uwsgi_os == 'Darwin':
GCC = 'llvm-' + GCC
else:
GCC = 'gcc'
gcc_version = spcall("%s -dumpversion" % GCC)

try:
add_it = False
cpp_include_list = str(spcall3("%s -v" % CPP)).split("\n")
for line in cpp_include_list:
if line.startswith('#include <...> search starts here:'):
add_it = True
elif line.startswith('End of search list.'):
add_it = False
elif add_it:
self.include_path.append(line.strip().split()[0])

if not self.include_path:
raise
except:
self.include_path = ['/usr/include', '/usr/local/include']

additional_include_paths = self.get('additional_include_paths')
if additional_include_paths:
for ipath in additional_include_paths.split():
self.include_path.append(ipath)

if 'UWSGI_REMOVE_INCLUDES' in os.environ:
for inc in os.environ['UWSGI_REMOVE_INCLUDES'].split(','):
try:
self.include_path.remove(inc)
except:
pass

if not mute:
print("detected include path: %s" % self.include_path)

try:
gcc_version_components = gcc_version.split('.')
gcc_major = int(gcc_version_components[0])
if len(gcc_version_components) > 1:
gcc_minor = int(gcc_version_components[1])
else:
# gcc 5.0 is represented as simply "5"
gcc_minor = 0
except:
raise Exception("you need a C compiler to build uWSGI")
if (sys.version_info[0] == 2) or (gcc_major < 4) or (gcc_major == 4 and
gcc_minor < 3):
self.cflags = self.cflags + ['-fno-strict-aliasing']
# add -fno-strict-aliasing only on python2 and gcc < 4.3
if gcc_major >= 4:
self.cflags = self.cflags + [ '-Wextra', '-Wno-unused-parameter', '-
Wno-missing-field-initializers' ]
if gcc_major == 4 and gcc_minor < 9:
self.cflags.append('-Wno-format -Wno-format-security')

self.ldflags = os.environ.get("LDFLAGS", "").split()


self.libs = ['-lpthread', '-lm', '-rdynamic']
if uwsgi_os in ('Linux', 'GNU', 'GNU/kFreeBSD'):
self.libs.append('-ldl')
if uwsgi_os == 'GNU/kFreeBSD':
self.cflags.append('-D__GNU_kFreeBSD__')
self.libs.append('-lbsd')

# check for inherit option


inherit = self.get('inherit')
if inherit:
if not '/' in inherit:
inherit = 'buildconf/%s' % inherit

if not inherit.endswith('.ini'):
inherit = '%s.ini' % inherit

interpolations = {}
for option in self.config.options('uwsgi'):
interpolations[option] = self.get(option, default='')
iconfig = ConfigParser.ConfigParser(interpolations)
if hasattr(self.config, 'read_file'):
iconfig.read_file(open_profile(inherit))
else:
iconfig.readfp(open_profile(inherit))
for opt in iconfig.options('uwsgi'):
if not self.config.has_option('uwsgi', opt):
self.set(opt, iconfig.get('uwsgi', opt))
elif self.get(opt):
if self.get(opt).startswith('+'):
self.set(opt, iconfig.get('uwsgi', opt) + self.get(opt)
[1:])
elif self.get(opt) == 'null':
self.config.remove_option('uwsgi', opt)

def set(self, key, value):


self.config.set('uwsgi',key, value)

def get(self,key,default=None):
try:
value = self.config.get('uwsgi', key)
if value == "" or value == "false":
return default
return value
except:
if default is not None:
return default
return None

def depends_on(self, what, dep):


for d in dep:
if not self.get(d):
print("%s needs %s support." % (what, d))
sys.exit(1)

def has_include(self, what):


for include in self.include_path:
if os.path.exists("%s/%s" %(include, what)):
return True
return False

def get_gcll(self):

global uwsgi_version

kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']

if 'UWSGI_PROFILE_OVERRIDE' in os.environ:
for item in os.environ['UWSGI_PROFILE_OVERRIDE'].split(';'):
k,v = item.split('=', 1)
self.set(k, v)

if 'UWSGI_AS_LIB' in os.environ:
self.set('as_shared_library', 'true')
self.set('bin_name', os.environ['UWSGI_AS_LIB'])

if self.has_include('ifaddrs.h'):
self.cflags.append('-DUWSGI_HAS_IFADDRS')
report['ifaddrs'] = True

if uwsgi_os in ('FreeBSD', 'DragonFly', 'OpenBSD'):


if self.has_include('execinfo.h') or
os.path.exists('/usr/local/include/execinfo.h'):
if os.path.exists('/usr/local/include/execinfo.h'):
self.cflags.append('-I/usr/local/include')
self.ldflags.append('-L/usr/local/lib')
self.cflags.append('-DUWSGI_HAS_EXECINFO')
self.libs.append('-lexecinfo')
report['execinfo'] = True

if uwsgi_os == 'GNU/kFreeBSD':
if self.has_include('execinfo.h'):
self.cflags.append('-DUWSGI_HAS_EXECINFO')
report['execinfo'] = True

if self.has_include('zlib.h'):
self.cflags.append('-DUWSGI_ZLIB')
self.libs.append('-lz')
self.gcc_list.append('core/zlib')
report['zlib'] = True

if uwsgi_os == 'OpenBSD':
try:
obsd_major = uwsgi_os_k.split('.')[0]
obsd_minor = uwsgi_os_k.split('.')[1]
obsd_ver = int(obsd_major + obsd_minor)
if obsd_ver > 50:
self.cflags.append('-DUWSGI_NEW_OPENBSD')
report['kernel'] = 'New OpenBSD'
except:
pass

if uwsgi_os == 'SunOS':
self.libs.append('-lsendfile')
self.libs.append('-lrt')
self.gcc_list.append('lib/sun_fixes')
self.ldflags.append('-L/lib')
if not uwsgi_os_v.startswith('Nexenta'):
self.libs.remove('-rdynamic')

if uwsgi_os == 'GNU/kFreeBSD':
if self.has_include('kvm.h'):
kvm_list.append('GNU/kFreeBSD')

if uwsgi_os in kvm_list:
self.libs.append('-lkvm')

if uwsgi_os == 'Haiku':
self.libs.remove('-rdynamic')
self.libs.remove('-lpthread')
self.libs.append('-lroot')

if uwsgi_os == 'Darwin':
if uwsgi_os_k.startswith('8'):
self.cflags.append('-DUNSETENV_VOID')
self.cflags.append('-DNO_SENDFILE')
self.cflags.append('-DNO_EXECINFO')
self.cflags.append('-DOLD_REALPATH')
self.cflags.append('-mmacosx-version-min=10.5')
if GCC in ('clang',):
self.libs.remove('-rdynamic')
# compile extras
extras = self.get('extras', None)
if extras:
for extra in extras.split(','):
self.gcc_list.append(extra)

# check for usable ucontext


report['ucontext'] = has_usable_ucontext()

# set locking subsystem


locking_mode = self.get('locking','auto')

if locking_mode == 'auto':
if uwsgi_os == 'Linux' or uwsgi_os == 'SunOS':
locking_mode = 'pthread_mutex'
# FreeBSD umtx is still not ready for process shared locking
# starting from FreeBSD 9 posix semaphores can be shared between
processes
elif uwsgi_os in ('FreeBSD', 'GNU/kFreeBSD'):
try:
fbsd_major = int(uwsgi_os_k.split('.')[0])
if fbsd_major >= 9:
locking_mode = 'posix_sem'
except:
pass
elif uwsgi_os == 'GNU':
locking_mode = 'posix_sem'
elif uwsgi_os == 'Darwin':
locking_mode = 'osx_spinlock'
elif uwsgi_os.startswith('CYGWIN'):
locking_mode = 'windows_mutex'

if locking_mode == 'pthread_mutex':
self.cflags.append('-DUWSGI_LOCK_USE_MUTEX')
# FreeBSD umtx is still not ready for process shared locking
elif locking_mode == 'posix_sem':
self.cflags.append('-DUWSGI_LOCK_USE_POSIX_SEM')
elif locking_mode == 'osx_spinlock':
self.cflags.append('-DUWSGI_LOCK_USE_OSX_SPINLOCK')
elif locking_mode == 'windows_mutex':
self.cflags.append('-DUWSGI_LOCK_USE_WINDOWS_MUTEX')
else:
self.cflags.append('-DUWSGI_IPCSEM_ATEXIT')

if locking_mode == 'auto':
report['locking'] = 'sysv semaphores'
else:
report['locking'] = locking_mode

# set event subsystem


event_mode = self.get('event','auto')

if event_mode == 'auto':
if uwsgi_os == 'Linux':
event_mode = 'epoll'
if uwsgi_os == 'SunOS':
event_mode = 'devpoll'
sun_major, sun_minor = uwsgi_os_k.split('.')
if int(sun_major) >= 5:
if int(sun_minor) >= 10:
event_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD',
'NetBSD', 'DragonFly'):
event_mode = 'kqueue'
elif uwsgi_os.startswith('CYGWIN') or uwsgi_os == 'GNU':
event_mode = 'poll'

if event_mode == 'epoll':
self.cflags.append('-DUWSGI_EVENT_USE_EPOLL')
elif event_mode == 'kqueue':
self.cflags.append('-DUWSGI_EVENT_USE_KQUEUE')
elif event_mode == 'devpoll':
self.cflags.append('-DUWSGI_EVENT_USE_DEVPOLL')
elif event_mode == 'port':
self.cflags.append('-DUWSGI_EVENT_USE_PORT')
elif event_mode == 'poll':
self.cflags.append('-DUWSGI_EVENT_USE_POLL')

report['event'] = event_mode

# set timer subsystem


timer_mode = self.get('timer','auto')

if timer_mode == 'auto':
if uwsgi_os == 'Linux':
k_all = uwsgi_os_k.split('.')
k_base = k_all[0]
k_major = k_all[1]
if len(k_all) > 2:
k_minor = k_all[2]
else:
k_minor = 0
if int(k_base) > 2:
timer_mode = 'timerfd'
elif int(k_minor) >= 25:
timer_mode = 'timerfd'
else:
timer_mode = 'none'

elif uwsgi_os == 'SunOS':


sun_major, sun_minor = uwsgi_os_k.split('.')
if int(sun_major) >= 5:
if int(sun_minor) >= 10:
timer_mode = 'port'

elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD',


'NetBSD', 'DragonFly'):
timer_mode = 'kqueue'

if timer_mode == 'timerfd':
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_TIMERFD')
if not self.has_include('sys/timerfd.h'):
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_TIMERFD_NOINC')
elif timer_mode == 'kqueue':
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_KQUEUE')
elif timer_mode == 'port':
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_PORT')
else:
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_NONE')

report['timer'] = timer_mode

# set filemonitor subsystem


filemonitor_mode = self.get('filemonitor','auto')

if filemonitor_mode == 'auto':
if uwsgi_os == 'Linux':
filemonitor_mode = 'inotify'
elif uwsgi_os == 'SunOS':
sun_major, sun_minor = uwsgi_os_k.split('.')
if int(sun_major) >= 5:
if int(sun_minor) >= 10:
filemonitor_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD',
'NetBSD', 'DragonFly'):
filemonitor_mode = 'kqueue'

if filemonitor_mode == 'inotify':
self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY')
elif filemonitor_mode == 'kqueue':
self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_KQUEUE')
elif filemonitor_mode == 'port':
self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_PORT')
else:
self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_NONE')

report['filemonitor'] = filemonitor_mode

if self.get('malloc_implementation') != 'libc':
if self.get('malloc_implementation') == 'tcmalloc':
self.libs.append('-ltcmalloc')
if self.get('malloc_implementation') == 'jemalloc':
self.libs.append('-ljemalloc')

report['malloc'] = self.get('malloc_implementation')

if self.get('as_shared_library'):
self.ldflags.append('-shared')
# on cygwin we do not need PIC (it is implicit)
if not uwsgi_os.startswith('CYGWIN'):
self.ldflags.append('-fPIC')
self.cflags.append('-fPIC')
self.cflags.append('-DUWSGI_AS_SHARED_LIBRARY')
if uwsgi_os == 'Darwin':
self.ldflags.append('-dynamiclib')
self.ldflags.append('-undefined dynamic_lookup')

if self.get('blacklist'):
self.cflags.append('-DUWSGI_BLACKLIST="\\"%s\\""' %
self.get('blacklist'))

if self.get('whitelist'):
self.cflags.append('-DUWSGI_WHITELIST="\\"%s\\""' %
self.get('whitelist'))
has_pcre = False

# re-enable after pcre fix


if self.get('pcre'):
if self.get('pcre') == 'auto':
pcreconf = spcall('pcre-config --libs')
if pcreconf:
self.libs.append(pcreconf)
pcreconf = spcall("pcre-config --cflags")
self.cflags.append(pcreconf)
self.gcc_list.append('core/regexp')
self.cflags.append("-DUWSGI_PCRE")
has_pcre = True

else:
pcreconf = spcall('pcre-config --libs')
if pcreconf is None:
print("*** libpcre headers unavailable. uWSGI build is
interrupted. You have to install pcre development package or disable pcre")
sys.exit(1)
else:
self.libs.append(pcreconf)
pcreconf = spcall("pcre-config --cflags")
self.cflags.append(pcreconf)
self.gcc_list.append('core/regexp')
self.cflags.append("-DUWSGI_PCRE")
has_pcre = True

if has_pcre:
report['pcre'] = True

if self.get('routing'):
if self.get('routing') == 'auto':
if has_pcre:
self.gcc_list.append('core/routing')
self.cflags.append("-DUWSGI_ROUTING")
report['routing'] = True
else:
self.gcc_list.append('core/routing')
self.cflags.append("-DUWSGI_ROUTING")
report['routing'] = True

if self.has_include('sys/capability.h') and uwsgi_os == 'Linux':


self.cflags.append("-DUWSGI_CAP")
self.libs.append('-lcap')
report['capabilities'] = True

if self.has_include('uuid/uuid.h'):
self.cflags.append("-DUWSGI_UUID")
if uwsgi_os in ('Linux', 'GNU', 'GNU/kFreeBSD') or
uwsgi_os.startswith('CYGWIN') or os.path.exists('/usr/lib/libuuid.so') or
os.path.exists('/usr/local/lib/libuuid.so') or
os.path.exists('/usr/lib64/libuuid.so') or
os.path.exists('/usr/local/lib64/libuuid.so'):
self.libs.append('-luuid')

if self.get('append_version'):
if not self.get('append_version').startswith('-'):
uwsgi_version += '-'
uwsgi_version += self.get('append_version')

if uwsgi_os in ('FreeBSD','GNU/kFreeBSD') and self.has_include('jail.h'):


self.cflags.append('-DUWSGI_HAS_FREEBSD_LIBJAIL')
self.libs.append('-ljail')

self.embed_config = None

if uwsgi_os not in ('Darwin',):


self.embed_config = os.environ.get('UWSGI_EMBED_CONFIG')
if not self.embed_config:
self.embed_config = self.get('embed_config')
if self.embed_config:
binary_link_cmd = "ld -r -b binary -o %s.o %s" %
(binarize(self.embed_config), self.embed_config)
print(binary_link_cmd)
os.system(binary_link_cmd)
self.cflags.append("-DUWSGI_EMBED_CONFIG=_binary_%s_start" %
binarize(self.embed_config))
self.cflags.append("-DUWSGI_EMBED_CONFIG_END=_binary_%s_end" %
binarize(self.embed_config))
embed_files = os.environ.get('UWSGI_EMBED_FILES')
if not embed_files:
embed_files = self.get('embed_files')
if embed_files:
for ef in embed_files.split(','):
ef_parts = ef.split('=')
symbase = None
if len(ef_parts) > 1:
ef = ef_parts[1]
symbase = ef_parts[0]
if os.path.isdir(ef):
for directory, directories, files in os.walk(ef):
for f in files:
fname = "%s/%s" % (directory, f)
binary_link_cmd = "ld -r -b binary -o %s.o %s" %
(binarize(fname), fname)
print(binary_link_cmd)
os.system(binary_link_cmd)
if symbase:
for kind in ('start','end'):
objcopy_cmd = "objcopy --redefine-sym
_binary_%s_%s=_binary_%s%s_%s build/%s.o" % (binarize(fname), kind,
binarize(symbase), binarize(fname[len(ef):]), kind, binarize(fname))
print(objcopy_cmd)
os.system(objcopy_cmd)
binary_list.append(binarize(fname))
else:
binary_link_cmd = "ld -r -b binary -o %s.o %s" %
(binarize(ef), ef)
print(binary_link_cmd)
os.system(binary_link_cmd)
binary_list.append(binarize(ef))
if symbase:
for kind in ('start','end'):
objcopy_cmd = "objcopy --redefine-sym _binary_%s_
%s=_binary_%s_%s build/%s.o" % (binarize(ef), kind, binarize(symbase), kind,
binarize(ef))
print(objcopy_cmd)
os.system(objcopy_cmd)

self.cflags.append('-DUWSGI_VERSION="\\"' + uwsgi_version + '\\""')

uver_whole = uwsgi_version.split('-', 1)
if len(uver_whole) == 1:
uver_custom = ''
else:
uver_custom = uver_whole[1]

uver_dots = uver_whole[0].split('.')

uver_base = uver_dots[0]
uver_maj = uver_dots[1]
uver_min = '0'
uver_rev = '0'

if len(uver_dots) > 2:
uver_min = uver_dots[2]

if len(uver_dots) > 3:
uver_rev = uver_dots[3]

self.cflags.append('-DUWSGI_VERSION_BASE="' + uver_base + '"')


self.cflags.append('-DUWSGI_VERSION_MAJOR="' + uver_maj + '"')
self.cflags.append('-DUWSGI_VERSION_MINOR="' + uver_min + '"')
self.cflags.append('-DUWSGI_VERSION_REVISION="' + uver_rev + '"')
self.cflags.append('-DUWSGI_VERSION_CUSTOM="\\"' + uver_custom + '\\""')

if self.get('yaml'):
self.cflags.append("-DUWSGI_YAML")
self.gcc_list.append('core/yaml')
report['yaml'] = 'embedded'
if self.get('yaml') == 'libyaml':
self.cflags.append("-DUWSGI_LIBYAML")
self.libs.append('-lyaml')
report['yaml'] = 'libyaml'

if self.get('json'):
if self.get('json') in ('auto', 'true'):
jsonconf = spcall("pkg-config --cflags jansson")
if jsonconf:
self.cflags.append(jsonconf)
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append(spcall("pkg-config --libs jansson"))
report['json'] = 'jansson'
elif self.has_include('jansson.h'):
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append('-ljansson')
report['json'] = 'jansson'
else:
jsonconf = spcall("pkg-config --cflags yajl")
if jsonconf:
if jsonconf.endswith('include/yajl'):
jsonconf = jsonconf.rstrip('yajl')
self.cflags.append(jsonconf)
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append(spcall("pkg-config --libs yajl"))
self.cflags.append("-DUWSGI_JSON_YAJL")
report['json'] = 'yajl'
elif self.get('json') == 'true':
print("*** jansson and yajl headers unavailable. uWSGI
build is interrupted. You have to install jansson or yajl development headers or
disable JSON")
sys.exit(1)
elif self.get('json') == 'jansson':
jsonconf = spcall("pkg-config --cflags jansson")
if jsonconf:
self.cflags.append(jsonconf)
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append(spcall("pkg-config --libs jansson"))
report['json'] = 'jansson'
elif self.has_include('jansson.h'):
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append('-ljansson')
report['json'] = 'jansson'
else:
print("*** jansson headers unavailable. uWSGI build is
interrupted. You have to install jansson development package or use yajl or disable
JSON")
sys.exit(1)
elif self.get('json') == 'yajl':
jsonconf = spcall("pkg-config --cflags yajl")
if jsonconf:
self.cflags.append(jsonconf)
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append(spcall("pkg-config --libs yajl"))
self.cflags.append("-DUWSGI_JSON_YAJL")
report['json'] = 'yajl'
elif self.has_include('yajl/yajl_tree.h'):
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append('-lyajl')
self.cflags.append("-DUWSGI_JSON_YAJL")
report['json'] = 'yajl'
elif self.has_include('yajl/yajl_parse.h'):
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('core/json')
self.libs.append('-lyajl')
self.cflags.append("-DUWSGI_JSON_YAJL_OLD")
report['json'] = 'yajl_old'
else:
print("*** yajl headers unavailable. uWSGI build is
interrupted. You have to install yajl development package or use jansson or disable
JSON")
sys.exit(1)
if self.get('ssl'):
if self.get('ssl') == 'auto':
if self.has_include('openssl/ssl.h'):
self.cflags.append("-DUWSGI_SSL")
self.libs.append('-lssl')
self.libs.append('-lcrypto')
self.gcc_list.append('core/ssl')
self.gcc_list.append('core/legion')
report['ssl'] = True
else:
self.cflags.append("-DUWSGI_SSL")
self.libs.append('-lssl')
self.libs.append('-lcrypto')
self.gcc_list.append('core/ssl')
self.gcc_list.append('core/legion')
report['ssl'] = True

if self.get('xml'):
if self.get('xml') == 'auto':
xmlconf = spcall('xml2-config --libs')
if xmlconf and uwsgi_os != 'Darwin':
self.libs.append(xmlconf)
xmlconf = spcall("xml2-config --cflags")
self.cflags.append(xmlconf)
self.cflags.append("-DUWSGI_XML -DUWSGI_XML_LIBXML2")
self.gcc_list.append('core/xmlconf')
report['xml'] = 'libxml2'
elif self.has_include('expat.h'):
self.cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT")
self.libs.append('-lexpat')
self.gcc_list.append('core/xmlconf')
report['xml'] = 'expat'
elif self.get('xml') == 'libxml2':
xmlconf = spcall('xml2-config --libs')
if xmlconf is None:
print("*** libxml2 headers unavailable. uWSGI build is
interrupted. You have to install libxml2 development package or use libexpat or
disable XML")
sys.exit(1)
else:
self.libs.append(xmlconf)
xmlconf = spcall("xml2-config --cflags")
if xmlconf is None:
print("*** libxml2 headers unavailable. uWSGI build is
interrupted. You have to install libxml2 development package or use libexpat or
disable XML")
sys.exit(1)
else:
self.cflags.append(xmlconf)
self.cflags.append("-DUWSGI_XML -DUWSGI_XML_LIBXML2")
self.gcc_list.append('core/xmlconf')
report['xml'] = 'libxml2'
elif self.get('xml') == 'expat':
self.cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT")
self.libs.append('-lexpat')
self.gcc_list.append('core/xmlconf')
report['xml'] = 'expat'
if self.get('plugin_dir'):
self.cflags.append('-DUWSGI_PLUGIN_DIR="\\"%s\\""' %
self.get('plugin_dir'))
report['plugin_dir'] = self.get('plugin_dir')

if self.get('debug'):
self.cflags.append("-DUWSGI_DEBUG")
self.cflags.append("-g")
report['debug'] = True

if self.get('unbit'):
self.cflags.append("-DUNBIT")

return self.gcc_list, self.cflags, self.ldflags, self.libs

def build_plugin(path, uc, cflags, ldflags, libs, name = None):


path = path.rstrip('/')

plugin_started_at = time.time()

up = {}

if path.startswith('http://') or path.startswith('https://') or
path.startswith('git://') or path.startswith('ssh://'):
git_dir = path.split('/').pop()
if not os.path.isdir(git_dir):
if os.system('git clone %s' % path) != 0:
sys.exit(1)
else:
if os.system('cd %s ; git pull' % git_dir) != 0:
sys.exit(1)
path = os.path.abspath(git_dir)

if os.path.isfile(path):
bname = os.path.basename(path)
# override path
path = os.path.dirname(path)
up['GCC_LIST'] = [bname]
up['NAME'] = bname.split('.')[0]
if not path: path = '.'
elif os.path.isdir(path):
try:
execfile('%s/uwsgiplugin.py' % path, up)
except:
f = open('%s/uwsgiplugin.py' % path)
exec(f.read(), up)
f.close()
else:
print("Error: unable to find directory '%s'" % path)
sys.exit(1)

requires = []

p_cflags = cflags[:]
p_ldflags = ldflags[:]

try:
p_cflags += up['CFLAGS']
except:
pass

try:
p_ldflags += up['LDFLAGS']
except:
pass

try:
p_libs = up['LIBS']
except:
p_libs = []

post_build = None

try:
requires = up['REQUIRES']
except:
pass

try:
post_build = up['post_build']
except:
pass

p_cflags.insert(0, '-I.')

if name is None:
name = up['NAME']
else:
p_cflags.append("-D%s_plugin=%s_plugin" % (up['NAME'], name))

try:
for opt in uc.config.options(name):
p_cflags.append('-DUWSGI_PLUGIN_%s_%s="%s"' % (name.upper(),
opt.upper(), uc.config.get(name, opt, '1')))
except:
pass

if uc:
plugin_dest = uc.get('plugin_build_dir', uc.get('plugin_dir')) + '/' + name
+ '_plugin'
else:
plugin_dest = name + '_plugin'

shared_flag = '-shared'

gcc_list = []

if uwsgi_os == 'Darwin':
shared_flag = '-dynamiclib -undefined dynamic_lookup'

for cfile in up['GCC_LIST']:


if cfile.endswith('.a'):
gcc_list.append(cfile)
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not
cfile.endswith('.m') and not cfile.endswith('.go') and not cfile.endswith('.o'):
gcc_list.append(path + '/' + cfile + '.c')
else:
if cfile.endswith('.go'):
p_cflags.append('-Wno-error')
gcc_list.append(path + '/' + cfile)
for bfile in up.get('BINARY_LIST', []):
try:
binary_link_cmd = "ld -r -b binary -o %s/%s.o %s/%s" % (path, bfile[1],
path, bfile[1])
print(binary_link_cmd)
if os.system(binary_link_cmd) != 0:
raise Exception('unable to link binary file')
for kind in ('start','end'):
objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=%s_%s %s/%s.o"
% (binarize('%s/%s' % (path, bfile[1])), kind, bfile[0], kind, path, bfile[1])
print(objcopy_cmd)
if os.system(objcopy_cmd) != 0:
raise Exception('unable to link binary file')
gcc_list.append('%s/%s.o' % (path, bfile[1]))
except:
pass

try:
p_ldflags.remove('-Wl,--no-undefined')
except:
pass

try:
p_cflags.remove('-Wwrite-strings')
except:
pass

try:
p_cflags.remove('-Werror=write-strings')
except:
pass

try:
p_cflags.remove('-Wdeclaration-after-statement')
except:
pass

try:
p_cflags.remove('-Werror=declaration-after-statement')
except:
pass

try:
p_cflags.remove('-Winline')
except:
pass

try:
p_cflags.remove('-pie')
except:
pass

if GCC in ('clang',):
try:
p_cflags.remove('-fno-fast-math')
p_cflags.remove('-ggdb3')
except:
pass

if uwsgi_os.startswith('CYGWIN'):
try:
p_cflags.remove('-fstack-protector')
p_ldflags.remove('-fstack-protector')
except:
pass

need_pic = ' -fPIC'


# on cygwin we do not need PIC
if uwsgi_os.startswith('CYGWIN'):
need_pic = ' -L. -luwsgi'

gccline = "%s%s %s -o %s.so %s %s %s %s" % (GCC, need_pic, shared_flag,


plugin_dest, ' '.join(uniq_warnings(p_cflags)), ' '.join(gcc_list), '
'.join(uniq_warnings(p_ldflags)), ' '.join(uniq_warnings(p_libs)) )
print_compilation_output("[%s] %s.so" % (GCC, plugin_dest), gccline)

ret = os.system(gccline)
if ret != 0:
print("*** unable to build %s plugin ***" % name)
sys.exit(1)

try:
if requires:
f = open('.uwsgi_plugin_section', 'w')
for rp in requires:
f.write("requires=%s\n" % rp)
f.close()
objline = "objcopy %s.so --add-section uwsgi=.uwsgi_plugin_section
%s.so" % (plugin_dest, plugin_dest)
print_compilation_output(None, objline)
os.system(objline)
os.unlink('.uwsgi_plugin_section')
except:
pass

if post_build:
post_build(uc)

print("build time: %d seconds" % (time.time() - plugin_started_at))


print("*** %s plugin built and available in %s ***" % (name, plugin_dest +
'.so'))

def vararg_callback(option, opt_str, value, parser):


assert value is None
value = []
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1:
break
value.append(arg)

del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-b", "--build", action="callback", callback=vararg_callback,
dest="build", help="build a specific profile if provided or default.ini",
metavar="PROFILE")
parser.add_option("-f", "--cflags", action="callback",
callback=vararg_callback, dest="cflags", help="same as --build but less verbose",
metavar="PROFILE")
parser.add_option("-u", "--unbit", action="store_true", dest="unbit",
help="build unbit profile")
parser.add_option("-p", "--plugin", action="callback",
callback=vararg_callback, dest="plugin", help="build a plugin as shared library,
optionally takes a build profile name", metavar="PLUGIN [PROFILE]")
parser.add_option("-x", "--extra-plugin", action="callback",
callback=vararg_callback, dest="extra_plugin", help="build an external plugin as
shared library, takes an optional include dir", metavar="PLUGIN [NAME]")
parser.add_option("-c", "--clean", action="store_true", dest="clean",
help="clean the build")
parser.add_option("-e", "--check", action="store_true", dest="check", help="run
cppcheck")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
help="more verbose build")
parser.add_option("-g", "--debug", action="store_true", dest="debug",
help="build with debug symbols, affects only full build")
parser.add_option("-a", "--asan", action="store_true", dest="asan", help="build
with address sanitizer, it's a debug option and affects only full build")

(options, args) = parser.parse_args()

if options.verbose:
verbose_build = True

add_cflags = []
add_ldflags = []

if options.debug:
add_cflags.append('-g')
add_ldflags.append('-g')

if options.asan:
add_cflags.extend(['-g', '-fsanitize=address', '-fno-omit-frame-pointer'])
add_ldflags.extend(['-g', '-fsanitize=address'])

if options.build is not None or options.cflags is not None:


is_cflags = options.cflags is not None
try:
if not is_cflags:
bconf = options.build[0]
else:
bconf = options.cflags[0]
except:
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf

uc = uConf(bconf, is_cflags)
if add_cflags or add_ldflags:
gcc_list, cflags, ldflags, libs = uc.get_gcll()
if add_cflags:
cflags.extend(add_cflags)
if add_ldflags:
ldflags.extend(add_ldflags)
gcll = (gcc_list, cflags, ldflags, libs)
else:
gcll = None
build_uwsgi(uc, is_cflags, gcll=gcll)
elif options.unbit:
build_uwsgi(uConf('buildconf/unbit.ini'))
elif options.plugin:
try:
bconf = options.plugin[1]
except:
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf
uc = uConf(bconf)
gcc_list, cflags, ldflags, libs = uc.get_gcll()
try:
name = options.plugin[2]
except:
name = None
print("*** uWSGI building and linking plugin %s ***" % options.plugin[0] )
build_plugin(options.plugin[0], uc, cflags, ldflags, libs, name)
elif options.extra_plugin:
print("*** uWSGI building and linking plugin from %s ***" %
options.extra_plugin[0])
cflags = os.environ['UWSGI_PLUGINS_BUILDER_CFLAGS'].split() +
os.environ.get("CFLAGS", "").split()
cflags.append('-I.uwsgi_plugins_builder/')
ldflags = os.environ.get("LDFLAGS", "").split()
name = None
try:
name = options.extra_plugin[1]
except:
pass
build_plugin(options.extra_plugin[0], None, cflags, ldflags, None, name)
elif options.clean:
os.system("rm -f core/*.o")
os.system("rm -f proto/*.o")
os.system("rm -f lib/*.o")
os.system("rm -f plugins/*/*.o")
os.system("rm -f build/*.o")
os.system("rm -f core/dot_h.c")
os.system("rm -f core/config_py.c")
elif options.check:
os.system("cppcheck --max-configs=1000 --enable=all -q core/ plugins/
proto/ lib/ apache2/")
else:
parser.print_help()
sys.exit(1)

You might also like