mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-01 05:25:55 +00:00
Remove outdated, unmaintained build system. Still one to go ;-)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40780 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
1585015805
commit
360b94ee35
357
INSTALL.scons
357
INSTALL.scons
@ -1,357 +0,0 @@
|
|||||||
=========================
|
|
||||||
Building LyX with SCons
|
|
||||||
=========================
|
|
||||||
|
|
||||||
July, 2006
|
|
||||||
|
|
||||||
|
|
||||||
The GNU Build System (autoconf, automake and make) has been used to build
|
|
||||||
and distribute lyx. These de facto *nix tools are readily available and
|
|
||||||
widely supported on the *nix systems, but not so under windows. They are
|
|
||||||
not necessarily easy to use and maintain (at least to non-m4 experts)
|
|
||||||
either. Because of these, a scons (http://www.scons.org) build system has
|
|
||||||
been set up as an alternative way to build lyx. As of writing, this system
|
|
||||||
only supports the qt4 frontend.
|
|
||||||
|
|
||||||
This file is organized as follows:
|
|
||||||
1. General usage of scons
|
|
||||||
2. *nix systems (Linux, Solaris and Mac OSX)
|
|
||||||
3. Windows/mingw
|
|
||||||
4. Windows/cygwin
|
|
||||||
5. Windows/msvc
|
|
||||||
6. Tips and hints
|
|
||||||
7. Troubleshooting
|
|
||||||
|
|
||||||
|
|
||||||
1. General usage of scons
|
|
||||||
=========================
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
--------------
|
|
||||||
|
|
||||||
* Python:
|
|
||||||
Python >= 2.6.0 is required to run scons, while LyX itself requires
|
|
||||||
Python >= 2.4.0 for scripts such as configure.py. Python is widely
|
|
||||||
available on non-windows systems. Windows users can download and
|
|
||||||
install python from http://www.python.org.
|
|
||||||
|
|
||||||
* SCons:
|
|
||||||
scons >= 1.1.0 is needed. You can either use a full system-wide scons
|
|
||||||
distribution or a light-weight one (called scons-local) installed along
|
|
||||||
with the lyx source tree. Both variants of scons are freely available
|
|
||||||
from http://www.scons.org. Note that LyX source may ship with scons-base
|
|
||||||
in the near future.
|
|
||||||
|
|
||||||
* Other libraries:
|
|
||||||
These include zlib (required), qt4 (required), gettext
|
|
||||||
(optional), boost (optional), aspell (optional) and Aiksaurus
|
|
||||||
(optional). Please refer to the system-specific sections regarding the
|
|
||||||
availability and installation of them.
|
|
||||||
|
|
||||||
|
|
||||||
Start scons:
|
|
||||||
------------
|
|
||||||
|
|
||||||
The scons system resides under development/scons. You can invoke it from
|
|
||||||
either development/scons by, for example:
|
|
||||||
> cd development/scons
|
|
||||||
> scons frontend=qt4 qt_dir=d:/qt4 -j3 lyx
|
|
||||||
or from any other directory and use -f option to point to the SConstruct
|
|
||||||
file:
|
|
||||||
> mkdir build
|
|
||||||
> cd build
|
|
||||||
> scons -f ../development/scons/SConstruct frontend=qt4 all
|
|
||||||
If you are tired of typing development/scons/SConstruct, you can link
|
|
||||||
development/scons/SConstruct to the top source directory and use this
|
|
||||||
SConstruct file.
|
|
||||||
|
|
||||||
There are three types of command line options:
|
|
||||||
* key=value are user options. They are used to tell scons which
|
|
||||||
frontend to use, whether or not use included boost libraries etc.
|
|
||||||
You can use 'scons -h' to list all of the options.
|
|
||||||
* parameters start with - or -- are scons options. Useful ones include
|
|
||||||
-j3 (with three threads) and --config=force (force reconfiguration).
|
|
||||||
* others options are targets, which are lyx objects to build.
|
|
||||||
|
|
||||||
|
|
||||||
User Options:
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Here I only list important options that you will likely use. Full option
|
|
||||||
list with detailed description and default value can be displayed using
|
|
||||||
command 'scons -h'.
|
|
||||||
|
|
||||||
Components to use/build:
|
|
||||||
|
|
||||||
* frontend=qt4: qt4 is the only option right now.
|
|
||||||
* mode=debug/release: lyx will be built under the debug or release
|
|
||||||
directory, with different default build options.
|
|
||||||
* boost=included/system/auto: whether or not use included boost, system
|
|
||||||
boost, or try to detect system boost first. Note that boost=included
|
|
||||||
is safer if system boost has a different version from the included
|
|
||||||
one.
|
|
||||||
* gettext=included/system/auto
|
|
||||||
* nls=yes/no whether or not enable natural language support.
|
|
||||||
* spell=aspell/auto: spell engine
|
|
||||||
|
|
||||||
|
|
||||||
Paths: Most of them will be probed if not specified.
|
|
||||||
|
|
||||||
* qt_dir: top level directory of qt (with at least subdirectory bin
|
|
||||||
containing commands uic and moc)
|
|
||||||
* qt_lib_path: path to the qt library, use only if there is no
|
|
||||||
$qt_dir/lib
|
|
||||||
* qt_inc_path: path to qt include directory, use only if there is no
|
|
||||||
$qt_dir/include
|
|
||||||
* extra_inc_path, extra_inc_path1, extra_lib_path, extra_lib_path1:
|
|
||||||
additional paths to other libraries
|
|
||||||
* extra_bin_path: a convenient way to add an extra path to $PATH
|
|
||||||
|
|
||||||
|
|
||||||
Convenience options:
|
|
||||||
|
|
||||||
* load_option=yes/no/opt1,opt2/-opt1,opt2: if true, load previously saved
|
|
||||||
command line options so you can run 'scons install' directly after a
|
|
||||||
long 'scons all' building command. You can load selected options using
|
|
||||||
load_option=opt1,opt2,... or exclude options using the - version of it.
|
|
||||||
Note that the option 'bundle' is not reloaded.
|
|
||||||
* rebuild=target1,target2... By default, scons will exam all components
|
|
||||||
when you build lyx. You can free scons from some hard work and save
|
|
||||||
yourself some time by telling scons to rebuild only specified
|
|
||||||
component(s). rebuild=no, none, yes or all can be used as well.
|
|
||||||
* log_file: a log file of executed commands, default to scons_lyx.log
|
|
||||||
|
|
||||||
|
|
||||||
Installation options:
|
|
||||||
|
|
||||||
* prefix: directory where lyx will be installed
|
|
||||||
* exec_dir: directory where lyx binaries will be installed.
|
|
||||||
Default to $prefix/bin
|
|
||||||
* DESTDIR: if specified, install to this directory instead of $prefix.
|
|
||||||
* version_suffix=yes/no/something : if specified, this suffix will be
|
|
||||||
appended to the user data directory.
|
|
||||||
* win_installer: if specified under windows, and if 'installer' target
|
|
||||||
is given, generate NSIS installer specifed as win_installer which can
|
|
||||||
be a full path name. The default is lyx-version-timestamp-Installer.exe
|
|
||||||
for a development version, and lyx-version-Installer.exe for a released
|
|
||||||
version.
|
|
||||||
|
|
||||||
|
|
||||||
Compiler choice and flags:
|
|
||||||
* use_vc: use msvc instead of mingw g++ under windows
|
|
||||||
* optimization: optimization flag to use (e.g. -O2)
|
|
||||||
* CC, LINK, CPP, CXX, CCFLAGS, LINKFLAGS etc: compiler commands and
|
|
||||||
flags. Setting CCFLAGS etc will replace default flags. These variables
|
|
||||||
can be set as environment variables as well.
|
|
||||||
|
|
||||||
|
|
||||||
Targets:
|
|
||||||
--------
|
|
||||||
|
|
||||||
You can specify one or more of the following targets:
|
|
||||||
|
|
||||||
Static libraries (names correspond to their directories):
|
|
||||||
boost, intl, support, mathed, insets, frontends, graphics,
|
|
||||||
controllers, client, qt4, lyxbase
|
|
||||||
Programs:
|
|
||||||
tex2lyx, client, lyx, all = tex2lyx + client + lyx
|
|
||||||
Installation:
|
|
||||||
po, install = all + po, installer (windows only, need NSIS)
|
|
||||||
Misc:
|
|
||||||
msvs_projects, update_po
|
|
||||||
|
|
||||||
Your built targets are put into $build_dir, which is debug (mode=debug),
|
|
||||||
release (mode=release) or any name specified via build_dir=name. The
|
|
||||||
directory structure is:
|
|
||||||
$build_dir
|
|
||||||
- common: most of the intermediate files, mostly object files
|
|
||||||
- libs: all static libraries
|
|
||||||
- executables: lyxclient, tex2lyx, lyx
|
|
||||||
|
|
||||||
MSVS projects will be put to development/scons (and you should invoke
|
|
||||||
scons from there for this target).
|
|
||||||
|
|
||||||
update_po is similar to 'cd po; make update-po' but does not generate
|
|
||||||
.gmo files, which is the task of the install target. Note that this
|
|
||||||
target is the only target that changes files (po/*.po in this case)
|
|
||||||
of the lyx source tree.
|
|
||||||
|
|
||||||
|
|
||||||
A typical working sequence:
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
> cd development/scons
|
|
||||||
> scons frontend=qt4 qt_dir=/path/to/qt4
|
|
||||||
(build lyx, and all needed libraries...)
|
|
||||||
> scons all -j3
|
|
||||||
(build lyx, client and tex2lyx, options like qt_dir will be carried
|
|
||||||
over here)
|
|
||||||
> scons rebuild=lyxbase
|
|
||||||
(working on LyX.cpp, so only need to rebuild lyxbase)
|
|
||||||
> scons
|
|
||||||
(build again, only lyxbase will be rebuilt)
|
|
||||||
> scons prefix=/usr/site DESTDIR=/install/dir
|
|
||||||
(lyx is built for /usr/site, but install to /install/dir)
|
|
||||||
|
|
||||||
|
|
||||||
2. *nix systems (Linux, Solaris and Mac OSX)
|
|
||||||
============================================
|
|
||||||
|
|
||||||
Proper use of extra_inc_path, qt_dir etc should solve most of the
|
|
||||||
problems.
|
|
||||||
|
|
||||||
|
|
||||||
3. Windows/mingw
|
|
||||||
================
|
|
||||||
|
|
||||||
* install mingw with the following packages:
|
|
||||||
binutils-2.16.91-...tar.gz
|
|
||||||
gcc-core-3.4.5-...tar.gz
|
|
||||||
gcc-g++-3.4.5-...tar.gz
|
|
||||||
mingw-runtime-3.9.tar.gz
|
|
||||||
mingw-utils-0.3.tar.gz
|
|
||||||
MSYS-1.0.11-...exe
|
|
||||||
msysDTK-1.0.1.exe
|
|
||||||
w32api-3.6.tar.gz
|
|
||||||
|
|
||||||
* install the latest Qt official "open source" binary package for
|
|
||||||
Windows/Mingw (required)
|
|
||||||
|
|
||||||
* install mingw/zlib (required):
|
|
||||||
Download zlib binaries and developer files (zlib-1.2.3-bin.zip and
|
|
||||||
zlib-1.2.3-lib.zip) from http://gnuwin32.sourceforge.net/packages/zlib.htm .
|
|
||||||
|
|
||||||
* install iconv (optional):
|
|
||||||
Download libiconv from http://gnuwin32.sourceforge.net/packages/libiconv.htm
|
|
||||||
The complete package (without source) is recommended.
|
|
||||||
|
|
||||||
You may also try the windows binary (libiconv-x.x.x.bin.woe32.zip) of
|
|
||||||
iconv from one of the GNU mirrors listed in http://www.gnu.org/prep/ftp.html.
|
|
||||||
|
|
||||||
* install gettext (optional):
|
|
||||||
Download gettext from http://gnuwin32.sourceforge.net/packages/gettext.htm
|
|
||||||
The complete package (without source) is recommended.
|
|
||||||
|
|
||||||
You may also try the windows binary (gettext-runtime-x.x.x.bin.woe32.zip
|
|
||||||
and gettext-tools-x.x.x.bin.woe32.zip) from one of the GNU mirrors
|
|
||||||
(e.g. http://mirrors.usc.edu/pub/gnu/gettext/).
|
|
||||||
|
|
||||||
* install aspell (optional):
|
|
||||||
LyX uses aspell 0.60.4 and there is no, as of now, official windows
|
|
||||||
version. If you do not want to compile aspell from source by yourself,
|
|
||||||
your best bet is using Abdel's lyx 1.5.0svn experimental package located
|
|
||||||
at http://wiki.lyx.org/Windows/LyX150Experimental. The link to his
|
|
||||||
pre-built aspell package is http://younes.a.free.fr/Lyx-15-experimental
|
|
||||||
|
|
||||||
* install aiksaurus (optional):
|
|
||||||
Try to build aiksaurus from source (both mingw or msvc should work),
|
|
||||||
or look for pre-built package from the lyx 1.5.0svn experimental page.
|
|
||||||
|
|
||||||
* Open a mingw xterm, and start scons as usual.
|
|
||||||
|
|
||||||
Note: gettext, iconv and zlib are usually decompressed to c:/mingw so no
|
|
||||||
extra_inc_path etc is needed.
|
|
||||||
|
|
||||||
|
|
||||||
4. Windows/cygwin
|
|
||||||
=================
|
|
||||||
|
|
||||||
To build lyx for cygwin, you should
|
|
||||||
|
|
||||||
* install (using the cygwin setup program) at least the following
|
|
||||||
packages and all other packages pulled in by dependencies:
|
|
||||||
|
|
||||||
aspell gzip libiconv libQtGui4
|
|
||||||
aspell-dev gettext libpng libQtGui4-devel
|
|
||||||
gcc gettext-devel libQtCore4 pkg-config
|
|
||||||
gcc4 libintl8 libQtCore4-devel python
|
|
||||||
|
|
||||||
* install aiksaurus (http://aiksaurus.sourceforge.net/, optional):
|
|
||||||
There is no cygwin package for aiksaurus, so you should build it from
|
|
||||||
source. However, aiksaurus builds smoothly on cygwin.
|
|
||||||
|
|
||||||
* run scons as you would do under linux.
|
|
||||||
|
|
||||||
Note: cygwin/qt does not follow the usual $qt_dir/include, $qt_dir/bin,
|
|
||||||
$qt_dir/lib directory structure. For example, cygwin/qt4 uses directories
|
|
||||||
/usr/include/qt4, /usr/lib/qt4/bin and /usr/lib/qt4/lib. If these
|
|
||||||
directories can not be detected automatically, use options, for example,
|
|
||||||
qt_dir=/usr/lib/qt4 qt_inc_path=/usr/include/qt4
|
|
||||||
|
|
||||||
|
|
||||||
5. Windows/msvc
|
|
||||||
===============
|
|
||||||
|
|
||||||
To build lyx with msvc, you should
|
|
||||||
|
|
||||||
* install msvc
|
|
||||||
It is recommended that you use MSVC2005 Express edition which is
|
|
||||||
freely available from microsoft.
|
|
||||||
|
|
||||||
* get windows platform SDK
|
|
||||||
Please follow the link in the MSVC webpage to download and configure.
|
|
||||||
It is important that you add SDK paths to %INCLUDE% and %LIB% in, e.g.,
|
|
||||||
C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\vsvars32.bat.
|
|
||||||
If you plan to use the MSVS IDE, you should also update the Visual C++
|
|
||||||
directories in VCProjectEngine.dll.express.config, as suggested in
|
|
||||||
http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/.
|
|
||||||
|
|
||||||
* build qt4
|
|
||||||
- download qt4 source from trolltech (not the binary version, which
|
|
||||||
only works with mingw)
|
|
||||||
- get q../free patch for qt4
|
|
||||||
- compile qt4 as instructed
|
|
||||||
|
|
||||||
* download and install the official zlib library from www.zlib.org.
|
|
||||||
|
|
||||||
* optionally install iconv, gettext, aspell, aiksaurus following
|
|
||||||
the mingw instructions.
|
|
||||||
|
|
||||||
* start from msvc command prompt, use the use_vc option to build lyx.
|
|
||||||
You may need to use extra_inc_path etc to point to zlib paths.
|
|
||||||
|
|
||||||
* you can use the msvs_projects target to obtain msvc project files
|
|
||||||
for each lyx component.
|
|
||||||
- go to development/scons (important)
|
|
||||||
- run
|
|
||||||
> scons [other options] msvs_projects
|
|
||||||
Note that
|
|
||||||
- The resulting project files will use scons to build lyx
|
|
||||||
- All command line options, including rebuild, can be used as usual
|
|
||||||
(when msvs invoke scons).
|
|
||||||
- To use the msvc debugger, you have to use mode=debug (default).
|
|
||||||
|
|
||||||
|
|
||||||
6. Tips and hints
|
|
||||||
=================
|
|
||||||
|
|
||||||
* Using external boost libraries (install boost libraries and use
|
|
||||||
option boost=system) can speed up scons' starting time a lot, since
|
|
||||||
the boost headers will then be considered as system headers and will
|
|
||||||
not be included in the dependency tree.
|
|
||||||
|
|
||||||
|
|
||||||
7. Troubleshooting
|
|
||||||
==================
|
|
||||||
|
|
||||||
When you get an error:
|
|
||||||
|
|
||||||
Q. Some path is not found.
|
|
||||||
A, Try options such as extra_inc_path, extra_lib_path.
|
|
||||||
|
|
||||||
Q. A test fails (failed to find zlib etc).
|
|
||||||
A. Have a look at config.log.
|
|
||||||
|
|
||||||
Q. I get a linking error.
|
|
||||||
A. Get the command sequence from scons_lyx.log and see what could
|
|
||||||
have gone wrong. You usually only need to tweak the last linking
|
|
||||||
command.
|
|
||||||
|
|
||||||
Q. Still can not figure it out.
|
|
||||||
A. Send an email to lyx-devel mailing list.
|
|
||||||
|
|
||||||
Q. Feeling too impatient/adventurous to wait for list response.
|
|
||||||
A. Read SConstruct and SConscript and see what went wrong. Trust me, they
|
|
||||||
are much easier to decipher than the autoconf/m4 files.
|
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ SUBDIRS = config development intl po $(BOOST) src sourcedoc lib \
|
|||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = ANNOUNCE INSTALL.autoconf RELEASE-NOTES UPGRADING \
|
EXTRA_DIST = ANNOUNCE INSTALL.autoconf RELEASE-NOTES UPGRADING \
|
||||||
INSTALL.Win32 INSTALL.MacOSX INSTALL.scons INSTALL.cmake \
|
INSTALL.Win32 INSTALL.MacOSX INSTALL.cmake \
|
||||||
README.Win32 README.Cygwin README.localization lyx.1in \
|
README.Win32 README.Cygwin README.localization lyx.1in \
|
||||||
autogen.sh
|
autogen.sh
|
||||||
|
|
||||||
|
@ -15,27 +15,13 @@ To build lyx, you will need to install the following cygwin packages
|
|||||||
gcc gettext-devel libQtCore4 pkg-config
|
gcc gettext-devel libQtCore4 pkg-config
|
||||||
gcc4 libintl8 libQtCore4-devel python
|
gcc4 libintl8 libQtCore4-devel python
|
||||||
|
|
||||||
Two building systems can be used to build lyx on cygwin: the traditional
|
Currently only the traditional autotools (autoconf, automake, make etc)
|
||||||
autotools (autoconf, automake, make etc), and a scons build system.
|
build system is recommended to build LyX on cygwin. It does not differ
|
||||||
The former is the preferred method and it does not differ from building lyx
|
from building lyx on any typical posix system, so you are referred to the
|
||||||
on any typical posix system, so you are referred to the INSTALL file.
|
INSTALL file.
|
||||||
Note that it is not advisable using the cmake build system on cygwin for
|
Note that it is not advisable using the cmake build system on cygwin for
|
||||||
the reasons explained here: http://www.cmake.org/Bug/view.php?id=10122
|
the reasons explained here: http://www.cmake.org/Bug/view.php?id=10122
|
||||||
|
|
||||||
If you prefer using scons, you will have to install it separately, as it
|
|
||||||
is not available as a cygwin package, and then build lyx with the command
|
|
||||||
|
|
||||||
> python scons.py -f development/scons/SConstruct mode=release install
|
|
||||||
|
|
||||||
Optionally, you can install to a DESTDIR using a command similar to
|
|
||||||
|
|
||||||
> python scons.py -f development/scons/SConstruct mode=release DESTDIR=./test install
|
|
||||||
|
|
||||||
For more details about the use of scons, please refer to INSTALL.scons.
|
|
||||||
However, be aware that scons is not fully supported on cygwin and you may
|
|
||||||
be missing some features (reverse dvi/pdf search, for example) and some
|
|
||||||
cygwin-specific ancillary programs that you get when building with autotools.
|
|
||||||
|
|
||||||
When lyx is built as outlined above, it will be a X-Window application,
|
When lyx is built as outlined above, it will be a X-Window application,
|
||||||
so you will need a X-server for running it. It is possible to build lyx
|
so you will need a X-server for running it. It is possible to build lyx
|
||||||
as a cygwin application but using the native Windows GDI backend instead
|
as a cygwin application but using the native Windows GDI backend instead
|
||||||
|
@ -127,10 +127,6 @@ Win32/packaging/AltInstaller/specials/PDFViewWin/PDFViewWin.res \
|
|||||||
Win32/packaging/AltInstaller/specials/AspellRepositories.txt \
|
Win32/packaging/AltInstaller/specials/AspellRepositories.txt \
|
||||||
Win32/packaging/AltInstaller/specials/AspellDictionaryNames.txt \
|
Win32/packaging/AltInstaller/specials/AspellDictionaryNames.txt \
|
||||||
Win32/pdfview/pdfview.nsi \
|
Win32/pdfview/pdfview.nsi \
|
||||||
scons/qt4.py \
|
|
||||||
scons/scons_manifest.py \
|
|
||||||
scons/SConstruct \
|
|
||||||
scons/scons_utils.py \
|
|
||||||
Win32/packaging/installer/lyx.nsi.cmake \
|
Win32/packaging/installer/lyx.nsi.cmake \
|
||||||
Win32/packaging/installer/settings.nsh.cmake \
|
Win32/packaging/installer/settings.nsh.cmake \
|
||||||
Win32/vld/cmake/CMakeLists.txt \
|
Win32/vld/cmake/CMakeLists.txt \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# this script compiles the three different installer variants at once
|
# this script compiles the three different installer variants at once
|
||||||
# this is necessary when the installer should e.g. be built by SCons or CMake
|
# this is necessary when the installer should e.g. be built by CMake
|
||||||
|
|
||||||
SetCompressor /SOLID lzma
|
SetCompressor /SOLID lzma
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
|||||||
call scons install prefix=..\..\build-msvc use_vc=yes spell=hunspell frontend=qt4 mode=release version_suffix=21 gettext=system nls=yes extra_inc_path=..\..\lyx-windows-deps-msvc2010\include extra_lib_path=..\..\lyx-windows-deps-msvc2010\lib extra_bin_path=..\..\lyx-windows-deps-msvc2010\bin qt_dir=..\..\..\..\Qt
|
|
@ -1,2 +0,0 @@
|
|||||||
call scons install prefix=..\..\build-msvc use_vc=yes frontend=qt4 mode=debug version_suffix=20 gettext=system nls=yes extra_inc_path=..\..\lyx-windows-deps-msvc2008\include extra_lib_path=..\..\lyx-windows-deps-msvc2008\lib extra_bin_path=..\..\lyx-windows-deps-msvc2008\bin qt_dir=..\..\lyx-windows-deps-msvc2008\qt-4
|
|
||||||
call scons msvs_projects
|
|
@ -1,373 +0,0 @@
|
|||||||
import re
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
|
|
||||||
class ToolQtWarning(SCons.Warnings.Warning):
|
|
||||||
pass
|
|
||||||
class GeneratedMocFileNotIncluded(ToolQtWarning):
|
|
||||||
pass
|
|
||||||
class QtdirNotFound(ToolQtWarning):
|
|
||||||
pass
|
|
||||||
SCons.Warnings.enableWarningClass(ToolQtWarning)
|
|
||||||
|
|
||||||
qrcinclude_re = re.compile(r'<file>([^<]*)</file>', re.M)
|
|
||||||
|
|
||||||
|
|
||||||
header_extensions = [".h", ".hxx", ".hpp", ".hh"]
|
|
||||||
if SCons.Util.case_sensitive_suffixes('.h', '.H'):
|
|
||||||
header_extensions.append('.H')
|
|
||||||
#cplusplus = __import__('c++', globals(), locals(), ['Scons.Tools'])
|
|
||||||
#cxx_suffixes = cplusplus.CXXSuffixes
|
|
||||||
cxx_suffixes = [".C", ".c", ".cxx", ".cpp", ".cc"]
|
|
||||||
|
|
||||||
def _checkMocIncluded(target, source, env):
|
|
||||||
moc = target[0]
|
|
||||||
cpp = source[0]
|
|
||||||
# looks like cpp.includes is cleared before the build stage :-(
|
|
||||||
# not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/
|
|
||||||
path = SCons.Defaults.CScan.path_function(env, moc.cwd)
|
|
||||||
includes = SCons.Defaults.CScan(cpp, env, path)
|
|
||||||
if not moc in includes:
|
|
||||||
SCons.Warnings.warn(
|
|
||||||
GeneratedMocFileNotIncluded,
|
|
||||||
"Generated moc file '%s' is not included by '%s'" %
|
|
||||||
(str(moc), str(cpp)))
|
|
||||||
|
|
||||||
def _find_file(filename, paths, node_factory):
|
|
||||||
retval = None
|
|
||||||
for dir in paths:
|
|
||||||
node = node_factory(filename, dir)
|
|
||||||
if node.rexists():
|
|
||||||
return node
|
|
||||||
return None
|
|
||||||
|
|
||||||
class _Automoc:
|
|
||||||
"""
|
|
||||||
Callable class, which works as an emitter for Programs, SharedLibraries and
|
|
||||||
StaticLibraries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, objBuilderName):
|
|
||||||
self.objBuilderName = objBuilderName
|
|
||||||
|
|
||||||
def __call__(self, target, source, env):
|
|
||||||
"""
|
|
||||||
Smart autoscan function. Gets the list of objects for the Program
|
|
||||||
or Lib. Adds objects and builders for the special qt files.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if int(env.subst('$QT_AUTOSCAN')) == 0:
|
|
||||||
return target, source
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
debug = int(env.subst('$QT_DEBUG'))
|
|
||||||
except ValueError:
|
|
||||||
debug = 0
|
|
||||||
|
|
||||||
# some shortcuts used in the scanner
|
|
||||||
FS = SCons.Node.FS.default_fs
|
|
||||||
splitext = SCons.Util.splitext
|
|
||||||
objBuilder = getattr(env, self.objBuilderName)
|
|
||||||
|
|
||||||
# some regular expressions:
|
|
||||||
# Q_OBJECT detection
|
|
||||||
q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]')
|
|
||||||
# cxx and c comment 'eater'
|
|
||||||
#comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)')
|
|
||||||
# CW: something must be wrong with the regexp. See also bug #998222
|
|
||||||
# CURRENTLY THERE IS NO TEST CASE FOR THAT
|
|
||||||
|
|
||||||
# The following is kind of hacky to get builders working properly (FIXME)
|
|
||||||
objBuilderEnv = objBuilder.env
|
|
||||||
objBuilder.env = env
|
|
||||||
mocBuilderEnv = env.Moc4.env
|
|
||||||
env.Moc4.env = env
|
|
||||||
|
|
||||||
# make a deep copy for the result; MocH objects will be appended
|
|
||||||
out_sources = source[:]
|
|
||||||
|
|
||||||
for obj in source:
|
|
||||||
if not obj.has_builder():
|
|
||||||
# binary obj file provided
|
|
||||||
if debug:
|
|
||||||
print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj)
|
|
||||||
continue
|
|
||||||
cpp = obj.sources[0]
|
|
||||||
if not splitext(str(cpp))[1] in cxx_suffixes:
|
|
||||||
if debug:
|
|
||||||
print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp)
|
|
||||||
# c or fortran source
|
|
||||||
continue
|
|
||||||
#cpp_contents = comment.sub('', cpp.get_contents())
|
|
||||||
cpp_contents = cpp.get_contents()
|
|
||||||
h=None
|
|
||||||
for h_ext in header_extensions:
|
|
||||||
# try to find the header file in the corresponding source
|
|
||||||
# directory
|
|
||||||
hname = splitext(cpp.name)[0] + h_ext
|
|
||||||
h = _find_file(hname,
|
|
||||||
(cpp.get_dir(),),
|
|
||||||
FS.File)
|
|
||||||
if h:
|
|
||||||
if debug:
|
|
||||||
print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp))
|
|
||||||
#h_contents = comment.sub('', h.get_contents())
|
|
||||||
h_contents = h.get_contents()
|
|
||||||
break
|
|
||||||
if not h and debug:
|
|
||||||
print "scons: qt: no header for '%s'." % (str(cpp))
|
|
||||||
if h and q_object_search.search(h_contents):
|
|
||||||
# h file with the Q_OBJECT macro found -> add moc_cpp
|
|
||||||
moc_cpp = env.Moc4(h)
|
|
||||||
moc_o = objBuilder(moc_cpp)
|
|
||||||
out_sources.append(moc_o)
|
|
||||||
#moc_cpp.target_scanner = SCons.Defaults.CScan
|
|
||||||
if debug:
|
|
||||||
print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp))
|
|
||||||
if cpp and q_object_search.search(cpp_contents):
|
|
||||||
# cpp file with Q_OBJECT macro found -> add moc
|
|
||||||
# (to be included in cpp)
|
|
||||||
moc = env.Moc4(cpp)
|
|
||||||
env.Ignore(moc, moc)
|
|
||||||
if debug:
|
|
||||||
print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))
|
|
||||||
#moc.source_scanner = SCons.Defaults.CScan
|
|
||||||
# restore the original env attributes (FIXME)
|
|
||||||
objBuilder.env = objBuilderEnv
|
|
||||||
env.Moc4.env = mocBuilderEnv
|
|
||||||
|
|
||||||
return (target, out_sources)
|
|
||||||
|
|
||||||
AutomocShared = _Automoc('SharedObject')
|
|
||||||
AutomocStatic = _Automoc('StaticObject')
|
|
||||||
|
|
||||||
def _detect(env):
|
|
||||||
"""Not really safe, but fast method to detect the QT library"""
|
|
||||||
|
|
||||||
QTDIR = env.get('QTDIR',None)
|
|
||||||
if QTDIR!=None : return QTDIR
|
|
||||||
|
|
||||||
QTDIR = os.environ.get('QTDIR',None)
|
|
||||||
if QTDIR!=None : return QTDIR
|
|
||||||
|
|
||||||
moc = env.WhereIs('moc-qt4') or env.WhereIs('moc')
|
|
||||||
if moc:
|
|
||||||
SCons.Warnings.warn(
|
|
||||||
QtdirNotFound,
|
|
||||||
"QTDIR variable is not defined, using moc executable as a hint (QTDIR=%s)" % QTDIR)
|
|
||||||
return os.path.dirname(os.path.dirname(moc))
|
|
||||||
|
|
||||||
SCons.Warnings.warn(
|
|
||||||
QtdirNotFound,
|
|
||||||
"Could not detect qt, using empty QTDIR")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for qt to an Environment."""
|
|
||||||
|
|
||||||
print "Loading qt4 tool..."
|
|
||||||
|
|
||||||
def locateQt4Command(env, command, qtdir) :
|
|
||||||
fullpath1 = os.path.join(qtdir,'bin',command +'-qt4')
|
|
||||||
if os.access(fullpath1, os.X_OK) or \
|
|
||||||
os.access(fullpath1+".exe", os.X_OK):
|
|
||||||
return fullpath1
|
|
||||||
fullpath2 = os.path.join(qtdir,'bin',command)
|
|
||||||
if os.access(fullpath2, os.X_OK) or \
|
|
||||||
os.access(fullpath2+".exe", os.X_OK):
|
|
||||||
return fullpath2
|
|
||||||
fullpath = env.Detect([command+'-qt4', command])
|
|
||||||
if not (fullpath is None) : return fullpath
|
|
||||||
raise "Qt4 command '" + command + "' not found. Tried: " + fullpath1 + " and "+ fullpath2
|
|
||||||
|
|
||||||
|
|
||||||
CLVar = SCons.Util.CLVar
|
|
||||||
Action = SCons.Action.Action
|
|
||||||
Builder = SCons.Builder.Builder
|
|
||||||
splitext = SCons.Util.splitext
|
|
||||||
|
|
||||||
# the basics
|
|
||||||
env['QTDIR'] = _detect(env)
|
|
||||||
env['QT4_MOC'] = locateQt4Command(env,'moc', env['QTDIR'])
|
|
||||||
env['QT4_UIC'] = locateQt4Command(env,'uic', env['QTDIR'])
|
|
||||||
env['QT4_RCC'] = locateQt4Command(env,'rcc', env['QTDIR'])
|
|
||||||
env['QT4_LUPDATE'] = locateQt4Command(env,'lupdate', env['QTDIR'])
|
|
||||||
env['QT4_LRELEASE'] = locateQt4Command(env,'lrelease', env['QTDIR'])
|
|
||||||
|
|
||||||
# Should the qt tool try to figure out, which sources are to be moc'ed ?
|
|
||||||
env['QT4_AUTOSCAN'] = 1
|
|
||||||
|
|
||||||
# Some QT specific flags. I don't expect someone wants to
|
|
||||||
# manipulate those ...
|
|
||||||
env['QT4_UICDECLFLAGS'] = CLVar('')
|
|
||||||
env['QT4_MOCFROMHFLAGS'] = CLVar('')
|
|
||||||
env['QT4_MOCFROMCXXFLAGS'] = CLVar('-i')
|
|
||||||
env['QT4_QRCFLAGS'] = '-name Resources'
|
|
||||||
|
|
||||||
# suffixes/prefixes for the headers / sources to generate
|
|
||||||
env['QT4_MOCHPREFIX'] = ''
|
|
||||||
env['QT4_MOCHSUFFIX'] = '$CXXFILESUFFIX'
|
|
||||||
env['QT4_MOCCXXPREFIX'] = 'moc_'
|
|
||||||
env['QT4_MOCCXXSUFFIX'] = '.moc'
|
|
||||||
env['QT4_UISUFFIX'] = '.ui'
|
|
||||||
env['QT4_UICDECLPREFIX'] = 'ui_'
|
|
||||||
env['QT4_UICDECLSUFFIX'] = '.h'
|
|
||||||
env['QT4_QRCSUFFIX'] = '.qrc',
|
|
||||||
env['QT4_QRCCXXSUFFIX'] = '$CXXFILESUFFIX'
|
|
||||||
env['QT4_QRCCXXPREFIX'] = 'qrc_'
|
|
||||||
|
|
||||||
env['QT4_LIB'] = '' # KLUDGE to avoid linking qt3 library
|
|
||||||
|
|
||||||
# Translation builder
|
|
||||||
tsbuilder = Builder(
|
|
||||||
action ='$QT4_LUPDATE $SOURCES -ts $TARGETS',
|
|
||||||
multi=1
|
|
||||||
)
|
|
||||||
env.Append( BUILDERS = { 'Ts': tsbuilder } )
|
|
||||||
qmbuilder = Builder(
|
|
||||||
action =[
|
|
||||||
'$QT4_LRELEASE $SOURCE',
|
|
||||||
],
|
|
||||||
src_suffix = '.ts',
|
|
||||||
suffix = '.qm',
|
|
||||||
single_source = True
|
|
||||||
)
|
|
||||||
env.Append( BUILDERS = { 'Qm': qmbuilder } )
|
|
||||||
|
|
||||||
# Resource builder
|
|
||||||
def scanResources(node, env, path, arg):
|
|
||||||
contents = node.get_contents()
|
|
||||||
includes = qrcinclude_re.findall(contents)
|
|
||||||
return includes
|
|
||||||
qrcscanner = env.Scanner(name = 'qrcfile',
|
|
||||||
function = scanResources,
|
|
||||||
argument = None,
|
|
||||||
skeys = ['.qrc'])
|
|
||||||
qrcbuilder = Builder(
|
|
||||||
action ='$QT4_RCC $QT4_QRCFLAGS $SOURCE -o $TARGET',
|
|
||||||
source_scanner = qrcscanner,
|
|
||||||
src_suffix = '$QT4_QRCSUFFIX',
|
|
||||||
suffix = '$QT4_QRCCXXSUFFIX',
|
|
||||||
prefix = '$QT4_QRCCXXPREFIX',
|
|
||||||
single_source = True
|
|
||||||
)
|
|
||||||
env.Append( BUILDERS = { 'Qrc': qrcbuilder } )
|
|
||||||
|
|
||||||
# Interface builder
|
|
||||||
#env['QT4_UIC4COM'] = [
|
|
||||||
# CLVar('$QT4_UIC $QT4_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'),
|
|
||||||
# ]
|
|
||||||
env['QT4_UIC4COM'] = '$QT4_UIC $QT4_UICDECLFLAGS -o $TARGET $SOURCE'
|
|
||||||
uic4builder = Builder(
|
|
||||||
action='$QT4_UIC4COM',
|
|
||||||
src_suffix='$QT4_UISUFFIX',
|
|
||||||
suffix='$QT4_UICDECLSUFFIX',
|
|
||||||
prefix='$QT4_UICDECLPREFIX',
|
|
||||||
single_source = True
|
|
||||||
)
|
|
||||||
env.Append( BUILDERS = { 'Uic4': uic4builder } )
|
|
||||||
|
|
||||||
# Metaobject builder
|
|
||||||
env['QT4_MOCFROMHCOM'] = (
|
|
||||||
'$QT4_MOC $QT4_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE')
|
|
||||||
env['QT4_MOCFROMCXXCOM'] = [
|
|
||||||
CLVar('$QT4_MOC $QT4_MOCFROMCXXFLAGS -o ${TARGETS[0]} $SOURCE'),
|
|
||||||
Action(_checkMocIncluded,None)]
|
|
||||||
mocBld = Builder(action={}, prefix={}, suffix={})
|
|
||||||
for h in header_extensions:
|
|
||||||
mocBld.add_action(h, '$QT4_MOCFROMHCOM')
|
|
||||||
mocBld.prefix[h] = '$QT4_MOCHPREFIX'
|
|
||||||
mocBld.suffix[h] = '$QT4_MOCHSUFFIX'
|
|
||||||
for cxx in cxx_suffixes:
|
|
||||||
mocBld.add_action(cxx, '$QT4_MOCFROMCXXCOM')
|
|
||||||
mocBld.prefix[cxx] = '$QT4_MOCCXXPREFIX'
|
|
||||||
mocBld.suffix[cxx] = '$QT4_MOCCXXSUFFIX'
|
|
||||||
env.Append( BUILDERS = { 'Moc4': mocBld } )
|
|
||||||
|
|
||||||
# er... no idea what that was for
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
|
||||||
static_obj.src_builder.append('Uic4')
|
|
||||||
shared_obj.src_builder.append('Uic4')
|
|
||||||
|
|
||||||
# We use the emitters of Program / StaticLibrary / SharedLibrary
|
|
||||||
# to scan for moc'able files
|
|
||||||
# We can't refer to the builders directly, we have to fetch them
|
|
||||||
# as Environment attributes because that sets them up to be called
|
|
||||||
# correctly later by our emitter.
|
|
||||||
env.AppendUnique(PROGEMITTER =[AutomocStatic],
|
|
||||||
SHLIBEMITTER=[AutomocShared],
|
|
||||||
LIBEMITTER =[AutomocStatic],
|
|
||||||
# Of course, we need to link against the qt libraries
|
|
||||||
CPPPATH=[os.path.join('$QTDIR', 'include')],
|
|
||||||
LIBPATH=[os.path.join('$QTDIR', 'lib')],
|
|
||||||
LIBS=['$QT4_LIB'])
|
|
||||||
|
|
||||||
import new
|
|
||||||
method = new.instancemethod(enable_modules, env, SCons.Environment)
|
|
||||||
env.EnableQt4Modules=method
|
|
||||||
|
|
||||||
def enable_modules(self, modules, debug=False) :
|
|
||||||
import sys
|
|
||||||
|
|
||||||
validModules = [
|
|
||||||
'QtCore',
|
|
||||||
'QtGui',
|
|
||||||
'QtOpenGL',
|
|
||||||
'Qt3Support',
|
|
||||||
# The next modules have not been tested yet so, please
|
|
||||||
# maybe they require additional work on non Linux platforms
|
|
||||||
'QtSql',
|
|
||||||
'QtNetwork',
|
|
||||||
'QtSvg',
|
|
||||||
'QtTest',
|
|
||||||
'QtXml',
|
|
||||||
'QtUiTools',
|
|
||||||
]
|
|
||||||
pclessModules = [
|
|
||||||
'QtUiTools',
|
|
||||||
'QtUiTools_debug',
|
|
||||||
]
|
|
||||||
invalidModules=[]
|
|
||||||
for module in modules:
|
|
||||||
if module not in validModules :
|
|
||||||
invalidModules.append(module)
|
|
||||||
if invalidModules :
|
|
||||||
raise "Modules %s are not Qt4 modules. Valid Qt4 modules are: %s"% \
|
|
||||||
(str(invalidModules),str(validModules))
|
|
||||||
|
|
||||||
# TODO: Check whether we should add QT_CORE_LIB, QT_XML_LIB, QT_NETWORK_LIB...
|
|
||||||
if 'QtGui' in modules:
|
|
||||||
self.AppendUnique(CPPFLAGS='-DQT_GUI_LIB')
|
|
||||||
|
|
||||||
if sys.platform == "linux2" :
|
|
||||||
if debug : modules = [module+"_debug" for module in modules]
|
|
||||||
for module in modules :
|
|
||||||
if module in pclessModules :
|
|
||||||
# self.AppendUnique(LIBS=[module])
|
|
||||||
self.AppendUnique(LIBPATH=[os.path.join(self["QTDIR"],"lib",module)])
|
|
||||||
self.AppendUnique(CPPPATH=[os.path.join(self["QTDIR"],"include","qt4",module)])
|
|
||||||
modules.remove(module)
|
|
||||||
self.ParseConfig('PKG_CONFIG_PATH=%s/lib:%s/lib/pkgconfig pkg-config %s --libs --cflags'%
|
|
||||||
(
|
|
||||||
self['QTDIR'], self['QTDIR'],
|
|
||||||
' '.join(modules)))
|
|
||||||
return
|
|
||||||
if sys.platform == "win32" :
|
|
||||||
if debug : debugSuffix = 'd'
|
|
||||||
else : debugSuffix = ''
|
|
||||||
self.AppendUnique(LIBS=[lib+'4'+debugSuffix for lib in modules])
|
|
||||||
if 'QtOpenGL' in modules:
|
|
||||||
self.AppendUnique(LIBS=['opengl32'])
|
|
||||||
self.AppendUnique(CPPPATH=[ '$QTDIR/include/'+module
|
|
||||||
for module in modules])
|
|
||||||
self.AppendUnique(LIBPATH=['$QTDIR/lib'])
|
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return _detect(env)
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,909 +0,0 @@
|
|||||||
# vi:filetype=python:expandtab:tabstop=4:shiftwidth=4
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
from SCons.Util import *
|
|
||||||
|
|
||||||
|
|
||||||
def getVerFromConfigure(path):
|
|
||||||
''' get lyx version from the AC_INIT line of configure.ac,
|
|
||||||
packed major and minor version numbers from the lyx version,
|
|
||||||
and LYX_DATE from an AC_SUBST line.
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
config = open(os.path.join(path, 'configure.ac'))
|
|
||||||
except:
|
|
||||||
print "Can not open configure.ac. "
|
|
||||||
return 'x.x.x'
|
|
||||||
# find a line like follows
|
|
||||||
# AC_INIT(LyX,1.4.4svn,[lyx-devel@lists.lyx.org],[lyx])
|
|
||||||
ver_pat = re.compile('AC_INIT\([^,]+,([^,]+),')
|
|
||||||
date_pat = re.compile('AC_SUBST\(LYX_DATE, \["(.*)"\]\)')
|
|
||||||
majmin_pat = re.compile('(\d+)\.(\d+)\..*')
|
|
||||||
version = 'x.x.x'
|
|
||||||
majmin = 'xx'
|
|
||||||
date = 'Not released'
|
|
||||||
for line in config.readlines():
|
|
||||||
if ver_pat.match(line):
|
|
||||||
(version,) = ver_pat.match(line).groups()
|
|
||||||
majmin_match = majmin_pat.match(version)
|
|
||||||
majmin = majmin_match.group(1) + majmin_match.group(2)
|
|
||||||
if date_pat.match(line):
|
|
||||||
(date,) = date_pat.match(line).groups()
|
|
||||||
if version != 'x.x.x' and date != 'Not released':
|
|
||||||
break
|
|
||||||
return version.strip(), majmin.strip(), date.strip()
|
|
||||||
|
|
||||||
|
|
||||||
def relativePath(path, base):
|
|
||||||
'''return relative path from base, which is usually top source dir'''
|
|
||||||
# full pathname of path
|
|
||||||
path1 = os.path.normpath(os.path.realpath(path)).split(os.sep)
|
|
||||||
path2 = os.path.normpath(os.path.realpath(base)).split(os.sep)
|
|
||||||
if path1[:len(path2)] != path2:
|
|
||||||
print "Path %s is not under top source directory" % path
|
|
||||||
if len(path2) == len(path1):
|
|
||||||
return ''
|
|
||||||
path3 = os.path.join(*path1[len(path2):]);
|
|
||||||
# replace all \ by / such that we get the same comments on Windows and *nix
|
|
||||||
path3 = path3.replace('\\', '/')
|
|
||||||
return path3
|
|
||||||
|
|
||||||
|
|
||||||
def isSubDir(path, base):
|
|
||||||
'''Whether or not path is a subdirectory of base'''
|
|
||||||
path1 = os.path.normpath(os.path.realpath(path)).split(os.sep)
|
|
||||||
path2 = os.path.normpath(os.path.realpath(base)).split(os.sep)
|
|
||||||
return len(path2) <= len(path1) and path1[:len(path2)] == path2
|
|
||||||
|
|
||||||
|
|
||||||
def writeToFile(filename, lines, append = False):
|
|
||||||
" utility function: write or append lines to filename "
|
|
||||||
# create directory if needed
|
|
||||||
dir = os.path.split(filename)[0]
|
|
||||||
if dir != '' and not os.path.isdir(dir):
|
|
||||||
os.makedirs(dir)
|
|
||||||
if append:
|
|
||||||
file = open(filename, 'a')
|
|
||||||
else:
|
|
||||||
file = open(filename, 'w')
|
|
||||||
file.write(lines)
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
|
|
||||||
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, v in env.items():
|
|
||||||
try:
|
|
||||||
val = env.subst('$'+k)
|
|
||||||
# temporary fix for the \Resource backslash problem
|
|
||||||
val = val.replace('\\', '/')
|
|
||||||
# multi-line replacement
|
|
||||||
val = val.replace('\n',r'\\n\\\n')
|
|
||||||
contents = re.sub('@'+k+'@', val, contents)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
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_nsis(source, target, env, for_signature):
|
|
||||||
''' Get nsis command line '''
|
|
||||||
def quoteIfSpaced(str):
|
|
||||||
if ' ' in str:
|
|
||||||
return '"' + str + '"'
|
|
||||||
else:
|
|
||||||
return str
|
|
||||||
ret = env['NSIS'] + " /V1 "
|
|
||||||
if env.has_key('NSISFLAGS'):
|
|
||||||
for flag in env['NSISFLAGS']:
|
|
||||||
ret += flag
|
|
||||||
ret += ' '
|
|
||||||
if env.has_key('NSISDEFINES'):
|
|
||||||
for d in env['NSISDEFINES']:
|
|
||||||
ret += '/D'+d
|
|
||||||
if env['NSISDEFINES'][d]:
|
|
||||||
ret += '=' + quoteIfSpaced(env['NSISDEFINES'][d])
|
|
||||||
ret += ' '
|
|
||||||
# bundled?
|
|
||||||
if '-bundle.exe' in str(target[0]):
|
|
||||||
ret += '/DSETUPTYPE=BUNDLE '
|
|
||||||
for s in source:
|
|
||||||
ret += quoteIfSpaced(str(s))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def env_toc(target, source, env):
|
|
||||||
'''Generate target from source files'''
|
|
||||||
# this is very tricky because we need to use installed lyx2lyx with
|
|
||||||
# correct lyx2lyx_version.py
|
|
||||||
sys.path.append(env['LYX2LYX_DEST'])
|
|
||||||
sys.path.append(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
|
|
||||||
import doc_toc
|
|
||||||
# build toc
|
|
||||||
doc_toc.build_toc(str(target[0]), [file.abspath for file in source])
|
|
||||||
|
|
||||||
|
|
||||||
def env_cat(target, source, env):
|
|
||||||
'''Cat source > target. Avoid pipe to increase portability'''
|
|
||||||
output = open(env.File(target[0]).abspath, 'w')
|
|
||||||
for src in source:
|
|
||||||
input = open(env.File(src).abspath)
|
|
||||||
output.write(input.read())
|
|
||||||
input.close()
|
|
||||||
output.close()
|
|
||||||
|
|
||||||
|
|
||||||
def env_potfiles(target, source, env):
|
|
||||||
'''Build po/POTFILES.in'''
|
|
||||||
# command
|
|
||||||
# grep -l '_(\".*\")' `find src \( -name '*.h' -o -name '*.cpp' -o -name '*.cpp.in' \) -print` | grep -v -e "src/support/Package.cpp$$" | sort | uniq
|
|
||||||
# is used under *nix but windows users have to do these all in python
|
|
||||||
target_file = open(str(target[0]), "w")
|
|
||||||
potfiles = []
|
|
||||||
trans = re.compile('_\(".*"\)', re.M)
|
|
||||||
for file in source:
|
|
||||||
rel_file = relativePath(str(file), env.subst('$TOP_SRCDIR'))
|
|
||||||
if rel_file not in potfiles and trans.search(open(str(file)).read()):
|
|
||||||
potfiles.append(rel_file)
|
|
||||||
potfiles.sort()
|
|
||||||
print >> target_file, '\n'.join(potfiles)
|
|
||||||
target_file.close()
|
|
||||||
|
|
||||||
|
|
||||||
def createResFromIcon(env, icon_file, rc_file):
|
|
||||||
''' create a rc file with icon, and return res file (windows only) '''
|
|
||||||
if os.name == 'nt':
|
|
||||||
rc_name = env.File(rc_file).abspath
|
|
||||||
dir = os.path.split(rc_name)[0]
|
|
||||||
if not os.path.isdir(dir):
|
|
||||||
os.makedirs(dir)
|
|
||||||
rc = open(rc_name, 'w')
|
|
||||||
print >> rc, 'IDI_ICON1 ICON DISCARDABLE "%s"' % \
|
|
||||||
os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'development', 'win32',
|
|
||||||
'packaging', 'icons', icon_file).replace('\\', '\\\\')
|
|
||||||
rc.close()
|
|
||||||
return env.RES(rc_name)
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def env_qtResource(target, source, env):
|
|
||||||
'''Create resource.qrc'''
|
|
||||||
qrc = open(str(target[0]), 'w')
|
|
||||||
print >> qrc, "<!DOCTYPE RCC><RCC version='1.0'><qresource>"
|
|
||||||
for file in source:
|
|
||||||
rel_file = relativePath(str(file), env.subst('$TOP_SRCDIR/lib'))
|
|
||||||
abs_file = str(file.abspath)
|
|
||||||
print >> qrc, '<file alias="%s">%s</file>' % (rel_file, abs_file)
|
|
||||||
print >> qrc, '</qresource></RCC>'
|
|
||||||
qrc.close()
|
|
||||||
|
|
||||||
#
|
|
||||||
# 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 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') or \
|
|
||||||
conf.TryLink('#include <unistd.h>' + check_mkdir_one_arg_source, '.c') or \
|
|
||||||
conf.TryLink('#include <direct.h>' + check_mkdir_one_arg_source, '.c')
|
|
||||||
if ret:
|
|
||||||
conf.Result('one')
|
|
||||||
else:
|
|
||||||
conf.Result('two')
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def checkCXXGlobalCstd(conf):
|
|
||||||
''' Checking the use of std::tolower or tolower '''
|
|
||||||
check_global_cstd_source = '''
|
|
||||||
#include <cctype>
|
|
||||||
using std::tolower;
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
conf.Message('Checking for the use of global cstd... ')
|
|
||||||
# if can not compile, define CXX_GLOBAL_CSTD
|
|
||||||
ret = conf.TryLink(check_global_cstd_source, '.cpp')
|
|
||||||
conf.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
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, libs, lib_paths, inc_paths, versions, isDebug):
|
|
||||||
''' look for boost libraries
|
|
||||||
libs: library names
|
|
||||||
lib_paths: try these paths for boost libraries
|
|
||||||
inc_paths: try these paths for boost headers
|
|
||||||
versions: supported boost versions
|
|
||||||
isDebug: if true, use debug libraries
|
|
||||||
'''
|
|
||||||
conf.Message('Checking for boost library %s... ' % ', '.join(libs))
|
|
||||||
libprefix = conf.env['LIBPREFIX']
|
|
||||||
libsuffix = '(%s|%s)' % (conf.env['LIBSUFFIX'], conf.env['SHLIBSUFFIX'])
|
|
||||||
found_lib = False
|
|
||||||
found_inc = False
|
|
||||||
lib_names = []
|
|
||||||
lib_path = None
|
|
||||||
inc_path = None
|
|
||||||
for path in lib_paths:
|
|
||||||
conf.Log("Looking into %s\n" % path)
|
|
||||||
for lib in libs:
|
|
||||||
# get all the libs, then filter for the right library
|
|
||||||
files = glob.glob(os.path.join(path, '%sboost_%s-*.*' % (libprefix, lib)))
|
|
||||||
# check things like libboost_iostreams-gcc-mt-d-1_33_1.a
|
|
||||||
if len(files) > 0:
|
|
||||||
conf.Log("Find boost libraries: %s\n" % files)
|
|
||||||
# runtime code includes s,g,y,d,p,n, where we should look for
|
|
||||||
# d,g,y for debug, s,p,n for release
|
|
||||||
lib_files = []
|
|
||||||
if isDebug:
|
|
||||||
for ver in versions:
|
|
||||||
lib_files += filter(lambda x: re.search('%sboost_%s-\w+-mt-[^spn]+-%s%s' % (libprefix, lib, ver, libsuffix), x), files)
|
|
||||||
else:
|
|
||||||
for ver in versions:
|
|
||||||
lib_files += filter(lambda x: re.search('%sboost_%s-\w+-mt-([^dgy]+-)*%s%s' % (libprefix, lib, ver, libsuffix), x), files)
|
|
||||||
if len(lib_files) == 0:
|
|
||||||
# use alternative libraries
|
|
||||||
for ver in versions:
|
|
||||||
lib_files += filter(lambda x: re.search('%sboost_%s-[\w-]+%s%s' % (libprefix, lib, ver, libsuffix), x), files)
|
|
||||||
if len(lib_files) > 0:
|
|
||||||
# get xxx-gcc-1_33_1 from /usr/local/lib/libboost_xxx-gcc-1_33_1.a
|
|
||||||
name = lib_files[0].split(os.sep)[-1][len(libprefix):]
|
|
||||||
lib_names.append(name.split('.')[0])
|
|
||||||
conf.Log("Qualified libraries: %s\n" % lib_names)
|
|
||||||
else:
|
|
||||||
conf.Log("No qualified library is found.\n")
|
|
||||||
break
|
|
||||||
if len(lib_names) == len(libs):
|
|
||||||
found_lib = True
|
|
||||||
lib_path = path
|
|
||||||
break
|
|
||||||
if not found_lib:
|
|
||||||
if len(lib_names) == 0:
|
|
||||||
conf.Log("No boost library is found\n")
|
|
||||||
else:
|
|
||||||
conf.Log("Found boost libraries: %s\n" % lib_names)
|
|
||||||
conf.Result('no')
|
|
||||||
return (None, None, None)
|
|
||||||
# check version number in boost/version.hpp
|
|
||||||
def isValidBoostDir(dir):
|
|
||||||
version_file = os.path.join(dir, 'boost', 'version.hpp')
|
|
||||||
if not os.path.isfile(version_file):
|
|
||||||
return False
|
|
||||||
version_file_content = open(version_file).read()
|
|
||||||
version_strings = ['#define BOOST_LIB_VERSION "%s"' % ver for ver in versions]
|
|
||||||
return True in [x in version_file_content for x in version_strings]
|
|
||||||
# check for boost header file
|
|
||||||
for path in inc_paths:
|
|
||||||
conf.Log("Checking for inc path: %s\n" % path)
|
|
||||||
if isValidBoostDir(path):
|
|
||||||
inc_path = path
|
|
||||||
found_inc = True
|
|
||||||
else: # check path/boost_1_xx_x/boost
|
|
||||||
dirs = glob.glob(os.path.join(path, 'boost-*'))
|
|
||||||
if len(dirs) > 0 and isValidBoostDir(dirs[0]):
|
|
||||||
conf.Log("Checing for sub directory: %s\n" % dirs[0])
|
|
||||||
inc_path = dirs[0]
|
|
||||||
found_inc = True
|
|
||||||
# return result
|
|
||||||
if found_inc:
|
|
||||||
conf.Result('yes')
|
|
||||||
conf.Log('Using boost libraries %s\n' % (', '.join(lib_names)))
|
|
||||||
return (lib_names, lib_path, inc_path)
|
|
||||||
else:
|
|
||||||
conf.Result('no')
|
|
||||||
return (None, None, None)
|
|
||||||
|
|
||||||
|
|
||||||
def checkCommand(conf, cmd):
|
|
||||||
''' check the existence of a command
|
|
||||||
return full path to the command, or none
|
|
||||||
'''
|
|
||||||
conf.Message('Checking for command %s...' % cmd)
|
|
||||||
res = WhereIs(cmd)
|
|
||||||
conf.Result(res is not None)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def checkNSIS(conf):
|
|
||||||
''' check the existence of nsis compiler, return the fullpath '''
|
|
||||||
conf.Message('Checking for nsis compiler...')
|
|
||||||
res = None
|
|
||||||
if can_read_reg:
|
|
||||||
# If we can read the registry, get the NSIS command from it
|
|
||||||
try:
|
|
||||||
k = RegOpenKeyEx(hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'SOFTWARE\\NSIS')
|
|
||||||
val, tok = RegQueryValueEx(k,None)
|
|
||||||
ret = val + os.path.sep + 'makensis.exe'
|
|
||||||
if os.path.isfile(ret):
|
|
||||||
res = '"' + ret + '"'
|
|
||||||
else:
|
|
||||||
res = None
|
|
||||||
except:
|
|
||||||
pass # Couldn't find the key, just act like we can't read the registry
|
|
||||||
# Hope it's on the path
|
|
||||||
if res is None:
|
|
||||||
res = WhereIs('makensis.exe')
|
|
||||||
conf.Result(res is not None)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def checkLC_MESSAGES(conf):
|
|
||||||
''' check the definition of LC_MESSAGES '''
|
|
||||||
check_LC_MESSAGES = '''
|
|
||||||
#include <locale.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return LC_MESSAGES;
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
conf.Message('Checking for LC_MESSAGES in locale.h... ')
|
|
||||||
ret = conf.TryLink(check_LC_MESSAGES, '.c')
|
|
||||||
conf.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def checkIconvConst(conf):
|
|
||||||
''' check the declaration of iconv '''
|
|
||||||
check_iconv_const = '''
|
|
||||||
#include <iconv.h>
|
|
||||||
// this declaration will fail when there already exists a non const char**
|
|
||||||
// version which returns size_t
|
|
||||||
double iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
|
|
||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
conf.Message('Checking if the declaration of iconv needs const... ')
|
|
||||||
ret = conf.TryLink(check_iconv_const, '.cpp')
|
|
||||||
conf.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def checkSizeOfWChar(conf):
|
|
||||||
''' check the size of wchar '''
|
|
||||||
check_sizeof_wchar = '''
|
|
||||||
#include <wchar.h>
|
|
||||||
int i[ ( sizeof(wchar_t)==%d ? 1 : -1 ) ];
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
conf.Message('Checking the size of wchar_t... ')
|
|
||||||
if conf.TryLink(check_sizeof_wchar % 2, '.cpp'):
|
|
||||||
ret = 2
|
|
||||||
elif conf.TryLink(check_sizeof_wchar % 4, '.cpp'):
|
|
||||||
ret = 4
|
|
||||||
else:
|
|
||||||
ret = 0
|
|
||||||
conf.Result(str(ret))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def checkDeclaration(conf, func, headers):
|
|
||||||
''' check if a function is declared in given headers '''
|
|
||||||
check_decl = '''
|
|
||||||
#include <%%s>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
#ifndef %s
|
|
||||||
char *p = (char *) %s;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
''' % (func, func)
|
|
||||||
conf.Message('Checking for the declaration of function %s... ' % func)
|
|
||||||
ret = True in [conf.TryLink(check_decl % header, '.c') for header in headers]
|
|
||||||
conf.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def createConfigFile(conf, config_file,
|
|
||||||
config_pre = '', config_post = '',
|
|
||||||
headers = [], functions = [], declarations = [], types = [], libs = [],
|
|
||||||
custom_tests = [], extra_items = []):
|
|
||||||
''' create a configuration file, with options
|
|
||||||
config_file: which file to create
|
|
||||||
config_pre: first part of the config file
|
|
||||||
config_post: last part of the config file
|
|
||||||
headers: header files to check, in the form of a list of
|
|
||||||
('file', 'HAVE_FILE', 'c'/'c++')
|
|
||||||
functions: functions to check, in the form of a list of
|
|
||||||
('func', 'HAVE_func', 'include lines'/None)
|
|
||||||
declarations: function declarations to check, in the form of a list of
|
|
||||||
('func', 'HAVE_DECL_func', header_files)
|
|
||||||
types: types to check, in the form of a list of
|
|
||||||
('type', 'HAVE_TYPE', 'includelines'/None)
|
|
||||||
libs: libraries to check, in the form of a list of
|
|
||||||
('lib', 'HAVE_LIB', 'LIB_NAME'). HAVE_LIB will be set if 'lib' exists,
|
|
||||||
or any of the libs exists if 'lib' is a list of libs.
|
|
||||||
Optionally, user can provide another key LIB_NAME, that will
|
|
||||||
be set to the detected lib (or None otherwise).
|
|
||||||
custom_tests: extra tests to perform, in the form of a list of
|
|
||||||
(test (True/False), 'key', 'desc', 'true config line', 'false config line')
|
|
||||||
If the last two are ignored, '#define key 1' '/*#undef key */'
|
|
||||||
will be used.
|
|
||||||
extra_items: extra configuration lines, in the form of a list of
|
|
||||||
('config', 'description')
|
|
||||||
Return:
|
|
||||||
The result of each test, as a dictioanry of
|
|
||||||
res['XXX'] = True/False
|
|
||||||
XXX are keys defined in each argument.
|
|
||||||
'''
|
|
||||||
cont = config_pre + '\n'
|
|
||||||
result = {}
|
|
||||||
# add to this string, in appropriate format
|
|
||||||
def configString(lines, desc=''):
|
|
||||||
text = ''
|
|
||||||
if lines.strip() != '':
|
|
||||||
if desc != '':
|
|
||||||
text += '/* ' + desc + ' */\n'
|
|
||||||
text += lines + '\n\n'
|
|
||||||
return text
|
|
||||||
#
|
|
||||||
# headers
|
|
||||||
for header in headers:
|
|
||||||
description = "Define to 1 if you have the <%s> header file." % header[0]
|
|
||||||
if (header[2] == 'c' and conf.CheckCHeader(header[0])) or \
|
|
||||||
(header[2] == 'cxx' and conf.CheckCXXHeader(header[0])):
|
|
||||||
result[header[1]] = 1
|
|
||||||
cont += configString('#define %s 1' % header[1], desc = description)
|
|
||||||
else:
|
|
||||||
result[header[1]] = 0
|
|
||||||
cont += configString('/* #undef %s */' % header[1], desc = description)
|
|
||||||
# functions
|
|
||||||
for func in functions:
|
|
||||||
description = "Define to 1 if you have the `%s' function." % func[0]
|
|
||||||
if conf.CheckFunc(func[0], header=func[2]):
|
|
||||||
result[func[1]] = 1
|
|
||||||
cont += configString('#define %s 1' % func[1], desc = description)
|
|
||||||
else:
|
|
||||||
result[func[1]] = 0
|
|
||||||
cont += configString('/* #undef %s */' % func[1], desc = description)
|
|
||||||
for decl in declarations:
|
|
||||||
description = "Define to 1 if you have the declaration of `%s', and to 0 if you don't." % decl[0]
|
|
||||||
if conf.CheckDeclaration(decl[0], decl[2]):
|
|
||||||
result[decl[1]] = 1
|
|
||||||
cont += configString('#define %s 1' % decl[1], desc = description)
|
|
||||||
else:
|
|
||||||
result[decl[1]] = 0
|
|
||||||
cont += configString('/* #undef %s */' % decl[1], desc = description)
|
|
||||||
# types
|
|
||||||
for t in types:
|
|
||||||
description = "Define to 1 if you have the `%s' type." % t[0]
|
|
||||||
if conf.CheckType(t[0], includes=t[2]):
|
|
||||||
result[t[1]] = 1
|
|
||||||
cont += configString('#define %s 1' % t[1], desc = description)
|
|
||||||
else:
|
|
||||||
result[t[1]] = 0
|
|
||||||
cont += configString('/* #undef %s */' % t[1], desc = description)
|
|
||||||
# libraries
|
|
||||||
for lib in libs:
|
|
||||||
description = "Define to 1 if you have the `%s' library (-l%s)." % (lib[0], lib[0])
|
|
||||||
if type(lib[0]) is type(''):
|
|
||||||
lib_list = [lib[0]]
|
|
||||||
else:
|
|
||||||
lib_list = lib[0]
|
|
||||||
# check if any of the lib exists
|
|
||||||
result[lib[1]] = 0
|
|
||||||
# if user want the name of the lib detected
|
|
||||||
if len(lib) == 3:
|
|
||||||
result[lib[2]] = None
|
|
||||||
for ll in lib_list:
|
|
||||||
if conf.CheckLib(ll):
|
|
||||||
result[lib[1]] = 1
|
|
||||||
if len(lib) == 3:
|
|
||||||
result[lib[2]] = ll
|
|
||||||
cont += configString('#define %s 1' % lib[1], desc = description)
|
|
||||||
break
|
|
||||||
# if not found
|
|
||||||
if not result[lib[1]]:
|
|
||||||
cont += configString('/* #undef %s */' % lib[1], desc = description)
|
|
||||||
# custom tests
|
|
||||||
for test in custom_tests:
|
|
||||||
if test[0]:
|
|
||||||
result[test[1]] = 1
|
|
||||||
if len(test) == 3:
|
|
||||||
cont += configString('#define %s 1' % test[1], desc = test[2])
|
|
||||||
else:
|
|
||||||
cont += configString(test[3], desc = test[2])
|
|
||||||
else:
|
|
||||||
result[test[1]] = 0
|
|
||||||
if len(test) == 3:
|
|
||||||
cont += configString('/* #undef %s */' % test[1], desc = test[2])
|
|
||||||
else:
|
|
||||||
cont += configString(test[4], desc = test[2])
|
|
||||||
# extra items (no key is returned)
|
|
||||||
for item in extra_items:
|
|
||||||
cont += configString(item[0], desc = item[1])
|
|
||||||
# add the last part
|
|
||||||
cont += '\n' + config_post + '\n'
|
|
||||||
# write to file
|
|
||||||
writeToFile(config_file, cont)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
def installCygwinPostinstallScript(path):
|
|
||||||
''' Install lyx.sh '''
|
|
||||||
postinstall_script = os.path.join(path, 'lyx.sh')
|
|
||||||
script = open(postinstall_script, 'w')
|
|
||||||
script.write(r'''#!/bin/sh
|
|
||||||
|
|
||||||
# Add /usr/share/lyx/fonts to /etc/fonts/local.conf
|
|
||||||
# if it is not already there.
|
|
||||||
if [ -f /etc/fonts/local.conf ]; then
|
|
||||||
grep -q /usr/share/lyx/fonts /etc/fonts/local.conf
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
sed 's/^<\/fontconfig>/<dir>\/usr\/share\/lyx\/fonts<\/dir>\n<\/fontconfig>/' /etc/fonts/local.conf > /etc/fonts/local.conf.tmp
|
|
||||||
mv -f /etc/fonts/local.conf.tmp /etc/fonts/local.conf
|
|
||||||
fc-cache /usr/share/lyx/fonts
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
''')
|
|
||||||
script.close()
|
|
||||||
return(postinstall_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
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user