#!/usr/bin/env python3
'''
This tool is used to generate user-config.jam and site-config.jam
for boost library automatically.
'''
import os
import os.path
__author__ = "Tianjiao Yin (ytj000@gamil.com)"
__date__ = "Fri, 24 Jun 2011 18:58:58 +0800"
__copyright__ = "Copyright 2011 Tianjiao Yin"
__license__ = "WTFPLv2"
__version__ = "0.3"
# Default path
site_path = "/etc/site-config.jam"
boostbook_path = "/usr/share/boostbook"
# Constant default path
QT_PATH = "/usr/share/qt" # useless useless
DOCBOOK_PATH = "/usr/share/xml/docbook/"
# Supporting list
TOOLS_LIST = ("specific_gcc", "python", "mpi", "boostbook")
# "using name ;" if name is executable
# Trivial tools don't need a special function.
# May be I should remove this and write functions for all;
TRIVIAL_TOOLS = ("gcc", "doxygen", "quickbook")
SITE_DATA = r'''# Copyright 2003, 2005 Douglas Gregor
# Copyright 2004 John Maddock
# Copyright 2002, 2003, 2004, 2007 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://w...content-available-to-author-only...t.org/LICENSE_1_0.txt)
# This file is used to configure your Boost.Build installation. You can modify
# this file in place, or you can place it in a permanent location so that it
# does not get overwritten should you get a new version of Boost.Build. See:
#
# http://w...content-available-to-author-only...t.org/boost-build2/doc/html/bbv2/overview/configuration.html
#
# for documentation about possible permanent locations.
# This file specifies which toolsets (C++ compilers), libraries, and other
# tools are available. Often, you should be able to just uncomment existing
# example lines and adjust them to taste. The complete list of supported tools,
# and configuration instructions can be found at:
#
# http://b...content-available-to-author-only...t.org/boost-build2/doc/html/bbv2/reference/tools.html
#
# This file uses Jam language syntax to describe available tools. Mostly,
# there are 'using' lines, that contain the name of the used tools, and
# parameters to pass to those tools -- where paremeters are separated by
# semicolons. Important syntax notes:
#
# - Both ':' and ';' must be separated from other tokens by whitespace
# - The '\' symbol is a quote character, so when specifying Windows paths you
# should use '/' or '\\' instead.
#
# More details about the syntax can be found at:
#
# http://b...content-available-to-author-only...t.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language
#
# -------------------
# MSVC configuration.
# -------------------
# Configure msvc (default version, searched for in standard locations and PATH).
# using msvc ;
# Configure specific msvc version (searched for in standard locations and PATH).
# using msvc : 8.0 ;
# ----------------------
# Borland configuration.
# ----------------------
# using borland ;
# ----------------------
# STLPort configuration.
# ----------------------
# Configure specifying location of STLPort headers. Libraries must be either
# not needed or available to the compiler by default.
# using stlport : : /usr/include/stlport ;
# Configure specifying location of both headers and libraries explicitly.
# using stlport : : /usr/include/stlport /usr/lib ;
# ------------------
# GCC configuration.
# ------------------
# Configure gcc (default version).
{gcc}
# Configure specific gcc version, giving alternative name to use.
{specific_gcc}
# -----------------
# QT configuration.
# -----------------
# Configure assuming QTDIR gives the installation prefix.
# using qt ;
# Configure with an explicit installation prefix.
# using qt : /usr/opt/qt ;
# ---------------------
# Python configuration.
# ---------------------
# Configure specific Python version.
{python}
# ------------------
# MPI configuration.
# ------------------
{mpi}
# ------------------------
# BoostBook configuration.
# ------------------------
{boostbook}
# ----------------------
# Doxygen configuration.
# ----------------------
{doxygen}
# ------------------------
# Quickbook configuration.
# ------------------------
{quickbook}
# --------------------
# Extra configuration.
# --------------------
'''
def get_all_exec():
'''
Find all executable files.
Return file_names_dict, paths_list
'''
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
rec = set()
ans = []
for path in os.environ["PATH"].split(os.pathsep):
if os.path.exists(path):
for name in os.listdir(path):
exe_file = os.path.join(path, name)
if name not in rec and is_exe(exe_file):
ans.append(exe_file)
rec.add(name)
return rec, ans
all_name, all_path = get_all_exec()
def specific_gcc():
gccs = []
for i in all_name:
if len(i) > 4 and i[:4] == "g++-":
gccs.append("using gcc : {} : {} ;\n".format(i[4:], i))
return "\n".join(gccs)
def python():
def getpyver(cmd):
'''
Get python version
getpyver(python_path) --> python_version
Simple example:
getpyver("python3") --> "3.2"
'''
import subprocess
p = subprocess.Popen((cmd, "--version"), stderr=subprocess.PIPE)
p.wait();
p = p.stderr.read().decode('ascii')
p = p.split()[1].split('.')
return p[0] + '.' + p[1]
def get_cpy(cmd):
'''
Get python configure.
'''
pyv = getpyver(cmd)
pyinc = "/usr/include/python{}mu".format(pyv)
if not os.path.isdir(pyinc):
pyinc = "/usr/include/python{}".format(pyv)
for i in all_path:
fpath, fname = os.path.split(i)
if "python{}".format(pyv[0]) == fname:
loca = i;
break
py = "using python : {} : {} : {} : /usr/lib ;"
return py.format(pyv, loca, pyinc)
pys = []
# We choose python2 as default, so python2 must appear before than python3.
if "python2" in all_name:
pys.append(get_cpy("python2"))
if "python3" in all_name:
pys.append(get_cpy("python3"))
return "\n".join(pys)
def mpi():
if "mpicc" in all_name:
return "using mpi ;"
return ""
def boostbook():
if not os.path.isdir(boostbook_path):
return ''
if not os.path.isdir(DOCBOOK_PATH):
return ''
s = "using boostbook\n: {DOCBOOK_XSL_DIR}\n: {DOCBOOK_DTD_DIR}\n: {BOOSTBOOK_DIR} ;"
ret = {}
path = (os.path.join(DOCBOOK_PATH, name) for name in os.listdir(DOCBOOK_PATH))
l = [i for i in path if os.path.isdir(i)]
xsl, xml = [], []
for i in l:
if "xsl" in i:
xsl.append(i)
if "xml" in i:
xml.append(i)
if not xsl or not xml:
return ""
# Find the newest version
def version_key(version):
import re
return re.split('\D*', version)
ret["BOOSTBOOK_DIR"] = boostbook_path
ret["DOCBOOK_XSL_DIR"] = max(xsl, key = version_key)
ret["DOCBOOK_DTD_DIR"] = max(xml, key = version_key)
return s.format(**ret)
def site_config():
conf = {}
for name in TRIVIAL_TOOLS:
conf[name] = "using {} ;".format(name) if name in all_name else ""
for name in TOOLS_LIST:
conf[name] = globals()[name]()
return conf
def main():
"""
Generate configuration file for boost build automatically.
"""
global site_path
global boostbook_path
import argparse
parser = argparse.ArgumentParser(
# display before help
description=main.__doc__,
# display after help
epilog=("License {}. This is free software. "
"If you are lucky, this program will not delete your /usr. "
"However, It has not been tested widely."
).format(__license__),
)
parser.add_argument('-s', '--setup',
required=True,
action='store_true',
help="You have to input this argument, otherwise it will not proceed."
)
parser.add_argument('--version',
action='version',
version='%(prog)s ' + __version__
)
parser.add_argument('-o',
default=site_path,
help="Place the configuration into %(metavar)s (default: %(default)s)",
metavar="<file>"
)
parser.add_argument('-b', "--boostbook_path",
default=boostbook_path,
help="Boost book directory (default: %(default)s)",
metavar="<path>"
)
parser.add_argument('-a', "--add_tools",
nargs=2,
# Bad idea:
# If using nargs='*' instead,
# No need to type quotation marks.
# However, it will confuse the user.
action='append',
help=('Force to add a tool. '
'Simple usage: -a gcc "using gcc : : \\"distcc g++\\" ;" '
),
metavar=("<name>", "<information>")
)
args = parser.parse_args()
site_path = args.o
boostbook_path = args.boostbook_path
add_conf = {}
if args.add_tools:
for i in args.add_tools:
add_conf[i[0]] = " ".join(i[1:])
conf = site_config()
conf.update(add_conf)
data = SITE_DATA
for i in conf:
if i not in TOOLS_LIST and i not in TRIVIAL_TOOLS:
data += "{" + i + "}\n"
data = data.format(**conf)
open(site_path,"w").write(data)
if __name__ == "__main__":
main()