git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/abakus@1071969 283d02a7-25f6-0310-bc7c-ecb5cbfe19dav3.5.13-sru
@ -0,0 +1 @@ | |||
Michael Pyne <michael.pyne@kdemail.net> |
@ -0,0 +1,341 @@ | |||
GNU GENERAL PUBLIC LICENSE | |||
Version 2, June 1991 | |||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |||
59 Temple Place, Suite 330, Boston, MA 02110-1301 USA | |||
Everyone is permitted to copy and distribute verbatim copies | |||
of this license document, but changing it is not allowed. | |||
Preamble | |||
The licenses for most software are designed to take away your | |||
freedom to share and change it. By contrast, the GNU General Public | |||
License is intended to guarantee your freedom to share and change free | |||
software--to make sure the software is free for all its users. This | |||
General Public License applies to most of the Free Software | |||
Foundation's software and to any other program whose authors commit to | |||
using it. (Some other Free Software Foundation software is covered by | |||
the GNU Library General Public License instead.) You can apply it to | |||
your programs, too. | |||
When we speak of free software, we are referring to freedom, not | |||
price. Our General Public Licenses are designed to make sure that you | |||
have the freedom to distribute copies of free software (and charge for | |||
this service if you wish), that you receive source code or can get it | |||
if you want it, that you can change the software or use pieces of it | |||
in new free programs; and that you know you can do these things. | |||
To protect your rights, we need to make restrictions that forbid | |||
anyone to deny you these rights or to ask you to surrender the rights. | |||
These restrictions translate to certain responsibilities for you if you | |||
distribute copies of the software, or if you modify it. | |||
For example, if you distribute copies of such a program, whether | |||
gratis or for a fee, you must give the recipients all the rights that | |||
you have. You must make sure that they, too, receive or can get the | |||
source code. And you must show them these terms so they know their | |||
rights. | |||
We protect your rights with two steps: (1) copyright the software, and | |||
(2) offer you this license which gives you legal permission to copy, | |||
distribute and/or modify the software. | |||
Also, for each author's protection and ours, we want to make certain | |||
that everyone understands that there is no warranty for this free | |||
software. If the software is modified by someone else and passed on, we | |||
want its recipients to know that what they have is not the original, so | |||
that any problems introduced by others will not reflect on the original | |||
authors' reputations. | |||
Finally, any free program is threatened constantly by software | |||
patents. We wish to avoid the danger that redistributors of a free | |||
program will individually obtain patent licenses, in effect making the | |||
program proprietary. To prevent this, we have made it clear that any | |||
patent must be licensed for everyone's free use or not licensed at all. | |||
The precise terms and conditions for copying, distribution and | |||
modification follow. | |||
GNU GENERAL PUBLIC LICENSE | |||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |||
0. This License applies to any program or other work which contains | |||
a notice placed by the copyright holder saying it may be distributed | |||
under the terms of this General Public License. The "Program", below, | |||
refers to any such program or work, and a "work based on the Program" | |||
means either the Program or any derivative work under copyright law: | |||
that is to say, a work containing the Program or a portion of it, | |||
either verbatim or with modifications and/or translated into another | |||
language. (Hereinafter, translation is included without limitation in | |||
the term "modification".) Each licensee is addressed as "you". | |||
Activities other than copying, distribution and modification are not | |||
covered by this License; they are outside its scope. The act of | |||
running the Program is not restricted, and the output from the Program | |||
is covered only if its contents constitute a work based on the | |||
Program (independent of having been made by running the Program). | |||
Whether that is true depends on what the Program does. | |||
1. You may copy and distribute verbatim copies of the Program's | |||
source code as you receive it, in any medium, provided that you | |||
conspicuously and appropriately publish on each copy an appropriate | |||
copyright notice and disclaimer of warranty; keep intact all the | |||
notices that refer to this License and to the absence of any warranty; | |||
and give any other recipients of the Program a copy of this License | |||
along with the Program. | |||
You may charge a fee for the physical act of transferring a copy, and | |||
you may at your option offer warranty protection in exchange for a fee. | |||
2. You may modify your copy or copies of the Program or any portion | |||
of it, thus forming a work based on the Program, and copy and | |||
distribute such modifications or work under the terms of Section 1 | |||
above, provided that you also meet all of these conditions: | |||
a) You must cause the modified files to carry prominent notices | |||
stating that you changed the files and the date of any change. | |||
b) You must cause any work that you distribute or publish, that in | |||
whole or in part contains or is derived from the Program or any | |||
part thereof, to be licensed as a whole at no charge to all third | |||
parties under the terms of this License. | |||
c) If the modified program normally reads commands interactively | |||
when run, you must cause it, when started running for such | |||
interactive use in the most ordinary way, to print or display an | |||
announcement including an appropriate copyright notice and a | |||
notice that there is no warranty (or else, saying that you provide | |||
a warranty) and that users may redistribute the program under | |||
these conditions, and telling the user how to view a copy of this | |||
License. (Exception: if the Program itself is interactive but | |||
does not normally print such an announcement, your work based on | |||
the Program is not required to print an announcement.) | |||
These requirements apply to the modified work as a whole. If | |||
identifiable sections of that work are not derived from the Program, | |||
and can be reasonably considered independent and separate works in | |||
themselves, then this License, and its terms, do not apply to those | |||
sections when you distribute them as separate works. But when you | |||
distribute the same sections as part of a whole which is a work based | |||
on the Program, the distribution of the whole must be on the terms of | |||
this License, whose permissions for other licensees extend to the | |||
entire whole, and thus to each and every part regardless of who wrote it. | |||
Thus, it is not the intent of this section to claim rights or contest | |||
your rights to work written entirely by you; rather, the intent is to | |||
exercise the right to control the distribution of derivative or | |||
collective works based on the Program. | |||
In addition, mere aggregation of another work not based on the Program | |||
with the Program (or with a work based on the Program) on a volume of | |||
a storage or distribution medium does not bring the other work under | |||
the scope of this License. | |||
3. You may copy and distribute the Program (or a work based on it, | |||
under Section 2) in object code or executable form under the terms of | |||
Sections 1 and 2 above provided that you also do one of the following: | |||
a) Accompany it with the complete corresponding machine-readable | |||
source code, which must be distributed under the terms of Sections | |||
1 and 2 above on a medium customarily used for software interchange; or, | |||
b) Accompany it with a written offer, valid for at least three | |||
years, to give any third party, for a charge no more than your | |||
cost of physically performing source distribution, a complete | |||
machine-readable copy of the corresponding source code, to be | |||
distributed under the terms of Sections 1 and 2 above on a medium | |||
customarily used for software interchange; or, | |||
c) Accompany it with the information you received as to the offer | |||
to distribute corresponding source code. (This alternative is | |||
allowed only for noncommercial distribution and only if you | |||
received the program in object code or executable form with such | |||
an offer, in accord with Subsection b above.) | |||
The source code for a work means the preferred form of the work for | |||
making modifications to it. For an executable work, complete source | |||
code means all the source code for all modules it contains, plus any | |||
associated interface definition files, plus the scripts used to | |||
control compilation and installation of the executable. However, as a | |||
special exception, the source code distributed need not include | |||
anything that is normally distributed (in either source or binary | |||
form) with the major components (compiler, kernel, and so on) of the | |||
operating system on which the executable runs, unless that component | |||
itself accompanies the executable. | |||
If distribution of executable or object code is made by offering | |||
access to copy from a designated place, then offering equivalent | |||
access to copy the source code from the same place counts as | |||
distribution of the source code, even though third parties are not | |||
compelled to copy the source along with the object code. | |||
4. You may not copy, modify, sublicense, or distribute the Program | |||
except as expressly provided under this License. Any attempt | |||
otherwise to copy, modify, sublicense or distribute the Program is | |||
void, and will automatically terminate your rights under this License. | |||
However, parties who have received copies, or rights, from you under | |||
this License will not have their licenses terminated so long as such | |||
parties remain in full compliance. | |||
5. You are not required to accept this License, since you have not | |||
signed it. However, nothing else grants you permission to modify or | |||
distribute the Program or its derivative works. These actions are | |||
prohibited by law if you do not accept this License. Therefore, by | |||
modifying or distributing the Program (or any work based on the | |||
Program), you indicate your acceptance of this License to do so, and | |||
all its terms and conditions for copying, distributing or modifying | |||
the Program or works based on it. | |||
6. Each time you redistribute the Program (or any work based on the | |||
Program), the recipient automatically receives a license from the | |||
original licensor to copy, distribute or modify the Program subject to | |||
these terms and conditions. You may not impose any further | |||
restrictions on the recipients' exercise of the rights granted herein. | |||
You are not responsible for enforcing compliance by third parties to | |||
this License. | |||
7. If, as a consequence of a court judgment or allegation of patent | |||
infringement or for any other reason (not limited to patent issues), | |||
conditions are imposed on you (whether by court order, agreement or | |||
otherwise) that contradict the conditions of this License, they do not | |||
excuse you from the conditions of this License. If you cannot | |||
distribute so as to satisfy simultaneously your obligations under this | |||
License and any other pertinent obligations, then as a consequence you | |||
may not distribute the Program at all. For example, if a patent | |||
license would not permit royalty-free redistribution of the Program by | |||
all those who receive copies directly or indirectly through you, then | |||
the only way you could satisfy both it and this License would be to | |||
refrain entirely from distribution of the Program. | |||
If any portion of this section is held invalid or unenforceable under | |||
any particular circumstance, the balance of the section is intended to | |||
apply and the section as a whole is intended to apply in other | |||
circumstances. | |||
It is not the purpose of this section to induce you to infringe any | |||
patents or other property right claims or to contest validity of any | |||
such claims; this section has the sole purpose of protecting the | |||
integrity of the free software distribution system, which is | |||
implemented by public license practices. Many people have made | |||
generous contributions to the wide range of software distributed | |||
through that system in reliance on consistent application of that | |||
system; it is up to the author/donor to decide if he or she is willing | |||
to distribute software through any other system and a licensee cannot | |||
impose that choice. | |||
This section is intended to make thoroughly clear what is believed to | |||
be a consequence of the rest of this License. | |||
8. If the distribution and/or use of the Program is restricted in | |||
certain countries either by patents or by copyrighted interfaces, the | |||
original copyright holder who places the Program under this License | |||
may add an explicit geographical distribution limitation excluding | |||
those countries, so that distribution is permitted only in or among | |||
countries not thus excluded. In such case, this License incorporates | |||
the limitation as if written in the body of this License. | |||
9. The Free Software Foundation may publish revised and/or new versions | |||
of the General Public License from time to time. Such new versions will | |||
be similar in spirit to the present version, but may differ in detail to | |||
address new problems or concerns. | |||
Each version is given a distinguishing version number. If the Program | |||
specifies a version number of this License which applies to it and "any | |||
later version", you have the option of following the terms and conditions | |||
either of that version or of any later version published by the Free | |||
Software Foundation. If the Program does not specify a version number of | |||
this License, you may choose any version ever published by the Free Software | |||
Foundation. | |||
10. If you wish to incorporate parts of the Program into other free | |||
programs whose distribution conditions are different, write to the author | |||
to ask for permission. For software which is copyrighted by the Free | |||
Software Foundation, write to the Free Software Foundation; we sometimes | |||
make exceptions for this. Our decision will be guided by the two goals | |||
of preserving the free status of all derivatives of our free software and | |||
of promoting the sharing and reuse of software generally. | |||
NO WARRANTY | |||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |||
REPAIR OR CORRECTION. | |||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |||
POSSIBILITY OF SUCH DAMAGES. | |||
END OF TERMS AND CONDITIONS | |||
How to Apply These Terms to Your New Programs | |||
If you develop a new program, and you want it to be of the greatest | |||
possible use to the public, the best way to achieve this is to make it | |||
free software which everyone can redistribute and change under these terms. | |||
To do so, attach the following notices to the program. It is safest | |||
to attach them to the start of each source file to most effectively | |||
convey the exclusion of warranty; and each file should have at least | |||
the "copyright" line and a pointer to where the full notice is found. | |||
<one line to give the program's name and a brief idea of what it does.> | |||
Copyright (C) 19yy <name of author> | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA | |||
Also add information on how to contact you by electronic and paper mail. | |||
If the program is interactive, make it output a short notice like this | |||
when it starts in an interactive mode: | |||
Gnomovision version 69, Copyright (C) 19yy name of author | |||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
This is free software, and you are welcome to redistribute it | |||
under certain conditions; type `show c' for details. | |||
The hypothetical commands `show w' and `show c' should show the appropriate | |||
parts of the General Public License. Of course, the commands you use may | |||
be called something other than `show w' and `show c'; they could even be | |||
mouse-clicks or menu items--whatever suits your program. | |||
You should also get your employer (if you work as a programmer) or your | |||
school, if any, to sign a "copyright disclaimer" for the program, if | |||
necessary. Here is a sample; alter the names: | |||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |||
`Gnomovision' (which makes passes at compilers) written by James Hacker. | |||
<signature of Ty Coon>, 1 April 1989 | |||
Ty Coon, President of Vice | |||
This General Public License does not permit incorporating your program into | |||
proprietary programs. If your program is a subroutine library, you may | |||
consider it more useful to permit linking proprietary applications with the | |||
library. If this is what you want to do, use the GNU Library General | |||
Public License instead of this License. |
@ -0,0 +1,183 @@ | |||
abakus, by Michael Pyne <michael.pyne@kdemail.net> | |||
Version: 0.91 | |||
This is my attempt at creating a light-calculator based on Roberto Alsina's | |||
initial usability suggestions, and based on the ideas of a few other KDE | |||
hackers. | |||
This software is distributed under the terms of the GNU GPL v2. | |||
Synopsis: | |||
$ tar xvjf abakus-0.91.tar.bz2 | |||
$ cd abakus-0.91 | |||
$ ./configure && make && make install | |||
$ abakus | |||
Type away, and press Enter to see the result. | |||
Changes since 0.90: | |||
* Add ability to remove all functions and variables to the context menus of | |||
their respective list boxes. | |||
* Convert out-of-range numbers to NaN. | |||
* Accept "," as a decimal separator for the benefit of European users. | |||
* Use correct decimal separator (per KLocale settings) in output. | |||
* For long results, show the beginning instead of the end of the result, | |||
since the beginning is the most significant part of the result. | |||
Changes since 0.85: | |||
* You now have the option of using the GNU Multiple Precision library for | |||
high-precision mathematics. It requires the MPFR library to also be | |||
installed (normally comes with GNU MP 4.x). It is used automatically if | |||
detected. | |||
* Jes Hall has contributed DocBook documentation to make Abakus integrate into | |||
KDE even more tightly. Thanks, Jes! | |||
* User defined functions can now be defined over. | |||
* Error handling with deriv() function improved. | |||
* Ariya Hidayat's name was misspelled everywhere in Abakus. Sorry, Ariya. :( | |||
* Speaking of Ariya, Abakus now uses the impressive user interface code from | |||
his SpeedCrunch calculator (http://speedcrunch.berlios.de/). This includes | |||
the Calc-as-you-Type tooltip, the function and variable dropdown, and | |||
syntax highlighting. It's not configurable at this point, expect that in | |||
the next release. | |||
* You can use the F6 key to select the expression editor if you're a big fan | |||
of the keyboard. | |||
* Raising negative numbers to integral powers should work with the internal | |||
high-precision library now. | |||
* You can no longer deselect the current precision menu item. | |||
* Fix crash bug when a user-defined function refers to another user-defined | |||
function, and then you remove or edit the function it referred to. | |||
* Add exact numerical derivatives for all functions supported. | |||
* Added the asinh, acosh, and atanh functions. | |||
* Fixed bug with loading of prior compact mode status. | |||
* Fixed bug where result text had wrong precision when you changed the | |||
precision and tried drag-and-drop. | |||
* Drag-and-drop improvements. | |||
* Fixed bug where Custom Precision menu entry was checked even if you canceled | |||
the dialog. | |||
* Made hyperbolic functions consistently ignore trigonometric mode. (Both | |||
Degrees and Radians make no sense for hyperbolic trig). | |||
* Whew! :) | |||
v0.85 adds a lot: | |||
* Improvements to the configure script. Since I didn't end up using libCLN it | |||
was mostly for naught, but the changes will be useful for the future. | |||
* abakus now uses the high-precision math routines from Ariya Hidayat's | |||
SpeedCrunch program. Thanks, Ariya! | |||
* High precision arithmetic can have between 0 and 75 digits of precision. | |||
* Support for approximate derivatives. For most functions the derivatives will | |||
be numerically accurate. For those functions where I didn't feel like typing | |||
in the exact form of the derivative an approximation is used instead. | |||
* Implicit multiplication has been added to the parser. That means you can | |||
type stuff like "3 sin pi" without having to manually add the * in between | |||
3 and sin. This also works with numbers and variables, and numbers and | |||
parenthesized expressions. | |||
* GUI changes. The main result view now uses KListView, so it gains tooltip | |||
support for long answers for free, along with a bevy of other improvements. | |||
* You can right-click on an answer and copy it to the clipboard. | |||
* Corrected information in the about box. | |||
* Restarting abakus with compact mode enabled should is much improved. | |||
v0.80.2 fixed an issue with the configure script for people who don't have | |||
exactly the same version of Python I do, and forcibly prevents flex/bison | |||
errors. | |||
v0.80.1 fixed an issue with the configure script for people who don't already | |||
have scons installed. | |||
Major changes since 0.76: | |||
* There is no more C code to interface between the parser and program. | |||
* RPN mode is improved. Now the stack is retained between calls, and there | |||
are a few commands only in RPN mode: | |||
1. pop - Return the top of the stack. | |||
2. clear - Clear the stack. | |||
* bksys is used instead of the custom Makefiles. | |||
* Lots of code cleanups, including license headers. | |||
* The nifty drag-and-drop image looks more rectangular, and is used with the | |||
two listviews on the right as well. | |||
* Improved error checking, with messages that should hopefully be more | |||
descriptive. | |||
Major changes since 0.75: | |||
* Reorder internal macro so that functions are declared *before* they're | |||
referenced, which helps build the program on systems with math.h files that | |||
don't export the long double version of their math functions. | |||
* Hitting a number or letter key right after evaluating an expression in RPN | |||
mode automatically prepends the 'ans' variable, which was a feature of the | |||
Normal mode. | |||
Major changes since 0.70: | |||
* Build system switched (somehow) to using qmake. The parser and lexer are | |||
still included, so bison and flex are still not required. Hopefully this | |||
will improve the ease of building. Of course, this means no more colored | |||
make output. | |||
* Changed most of the keyboard shortcuts to use Shift + Alt + foo instead of | |||
Alt + foo since that was interfering with the menu bar. | |||
* RPN mode!! If you enable RPN mode, then your expressions will be evaluated | |||
using the Reverse Polish Notation popular with users of HP calculators. Note | |||
that although you can use values and functions while in RPN mode, you cannot | |||
set or remove them from the expression editor like you can in normal mode. | |||
* abakus will display a small token starting with a dollar sign ($) in italics | |||
next to results. You can use these tokens to quickly reference a result in | |||
your expression. The most recent result is always $0, with the number | |||
increasing from most recent to least recent result. For example, typing | |||
2 <Enter> 3 <Enter> $0 ^ $1 <Enter> would give a result of 9. | |||
* You can right click on functions and values in the list views to remove them | |||
from the GUI. | |||
* Changed the result items to use word wrapping when needed to fit all the | |||
text. | |||
* Very small DCOP interface. | |||
* More code cleanup. | |||
* Added a .desktop file. | |||
* Test client removed again. | |||
* Double-clicking on an error message (or OK message) no longer inserts them | |||
into the edit box. | |||
Major changes since 0.61: | |||
* User defined Functions. | |||
* Save state of program between runs. | |||
* Miscellaneous fun stuff. | |||
Currently implemented features: | |||
* Parser built using flex and bison. The generated files are included so it | |||
should compile fine for you. | |||
* Fully C++. The parser and lexer code require C++ to compile. | |||
* Supports several built-in functions: | |||
- sin, cos, tan, sinh, cosh, tanh, asin, acos, atan in either radian or | |||
degree mode. | |||
abs, exp (e raised to the given power), ln, log (base 10), | |||
sqrt, ceil, floor | |||
* Supported operators: +, -, *, /, ^ (or **). | |||
* Includes a window showing the values and user-defined functions you have. | |||
* Predefined constants: pi, and e (Euler' constant). | |||
* You can assign to variables by using an expression of the form: | |||
identifier = expression. You can then reuse these variables later. | |||
* You can create user-defined functions of one variable using the syntax | |||
set foo(var) = <expr>, where <expr> calculates the value in terms of var. | |||
* You can delete user-defined variables by doing: remove var | |||
* You can delete user-defined functions by doing: remove foo(). Notice that | |||
the variable is NOT included in that expression. | |||
* Functions and variables are saved on exit, and then loaded when abakus is | |||
started again. | |||
* The ans variable contains the result of the last computation. | |||
* Pressing +, -, *, or / immediately after your last computation automatically | |||
inserts ans for you, saving you typing. | |||
* A compact mode for the program. | |||
* Operator precedence should be correct, including the right association of | |||
the power operator. So, 2 ^ 3 ^ 2 == 512, just as it does when you write | |||
it out. You can use parentheses to force precedence. | |||
* Parentheses are not required around functions. So, sin 3 is a valid | |||
expression. Note that sin 3 + cos 4 translates internally as (sin 3) + | |||
(cos 4), not as sin (3 + cos (4)). | |||
* I took some pains to try to make things like 3 + -2 work right. | |||
* inf and nan are accepted as numeric input for completeness. | |||
* abakus will automatically add ) characters to the end of the expression as | |||
needed to balance your expression. This means that expressions like | |||
sin (cos (2 + 3 will evaluate with no error. | |||
* A rudimentary RPN mode is included. Most everything works, except for | |||
derivatives and creating functions or new variables. | |||
Bugs: | |||
* More functions would be nice. | |||
* The lexer assumes that the decimal marker is a period. (.) I'm not exactly | |||
sure how to cleanly solve this problem with flex. :-( | |||
* Documentation could be better. |
@ -0,0 +1,36 @@ | |||
#! /usr/bin/env python | |||
################################################################### | |||
# LOAD THE ENVIRONMENT AND SET UP THE TOOLS | |||
################################################################### | |||
## Load the builders in config | |||
tools = [ 'default', 'help', 'generic', 'kde', 'abakus' ] | |||
toolpath = [ './', './bksys' ] | |||
# Required as part of SCons | |||
env = Environment(tools = tools, toolpath = toolpath) | |||
# Pull in some default settings. | |||
env.KDEuse("environ rpath nohelp") | |||
#env.KDEuse("environ rpath lang_qt thread nohelp") | |||
# If we're asking for help just go ahead and exit now. | |||
if env['HELP']: | |||
print env.helpText() | |||
Exit() | |||
if env['flex'] and env['bison']: | |||
env['PARSER_INCLUDED'] = True | |||
# Export the environment so that SConscript files in subdirs can access it. | |||
Export('env') | |||
################################################################### | |||
# SCRIPTS FOR BUILDING THE TARGETS | |||
################################################################### | |||
env.subdirs('src') | |||
env.docfolder('doc/en', 'en', 'abakus/') | |||
env.SConscript('doc/en/SConscript') |
@ -0,0 +1,178 @@ | |||
#!/usr/bin/env python | |||
""" | |||
Run scons -h to display the associated help, or look below .. | |||
""" | |||
BOLD ="\033[1m" | |||
RED ="\033[91m" | |||
GREEN ="\033[92m" | |||
YELLOW ="\033[1m" #"\033[93m" # unreadable on white backgrounds | |||
CYAN ="\033[96m" | |||
NORMAL ="\033[0m" | |||
def exists(env): | |||
return true | |||
def printColorCoded(msg): | |||
msg = msg.replace(']', NORMAL) | |||
msg = msg.replace('b[', BOLD) | |||
msg = msg.replace('g[', GREEN) | |||
msg = msg.replace('r[', RED) | |||
msg = msg.replace('c[', CYAN) | |||
msg = msg.replace('y[', YELLOW) | |||
print msg | |||
def generate(env): | |||
import SCons.Util, os | |||
env.addHelpText("""b[hi] | |||
b[*** abakus options *** | |||
----------------------] | |||
b[* bison=(no|yes): Enable parser support. Only needed for developers. | |||
b[* flex=(no|yes): Enable lexer support. Only needed for developers. | |||
b[* mpfr=(no|yes|check): Enable the MPFR library, which is faster and more | |||
precise than abakus's high-precision code. | |||
ie: b[scons configure] | |||
""") | |||
if env['HELP']: | |||
# Don't even bother. | |||
return env | |||
from SCons.Options import Options, PackageOption, EnumOption | |||
import os | |||
def CheckFlags(context): | |||
context.Message('Checking if ld supports --as-needed... ') | |||
lastLINKFLAGS = context.env['LINKFLAGS'] | |||
context.env.Append(LINKFLAGS = '-Wl,--as-needed') | |||
ret = context.TryLink(""" | |||
#include <iostream> | |||
using namespace std; | |||
int main() | |||
{ | |||
cout << "Test" << endl; | |||
} | |||
""", ".cpp") | |||
if not ret: | |||
context.env.Replace(LINKFLAGS = lastLINKFLAGS) | |||
context.Result(ret) | |||
return ret | |||
def CheckPath(context, prog, versionFlag = ''): | |||
if context.env[prog] == 'yes': | |||
context.env[prog] = prog | |||
context.Message('Checking for %s... ' % prog) | |||
ret = True | |||
# If absolute path, just try this one. | |||
if prog[0] == '/': | |||
ret = context.TryAction('%s %s' % (context.env[prog], versionFlag))[0] | |||
if ret: | |||
context.Result(ret) | |||
return True | |||
path = context.env.WhereIs(prog) | |||
if ret and path != None: | |||
context.env[prog] = path | |||
context.Result(1) | |||
else: | |||
context.env[prog] = False | |||
context.Result(0) | |||
print """ | |||
The $foo program was not found! You asked to use it so we will stop here. It | |||
is not required, you may use $foo=no on the command line to go without it.""".replace('$foo', prog) | |||
Exit(1) | |||
return False | |||
context.Result(1) | |||
return True | |||
cachefile = env['CACHEDIR'] + '/abakus.cache.py' | |||
fixup = lambda x: "%s installed here (yes = search)" % x | |||
opts = None | |||
if env.doConfigure(): | |||
opts = Options(None, env['ARGS']) | |||
else: | |||
opts = Options(cachefile, env['ARGS']) | |||
opts.AddOptions( | |||
PackageOption('bison', fixup('use the Bison parser generator'), 'yes'), | |||
PackageOption('flex', fixup('use the Flex scanner generator'), 'yes'), | |||
EnumOption ('mpfr', 'use the MPFR high-precision library', 'check', | |||
allowed_values=('yes', 'no', 'check'), map={}, ignorecase=1), | |||
('ABAKUS_CONFIGURED', '', 0), | |||
('HAVE_ASNEEDED', '', 0) | |||
) | |||
# We must manually pass the ARGS in. | |||
opts.Update(env, env['ARGS']) | |||
if env.doConfigure() or not env['ABAKUS_CONFIGURED']: | |||
# Configure stuff | |||
conf = env.Configure(custom_tests = {'CheckPath': CheckPath, 'CheckFlags' : CheckFlags}) | |||
if env['bison'] and env['bison'] != 'no': | |||
conf.CheckPath('bison', '-V') | |||
if env['flex'] and env['flex'] != 'no': | |||
conf.CheckPath('flex', '-V') | |||
if env['mpfr'] != 'no': | |||
oldLibs = conf.env.get('LIBS', '') | |||
conf.env.AppendUnique(LIBS = 'gmp') | |||
if conf.CheckLibWithHeader('mpfr', 'mpfr.h', 'c++', ''' | |||
mpfr_t a; | |||
mpfr_ptr ptr; | |||
__mpfr_struct debug; | |||
mpfr_init(a); | |||
''', autoadd = True): | |||
env['mpfr'] = 'yes' | |||
else: | |||
conf.env.Replace(LIBS = oldLibs) | |||
if env['mpfr'] == 'yes': | |||
print "Unable to find requested library mpfr!" | |||
env.Exit(1) | |||
else: | |||
env['mpfr'] = 'no' | |||
env['HAVE_ASNEEDED'] = 0 | |||
if conf.CheckFlags(): | |||
env['HAVE_ASNEEDED'] = 1 | |||
env['ABAKUS_CONFIGURED'] = 1 | |||
env = conf.Finish() | |||
try: | |||
f = open("config.h", "w+") | |||
f.write("""/* config.h -- Automatically generated by abakus.py | |||
* Any changes you make to this file will be overwritten! | |||
*/ | |||
""") | |||
f.write("/* HAVE_MPFR -- Defined if the MPFR library is being used. */\n") | |||
if env['mpfr'] == 'yes': | |||
f.write ("#define HAVE_MPFR 1\n") | |||
else: | |||
f.write ("/* #undef HAVE_MPFR */\n") | |||
f.close() | |||
except IOError: | |||
print "Unable to write config.h!" | |||
opts.Save(cachefile, env) | |||
# vim: set et ts=8 sw=4: |
@ -0,0 +1,498 @@ | |||
## Thomas Nagy, 2005 | |||
""" | |||
Detect and store the most common options | |||
* kdecxxflags : debug=1 (-g) or debug=full (-g3, slower) | |||
else use the user CXXFLAGS if any, - or -O2 by default | |||
* prefix : the installation path | |||
* extraincludes : a list of paths separated by ':' | |||
ie: scons configure debug=full prefix=/usr/local extraincludes=/tmp/include:/usr/local | |||
""" | |||
BOLD ="\033[1m" | |||
RED ="\033[91m" | |||
GREEN ="\033[92m" | |||
YELLOW ="\033[1m" #"\033[93m" # unreadable on white backgrounds | |||
CYAN ="\033[96m" | |||
NORMAL ="\033[0m" | |||
import os, re, types, sys, string, shutil, stat | |||
import SCons.Defaults | |||
import SCons.Tool | |||
import SCons.Util | |||
from SCons.Script.SConscript import SConsEnvironment | |||
from SCons.Options import Options, PathOption | |||
class genobj: | |||
def __init__(self, val, env): | |||
if not val in "program shlib kioslave staticlib".split(): | |||
print "unknown genobj given: "+val | |||
env.Exit(1) | |||
self.type = val | |||
self.orenv = env | |||
self.env = None | |||
self.executed = 0 | |||
self.target='' | |||
self.src=None | |||
self.cxxflags='' | |||
self.cflags='' | |||
self.includes='' | |||
self.linkflags='' | |||
self.libpaths='' | |||
self.libs='' | |||
# vars used by shlibs | |||
self.vnum='' | |||
self.libprefix='' | |||
# a directory where to install the targets (optional) | |||
self.instdir='' | |||
# ignore the DESTDIR (optional) | |||
self.nodestdir='' | |||
# change the working directory before reading the targets | |||
self.chdir='' | |||
# these members are private | |||
self.chdir_lock=None | |||
self.old_os_dir='' | |||
self.old_fs_dir='' | |||
self.p_local_shlibs=[] | |||
self.p_local_staticlibs=[] | |||
self.p_global_shlibs=[] | |||
#if not env.has_key('USE_THE_FORCE_LUKE'): env['USE_THE_FORCE_LUKE']=[self] | |||
#else: env['USE_THE_FORCE_LUKE'].append(self) | |||
def lockchdir(self): | |||
if not self.chdir: return | |||
self.chdir_lock=1 | |||
SConfFS=SCons.Node.FS.default_fs | |||
self.old_fs_dir=SConfFS.getcwd() | |||
self.old_os_dir=os.getcwd() | |||
#os.chdir(old_os_dir+'/'+self.chdir) | |||
SConfFS.chdir( SConfFS.Dir('#/'+self.chdir), change_os_dir=1) | |||
def unlockchdir(self): | |||
if not self.chdir: return | |||
if self.chdir_lock: | |||
#os.chdir(self.old_os_dir) | |||
SCons.Node.FS.default_fs.chdir(self.old_fs_dir, change_os_dir=0) | |||
self.chdir_lock=None | |||
def execute(self): | |||
if self.orenv.has_key('DUMPCONFIG'): | |||
print self.xml() | |||
return | |||
self.lockchdir() | |||
self.env = self.orenv.Copy() | |||
if not self.src or len(self.src) == 0: | |||
print RED+"no source file given to object - self.src"+NORMAL | |||
self.env.Exit(1) | |||
if not self.env.has_key('nosmart_includes'): self.env.AppendUnique(CPPPATH=['./']) | |||
if self.type == "kioslave": self.libprefix='' | |||
if len(self.includes)>0: self.env.AppendUnique(CPPPATH=self.env.make_list(self.includes)) | |||
if len(self.cxxflags)>0: self.env.AppendUnique(CXXFLAGS=self.env.make_list(self.cxxflags)) | |||
if len(self.cflags)>0: self.env.AppendUnique(CCFLAGS=self.env.make_list(self.cflags)) | |||
llist=self.env.make_list(self.libs) | |||
lext='.so .la'.split() | |||
sext='.a'.split() | |||
for l in llist: | |||
sal=SCons.Util.splitext(l) | |||
if len(sal)>1: | |||
if sal[1] in lext: self.p_local_shlibs.append(sal[0]+'.so') | |||
elif sal[1] in sext: self.p_local_staticlibs.append(sal[0]+'.a') | |||
else: self.p_global_shlibs.append(l) | |||
if len(self.p_global_shlibs)>0: self.env.AppendUnique(LIBS=self.p_global_shlibs) | |||
if len(self.libpaths)>0: self.env.PrependUnique(LIBPATH=self.env.make_list(self.libpaths)) | |||
if len(self.linkflags)>0: self.env.PrependUnique(LINKFLAGS=self.env.make_list(self.linkflags)) | |||
# the target to return | |||
ret=None | |||
if self.type=='shlib' or self.type=='kioslave': | |||
ret=self.env.bksys_shlib(self.target, self.src, self.instdir, | |||
self.libprefix, self.vnum, nodestdir=self.nodestdir) | |||
elif self.type=='program': | |||
ret=self.env.Program(self.target, self.src) | |||
if not self.env.has_key('NOAUTOINSTALL'): | |||
self.env.bksys_install(self.instdir, ret, nodestdir=self.nodestdir) | |||
elif self.type=='staticlib': | |||
ret=self.env.StaticLibrary(self.target, self.src) | |||
# we link the program against a shared library made locally, add the dependency | |||
if len(self.p_local_shlibs)>0: | |||
self.env.link_local_shlib(self.p_local_shlibs) | |||
if ret: self.env.Depends( ret, self.p_local_shlibs ) | |||
if len(self.p_local_staticlibs)>0: | |||
self.env.link_local_staticlib(self.p_local_staticlibs) | |||
if ret: self.env.Depends( ret, self.p_local_staticlibs ) | |||
self.unlockchdir() | |||
## Copy function that honors symlinks | |||
def copy_bksys(dest, source, env): | |||
if os.path.islink(source): | |||
#print "symlinking "+source+" "+dest | |||
if os.path.islink(dest): | |||
os.unlink(dest) | |||
os.symlink(os.readlink(source), dest) | |||
else: | |||
shutil.copy2(source, dest) | |||
st=os.stat(source) | |||
os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) | |||
return 0 | |||
## Return a list of things | |||
def make_list(env, s): | |||
if type(s) is types.ListType: | |||
return s | |||
else: | |||
return s.split() | |||
def exists(env): | |||
return true | |||
def generate(env): | |||
## Bksys requires scons 0.96 | |||
env.EnsureSConsVersion(0, 96) | |||
SConsEnvironment.make_list = make_list | |||
def doConfigure(env): | |||
return not env['HELP'] and (env['_CONFIGURE'] or not env.has_key('ISCONFIGURED')) | |||
SConsEnvironment.doConfigure = doConfigure | |||
env['HELP']=0 | |||
if '--help' in sys.argv or '-h' in sys.argv or 'help' in sys.argv: | |||
env['HELP']=1 | |||
env.addHelpText(""" | |||
b[*** Generic options *** | |||
-----------------------] | |||
b[* debug ]: debug=1 (-g) or debug=full (-g3, slower), otherwise use | |||
environment CXXFLAGS, or -O2 by default. | |||
b[* prefix ]: the installation path | |||
b[* extraincludes ]: a list of paths separated by ':' | |||
ie: b[scons configure debug=full prefix=/usr/local extraincludes=/tmp/include:/usr/local] | |||
""") | |||
## Global cache directory | |||
# Put all project files in it so a rm -rf cache will clean up the config | |||
if not env.has_key('CACHEDIR'): | |||
env['CACHEDIR'] = os.getcwd()+'/cache/' | |||
if not os.path.isdir(env['CACHEDIR']): | |||
os.mkdir(env['CACHEDIR']) | |||
## SCons cache directory | |||
# This avoids recompiling the same files over and over again: | |||
# very handy when working with cvs | |||
if os.getuid() != 0: | |||
env.CacheDir(os.getcwd()+'/cache/objects') | |||
# Avoid spreading .sconsign files everywhere - keep this line | |||
env.SConsignFile(env['CACHEDIR']+'/scons_signatures') | |||
def makeHashTable(args): | |||
table = { } | |||
for arg in args: | |||
if len(arg) > 1: | |||
lst=arg.split('=') | |||
if len(lst) < 2: | |||
continue | |||
key=lst[0] | |||
value=lst[1] | |||
if len(key) > 0 and len(value) >0: | |||
table[key] = value | |||
return table | |||
env['ARGS']=makeHashTable(sys.argv) | |||
## Special trick for installing rpms ... | |||
env['DESTDIR']='' | |||
if 'install' in sys.argv: | |||
dd='' | |||
if os.environ.has_key('DESTDIR'): | |||
dd=os.environ['DESTDIR'] | |||
if not dd: | |||
if env['ARGS']: dd=env['ARGS']['DESTDIR'] | |||
if dd: | |||
env['DESTDIR']=dd+'/' | |||
print CYAN+'** Enabling DESTDIR for the project ** ' + NORMAL + env['DESTDIR'] | |||
## install symlinks for shared libraries properly | |||
env['INSTALL'] = copy_bksys | |||
## Use the same extension .o for all object files | |||
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 | |||
## load the options | |||
cachefile=env['CACHEDIR']+'generic.cache.py' | |||
opts = Options(cachefile) | |||
opts.AddOptions( | |||
( 'GENCCFLAGS', 'C flags' ), | |||
( 'GENCXXFLAGS', 'debug level for the project : full or just anything' ), | |||
( 'GENLINKFLAGS', 'additional link flags' ), | |||
( 'PREFIX', 'prefix for installation' ), | |||
( 'EXTRAINCLUDES', 'extra include paths for the project' ), | |||
( 'ISCONFIGURED', 'is the project configured' ), | |||
) | |||
opts.Update(env) | |||
# Use this to avoid an error message 'how to make target configure ?' | |||
env.Alias('configure', None) | |||
# Check if the following command line arguments have been given | |||
# and set a flag in the environment to show whether or not it was | |||
# given. | |||
if 'install' in sys.argv: | |||
env['_INSTALL']=1 | |||
else: | |||
env['_INSTALL']=0 | |||
if 'configure' in sys.argv: | |||
env['_CONFIGURE']=1 | |||
else: | |||
env['_CONFIGURE']=0 | |||
# Configure the environment if needed | |||
if doConfigure(env): | |||
# be paranoid, unset existing variables | |||
for var in "GENCXXFLAGS GENCCFLAGS GENLINKFLAGS PREFIX EXTRAINCLUDES ISCONFIGURED EXTRAINCLUDES".split(): | |||
if env.has_key(var): env.__delitem__(var) | |||
if env['ARGS'].get('debug', None): | |||
debuglevel = env['ARGS'].get('debug', None) | |||
print CYAN+'** Enabling debug for the project **' + NORMAL | |||
if (debuglevel == "full"): | |||
env['GENCXXFLAGS'] = ['-DDEBUG', '-g3', '-Wall'] | |||
else: | |||
env['GENCXXFLAGS'] = ['-DDEBUG', '-g', '-Wall'] | |||
else: | |||
if os.environ.has_key('CXXFLAGS'): | |||
# user-defined flags (gentooers will be elighted) | |||
env['GENCXXFLAGS'] = SCons.Util.CLVar( os.environ['CXXFLAGS'] ) | |||
env.Append( GENCXXFLAGS = ['-DNDEBUG', '-DNO_DEBUG'] ) | |||
else: | |||
env.Append(GENCXXFLAGS = ['-O2', '-DNDEBUG', '-DNO_DEBUG']) | |||
if os.environ.has_key('CFLAGS'): | |||
env['GENCCFLAGS'] = SCons.Util.CLVar( os.environ['CFLAGS'] ) | |||
## FreeBSD settings (contributed by will at freebsd dot org) | |||
if os.uname()[0] == "FreeBSD": | |||
if os.environ.has_key('PTHREAD_LIBS'): | |||
env.AppendUnique( GENLINKFLAGS = SCons.Util.CLVar( os.environ['PTHREAD_LIBS'] ) ) | |||
else: | |||
syspf = os.popen('/sbin/sysctl kern.osreldate') | |||
osreldate = int(syspf.read().split()[1]) | |||
syspf.close() | |||
if osreldate < 500016: | |||
env.AppendUnique( GENLINKFLAGS = ['-pthread']) | |||
env.AppendUnique( GENCXXFLAGS = ['-D_THREAD_SAFE']) | |||
elif osreldate < 502102: | |||
env.AppendUnique( GENLINKFLAGS = ['-lc_r']) | |||
env.AppendUnique( GENCXXFLAGS = ['-D_THREAD_SAFE']) | |||
else: | |||
env.AppendUnique( GENLINKFLAGS = ['-pthread']) | |||
# User-specified prefix | |||
if env['ARGS'].has_key('prefix'): | |||
env['PREFIX'] = os.path.abspath( env['ARGS'].get('prefix', '') ) | |||
print (CYAN+'** installation prefix for the project set to : ' + | |||
env['PREFIX'] +' **'+ NORMAL) | |||
# User-specified include paths | |||
env['EXTRAINCLUDES'] = env['ARGS'].get('extraincludes', None) | |||
if env['EXTRAINCLUDES']: | |||
print (CYAN+'** extra include paths for the project set to: ' + | |||
env['EXTRAINCLUDES'] +' **'+ NORMAL) | |||
env['ISCONFIGURED']=1 | |||
# And finally save the options in the cache | |||
opts.Save(cachefile, env) | |||
def bksys_install(lenv, subdir, files, destfile=None, nodestdir=None): | |||
""" Install files on "scons install" | |||
If the DESTDIR env variable has been set, (e.g. by | |||
"scons install DESTDIR=$CURDIR/debian) then install files to that | |||
directory, regardless of where the configure stage showed that | |||
files should be installed. | |||
This feature is useful for packagers, and users of GNU stow. | |||
NB. The DESTDIR will be ignored if NODESTDIR is also set, although | |||
the same effect can be acheived by not setting DESTDIR in the first | |||
place.""" | |||
if not env['_INSTALL']: | |||
return | |||
basedir = env['DESTDIR'] | |||
if nodestdir or env.has_key('NODESTDIR') : basedir = "/" | |||
install_list = None | |||
if not destfile: | |||
install_list = env.Install(basedir+subdir+'/', files) | |||
else: | |||
if subdir: | |||
install_list = env.InstallAs(basedir+subdir+'/'+destfile, files) | |||
else: | |||
install_list = env.InstallAs(basedir+'/'+destfile, files) | |||
env.Alias('install', install_list) | |||
return install_list | |||
def build_la_file(target, source, env): | |||
""" Action for building libtool files. | |||
Writes a .la file, as used by libtool.""" | |||
dest=open(target[0].path, 'w') | |||
sname=source[0].name | |||
dest.write("dlname='%s'\n" % sname) | |||
if len(env['BKSYS_VNUM'])>0: | |||
vnum=env['BKSYS_VNUM'] | |||
nums=vnum.split('.') | |||
src=source[0].name | |||
name = src.split('so.')[0] + 'so' | |||
strn = src+" "+name+"."+str(nums[0])+" "+name | |||
dest.write("library_names='%s'\n" % (strn) ) | |||
else: | |||
dest.write("library_names='%s %s %s'\n" % (sname, sname, sname) ) | |||
dest.write("old_library=''\ndependency_libs=''\ncurrent=0\n") | |||
dest.write("age=0\nrevision=0\ninstalled=yes\nshouldnotlink=no\n") | |||
dest.write("dlopen=''\ndlpreopen=''\n") | |||
dest.write("libdir='%s'" % env['BKSYS_DESTDIR']) | |||
dest.close() | |||
return 0 | |||
def string_la_file(target, source, env): | |||
print "building '%s' from '%s'" % (target[0].name, source[0].name) | |||
la_file = env.Action(build_la_file, string_la_file, ['BKSYS_VNUM', 'BKSYS_DESTDIR']) | |||
env['BUILDERS']['LaFile'] = env.Builder(action=la_file,suffix='.la',src_suffix=env['SHLIBSUFFIX']) | |||
## Function for building shared libraries | |||
def bksys_shlib(lenv, target, source, libdir, libprefix='lib', vnum='', noinst=None, nodestdir=None): | |||
""" Install a shared library. | |||
Installs a shared library, with or without a version number, and create a | |||
.la file for use by libtool. | |||
If library version numbering is to be used, the version number | |||
should be passed as a period-delimited version number (e.g. | |||
vnum = '1.2.3'). This causes the library to be installed | |||
with its full version number, and with symlinks pointing to it. | |||
For example, for libfoo version 1.2.3, install the file | |||
libfoo.so.1.2.3, and create symlinks libfoo.so and | |||
libfoo.so.1 that point to it. | |||
""" | |||
thisenv = lenv.Copy() # copying an existing environment is cheap | |||
thisenv['BKSYS_DESTDIR']=libdir | |||
thisenv['BKSYS_VNUM']=vnum | |||
thisenv['SHLIBPREFIX']=libprefix | |||
if len(vnum)>0: | |||
thisenv['SHLIBSUFFIX']='.so.'+vnum | |||
thisenv.Depends(target, thisenv.Value(vnum)) | |||
# Fix against a scons bug - shared libs and ordinal out of range(128) | |||
if type(source) is types.ListType: | |||
src2=[] | |||
for i in source: | |||
src2.append( str(i) ) | |||
source=src2 | |||
library_list = thisenv.SharedLibrary(target, source) | |||
lafile_list = thisenv.LaFile(target, library_list) | |||
## Install the libraries automatically | |||
if not thisenv.has_key('NOAUTOINSTALL') and not noinst: | |||
thisenv.bksys_install(libdir, library_list, nodestdir=nodestdir) | |||
thisenv.bksys_install(libdir, lafile_list, nodestdir=nodestdir) | |||
## Handle the versioning | |||
if len(vnum)>0: | |||
nums=vnum.split('.') | |||
symlinkcom = ('cd $TARGET.dir && ' + | |||
'rm -f $TARGET.name && ' + | |||
'ln -s $SOURCE.name $TARGET.name') | |||
tg = target+'.so.'+vnum | |||
nm1 = target+'.so' | |||
nm2 = target+'.so.'+nums[0] | |||
thisenv.Command(nm1, tg, symlinkcom) | |||
thisenv.Command(nm2, tg, symlinkcom) | |||
#base=env['DESTDIR']+libdir+'/' | |||
thisenv.bksys_install(libdir, nm1, nodestdir=nodestdir) | |||
thisenv.bksys_install(libdir, nm2, nodestdir=nodestdir) | |||
# Declare scons scripts to process | |||
def subdirs(lenv, folderlist): | |||
flist=[] | |||
if type(folderlist) is types.ListType: flist = folderlist | |||
else: flist = folderlist.split() | |||
for i in flist: | |||
lenv.SConscript(i+"/SConscript") | |||
def link_local_shlib(lenv, str): | |||
""" Links against a shared library made in the project """ | |||
lst = lenv.make_list(str) | |||
for file in lst: | |||
import re | |||
reg = re.compile("(.*)/lib(.*).(la|so)") | |||
result = reg.match(file) | |||
if not result: | |||
print "Unknown la file given "+file | |||
continue | |||
dir = result.group(1) | |||
link = result.group(2) | |||
lenv.AppendUnique(LIBS = [link]) | |||
lenv.PrependUnique(LIBPATH = [dir]) | |||
def link_local_staticlib(lenv, str): | |||
""" Links against a shared library made in the project """ | |||
lst = lenv.make_list(str) | |||
for file in lst: | |||
import re | |||
reg = re.compile("(.*)/(lib.*.a)") | |||
result = reg.match(file) | |||
if not result: | |||
print "Unknown archive file given "+file | |||
continue | |||
f=SCons.Node.FS.default_fs.File(file) | |||
lenv.Append(LINKFLAGS=[f.path]) | |||
#valid_targets = "program shlib kioslave staticlib".split() | |||
SConsEnvironment.bksys_install = bksys_install | |||
SConsEnvironment.bksys_shlib = bksys_shlib | |||
SConsEnvironment.subdirs = subdirs | |||
SConsEnvironment.link_local_shlib = link_local_shlib | |||
SConsEnvironment.link_local_staticlib = link_local_staticlib | |||
SConsEnvironment.genobj=genobj | |||
if env.has_key('GENCXXFLAGS'): | |||
env.PrependUnique( CXXFLAGS = env['GENCXXFLAGS'] ) | |||
if env.has_key('GENCCFLAGS'): | |||
env.AppendUnique( CCFLAGS = env['GENCCFLAGS'] ) | |||
if env.has_key('GENLINKFLAGS'): | |||
env.AppendUnique( LINKFLAGS = env['GENLINKFLAGS'] ) | |||
if env.has_key('EXTRAINCLUDES'): | |||
if env['EXTRAINCLUDES']: | |||
incpaths = [] | |||
for dir in str(env['EXTRAINCLUDES']).split(':'): | |||
incpaths.append( dir ) | |||
env.Append(CPPPATH = incpaths) | |||
env.Export('env') |
@ -0,0 +1,43 @@ | |||
## Thomas Nagy, 2005 | |||
""" | |||
Detect and store the most common options | |||
* kdecxxflags : debug=1 (-g) or debug=full (-g3, slower) | |||
else use the user CXXFLAGS if any, - or -O2 by default | |||
* prefix : the installation path | |||
* extraincludes : a list of paths separated by ':' | |||
ie: scons configure debug=full prefix=/usr/local extraincludes=/tmp/include:/usr/local | |||
""" | |||
BOLD ="\033[1m" | |||
RED ="\033[91m" | |||
GREEN ="\033[92m" | |||
YELLOW ="\033[1m" #"\033[93m" # unreadable on white backgrounds | |||
CYAN ="\033[96m" | |||
NORMAL ="\033[0m" | |||
def exists(env): | |||
return true | |||
def generate(env): | |||
## Bksys requires scons 0.96 | |||
env.EnsureSConsVersion(0, 96) | |||
env._help = '' | |||
def addHelpText(env, text): | |||
env._help = env._help + text | |||
def helpText(env): | |||
text = env._help.replace(']', NORMAL) | |||
text = text.replace('b[', BOLD) | |||
text = text.replace('g[', GREEN) | |||
text = text.replace('r[', RED) | |||
text = text.replace('y[', YELLOW) | |||
text = text.replace('c[', CYAN) | |||
return text | |||
from SCons.Script.SConscript import SConsEnvironment | |||
SConsEnvironment.addHelpText = addHelpText | |||
SConsEnvironment.helpText = helpText |
@ -0,0 +1,820 @@ | |||
# Made from scons qt.py and (heavily) modified into kde.py | |||
# Thomas Nagy, 2004, 2005 <tnagy2^8@yahoo.fr> | |||
""" | |||
Run scons -h to display the associated help, or look below .. | |||
""" | |||
BOLD ="\033[1m" | |||
RED ="\033[91m" | |||
GREEN ="\033[92m" | |||
YELLOW ="\033[1m" #"\033[93m" # unreadable on white backgrounds | |||
CYAN ="\033[96m" | |||
NORMAL ="\033[0m" | |||
import os, re, types | |||
from SCons.Script.SConscript import SConsEnvironment | |||
# Returns the name of the shared object (i.e. libkdeui.so.4) | |||
# referenced by a libtool archive (like libkdeui.la) | |||
def getSOfromLA(lafile): | |||
contents = open(lafile, 'r').read() | |||
match = re.search("^dlname='([^']*)'$", contents, re.M) | |||
if match: | |||
return match.group(1) | |||
return None | |||
# A helper, needed .. everywhere | |||
def KDEuse(lenv, flags): | |||
if lenv['HELP']: lenv.Exit(0) | |||
_flags=lenv.make_list(flags) | |||
if 'environ' in _flags: | |||
## The scons developers advise against using this but it is mostly innocuous :) | |||
lenv.AppendUnique( ENV = os.environ ) | |||
if not 'lang_qt' in _flags: | |||
## Use this define if you are using the kde translation scheme (.po files) | |||
lenv.Append( CPPFLAGS = '-DQT_NO_TRANSLATION' ) | |||
if 'rpath' in _flags: | |||
## Use this to set rpath - this may cause trouble if folders are moved (chrpath) | |||
lenv.Append( RPATH = [lenv['QTLIBPATH'], lenv['KDELIBPATH'], lenv['KDEMODULE']] ) | |||
kdelibpaths=[] | |||
if lenv['KDELIBPATH'] == lenv['KDELIB']: | |||
kdelibpaths = [lenv['KDELIB']] | |||
else: | |||
kdelibpaths = [lenv['KDELIBPATH'], lenv['KDELIB']] | |||
lenv.Append( RPATH = [lenv['QTLIBPATH'], lenv['KDEMODULE']]+kdelibpaths ) | |||
if 'thread' in _flags: | |||
## Uncomment the following if you need threading support | |||
lenv.KDEaddflags_cxx( ['-DQT_THREAD_SUPPORT', '-D_REENTRANT'] ) | |||
if 'fastmoc' in _flags: | |||
lenv['BKSYS_FASTMOC']=1 | |||
if not 'nohelp' in _flags: | |||
if lenv['_CONFIGURE'] or lenv['HELP']: | |||
lenv.Exit(0) | |||
if not 'nosmart' or not lenv.has_key('nosmart_includes'): | |||
lenv.AppendUnique(CPPPATH=['#/']) | |||
lst=[] | |||
if lenv.has_key('USE_THE_FORCE_LUKE'): | |||
lst=lenv['USE_THE_FORCE_LUKE'] | |||
lenv.__delitem__('USE_THE_FORCE_LUKE') | |||
for v in lst: | |||
v.execute() | |||
else: | |||
lenv['nosmart_includes']=1 | |||
## To use kdDebug(intvalue)<<"some trace"<<endl; you need to define -DDEBUG | |||
## it is done in admin/generic.py automatically when you do scons configure debug=1 | |||
def exists(env): | |||
return True | |||
def detect_kde(env): | |||
""" Detect the qt and kde environment using kde-config mostly """ | |||
def getpath(varname): | |||
if not env.has_key('ARGS'): return None | |||
v=env['ARGS'].get(varname, None) | |||
if v: v=os.path.abspath(v) | |||
return v | |||
prefix = getpath('prefix') | |||
execprefix = getpath('execprefix') | |||
datadir = getpath('datadir') | |||
libdir = getpath('libdir') | |||
kdeincludes = getpath('kdeincludes') | |||
kdelibs = getpath('kdelibs') | |||
qtincludes = getpath('qtincludes') | |||
qtlibs = getpath('qtlibs') | |||
libsuffix = '' | |||
if env.has_key('ARGS'): libsuffix=env['ARGS'].get('libsuffix', '') | |||
if libdir: libdir = libdir+libsuffix | |||
## Detect the kde libraries | |||
print "Checking for kde-config : ", | |||
kde_config = os.popen("which kde-config 2>/dev/null").read().strip() | |||
if len(kde_config): | |||
print GREEN+"kde-config was found"+NORMAL | |||
else: | |||
print RED+"kde-config was NOT found in your PATH"+NORMAL | |||
print "Make sure kde is installed properly" | |||
print "(missing package kdebase-devel?)" | |||
env.Exit(1) | |||
env['KDEDIR'] = os.popen('kde-config -prefix').read().strip() | |||
print "Checking for kde version : ", | |||
kde_version = os.popen("kde-config --version|grep KDE").read().strip().split()[1] | |||
if int(kde_version[0]) != 3 or int(kde_version[2]) < 2: | |||
print RED+kde_version | |||
print RED+"Your kde version can be too old"+NORMAL | |||
print RED+"Please make sure kde is at least 3.2"+NORMAL | |||
else: | |||
print GREEN+kde_version+NORMAL | |||
## Detect the qt library | |||
print "Checking for the qt library : ", | |||
qtdir = os.getenv("QTDIR") | |||
if qtdir: | |||
print GREEN+"qt is in "+qtdir+NORMAL | |||
else: | |||
try: | |||
tmplibdir = os.popen('kde-config --expandvars --install lib').read().strip() | |||
libkdeuiSO = tmplibdir+'/'+getSOfromLA(tmplibdir+'/libkdeui.la') | |||
m = re.search('(.*)/lib/libqt.*', os.popen('ldd ' + libkdeuiSO + ' | grep libqt').read().strip().split()[2]) | |||
except: | |||
m=None | |||
if m: | |||
qtdir = m.group(1) | |||
print YELLOW+"qt was found as "+m.group(1)+NORMAL | |||
else: | |||
print RED+"qt was not found"+NORMAL | |||
print RED+"Please set QTDIR first (/usr/lib/qt3?) or try scons -h for more options"+NORMAL | |||
env.Exit(1) | |||
env['QTDIR'] = qtdir.strip() | |||
## Find the necessary programs uic and moc | |||
print "Checking for uic : ", | |||
uic = qtdir + "/bin/uic" | |||
if os.path.isfile(uic): | |||
print GREEN+"uic was found as "+uic+NORMAL | |||
else: | |||
uic = os.popen("which uic 2>/dev/null").read().strip() | |||
if len(uic): | |||
print YELLOW+"uic was found as "+uic+NORMAL | |||
else: | |||
uic = os.popen("which uic 2>/dev/null").read().strip() | |||
if len(uic): | |||
print YELLOW+"uic was found as "+uic+NORMAL | |||
else: | |||
print RED+"uic was not found - set QTDIR put it in your PATH ?"+NORMAL | |||
env.Exit(1) | |||
env['QT_UIC'] = uic | |||
print "Checking for moc : ", | |||
moc = qtdir + "/bin/moc" | |||
if os.path.isfile(moc): | |||
print GREEN + "moc was found as " + moc + NORMAL | |||
else: | |||
moc = os.popen("which moc 2>/dev/null").read().strip() | |||
if len(moc): | |||
print YELLOW + "moc was found as " + moc + NORMAL | |||
elif os.path.isfile("/usr/share/qt3/bin/moc"): | |||
moc = "/usr/share/qt3/bin/moc" | |||
print YELLOW + "moc was found as " + moc + NORMAL | |||
else: | |||
print RED + "moc was not found - set QTDIR or put it in your PATH ?" + NORMAL | |||
env.Exit(1) | |||
env['QT_MOC'] = moc | |||
## check for the qt and kde includes | |||
print "Checking for the qt includes : ", | |||
if qtincludes and os.path.isfile(qtincludes + "/qlayout.h"): | |||
# The user told where to look for and it looks valid | |||
print GREEN + "ok " + qtincludes + NORMAL | |||
else: | |||
if os.path.isfile(qtdir + "/include/qlayout.h"): | |||
# Automatic detection | |||
print GREEN + "ok " + qtdir + "/include/ " + NORMAL | |||
qtincludes = qtdir + "/include/" | |||
elif os.path.isfile("/usr/include/qt3/qlayout.h"): | |||
# Debian probably | |||
print YELLOW + "the qt headers were found in /usr/include/qt3/ " + NORMAL | |||
qtincludes = "/usr/include/qt3" | |||
else: | |||
print RED + "the qt headers were not found" + NORMAL | |||
env.Exit(1) | |||
print "Checking for the kde includes : ", | |||
kdeprefix = os.popen("kde-config --prefix").read().strip() | |||
if not kdeincludes: | |||
kdeincludes = kdeprefix+"/include/" | |||
if os.path.isfile(kdeincludes + "/klineedit.h"): | |||
print GREEN + "ok " + kdeincludes + NORMAL | |||
else: | |||
if os.path.isfile(kdeprefix+"/include/kde/klineedit.h"): | |||
# Debian, Fedora probably | |||
print YELLOW + "the kde headers were found in " + kdeprefix + "/include/kde/" + NORMAL | |||
kdeincludes = kdeprefix + "/include/kde/" | |||
else: | |||
print RED + "The kde includes were NOT found" + NORMAL | |||
env.Exit(1) | |||
# kde-config options | |||
kdec_opts = {'KDEBIN' : 'exe', 'KDEAPPS' : 'apps', | |||
'KDEDATA' : 'data', 'KDEICONS' : 'icon', | |||
'KDEMODULE' : 'module', 'KDELOCALE' : 'locale', | |||
'KDEKCFG' : 'kcfg', 'KDEDOC' : 'html', | |||
'KDEMENU' : 'apps', 'KDEXDG' : 'xdgdata-apps', | |||
'KDEMIME' : 'mime', 'KDEXDGDIR' : 'xdgdata-dirs', | |||
'KDESERV' : 'services','KDESERVTYPES' : 'servicetypes', | |||
'KDEINCLUDE': 'include' | |||
} | |||
if prefix: | |||
## use the user-specified prefix | |||
if not execprefix: | |||
execprefix = prefix | |||
if not datadir: | |||
datadir=prefix+"/share" | |||
if not libdir: | |||
libdir=execprefix+"/lib"+libsuffix | |||
subst_vars = lambda x: x.replace('${exec_prefix}', execprefix)\ | |||
.replace('${datadir}', datadir)\ | |||
.replace('${libdir}', libdir) | |||
debian_fix = lambda x: x.replace('/usr/share', '${datadir}') | |||
env['PREFIX'] = prefix | |||
env['KDELIB'] = libdir | |||
for (var, option) in kdec_opts.items(): | |||
dir = os.popen('kde-config --install ' + option).read().strip() | |||
if var == 'KDEDOC': dir = debian_fix(dir) | |||
env[var] = subst_vars(dir) | |||
else: | |||
env['PREFIX'] = os.popen('kde-config --expandvars --prefix').read().strip() | |||
env['KDELIB'] = os.popen('kde-config --expandvars --install lib').read().strip() | |||
for (var, option) in kdec_opts.items(): | |||
dir = os.popen('kde-config --expandvars --install ' + option).read().strip() | |||
env[var] = dir | |||
env['QTPLUGINS']=os.popen('kde-config --expandvars --install qtplugins').read().strip() | |||
## kde libs and includes | |||
env['KDEINCLUDEPATH']=kdeincludes | |||
if not kdelibs: | |||
kdelibs=os.popen('kde-config --expandvars --install lib').read().strip() | |||
env['KDELIBPATH']=kdelibs | |||
## qt libs and includes | |||
env['QTINCLUDEPATH']=qtincludes | |||
if not qtlibs: | |||
qtlibs=qtdir+"/lib"+libsuffix | |||
env['QTLIBPATH']=qtlibs | |||
def generate(env): | |||
""""Set up the qt and kde environment and builders - the moc part is difficult to understand """ | |||
# attach this function immediately | |||
SConsEnvironment.KDEuse = KDEuse | |||
env.addHelpText(""" | |||
b[*** KDE options *** | |||
-------------------] | |||
b[* prefix ]: base install path, ie: /usr/local | |||
b[* execprefix ]: install path for binaries, ie: /usr/bin | |||
b[* datadir ]: install path for the data, ie: /usr/local/share | |||
b[* libdir ]: install path for the libs, ie: /usr/lib | |||
b[* libsuffix ]: suffix of libraries on amd64, ie: 64, 32 | |||
b[* kdeincludes]: path to the kde includes (/usr/include/kde on debian, ...) | |||
b[* qtincludes ]: path to the for qt includes (/usr/include/qt on debian, ...) | |||
b[* kdelibs ]: path to the kde libs, for linking the programs | |||
b[* qtlibs ]: path to the qt libs, for linking the programs | |||
ie: b[scons configure libdir=/usr/local/lib qtincludes=/usr/include/qt] | |||
""") | |||
import SCons.Defaults | |||
import SCons.Tool | |||
import SCons.Util | |||
import SCons.Node | |||
CLVar = SCons.Util.CLVar | |||
splitext = SCons.Util.splitext | |||
Builder = SCons.Builder.Builder | |||
# Detect the environment - replaces ./configure implicitely and store the options into a cache | |||
from SCons.Options import Options | |||
cachefile=env['CACHEDIR']+'kde.cache.py' | |||
opts = Options(cachefile) | |||
opts.AddOptions( | |||
('PREFIX', 'root of the program installation'), | |||
('QTDIR', ''), | |||
('QTLIBPATH', 'path to the qt libraries'), | |||
('QTINCLUDEPATH', 'path to the qt includes'), | |||
('QT_UIC', 'uic command'), | |||
('QT_MOC', 'moc command'), | |||
('QTPLUGINS', 'uic executable command'), | |||
('KDEDIR', ''), | |||
('KDELIBPATH', 'path to the installed kde libs'), | |||
('KDEINCLUDEPATH', 'path to the installed kde includes'), | |||
('KDEBIN', 'inst path of the kde binaries'), | |||
('KDEINCLUDE', 'inst path of the kde include files'), | |||
('KDELIB', 'inst path of the kde libraries'), | |||
('KDEMODULE', 'inst path of the parts and libs'), | |||
('KDEDATA', 'inst path of the application data'), | |||
('KDELOCALE', ''), ('KDEDOC', ''), ('KDEKCFG', ''), | |||