mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-23 13:31:49 +00:00
c7fa09fe9f
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13831 a592a061-630c-0410-9148-cb99ea01b6c8
786 lines
22 KiB
Python
786 lines
22 KiB
Python
# vi:filetype=python:expandtab:tabstop=2:shiftwidth=2
|
|
#
|
|
# file scons_utils.py
|
|
#
|
|
# This file is part of LyX, the document processor.
|
|
# Licence details can be found in the file COPYING.
|
|
#
|
|
# \author Bo Peng
|
|
# Full author contact details are available in file CREDITS.
|
|
#
|
|
# This file defines all the utility functions for the
|
|
# scons-based build system of lyx
|
|
#
|
|
|
|
import os, sys, re, shutil, glob
|
|
|
|
config_h = os.path.join('src', 'config.h')
|
|
|
|
def writeToFile(filename, lines, append = False):
|
|
" utility function: write or append lines to filename "
|
|
if append:
|
|
file = open(filename, 'a')
|
|
else:
|
|
file = open(filename, 'w')
|
|
file.write(lines)
|
|
file.close()
|
|
|
|
|
|
def addToConfig(lines, top_src_dir):
|
|
''' utility function: shortcut for appending lines to outfile
|
|
add newline at the end of lines.
|
|
'''
|
|
if lines.strip() != '':
|
|
writeToFile(os.path.join(top_src_dir, config_h), lines + '\n\n', append = True)
|
|
|
|
|
|
def printEnvironment(env, keys=[]):
|
|
''' used to check profile settings '''
|
|
dict = env.Dictionary()
|
|
if len(keys) == 0:
|
|
keys = dict.keys()
|
|
keys.sort()
|
|
for key in keys:
|
|
try:
|
|
# try to expand, but this is not always possible
|
|
print key, '=', env.subst('$'+key)
|
|
except:
|
|
print '<<UNEXPANDED>>:', key, '=', dict[key]
|
|
|
|
|
|
def env_subst(target, source, env):
|
|
''' subst variables in source by those in env, and output to target
|
|
source and target are scons File() objects
|
|
|
|
%key% (not key itself) is an indication of substitution
|
|
'''
|
|
assert len(target) == 1
|
|
assert len(source) == 1
|
|
target_file = file(str(target[0]), "w")
|
|
source_file = file(str(source[0]), "r")
|
|
|
|
contents = source_file.read()
|
|
for k in env.get('SUBST_KEYS', []):
|
|
if not env.has_key(k):
|
|
print "Failed to subst key ", k, " from file", str(source[0])
|
|
raise
|
|
contents = re.sub('@'+k+'@', env.subst('$'+k).replace('\n',r'\\n\\\n'), contents)
|
|
target_file.write(contents + "\n")
|
|
target_file.close()
|
|
#st = os.stat(str(source[0]))
|
|
#os.chmod(str(target[0]), stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
|
|
|
|
|
|
def env_filecopy(target, source, env):
|
|
shutil.copy(str(source[0]), str(target[0]))
|
|
|
|
|
|
#
|
|
# autoconf tests
|
|
#
|
|
|
|
def checkPkgConfig(conf, version):
|
|
''' Return false if pkg_config does not exist, or is too old '''
|
|
conf.Message('Checking for pkg-config...')
|
|
ret = conf.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
|
|
conf.Result(ret)
|
|
return ret
|
|
|
|
|
|
def checkPackage(conf, pkg):
|
|
''' check if pkg is under the control of conf '''
|
|
conf.Message('Checking for package %s...' % pkg)
|
|
ret = conf.TryAction("pkg-config --print-errors --exists %s" % pkg)[0]
|
|
conf.Result(ret)
|
|
return ret
|
|
|
|
|
|
def startConfigH(top_src_dir):
|
|
''' Write the first part of config.h '''
|
|
writeToFile(os.path.join(top_src_dir, config_h),
|
|
'''/* src/config.h. Generated by scon. */
|
|
|
|
/* -*- C++ -*- */
|
|
/*
|
|
* \file config.h
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* This is the compilation configuration file for LyX.
|
|
* It was generated by scon.
|
|
* You might want to change some of the defaults if something goes wrong
|
|
* during the compilation.
|
|
*/
|
|
|
|
#ifndef _CONFIG_H
|
|
#define _CONFIG_H
|
|
''')
|
|
|
|
|
|
def endConfigH(top_src_dir):
|
|
''' Write the last part of config.h '''
|
|
writeToFile(os.path.join(top_src_dir, config_h), '''
|
|
/************************************************************
|
|
** You should not need to change anything beyond this point */
|
|
|
|
#ifndef HAVE_STRERROR
|
|
#if defined(__cplusplus)
|
|
extern "C"
|
|
#endif
|
|
char * strerror(int n);
|
|
#endif
|
|
|
|
#ifdef HAVE_MKSTEMP
|
|
#ifndef HAVE_DECL_MKSTEMP
|
|
#if defined(__cplusplus)
|
|
extern "C"
|
|
#endif
|
|
int mkstemp(char*);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __EMX__
|
|
# include "support/os2_defines.h"
|
|
#endif
|
|
|
|
#if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
|
|
# define USE_BOOST_FORMAT 1
|
|
#else
|
|
# define USE_BOOST_FORMAT 0
|
|
#endif
|
|
|
|
#define BOOST_USER_CONFIG <config.h>
|
|
|
|
#if !defined(ENABLE_ASSERTIONS)
|
|
# define BOOST_DISABLE_ASSERTS 1
|
|
#endif
|
|
#define BOOST_ENABLE_ASSERT_HANDLER 1
|
|
|
|
#define BOOST_DISABLE_THREADS 1
|
|
#define BOOST_NO_WREGEX 1
|
|
#define BOOST_NO_WSTRING 1
|
|
|
|
#ifdef __CYGWIN__
|
|
# define BOOST_POSIX 1
|
|
#endif
|
|
|
|
#if defined(HAVE_NEWAPIS_H)
|
|
# define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
|
|
#endif
|
|
|
|
#endif
|
|
''', append=True)
|
|
|
|
|
|
#HAVE_PUTENV
|
|
def checkPutenv(conf):
|
|
check_putenv_source = """
|
|
#include <stdlib.h>
|
|
int main()
|
|
{
|
|
putenv("");
|
|
return(0);
|
|
}
|
|
"""
|
|
conf.Message('Checking for putenv... ')
|
|
ret = conf.TryLink(check_putenv_source, '.c')
|
|
conf.Result(ret)
|
|
return ret
|
|
|
|
|
|
#HAVE_DECL_ISTREAMBUF_ITERATOR
|
|
def checkIstreambufIterator(conf):
|
|
check_istreambuf_iterator_source = """
|
|
#include <streambuf>
|
|
#include <istream>
|
|
int main()
|
|
{
|
|
std::istreambuf_iterator<std::istream> iter;
|
|
return 0;
|
|
}
|
|
"""
|
|
conf.Message('Checking for iostreambuf::iterator... ')
|
|
ret = conf.TryLink(check_istreambuf_iterator_source, '.cpp')
|
|
conf.Result(ret)
|
|
return ret
|
|
|
|
|
|
#MKDIR_TAKES_ONE_ARG
|
|
def checkMkdirOneArg(conf):
|
|
check_mkdir_one_arg_source = """
|
|
#include <sys/stat.h>
|
|
int main()
|
|
{
|
|
mkdir("somedir");
|
|
}
|
|
"""
|
|
conf.Message('Checking for the number of args for mkdir... ')
|
|
ret = conf.TryLink(check_mkdir_one_arg_source, '.c')
|
|
if ret:
|
|
conf.Result('one')
|
|
else:
|
|
conf.Result('two')
|
|
return ret
|
|
|
|
|
|
#HAVE_STD_COUNT
|
|
def checkStdCount(conf):
|
|
check_std_count_source = """
|
|
#include <algorithm>
|
|
using std::count;
|
|
int countChar(char * b, char * e, char const c)
|
|
{
|
|
return count(b, e, c);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
char a[] = "hello";
|
|
int i = countChar(a, a + 5, 'l');
|
|
}
|
|
"""
|
|
conf.Message('Checking for std::count... ')
|
|
ret = conf.TryLink(check_std_count_source, '.cpp')
|
|
conf.Result(ret)
|
|
return ret
|
|
|
|
|
|
# SELECT_TYPE_ARG1
|
|
# SELECT_TYPE_ARG234
|
|
# SELECT_TYPE_ARG5
|
|
def checkSelectArgType(conf):
|
|
''' Adapted from autoconf '''
|
|
conf.Message('Checking for arg types for select... ')
|
|
for arg234 in ['fd_set *', 'int *', 'void *']:
|
|
for arg1 in ['int', 'size_t', 'unsigned long', 'unsigned']:
|
|
for arg5 in ['struct timeval *', 'const struct timeval *']:
|
|
check_select_source = '''
|
|
#if HAVE_SYS_SELECT_H
|
|
# include <sys/select.h>
|
|
#endif
|
|
#if HAVE_SYS_SOCKET_H
|
|
# include <sys/socket.h>
|
|
#endif
|
|
extern int select (%s, %s, %s, %s, %s);
|
|
int main()
|
|
{
|
|
return(0);
|
|
}
|
|
''' % (arg1, arg234, arg234, arg234, arg5)
|
|
ret = conf.TryLink(check_select_source, '.c')
|
|
if ret:
|
|
conf.Result(ret)
|
|
return (arg1, arg234, arg5)
|
|
conf.Result('no (use default)')
|
|
return ('int', 'int *', 'struct timeval *')
|
|
|
|
|
|
def checkBoostLibraries(conf, lib, pathes):
|
|
''' look for boost libraries '''
|
|
conf.Message('Checking for boost library %s... ' % lib)
|
|
for path in pathes:
|
|
# direct form: e.g. libboost_iostreams.a
|
|
if os.path.isfile(os.path.join(path, 'lib%s.a' % lib)):
|
|
conf.Result('yes')
|
|
return (path, lib)
|
|
# check things like libboost_iostreams-gcc.a
|
|
files = glob.glob(os.path.join(path, 'lib%s-*.a' % lib))
|
|
# if there are more than one, choose the first one
|
|
# FIXME: choose the best one.
|
|
if len(files) >= 1:
|
|
# get xxx-gcc from /usr/local/lib/libboost_xxx-gcc.a
|
|
conf.Result('yes')
|
|
return (path, files[0].split(os.sep)[-1][3:-2])
|
|
conf.Result('n')
|
|
return ('','')
|
|
|
|
|
|
import SCons.Node
|
|
def processLang(env, folder):
|
|
""" Process translations (.po files) in a po/ dir
|
|
This is copied from KDE knetstats-1.5/admin/kde.py
|
|
|
|
FIXME: imcomplete
|
|
"""
|
|
import glob
|
|
dir=SCons.Node.FS.default_fs.Dir(folder).srcnode()
|
|
fld=dir.srcnode()
|
|
tmptransfiles = glob.glob(str(fld)+'/*.po')
|
|
|
|
transfiles=[]
|
|
if env.has_key('_BUILDDIR_'):
|
|
bdir=env['_BUILDDIR_']
|
|
for dir in env.make_list(tmptransfiles):
|
|
transfiles.append( env.join(bdir, dir) )
|
|
else:
|
|
transfiles=tmptransfiles
|
|
|
|
env['MSGFMT'] = 'msgfmt'
|
|
env['BUILDERS']['Transfiles']=SCons.Builder.Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
|
|
languages=None
|
|
# FIXME: KDE has this ARGS thing...
|
|
#if env['ARGS'] and env['ARGS'].has_key('languages'):
|
|
# languages=env.make_list(env['ARGS']['languages'])
|
|
mydir=SCons.Node.FS.default_fs.Dir('.')
|
|
for f in transfiles:
|
|
fname=f.replace(mydir.abspath, '')
|
|
file=SCons.Node.FS.default_fs.File(fname)
|
|
country = SCons.Util.splitext(file.name)[0]
|
|
if not languages or country in languages:
|
|
result = env.Transfiles(file)
|
|
# FIXME
|
|
|
|
|
|
def installCygwinLDScript(path):
|
|
''' Install i386pe.x-no-rdata '''
|
|
ld_script = os.path.join(path, 'i386pe.x-no-rdata')
|
|
script = open(ld_script, 'w')
|
|
script.write('''/* specific linker script avoiding .rdata sections, for normal executables
|
|
for a reference see
|
|
http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
|
|
http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
|
|
*/
|
|
OUTPUT_FORMAT(pei-i386)
|
|
SEARCH_DIR("/usr/i686-pc-cygwin/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib/w32api");
|
|
ENTRY(_mainCRTStartup)
|
|
SECTIONS
|
|
{
|
|
.text __image_base__ + __section_alignment__ :
|
|
{
|
|
*(.init)
|
|
*(.text)
|
|
*(SORT(.text$*))
|
|
*(.glue_7t)
|
|
*(.glue_7)
|
|
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
|
|
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);
|
|
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
|
|
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);
|
|
*(.fini)
|
|
/* ??? Why is .gcc_exc here? */
|
|
*(.gcc_exc)
|
|
PROVIDE (etext = .);
|
|
*(.gcc_except_table)
|
|
}
|
|
/* The Cygwin32 library uses a section to avoid copying certain data
|
|
on fork. This used to be named ".data". The linker used
|
|
to include this between __data_start__ and __data_end__, but that
|
|
breaks building the cygwin32 dll. Instead, we name the section
|
|
".data_cygwin_nocopy" and explictly include it after __data_end__. */
|
|
.data BLOCK(__section_alignment__) :
|
|
{
|
|
__data_start__ = . ;
|
|
*(.data)
|
|
*(.data2)
|
|
*(SORT(.data$*))
|
|
*(.rdata)
|
|
*(SORT(.rdata$*))
|
|
*(.eh_frame)
|
|
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
|
__RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
|
*(.rdata_runtime_pseudo_reloc)
|
|
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
|
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
|
__data_end__ = . ;
|
|
*(.data_cygwin_nocopy)
|
|
}
|
|
.rdata BLOCK(__section_alignment__) :
|
|
{
|
|
}
|
|
.pdata BLOCK(__section_alignment__) :
|
|
{
|
|
*(.pdata)
|
|
}
|
|
.bss BLOCK(__section_alignment__) :
|
|
{
|
|
__bss_start__ = . ;
|
|
*(.bss)
|
|
*(COMMON)
|
|
__bss_end__ = . ;
|
|
}
|
|
.edata BLOCK(__section_alignment__) :
|
|
{
|
|
*(.edata)
|
|
}
|
|
/DISCARD/ :
|
|
{
|
|
*(.debug$S)
|
|
*(.debug$T)
|
|
*(.debug$F)
|
|
*(.drectve)
|
|
}
|
|
.idata BLOCK(__section_alignment__) :
|
|
{
|
|
/* This cannot currently be handled with grouped sections.
|
|
See pe.em:sort_sections. */
|
|
SORT(*)(.idata$2)
|
|
SORT(*)(.idata$3)
|
|
/* These zeroes mark the end of the import list. */
|
|
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
|
SORT(*)(.idata$4)
|
|
SORT(*)(.idata$5)
|
|
SORT(*)(.idata$6)
|
|
SORT(*)(.idata$7)
|
|
}
|
|
.CRT BLOCK(__section_alignment__) :
|
|
{
|
|
___crt_xc_start__ = . ;
|
|
*(SORT(.CRT$XC*)) /* C initialization */
|
|
___crt_xc_end__ = . ;
|
|
___crt_xi_start__ = . ;
|
|
*(SORT(.CRT$XI*)) /* C++ initialization */
|
|
___crt_xi_end__ = . ;
|
|
___crt_xl_start__ = . ;
|
|
*(SORT(.CRT$XL*)) /* TLS callbacks */
|
|
/* ___crt_xl_end__ is defined in the TLS Directory support code */
|
|
___crt_xp_start__ = . ;
|
|
*(SORT(.CRT$XP*)) /* Pre-termination */
|
|
___crt_xp_end__ = . ;
|
|
___crt_xt_start__ = . ;
|
|
*(SORT(.CRT$XT*)) /* Termination */
|
|
___crt_xt_end__ = . ;
|
|
}
|
|
.tls BLOCK(__section_alignment__) :
|
|
{
|
|
___tls_start__ = . ;
|
|
*(.tls)
|
|
*(.tls$)
|
|
*(SORT(.tls$*))
|
|
___tls_end__ = . ;
|
|
}
|
|
.endjunk BLOCK(__section_alignment__) :
|
|
{
|
|
/* end is deprecated, don't use it */
|
|
PROVIDE (end = .);
|
|
PROVIDE ( _end = .);
|
|
__end__ = .;
|
|
}
|
|
.rsrc BLOCK(__section_alignment__) :
|
|
{
|
|
*(.rsrc)
|
|
*(SORT(.rsrc$*))
|
|
}
|
|
.reloc BLOCK(__section_alignment__) :
|
|
{
|
|
*(.reloc)
|
|
}
|
|
.stab BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.stab)
|
|
}
|
|
.stabstr BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.stabstr)
|
|
}
|
|
/* DWARF debug sections.
|
|
Symbols in the DWARF debugging sections are relative to the beginning
|
|
of the section. Unlike other targets that fake this by putting the
|
|
section VMA at 0, the PE format will not allow it. */
|
|
/* DWARF 1.1 and DWARF 2. */
|
|
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_aranges)
|
|
}
|
|
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_pubnames)
|
|
}
|
|
/* DWARF 2. */
|
|
.debug_info BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_info) *(.gnu.linkonce.wi.*)
|
|
}
|
|
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_abbrev)
|
|
}
|
|
.debug_line BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_line)
|
|
}
|
|
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_frame)
|
|
}
|
|
.debug_str BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_str)
|
|
}
|
|
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_loc)
|
|
}
|
|
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_macinfo)
|
|
}
|
|
/* SGI/MIPS DWARF 2 extensions. */
|
|
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_weaknames)
|
|
}
|
|
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_funcnames)
|
|
}
|
|
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_typenames)
|
|
}
|
|
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_varnames)
|
|
}
|
|
/* DWARF 3. */
|
|
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
|
|
{
|
|
*(.debug_ranges)
|
|
}
|
|
}
|
|
''')
|
|
script.close()
|
|
return(ld_script)
|
|
|
|
|
|
try:
|
|
# these will be used under win32
|
|
import win32file
|
|
import win32event
|
|
import win32process
|
|
import win32security
|
|
except:
|
|
# does not matter if it fails on other systems
|
|
pass
|
|
|
|
|
|
class loggedSpawn:
|
|
def __init__(self, env, logfile, longarg, info):
|
|
# save the spawn system
|
|
self.env = env
|
|
self.logfile = logfile
|
|
# clear the logfile (it may not exist)
|
|
if logfile != '':
|
|
# this will overwrite existing content.
|
|
writeToFile(logfile, info, append=False)
|
|
#
|
|
self.longarg = longarg
|
|
# get hold of the old spawn? (necessary?)
|
|
self._spawn = env['SPAWN']
|
|
|
|
# define new SPAWN
|
|
def spawn(self, sh, escape, cmd, args, spawnenv):
|
|
# get command line
|
|
newargs = ' '.join(map(escape, args[1:]))
|
|
cmdline = cmd + " " + newargs
|
|
#
|
|
# if log is not empty, write to it
|
|
if self.logfile != '':
|
|
# this tend to be slow (?) but ensure correct output
|
|
# Note that cmdline may be long so I do not escape it
|
|
try:
|
|
# since this is not an essential operation, proceed if things go wrong here.
|
|
writeToFile(self.logfile, cmd + " " + ' '.join(args[1:]) + '\n', append=True)
|
|
except:
|
|
print "Warning: can not write to log file ", self.logfile
|
|
#
|
|
# if the command is not too long, use the old
|
|
if not self.longarg or len(cmdline) < 8000:
|
|
exit_code = self._spawn(sh, escape, cmd, args, spawnenv)
|
|
else:
|
|
sAttrs = win32security.SECURITY_ATTRIBUTES()
|
|
StartupInfo = win32process.STARTUPINFO()
|
|
for var in spawnenv:
|
|
spawnenv[var] = spawnenv[var].encode('ascii', 'replace')
|
|
# check for any special operating system commands
|
|
if cmd == 'del':
|
|
for arg in args[1:]:
|
|
win32file.DeleteFile(arg)
|
|
exit_code = 0
|
|
else:
|
|
# otherwise execute the command.
|
|
hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo)
|
|
win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
|
|
exit_code = win32process.GetExitCodeProcess(hProcess)
|
|
win32file.CloseHandle(hProcess);
|
|
win32file.CloseHandle(hThread);
|
|
return exit_code
|
|
|
|
|
|
def setLoggedSpawn(env, logfile = '', longarg=False, info=''):
|
|
''' This function modify env and allow logging of
|
|
commands to a logfile. If the argument is too long
|
|
a win32 spawn will be used instead of the system one
|
|
'''
|
|
#
|
|
# create a new spwn object
|
|
ls = loggedSpawn(env, logfile, longarg, info)
|
|
# replace the old SPAWN by the new function
|
|
env['SPAWN'] = ls.spawn
|
|
|
|
#
|
|
# Install program with permission
|
|
# http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/InstallTargets
|
|
#
|
|
import SCons
|
|
from SCons.Script.SConscript import SConsEnvironment
|
|
|
|
SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
|
|
lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
|
|
|
|
def installPerm(target, source, env, perm):
|
|
''' install program with permission, will copy
|
|
files recursively if needed '''
|
|
# FIXME: mixed use of scons and python interfaces?
|
|
target_dir = str(target[0])
|
|
if os.path.isfile(target_dir):
|
|
print "Target should be a directory: ", target_dir
|
|
return
|
|
if not os.path.isdir(target_dir):
|
|
os.makedirs(target_dir)
|
|
objs = []
|
|
for fnode in source:
|
|
fname = str(fnode)
|
|
print "Installing", fname, "to", target_dir
|
|
if os.path.isfile(fname):
|
|
objs.append(os.path.join(target_dir, fname))
|
|
shutil.copy(fname, target_dir)
|
|
elif os.path.isdir(fname):
|
|
# FIXME: directory permission is not set
|
|
if os.path.isdir(os.path.join(target_dir, fname)):
|
|
shutil.rmtree(os.path.join(target_dir, fname))
|
|
shutil.copytree(fname, target_dir)
|
|
#for i in objs:
|
|
# env.AddPostAction(File(i), env.Chmod(i, perm))
|
|
return target
|
|
|
|
def env_installProg(target, source, env):
|
|
installPerm(target, source, env, 0755)
|
|
|
|
def env_installFile(target, source, env):
|
|
installPerm(target, source, env, 0644)
|
|
|
|
## def DistSources(env, node):
|
|
## env.DistFiles(_get_sources(env, node))
|
|
##
|
|
## def DistFiles(env, files):
|
|
## assert isinstance(files, (list, tuple))
|
|
## DISTFILES = [env.File(fname) for fname in files]
|
|
## env.AppendUnique(DISTFILES=DISTFILES)
|
|
##
|
|
##
|
|
## def make_distdir(target=None, source=None, env=None):
|
|
## distdir = env.subst('$DISTDIR')
|
|
## Execute(Delete(distdir))
|
|
## Execute(Mkdir(distdir))
|
|
## for fnode in env["DISTFILES"]:
|
|
## dirname, fname = os.path.split(str(fnode))
|
|
## if dirname:
|
|
## distdirname = os.path.join(distdir, dirname)
|
|
## if not os.path.exists(distdirname):
|
|
## Execute(Mkdir(distdirname))
|
|
## Execute(Copy(os.path.join(distdir, dirname, fname), str(fnode)))
|
|
##
|
|
## def make_dist(target=None, source=None, env=None):
|
|
## return Popen([env['TAR'], "-zcf",
|
|
## env.subst("${PACKAGE}-${VERSION}.tar.gz"),
|
|
## env.subst('$DISTDIR')]).wait()
|
|
##
|
|
## def make_distcheck(target=None, source=None, env=None):
|
|
## distdir = env.subst('$DISTDIR')
|
|
## distcheckinstdir = tempfile.mkdtemp('', env.subst('${PACKAGE}-${VERSION}-instdir-'))
|
|
## distcheckdestdir = tempfile.mkdtemp('', env.subst('${PACKAGE}-${VERSION}-destdir-'))
|
|
## instdirs = [os.path.join(distcheckinstdir, d) for d in
|
|
## 'lib', 'share', 'bin', 'include']
|
|
## for dir_ in instdirs:
|
|
## Execute(Mkdir(dir_))
|
|
##
|
|
## cmd = env.subst("cd $DISTDIR && scons DESTDIR=%s prefix=%s"
|
|
## " && scons check && scons install") %\
|
|
## (os.path.join(distcheckdestdir, ''), distcheckinstdir)
|
|
## status = Popen(cmd, shell=True).wait()
|
|
## if status:
|
|
## return status
|
|
## ## Check that inst dirs are empty (to catch cases of $DESTDIR not being honored
|
|
## for dir_ in instdirs:
|
|
## if os.listdir(dir_):
|
|
## raise SCons.Errors.BuildError(target, "%s not empy" % dir_)
|
|
## ## Check that something inside $DESTDIR was installed
|
|
## dir_ = os.path.join(distcheckdestdir, distcheckinstdir)
|
|
## if not os.path.exists(dir_):
|
|
## raise SCons.Errors.BuildError(target, "%s does not exist" % dir_)
|
|
## Execute(Delete(distcheckinstdir))
|
|
## Execute(Delete(distcheckdestdir))
|
|
## Execute(Delete(distdir))
|
|
##
|
|
## def InstallWithDestDir(self, dir_, source):
|
|
## dir_ = '${DESTDIR}' + str(dir_)
|
|
## return SConsEnvironment.Install(self, dir_, source)
|
|
##
|
|
##
|
|
## def InstallAsWithDestDir(self, target, source):
|
|
## target = '${DESTDIR}' + str(target)
|
|
## return SConsEnvironment.InstallAs(self, target, source)
|
|
##
|
|
## def generate(env):
|
|
## env.EnsureSConsVersion(0, 96, 91)
|
|
##
|
|
## opts = Options(['options.cache'], ARGUMENTS)
|
|
## opts.Add(PathOption('prefix', 'Installation prefix', '/usr/local'))
|
|
## opts.Add(PathOption('exec_prefix', 'Installation prefix blah blah',
|
|
## '$prefix'))
|
|
## opts.Add(PathOption('libdir',
|
|
## 'Installation prefix for architecture dependent files', '$prefix/lib'))
|
|
## opts.Add(PathOption('includedir',
|
|
## 'Installation prefix for C header files', '$prefix/include'))
|
|
## opts.Add(PathOption('datadir',
|
|
## 'Installation prefix for architecture independent files', '$prefix/share'))
|
|
## opts.Add(PathOption('bindir', 'Installation prefix for programs', '$prefix/bin'))
|
|
## opts.Add(PathOption('DESTDIR', 'blah blah', None))
|
|
## opts.Update(env)
|
|
## opts.Save('options.cache', env)
|
|
## SConsEnvironment.Help(env, opts.GenerateHelpText(env))
|
|
##
|
|
## env.Append(CPPFLAGS=r' -DVERSION=\"$VERSION\"')
|
|
## env.Append(CCFLAGS=ARGUMENTS.get('CCFLAGS', '-g -O2'))
|
|
##
|
|
## env['GNOME_TESTS'] = dict(CheckPython=CheckPython,
|
|
## CheckPythonHeaders=CheckPythonHeaders,
|
|
## PkgCheckModules=PkgCheckModules)
|
|
##
|
|
## SConsEnvironment.DistSources = DistSources
|
|
## SConsEnvironment.DistFiles = DistFiles
|
|
## env['DISTDIR'] = "${PACKAGE}-${VERSION}"
|
|
##
|
|
## #env.Command(env.Dir("$DISTDIR"), None, make_distdir)
|
|
##
|
|
## distdir_alias = env.Alias("distdir", None, make_distdir)
|
|
## dist_alias = env.Alias("dist", None, make_dist)
|
|
## env.Depends(dist_alias, distdir_alias)
|
|
## distcheck_alias = env.Alias("distcheck", None, make_distcheck)
|
|
## env.Depends(distcheck_alias, distdir_alias)
|
|
## env.AlwaysBuild(env.Alias('check'))
|
|
##
|
|
## #env['TARFLAGS'] ='-c -z'
|
|
## #env['TARSUFFIX'] = '.tar.gz'
|
|
## #tar = env.Tar('${PACKAGE}-${VERSION}.tar.gz', "${DISTDIR}")
|
|
## #env.Depends(tar, distdir_alias)
|
|
## #print env['DEFAULT_TARGETS']
|
|
##
|
|
## #env.Depends(distdir_alias, "${DISTFILES}")
|
|
## #env.Alias('dist', tar)
|
|
## env.AlwaysBuild('dist')
|
|
## env.AlwaysBuild('distdir')
|
|
## env.AlwaysBuild('distcheck')
|
|
## env.DistFiles(['SConstruct', 'scons/gnome.py'])
|
|
##
|
|
## env['BUILDERS']['EnvSubstFile'] = SCons.Builder.Builder(action=env_subst)
|
|
##
|
|
## SConsEnvironment.PythonByteCompile = env.Action(byte_compile_python)
|
|
##
|
|
## env.Install = new.instancemethod(InstallWithDestDir, env, env.__class__)
|
|
## env.InstallAs = new.instancemethod(InstallAsWithDestDir, env, env.__class__)
|
|
##
|
|
##
|
|
##
|
|
|