import
authorTimo Savola <tsavola@movial.fi>
Tue, 1 Apr 2008 14:18:31 +0000 (17:18 +0300)
committerTimo Savola <tsavola@movial.fi>
Wed, 2 Apr 2008 10:52:42 +0000 (13:52 +0300)
based on commit 83b977db1f5e0c260c7396ce32c4c6d5ccc1173d from original
repository.

22 files changed:
.gitignore [new file with mode: 0644]
COPYING [new file with mode: 0644]
boards [new file with mode: 0644]
components/components [new file with mode: 0644]
components/components.all [new file with mode: 0644]
config [new file with mode: 0644]
documentation/samples/plug [new file with mode: 0644]
documentation/samples/sample.package [new file with mode: 0644]
matrix [new file with mode: 0755]
matrix-graph [new file with mode: 0755]
mtxbld/__init__.py [new file with mode: 0644]
mtxbld/config.py [new file with mode: 0644]
mtxbld/git.py [new file with mode: 0644]
mtxbld/graph.py [new file with mode: 0644]
mtxbld/matrix.py [new file with mode: 0644]
mtxbld/rootfs.py [new file with mode: 0644]
rootfs [new file with mode: 0644]
scripts/matrix-autotools.mak [new file with mode: 0644]
scripts/matrix-common.mak [new file with mode: 0644]
scripts/matrix-custom.mak [new file with mode: 0644]
scripts/matrix.mak [new file with mode: 0644]
scripts/matrixify.sh [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..6ef0c29
--- /dev/null
@@ -0,0 +1,17 @@
+.*.swp
+*~
+*.*~
+*.py[co]
+config.local
+scripts/build
+gtk/*
+core/*
+net/*
+af/*
+app/*
+devel/*
+X/*
+.package_map
+.mtxbld-cache
+.matrix-install.lock
+dist
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, 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 Lesser 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) <year>  <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.,
+    51 Franklin Street, Fifth Floor, 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) year 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 Lesser General
+Public License instead of this License.
diff --git a/boards b/boards
new file mode 100644 (file)
index 0000000..9f3b66d
--- /dev/null
+++ b/boards
@@ -0,0 +1,39 @@
+# The AMD64 64bit x86 cpus on a generic desktop
+Board(name      = 'x86_64',
+      arch      = 'x86_64',
+      gcc_march = 'i686',
+      gnu_host  = 'i686-pc-linux-gnu')
+
+# Generic i686+ desktop PC
+Board(name      = 'x86_i686',
+      arch      = 'i386',
+      gcc_march = 'i686',
+      gnu_host  = 'i686-pc-linux-gnu')
+
+# Plain old i386 PC
+Board(name      = 'x86_i386',
+      arch      = 'i386',
+      gcc_march = 'i386',
+      gnu_host  = 'i386-pc-linux-gnu')
+
+# Generic ARM target for ARMv5 (ARM9/11 processors)
+Board(name        = 'arm',
+      arch        = 'arm',
+      gcc_march   = 'armv5t',
+      gcc_options = '-O2 -mfloat-abi=softfp -Wno-poison-system-directories',
+      gnu_host    = 'arm-unknown-linux-gnueabi')
+
+# Nokia 770 Internet Tablet
+Board(name        = 'nokia_770',
+      arch        = 'arm',
+      gcc_march   = 'armv5t',
+      gcc_options = '-O2 -mfloat-abi=softfp',
+      gnu_host    = 'armv5t-unknown-linux-gnueabi')
+
+# Nokia n800 Internet Tablet
+Board(name        = 'nokia_800',
+      arch        = 'arm',
+      gcc_march   = 'armv6',
+      gcc_mfpu    = 'vfp',
+      gcc_options = '-O2 -mfloat-abi=softfp',
+      gnu_host    = 'armv6-unknown-linux-gnueabi')
diff --git a/components/components b/components/components
new file mode 100644 (file)
index 0000000..e8fe571
--- /dev/null
@@ -0,0 +1,170 @@
+Component('bsp/base-system',           tag='master')
+Component('bsp/busybox')
+Component('bsp/zlib')
+Component('bsp/udev')
+Component('bsp/openssl')
+Component('bsp/libusb')
+Component('bsp/usbutils')
+Component('bsp/asound2')
+Component('bsp/alsa-utils')
+Component('bsp/ncurses')
+Component('core/common/dbus')
+Component('core/common/glib')
+Component('core/common/dbus-glib')
+Component('core/common/expat')
+Component('core/common/fontconfig')
+Component('core/common/freetype2')
+Component('core/common/drm')
+Component('core/common/tiff')
+Component('core/common/jpeg')
+Component('core/common/libpng')
+Component('core/common/libidl')
+Component('core/common/libxml2')
+Component('core/common/gconf2')
+Component('core/common/hal')
+Component('core/common/hal-info')
+Component('core/common/liboil')
+Component('core/common/bzip2')
+Component('core/common/gnome-mime-data')
+Component('core/common/gnome-vfs')
+Component('core/common/libgpg-error')
+Component('core/common/libgcrypt')
+Component('core/common/gnome-keyring')
+Component('core/common/pixman')
+Component('core/common/tslib')
+Component('core/common/ohm')
+Component('core/X/util/macros')
+Component('core/X/proto/bigreqsproto')
+Component('core/X/proto/compositeproto')
+Component('core/X/proto/damageproto')
+Component('core/X/proto/dmxproto')
+Component('core/X/proto/evieproto')
+Component('core/X/proto/fixesproto')
+Component('core/X/proto/fontcacheproto')
+Component('core/X/proto/fontsproto')
+Component('core/X/proto/glproto')
+Component('core/X/proto/inputproto')
+Component('core/X/proto/kbproto')
+Component('core/X/proto/pmproto')
+Component('core/X/proto/printproto')
+Component('core/X/proto/randrproto')
+Component('core/X/proto/recordproto')
+Component('core/X/proto/renderproto')
+Component('core/X/proto/resourceproto')
+Component('core/X/proto/scrnsaverproto')
+Component('core/X/proto/trapproto')
+Component('core/X/proto/videoproto')
+Component('core/X/proto/x11proto')
+Component('core/X/proto/xcmiscproto')
+Component('core/X/proto/xextproto')
+Component('core/X/proto/xf86bigfontproto')
+Component('core/X/proto/xf86dgaproto')
+Component('core/X/proto/xf86driproto')
+Component('core/X/proto/xf86miscproto')
+Component('core/X/proto/xf86rushproto')
+Component('core/X/proto/xf86vidmodeproto')
+Component('core/X/proto/xorg-protos',  tag='master')
+Component('core/X/lib/libxtrans')
+Component('core/X/lib/libdmx')
+Component('core/X/lib/libfontenc')
+Component('core/X/lib/libFS')
+Component('core/X/lib/libICE')
+Component('core/X/lib/liblbxutil')
+Component('core/X/lib/liboldX')
+Component('core/X/lib/libpciaccess')
+Component('core/X/lib/libSM')
+Component('core/X/lib/libX11')
+Component('core/X/lib/libXau')
+Component('core/X/lib/libXcursor')
+Component('core/X/lib/libXcomposite')
+Component('core/X/lib/libXdamage')
+Component('core/X/lib/libXdmcp')
+Component('core/X/lib/libXevie')
+Component('core/X/lib/libXext')
+Component('core/X/lib/libXfixes')
+Component('core/X/lib/libXfont')
+Component('core/X/lib/libXfontcache')
+Component('core/X/lib/libXft')
+Component('core/X/lib/libXi')
+Component('core/X/lib/libxkbfile')
+Component('core/X/lib/libxkbui')
+Component('core/X/lib/libXmu')
+Component('core/X/lib/libXp')
+Component('core/X/lib/libXpm')
+Component('core/X/lib/libXprintAppUtil')
+Component('core/X/lib/libXprintUtil')
+Component('core/X/lib/libXrandr')
+Component('core/X/lib/libXrender')
+Component('core/X/lib/libXRes')
+Component('core/X/lib/libXScrnSaver')
+Component('core/X/lib/libXt')
+Component('core/X/lib/libXTrap')
+Component('core/X/lib/libXtst')
+Component('core/X/lib/libXv')
+Component('core/X/lib/libXvMC')
+Component('core/X/lib/libXxf86dga')
+Component('core/X/lib/libXxf86misc')
+Component('core/X/lib/libXxf86vm')
+Component('core/X/xserver')
+Component('core/X/driver/xf86-input-evdev')
+Component('core/X/driver/xf86-input-keyboard')
+Component('core/X/driver/xf86-input-tslib')
+Component('core/X/driver/xf86-video-fbdev')
+Component('core/X/app/mkfontdir')
+Component('core/X/app/mkfontscale')
+Component('core/X/app/bdftopcf')
+Component('core/X/app/xkbcomp')
+Component('core/X/app/xkeyboard-config')
+Component('core/X/font/alias')
+Component('core/X/font/util')
+Component('core/fonts/bitstream-vera')
+Component('framework/ui/atk')
+Component('framework/ui/pango')
+Component('framework/ui/cairo')
+Component('framework/ui/gtk+')
+Component('framework/ui/libnotify')
+Component('framework/ui/libsexy')
+Component('framework/ui/libwnck')
+Component('framework/ui/libglade')
+Component('framework/ui/scim')
+Component('framework/ui/hicolor-icon-theme')
+Component('framework/media/gstreamer0.10')
+Component('framework/media/gst-plugins-base')
+Component('framework/media/gst-plugins-good')
+Component('framework/media/gst-plugins-bad')
+Component('framework/media/gst-plugins-ugly')
+Component('framework/media/gst-ffmpeg')
+Component('framework/media/libmad')
+Component('framework/media/libid3tag')
+Component('framework/media/libogg')
+Component('framework/media/tremor')
+Component('framework/device/gnome-volume-manager')
+Component('framework/device/wireless-tools')
+Component('framework/device/libnl')
+Component('framework/device/dhclient')
+Component('framework/device/dhcdbd')
+Component('framework/device/wpa_supplicant')
+Component('framework/device/NetworkManager')
+Component('framework/device/seal')
+Component('framework/browser/xulrunner')
+Component('tools/openssh')
+Component('tools/sigwrap')
+Component('example-ui/matchbox/matchbox-common')
+Component('example-ui/matchbox/matchbox-window-manager')
+Component('example-ui/matchbox/matchbox-desktop')
+Component('example-ui/matchbox/libmatchbox')
+Component('example-ui/matchbox/libfakekey')
+Component('example-ui/matchbox/matchbox-keyboard')
+Component('example-ui/matchbox/matchbox-panel-2')
+Component('example-ui/matchbox/mb-applet-brightness')
+Component('example-ui/matchbox/mb-applet-volume')
+Component('example-ui/themes/sato-theme')
+Component('example-ui/themes/gonxical-theme')
+Component('example-ui/multimedia/kilikali')
+Component('example-ui/system/network-manager-applet')
+Component('example-ui/system/gtk-chtheme')
+Component('example-ui/system/notification-daemon')
+Component('example-ui/branding/brand-movial')
+Component('example-ui/internet/nitehawk')
+Component('example-ui/utilities/rxvt')
+Component('example-ui/utilities/mtpaint')
diff --git a/components/components.all b/components/components.all
new file mode 100644 (file)
index 0000000..690e6b8
--- /dev/null
@@ -0,0 +1,188 @@
+Component('bsp/base-system',           tag='master')
+Component('bsp/busybox')
+Component('bsp/zlib')
+Component('bsp/udev')
+Component('bsp/openssl')
+Component('bsp/libusb')
+Component('bsp/usbutils')
+Component('bsp/asound2')
+Component('bsp/alsa-utils')
+Component('bsp/ncurses')
+Component('core/common/libsigc++')
+Component('core/common/dbus')
+Component('core/common/glib')
+Component('core/common/dbus-glib')
+Component('core/common/expat')
+Component('core/common/fontconfig')
+Component('core/common/freetype2')
+Component('core/common/drm')
+Component('core/common/tiff')
+Component('core/common/jpeg')
+Component('core/common/libpng')
+Component('core/common/libidl')
+Component('core/common/libxml2')
+Component('core/common/gconf2')
+Component('core/common/hal')
+Component('core/common/hal-info')
+Component('core/common/liboil')
+Component('core/common/bzip2')
+Component('core/common/gnome-mime-data')
+Component('core/common/gnome-vfs')
+Component('core/common/libgpg-error')
+Component('core/common/libgcrypt')
+Component('core/common/gnome-keyring')
+Component('core/common/pixman')
+Component('core/common/tslib')
+Component('core/common/ohm')
+Component('core/X/util/macros')
+Component('core/X/proto/bigreqsproto')
+Component('core/X/proto/compositeproto')
+Component('core/X/proto/damageproto')
+Component('core/X/proto/dmxproto')
+Component('core/X/proto/evieproto')
+Component('core/X/proto/fixesproto')
+Component('core/X/proto/fontcacheproto')
+Component('core/X/proto/fontsproto')
+Component('core/X/proto/glproto')
+Component('core/X/proto/inputproto')
+Component('core/X/proto/kbproto')
+Component('core/X/proto/pmproto')
+Component('core/X/proto/printproto')
+Component('core/X/proto/randrproto')
+Component('core/X/proto/recordproto')
+Component('core/X/proto/renderproto')
+Component('core/X/proto/resourceproto')
+Component('core/X/proto/scrnsaverproto')
+Component('core/X/proto/trapproto')
+Component('core/X/proto/videoproto')
+Component('core/X/proto/x11proto')
+Component('core/X/proto/xcmiscproto')
+Component('core/X/proto/xextproto')
+Component('core/X/proto/xf86bigfontproto')
+Component('core/X/proto/xf86dgaproto')
+Component('core/X/proto/xf86driproto')
+Component('core/X/proto/xf86miscproto')
+Component('core/X/proto/xf86rushproto')
+Component('core/X/proto/xf86vidmodeproto')
+Component('core/X/proto/xorg-protos',  tag='master')
+Component('core/X/lib/libxtrans')
+Component('core/X/lib/libdmx')
+Component('core/X/lib/libfontenc')
+Component('core/X/lib/libFS')
+Component('core/X/lib/libICE')
+Component('core/X/lib/liblbxutil')
+Component('core/X/lib/liboldX')
+Component('core/X/lib/libpciaccess')
+Component('core/X/lib/libSM')
+Component('core/X/lib/libX11')
+Component('core/X/lib/libXau')
+Component('core/X/lib/libXcursor')
+Component('core/X/lib/libXcomposite')
+Component('core/X/lib/libXdamage')
+Component('core/X/lib/libXdmcp')
+Component('core/X/lib/libXevie')
+Component('core/X/lib/libXext')
+Component('core/X/lib/libXfixes')
+Component('core/X/lib/libXfont')
+Component('core/X/lib/libXfontcache')
+Component('core/X/lib/libXft')
+Component('core/X/lib/libXi')
+Component('core/X/lib/libxkbfile')
+Component('core/X/lib/libxkbui')
+Component('core/X/lib/libXmu')
+Component('core/X/lib/libXp')
+Component('core/X/lib/libXpm')
+Component('core/X/lib/libXprintAppUtil')
+Component('core/X/lib/libXprintUtil')
+Component('core/X/lib/libXrandr')
+Component('core/X/lib/libXrender')
+Component('core/X/lib/libXRes')
+Component('core/X/lib/libXScrnSaver')
+Component('core/X/lib/libXt')
+Component('core/X/lib/libXTrap')
+Component('core/X/lib/libXtst')
+Component('core/X/lib/libXv')
+Component('core/X/lib/libXvMC')
+Component('core/X/lib/libXxf86dga')
+Component('core/X/lib/libXxf86misc')
+Component('core/X/lib/libXxf86vm')
+Component('core/X/xserver')
+Component('core/X/driver/xf86-input-evdev')
+Component('core/X/driver/xf86-input-mouse')
+Component('core/X/driver/xf86-input-keyboard')
+Component('core/X/driver/xf86-input-tslib')
+Component('core/X/driver/xf86-video-fbdev')
+Component('core/X/app/mkfontdir')
+Component('core/X/app/mkfontscale')
+Component('core/X/app/bdftopcf')
+Component('core/X/app/xkbcomp')
+Component('core/X/app/xkeyboard-config')
+Component('core/X/app/xrandr')
+Component('core/X/font/alias')
+Component('core/X/font/util')
+Component('core/X/font/cursor-misc')
+Component('core/X/font/misc-misc')
+Component('core/fonts/bitstream-vera')
+Component('framework/ui/atk')
+Component('framework/ui/pango')
+Component('framework/ui/cairo')
+Component('framework/ui/gtk+')
+Component('framework/ui/libnotify')
+Component('framework/ui/libsexy')
+Component('framework/ui/libwnck')
+Component('framework/ui/libglade')
+Component('framework/ui/scim')
+Component('framework/ui/hicolor-icon-theme')
+Component('framework/media/gstreamer0.10')
+Component('framework/media/gst-plugins-base')
+Component('framework/media/gst-plugins-good')
+Component('framework/media/gst-plugins-bad')
+Component('framework/media/gst-plugins-ugly')
+Component('framework/media/gst-ffmpeg')
+Component('framework/media/libmad')
+Component('framework/media/libid3tag')
+Component('framework/media/libogg')
+Component('framework/media/tremor')
+Component('framework/device/gnome-volume-manager')
+Component('framework/device/wireless-tools')
+Component('framework/device/libnl')
+Component('framework/device/dhclient')
+Component('framework/device/dhcdbd')
+Component('framework/device/wpa_supplicant')
+Component('framework/device/NetworkManager')
+Component('framework/device/seal')
+Component('framework/browser/libgtkembedmoz')
+Component('framework/browser/microb-engine')
+Component('framework/browser/xulrunner')
+Component('framework/addressbook/eds-dbus')
+Component('tools/openssh')
+Component('tools/popt')
+Component('tools/binutils')
+Component('tools/x11perf')
+Component('tools/xnee')
+Component('tools/oprofile')
+Component('tools/python2.5')
+Component('tools/sigwrap')
+Component('example-ui/matchbox/matchbox-common')
+Component('example-ui/matchbox/matchbox-window-manager')
+Component('example-ui/matchbox/matchbox-desktop')
+Component('example-ui/matchbox/libmatchbox')
+Component('example-ui/matchbox/libfakekey')
+Component('example-ui/matchbox/matchbox-keyboard')
+Component('example-ui/matchbox/matchbox-panel-2')
+Component('example-ui/matchbox/mb-applet-brightness')
+Component('example-ui/matchbox/mb-applet-volume')
+Component('example-ui/themes/sato-theme')
+Component('example-ui/themes/gonxical-theme')
+Component('example-ui/multimedia/kilikali')
+Component('example-ui/internet/microb-eal')
+Component('example-ui/internet/browser-eal')
+Component('example-ui/internet/gtkadi')
+Component('example-ui/internet/tablet-browser-ui')
+Component('example-ui/system/network-manager-applet')
+Component('example-ui/system/gtk-chtheme')
+Component('example-ui/system/notification-daemon')
+Component('example-ui/branding/brand-movial')
+Component('example-ui/internet/nitehawk')
+Component('example-ui/utilities/rxvt')
+Component('example-ui/utilities/mtpaint')
diff --git a/config b/config
new file mode 100644 (file)
index 0000000..22ad0b4
--- /dev/null
+++ b/config
@@ -0,0 +1,9 @@
+if not roots:
+       roots = ['matrix.movial.fi:/matrix/shared/repo']
+
+if not board:
+       board = 'arm'
+
+# If you are not using a prebuilt rootfs, remove the 'global-cache' flag
+if not flags:
+       flags = ['debug', 'global-cache', 'no-docs', 'no-examples', 'no-tests']
diff --git a/documentation/samples/plug b/documentation/samples/plug
new file mode 100644 (file)
index 0000000..591cd28
--- /dev/null
@@ -0,0 +1,16 @@
+# This is a sample .matrix/plug file
+
+MATRIX_BUILD_STYLE = autotools
+
+# this makes the build happen outside of the source tree
+MATRIX_OBJ_DIR = .matrix/obj
+
+# run autogen.sh with no parameters
+MATRIX_AUTOGEN_WITH = ""
+
+ifdef custom_flag
+MATRIX_CONFIGURE_ENV = "CC=my-special-gcc"
+endif
+MATRIX_CONFIGURE_ARGS = "--prefix=/usr"
+
+
diff --git a/documentation/samples/sample.package b/documentation/samples/sample.package
new file mode 100644 (file)
index 0000000..4dc841f
--- /dev/null
@@ -0,0 +1,7 @@
+name="sample"
+depends="some_package1:>=1.2.3-m5:flag1,flag2 some_package2"
+conflicts="some_package3::flag some_package1::flag3"
+license="GPL 9"
+description="A Sample Package"
+
+
diff --git a/matrix b/matrix
new file mode 100755 (executable)
index 0000000..842e2ca
--- /dev/null
+++ b/matrix
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+import sys
+from mtxbld import matrix
+
+try:
+       matrix.main()
+
+except RuntimeError, e:
+       print >>sys.stderr, str(e)
+       sys.exit(1)
+
+except KeyboardInterrupt:
+       sys.exit(1)
diff --git a/matrix-graph b/matrix-graph
new file mode 100755 (executable)
index 0000000..34a053e
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+import sys
+from mtxbld import graph
+
+commands = [
+       ("components", graph.ComponentGraph, "Create a components file from the dependancy tree"),
+       ("dot", graph.DotGraph, "Create a graph from the dependancy tree with 'dot'"),
+]
+
+print "\nCopyright (C) 2007-2008 Movial Oy\n"
+
+if len(sys.argv) < 2:
+       print "Please specify one of the following commands:\n"
+       for command, obj, description in commands:
+               print "  %-15s %s" % (command, description)
+       print
+       sys.exit(1)
+
+if sys.argv[1] == "components":
+       g = graph.ComponentGraph(sys.argv[2:])
+elif sys.argv[1] == "dot":
+       g = graph.DotGraph(sys.argv[2:])
+else:
+       print "Unknown command", sys.argv[1]
+       sys.exit(1)
+  
+g.output()
diff --git a/mtxbld/__init__.py b/mtxbld/__init__.py
new file mode 100644 (file)
index 0000000..54a18a5
--- /dev/null
@@ -0,0 +1,6 @@
+__all__ = (
+       'config',
+       'git',
+       'matrix',
+       "graph",
+)
diff --git a/mtxbld/config.py b/mtxbld/config.py
new file mode 100644 (file)
index 0000000..001594b
--- /dev/null
@@ -0,0 +1,79 @@
+# Copyright (C) 2007-2008 Movial Oy
+# Authors: Timo Savola <tsavola@movial.fi>
+#          Kalle Vahlman <kalle.vahlman@movial.fi>
+
+import os as __os
+
+top_dir = __os.environ.get('MATRIX_TOPDIR', __os.getcwd())
+cache_dir = __os.path.join(top_dir, '.mtxbld-cache')
+global_cache_dir = '/usr/share/matrix/build-cache'
+
+boards = {}
+board = None
+components = {}
+roots = []
+flags = []
+libc = 'glibc'
+verbose = False
+debug = False
+
+class Board:
+       def __init__(self, name, arch, gcc_march, gcc_mcpu='', gcc_mfpu='', gcc_options='', gnu_host='', flash_erase_size='65536', flash_pad_size='0'):
+               self.name = name
+               self.arch = arch
+               self.gcc_march = gcc_march
+               self.gcc_mcpu = gcc_mcpu
+               self.gcc_mfpu = gcc_mfpu
+               self.gcc_options = gcc_options
+               self.gnu_host = gnu_host
+               self.flash_erase_size = flash_erase_size
+               self.flash_pad_size = flash_pad_size
+
+               boards[name] = self
+
+class Component:
+       import git
+
+       from_platform = False
+
+       def __init__(self, name, tag='matrix', tags={}, flags=[]):
+               self.name = name
+
+               self.tags = {}
+               self.tags.update(tags)
+               self.tags[None] = tag
+
+               self.flags = flags
+
+               self.active_url = None
+               self.__active_tag = None
+               self.active_packages = None
+               self.active_depends = None
+               self.__active_hash = None
+               self.active_state = None
+
+               components[name] = self
+
+       def get_active_tag(self):
+               global board
+
+               if self.__active_tag is None:
+                       tag = self.tags.get(board)
+                       if not tag:
+                               tag = self.tags.get(None)
+                       self.__active_tag = tag
+
+               return self.__active_tag
+
+       def get_active_hash(self):
+               if self.__active_hash is None:
+                       self.__active_hash \
+                           = self.git.rev_parse(self.name, 'HEAD')
+
+               return self.__active_hash
+
+class PlatformProvidedComponent(Component):
+       """A Component that is provided by the platform.
+          The sources will not be built during install."""
+
+       from_platform = True
diff --git a/mtxbld/git.py b/mtxbld/git.py
new file mode 100644 (file)
index 0000000..ffa5334
--- /dev/null
@@ -0,0 +1,236 @@
+# Copyright (C) 2007-2008 Movial Oy
+# Authors: Timo Savola <tsavola@movial.fi>
+#          Toni Timonen
+
+import os, sys
+import bz2
+
+import config
+
+class Error (RuntimeError):
+       def __init__(self, args, workdir=None):
+               command = ' '.join(args)
+
+               if workdir:
+                       message = 'Failed in %s: %s' % (workdir, command)
+               else:
+                       message = 'Failed: %s' % command
+
+               RuntimeError.__init__(self, message)
+
+def call(args, workdir=None, quiet=False, fail=False):
+       args = ['git'] + args
+
+       if config.debug:
+               if workdir:
+                       print 'Executing in %s:' % workdir,
+               else:
+                       print 'Executing:',
+
+               print ' '.join(args)
+
+       pid = os.fork()
+       if pid == 0:
+               try:
+                       if workdir:
+                               os.chdir(workdir)
+
+                       if quiet:
+                               fd = os.open('/dev/null', os.O_WRONLY)
+                               os.dup2(fd, 1)
+                               os.dup2(fd, 2)
+                               if fd not in (1, 2):
+                                       os.close(fd)
+
+                       os.execvp(args[0], args)
+
+               except Exception, e:
+                       print >>sys.stderr, e
+
+               os._exit(127)
+
+       pid, status = os.waitpid(pid, 0)
+       if status != 0 and fail:
+               raise Error(args, workdir)
+
+       return status
+
+def call_output(args, workdir=None, fd=None, lines=True,wait=True):
+       args = ['git'] + args
+
+       if config.debug:
+               if workdir:
+                       print 'Executing in %s:' % workdir,
+               else:
+                       print 'Executing:',
+
+               print ' '.join(args)
+
+       if fd is None:
+               input, output = os.pipe()
+
+       pid = os.fork()
+       if pid == 0:
+               try:
+                       if workdir:
+                               os.chdir(workdir)
+
+                       if fd is not None:
+                               if fd != 1:
+                                       os.dup2(fd, 1)
+                       else:
+                               os.close(input)
+                               if output != 1:
+                                       os.dup2(output, 1)
+                                       os.close(output)
+
+                       os.execvp(args[0], args)
+
+               except Exception, e:
+                       print >>sys.stderr, e
+
+               os._exit(127)
+
+       if fd is None:
+               os.close(output)
+
+               f = os.fdopen(input, 'r')
+               if lines:
+                       contents = f.readlines()
+               else:
+                       contents = f.read()
+               f.close()
+
+       if not wait and fd is not None:
+               return
+       pid, status = os.waitpid(pid, 0)
+       if status != 0:
+               raise Error(args, workdir)
+
+       if fd is None:
+               if lines:
+                       return [i.strip() for i in contents]
+               else:
+                       return contents
+
+def peek_remote(url, quiet=False):
+       args = ['peek-remote', url]
+       return call(args, quiet=quiet, fail=not quiet) == 0
+
+def clone(name, url, checkout=True):
+       options = []
+       if not checkout:
+               options = ['-n']
+
+       call(['clone'] + options + [url, name], fail=True)
+
+def pull(name, url=None, refspec=None):
+       if url is None and refspec is None:
+               cmd = ['pull']
+       else:
+               cmd = ['pull',url,refspec]
+       if call(cmd, workdir=name) != 0:
+               raise Error('pull', url)
+
+def create_branch(name, branch, point, checkout=False,link=False,force=False):
+       if checkout:
+               command = ['checkout', '-b']
+       else:
+               command = ['branch']
+
+       if not force:
+               call(command + [branch, point], workdir=name, fail=True)
+       else:
+               #If we need more force, branch to temprepo first and rename
+               call(command + ['_matrix_tmp', point], workdir=name, fail=True)
+               call(['branch','-M','_matrix_tmp',branch],workdir=name,fail=True)
+
+       if link:
+               call(['config','branch.%s.merge'%branch,'refs/heads/%s'%branch],workdir=name)
+
+def delete_branch(name, branch, force=False, quiet=False):
+       if force:
+               command = '-D'
+       else:
+               command = '-d'
+
+       return call(['branch', command, branch], name, quiet, not quiet) == 0
+
+def checkout(name, branch):
+       call(['checkout', branch], workdir=name, fail=True)
+
+def rev_parse(name, arg):
+       lines = call_output(['rev-parse', arg], workdir=name)
+       if lines:
+               return lines[0].strip()
+       else:
+               return None
+
+def getvar(name,var):
+       if not os.path.exists(name):
+               return None
+       res=call_output(['config',var],workdir=name)
+       if res and len(res)==1:
+               return res[0]
+       return None
+
+def ls_tree(name, treeish, name_only=False, recursive=False):
+       options = []
+       if name_only:
+               options.append('--name-only')
+       if recursive:
+               options.append('-r')
+
+       return call_output(['ls-tree'] + options + [treeish], workdir=name)
+
+def ls_files(name, options):
+       return call_output(['ls-files'] + options, workdir=name)
+
+
+def archive(name, arch_name,prefix=None,branch='HEAD'):
+       cmd = ['archive','--format=tar']
+       if prefix:
+               cmd.append('--prefix=%s'%prefix)
+
+       inp,out = os.pipe()
+       call_output(cmd+[branch],workdir=name,fd=out,wait=False)
+       os.close(out)
+       infile=os.fdopen(inp)
+       outfile=bz2.BZ2File(arch_name,'w')
+       data=infile.read(1024*50)
+       while data:
+               outfile.write(data)
+               data=infile.read(1024*50)
+       infile.close()
+       outfile.close()
+
+def describe(name,branch='HEAD'):
+       cmd={'args':['describe',branch],'workdir':name}
+       try:
+               call(quiet=True,fail=True,**cmd)
+               res=call_output(**cmd)
+       except Error,e:
+               return None
+
+       if res and len(res)==1:
+               return res[0]
+       return None
+
+def cat_file(name, hash, blob=False, size=False):
+       if blob:
+               option = 'blob'
+       elif size:
+               option = '-s'
+       else:
+               return None
+
+       contents = call_output(['cat-file', option, hash], workdir=name,
+                              lines=False)
+
+       if size:
+               return int(contents.strip())
+       else:
+               return contents
+
+def log(name, options, fd=None):
+       return call_output(['log'] + options + ['--'], workdir=name, fd=fd)
diff --git a/mtxbld/graph.py b/mtxbld/graph.py
new file mode 100644 (file)
index 0000000..85ca2a8
--- /dev/null
@@ -0,0 +1,226 @@
+# Copyright (C) 2006-2008 Movial Oy
+# Authors: Kalle Vahlman <kalle.vahlman@movial.fi>
+
+import os
+import sys
+
+import config
+import matrix
+
+
+class Option:
+       short_opt = None
+       long_opt = None
+       takes_arg = False
+       help = None
+       argument = None
+
+       def __init__(self, short_opt, long_opt, takes_arg, help):
+               self.short_opt = short_opt
+               self.long_opt = long_opt
+               self.takes_arg = takes_arg
+               self.help = help
+
+
+class Graph:
+       all_targets = []
+       all_deps = []
+       maxdepth = -1
+
+       options = {}
+       args = []
+       roots = None
+
+       def __init__(self, arguments):
+               self.args.append(Option("h", "help", False,
+                       "Show this help"))
+               self.args.append(Option("c", "components", True,
+                       "Read components from specified file (default: 'components.all')"))
+               self.args.append(Option("i", "input", True,
+                       "Read active components from specified file"))
+               self.args.append(Option("o", "output", True,
+                       "Write graph to specified file (type autodetected)"))
+               self.args.append(Option("r", "root", True,
+                       "Start graphing from specified component"))
+               self.args.append(Option("d", "depth", True,
+                       "Limit graph to specified depth"))
+
+               self.parse_args(arguments)
+
+               try:
+                       if self.options["help"]:
+                               print "\nCopyright (C) 2007 Movial Oy\n"
+                               print "Usage: %s [options]\n" % sys.argv[0]
+
+                               for opt in self.args:
+                                       argstr = ""
+                                       if opt.takes_arg:
+                                               argstr = "[arg]"
+
+                                       print " %-25s %s" % ("-" + opt.short_opt + ", --" + opt.long_opt + " " + argstr, opt.help)
+                       print
+                       sys.exit()
+               except KeyError:
+                       pass
+
+               try:
+                       matrix.parse_config(self.options["components"].argument)
+               except KeyError:
+                       # Default to components.all
+                       matrix.parse_config('components/components.all')
+                       print "huuhaaaaaa"
+
+               matrix.update_components()
+
+               try:
+                       self.maxdepth = int(self.options["depth"].argument)
+               except KeyError:
+                       self.maxdepth = -1
+
+               roots = self.get_roots()
+
+               depth = 1
+               for component in config.components.values():
+                       if roots is None or component.name in roots:
+
+                               self.add_component(component, self.maxdepth, depth)
+
+       def add_component(self, component, maxdepth, depth):
+               for dep in component.active_depends:
+                       dependancy = self.depends(component, dep)
+                       if dependancy not in self.all_deps:
+                               self.all_deps.append(dependancy)
+                       if maxdepth < 0 or depth < maxdepth:
+                               self.add_component(dep, maxdepth, depth + 1)
+
+       def parse_args(self, arguments):
+               arg = None
+               argarg = None
+               for argument in arguments:
+                       if arg is not None and arg.takes_arg:
+                               if not argument.startswith("-"):
+                                       arg.argument = argument
+                                       arg = None
+                                       continue
+                               else:
+                                       arg = None
+
+                       for opt in self.args:
+                               if argument.startswith("-") or argument.startswith("--"):
+                                       if argument[1:] == opt.short_opt or argument[2:] == opt.long_opt:
+                                               self.options[opt.long_opt] = opt
+                                               arg = opt
+                                               break
+
+                       if arg is None:
+                               raise RuntimeError, "Unkown argument '" + argument + "'"
+
+       def read_roots(self, active_components_file="components.active"):
+               f = open(active_components_file, "r")
+               self.roots = []
+               for root in f.readlines():
+                       if len(root.strip()) > 0:
+                               self.roots.append(root.strip())
+               f.close()
+               print "Active components read from", active_components_file
+
+       def get_roots(self):
+               if self.roots is not None:
+                       return self.roots
+
+               try:
+                       active_components_file = self.options["input"].argument
+                       self.read_roots(active_components_file)
+               except KeyError:
+                       try:
+                               self.read_roots()
+                       except IOError:
+                               try:
+                                       self.roots = [self.options["root"].argument]
+                                       print "Active component: %s" % self.roots[0]
+                               except KeyError:
+                                       print "Including all known components as active"
+
+               return self.roots
+
+       def depends(self, component, dependancy):
+               raise NotImplementedError, 'Method depends not implemented by derived class'
+
+       def output(self):
+               raise NotImplementedError, 'Method output not implemented by derived class'
+
+
+class DotGraph(Graph):
+       def __init__(self, arguments):
+               self.args.append(Option("a", "aspect-ratio", True,
+                       "Dot: Aspect ratio for the graph"))
+               self.args.append(Option("s", "size", True,
+                       "Dot: Size of the graph ('xx.x,xx.x', in inches)"))
+               Graph.__init__(self, arguments)
+
+       def depends(self, component, dependancy):
+               return "\t\"" + component.name + "\" -> \"" + dependancy.name + "\""
+
+       def output(self):
+               try:
+                       fname = self.options["output"].argument
+                       otype = self.options["output"].argument[self.options["output"].argument.rindex(".")+1:]
+               except KeyError:
+                       fname = "graph.svg"
+                       otype = "svg"
+
+               try:
+                       ratio = self.options["aspect"].argument
+               except KeyError:
+                       ratio = "0.7" # default to landscape A4
+
+               try:
+                       size = "-Gsize=" + self.options["size"].argument
+               except KeyError:
+                       size = '' # default to native size
+
+               f = open("graph.dot", "w")
+               f.write("digraph {\n")
+               for depstr in self.all_deps:
+                       f.write(depstr + "\n")
+               f.write("}\n")
+               f.close()
+
+               print "Writing", fname
+               os.system("dot graph.dot -Grankdir=LR -Gsplines=true -Nrotate=90 -Gratio=" + ratio + " -T" + otype + " " + size + " -o " + fname)
+               os.remove("graph.dot")
+
+class ComponentGraph(Graph):
+       def __init__(self, arguments):
+               Graph.__init__(self, arguments)
+
+               if self.roots is not None:
+                       for component in config.components.values():
+                               if component.name in self.roots:
+                                       self.all_deps.append(self.depends(None, component))
+                                       break
+
+       def depends(self, component, dependancy):
+               tagstr = ""
+               flagstr = ""
+               if dependancy.tags[None] != "matrix":
+                       tagstr = ",\ttag='" + dependancy.tags[None] + "'"
+               if len(dependancy.flags) > 0:
+                       flagstr = ",\tflags=["
+                       for flag in dependancy.flags:
+                               flagstr += "'" + flag + "',"
+                       flagstr = flagstr[:-1] + "]"
+
+               return "Component('" + dependancy.name + "'" + tagstr + flagstr + ")"
+
+       def output(self):
+               try:
+                       fname = self.options["output"].argument
+               except KeyError:
+                       fname = "components"
+
+               print "Writing", fname
+               f = open(fname, "w")
+               for depstr in self.all_deps:
+                       f.write(depstr + "\n")
+               f.close()
diff --git a/mtxbld/matrix.py b/mtxbld/matrix.py
new file mode 100644 (file)
index 0000000..1b0c41e
--- /dev/null
@@ -0,0 +1,591 @@
+# Copyright (C) 2006-2008 Movial Oy
+# Authors: Timo Savola <tsavola@movial.fi>
+#          Toni Timonen
+#          Kalle Vahlman <kalle.vahlman@movial.fi>
+#          Tuomas Kulve <tuomas.kulve@movial.fi>
+
+import sys
+import os
+import glob
+import re
+import tarfile
+from sets import Set as set
+
+import config
+import git
+from rootfs import RootFS
+
+Error = RuntimeError
+
+def main():
+       parse_config('config.local')
+
+       command, params, targets = parse_args(sys.argv)
+
+       parse_config('config')
+       parse_config('boards')
+       parse_config('components/components')
+
+       if 'global-cache' in config.flags:
+               config.cache_dir = config.global_cache_dir
+
+       if not os.path.exists(config.cache_dir):
+               os.makedirs(config.cache_dir)
+
+       all_targets = update_components()
+
+       for name in targets:
+               if name not in config.components:
+                       raise Error('Component "%s" does not exist' % name)
+
+       if not targets:
+               targets = all_targets
+
+       if command == 'install':
+               build_components(targets, **params)
+       elif command == 'download':
+               # Actual downloading took place already in update_components()
+               pass
+       elif command == 'clean':
+               clean_components(targets)
+       elif command == 'pull':
+               pull_components(targets)
+       elif command == 'source-dist':
+               source_dist_components(targets)
+       elif command == 'rootfs':
+               build_rootfs(**params)
+       else:
+               raise Error('Invalid command: ' + command)
+
+def help(file, args):
+       print >>file, '''
+Copyright (C) 2006-2008 Movial Oy
+
+Usage: %(progname)s [options] [command] [params] [component1 component2 ...]
+
+Components must be given like this: core/glibc core/busybox X/xserver
+If no components are given, all of them will be subject to the operation.
+
+Options:
+       -v              Verbose output
+       -d              Debug output
+       -r URL          Specify the root for component git repos to clone from.
+                       If this option is not given, the default specified in
+                       the components file will be used.  This option may be
+                       specified multiple times.
+       -h, --help      Print this help text.
+
+Commands and their parameters:
+
+       download        Only download the components and validate the tree.
+       install         Download, build and install the components.
+               -j N            Execute N build jobs in parallel.
+               -mj N           Run component builds with make -j N.
+       clean           Remove all non-tracked files from the component git
+                       repository directories.
+       pull            Run git pull for the components.
+       source-dist     Download and package the component sources.
+       rootfs          Build a rootfs from the current target installation.
+               -n              Do not clean env.faked and stripped directory.
+               -r              Only generate a stripped rootfs.
+               -j              Only generate a jffs2 image
+               -d              Only generate a rootstrap (development rootfs).
+       list [parameter] [pattern]
+               -p              List packages.
+               -pv             List packages with full details.
+               -c              List components (default).
+               -cdep           List components and their dependencies.
+''' % {'progname': args[0]}
+
+def parse_args(args):
+       def parse_jobs(arg):
+               jobs = int(arg)
+               if jobs <= 0:
+                       raise Error('Please specify a valid number of jobs')
+               return jobs
+
+       command = None
+       params = {}
+       targets = []
+
+       i = 1
+       while i < len(args):
+               if args[i].startswith('-'):
+                       if not command:
+                               if args[i] == '-v':
+                                       config.verbose = True
+                               elif args[i] == '-d':
+                                       config.debug = True
+                               elif args[i] == '-r':
+                                       i += 1
+                                       config.roots.append(args[i])
+                               elif args[i] in ('-h', '--help'):
+                                       help(sys.stdout, args)
+                                       sys.exit(0)
+                               else:
+                                       raise Error('Bad option: ' + args[i])
+                       elif command == 'install':
+                               if args[i] == '-j':
+                                       i += 1
+                                       params['build_jobs'] = parse_jobs(args[i])
+                               elif args[i] == '-mj':
+                                       i += 1
+                                       params['make_jobs'] = parse_jobs(args[i])
+                               else:
+                                       raise Error('Bad parameter: ' + args[i])
+                       elif command == 'rootfs':
+                               if args[i] == '-n':
+                                       i += 1
+                                       params['clean'] = False
+                               elif args[i] == '-r':
+                                       i += 1
+                                       params['rootfs_only'] = True
+                               elif args[i] == '-j':
+                                       i += 1
+                                       params['jffs2_only'] = True
+                               elif args[i] == '-d':
+                                       i += 1
+                                       params['devrootfs_only'] = True
+                       else:
+                               raise Error('Command takes no parameters')
+               elif not command:
+                       command = args[i]
+               else:
+                       targets.append(args[i])
+               i += 1
+
+       if not command:
+               help(sys.stderr, args)
+               sys.exit(1)
+
+       return command, params, targets
+
+def parse_config(path):
+       if os.path.isabs(path):
+               path = os.path.join(config.top_dir, path)
+
+       if os.path.exists(path):
+               print 'Reading', path
+               execfile(path, config.__dict__, config.__dict__)
+
+def update_components():
+       targets = []
+       packages = {}
+
+       for c in config.components.itervalues():
+               update_component_url(c)
+               download_component(c)
+               update_component_packages(c, targets, packages)
+               c.active_depends = []
+
+       update_component_depends(packages)
+
+       return targets
+
+def update_component_url(c):
+       url=git.getvar(c.name,'remote.origin.url')
+       if url:
+               c.active_url=url
+               if config.debug:
+                       print 'Using', c.active_url
+               return
+
+       for root in config.roots:
+               for suffix in ('.git', ''):
+                       url = root + '/' + c.name + suffix
+
+                       if config.debug:
+                               print 'Trying', url
+
+                       if not git.peek_remote(url, quiet=True):
+                               continue
+
+                       c.active_url = url
+                       if config.debug:
+                               print 'Found', c.active_url
+                       return
+
+       raise Error('Failed to locate repository of ' + c.name)
+
+def update_component_depends(packages):
+       for pkg in packages.itervalues():
+               for spec in pkg.depends.split():
+                       depname = Depend(spec).name
+                       deppkg = packages.get(depname)
+
+                       if not deppkg:
+                               print >>sys.stderr, 'Package', pkg.name, \
+                                       'depends on non-existent package', depname
+                               continue
+
+                       if deppkg.component == pkg.component:
+                               continue
+
+                       pkg.component.active_depends.append(deppkg.component)
+
+       fail = False
+       for pkg in packages.itervalues():
+               for spec in pkg.depends.split():
+                       if not Depend(spec).check(packages):
+                               fail = True
+                               print >>sys.stderr, 'Dependency', spec, \
+                                       'failed for', pkg.name
+
+               for spec in pkg.conflicts.split():
+                       if Depend(spec).check(packages):
+                               fail = True
+                               print >>sys.stderr, pkg.name, \
+                                       'conflicts with', spec
+
+       if fail:
+               raise Error('Invalid component tree')
+
+class Depend:
+       regex = re.compile(r'([@]?)([^\s:]+)[:]?([<>=]*)([^\s:]*)[:]?(.*)')
+
+       def __init__(self, spec):
+               match = self.regex.match(spec)
+               if not match:
+                       raise Error('Bad dependency specification: ' + spec)
+
+               self.build, self.name, self.tag_op, self.tag, flags \
+                       = match.groups()
+               self.flags = flags.split()
+
+       def check(self, packages):
+               # TODO: check version and flags
+               return self.name in packages
+
+def execute(args):
+       if config.debug:
+               print 'Executing:', ' '.join(args)
+
+       if os.spawnvp(os.P_WAIT, args[0], args) != 0:
+               raise Error('Failed: ' + ' '.join(args))
+
+def download_component(c, overwrite=False):
+       if os.path.exists(c.name) and not overwrite:
+               return
+
+       print 'Downloading component:', c.name
+
+       execute(['rm', '-rf', c.name])
+       git.clone(c.name, c.active_url, checkout=False)
+
+       branch = c.get_active_tag()
+       git.create_branch(c.name, branch, 'origin/%s'%branch, checkout=True, link=True,force=True)
+
+def update_component_packages(c, targets, packages):
+       c.active_packages = {}
+
+       for path in glob.glob(os.path.join(c.name, '.matrix', '*.package')):
+               name = os.path.basename(path)[:-8]
+
+               pkg = parse_package(name, c, path)
+               if not pkg:
+                       continue
+
+               c.active_packages[name] = pkg
+               packages[name] = pkg
+
+               if config.debug:
+                       print 'Component', c.name, 'provides', name
+
+       if c.active_packages:
+               targets.append(c.name)
+       elif config.debug:
+               print 'Component', c.name, 'does not provide any packages'
+
+class Package:
+       def __init__(self, name, component):
+               self.name = name
+               self.component = component
+
+               self.depends = []
+               self.conflicts = []
+               self.architectures = None
+
+def parse_package(name, component, path):
+       pkg = Package(name, component)
+       execfile(path, pkg.__dict__, pkg.__dict__)
+
+       if pkg.architectures:
+               arch = config.boards[config.board].arch
+               if arch not in pkg.architectures:
+                       return None
+
+       return pkg
+
+def get_active_arch():
+       config.boards[config.board].arch
+
+def build_components(targets, build_jobs=1, make_jobs=1):
+       selected = set([config.components[i] for i in targets])
+
+       depends = None
+       while depends is None or depends:
+               depends = set()
+
+               for c in selected:
+                       for dep in c.active_depends:
+                               if dep not in selected:
+                                       depends.add(dep)
+
+               selected |= depends
+
+       components = list(selected)
+       components.sort()
+
+       if config.debug:
+               print 'Building components:'
+               for c in components:
+                       print '\t' + c.name
+
+       jobs = {}
+
+       while True:
+               found = False
+               for c in components:
+                       if len(jobs) >= build_jobs:
+                               break
+
+                       if component_buildable(c):
+                               found = True
+
+                               if not component_cached(c):
+                                       print 'Starting to build', c.name
+                                       start_job(c, jobs, make_jobs)
+                               else:
+                                       print c.name, 'found from cache'
+                                       c.active_state = 'built'
+
+               if not found and not jobs:
+                       for c in components:
+                               if c.active_state != 'built':
+                                       raise Error('Internal error')
+                       break
+
+               wait_for_job(jobs)
+
+def component_buildable(c):
+       if c.active_state:
+               if config.debug:
+                       print c.name, 'is in state:', c.active_state
+               return False
+
+       for dep in c.active_depends:
+               if config.components[dep.name].active_state != 'built':
+                       if config.debug:
+                               print c.name, 'depends on unbuilt', dep.name
+                       return False
+
+       return True
+
+def component_cached(c):
+       if c.from_platform:
+               return True
+
+       if git.ls_files(c.name, ['-m', '-d']):
+               raise Error('Component contains dirty files: ' + c.name)
+
+       path = os.path.join(config.cache_dir, c.name)
+       if not os.path.exists(path):
+               return False
+
+       file = open(path, 'r')
+       line = file.readline()
+       file.close()
+
+       match = re.match(r'([^\s]+)[\s]?([^\s]*)', line)
+       if not match:
+               return False
+
+       hash, flagstring = match.groups()
+
+       if hash != c.get_active_hash():
+               print 'Component has been changed:', c.name
+               return False
+
+       if flagstring:
+               flags = flagstring.split(',')
+       else:
+               flags = []
+
+       if set(flags) != set(c.flags):
+               print 'Component flags have been changed:', c.name
+               return False
+
+       return True
+
+def update_cache(c):
+       path = os.path.join(config.cache_dir, c.name)
+
+       dir = os.path.dirname(path)
+       if not os.path.exists(dir):
+               os.makedirs(dir)
+
+       file = open(path, 'w')
+       print >>file, c.get_active_hash(), ','.join(c.flags)
+       file.close()
+
+def start_job(c, jobs, make_jobs):
+       board = config.boards[config.board]
+
+       makefile = os.path.join(config.top_dir, 'scripts', 'matrix.mak')
+
+       args = ['make', '--no-print-directory', '-f', makefile, '-C', c.name,
+               '-j', str(make_jobs), 'build_matrix_component',
+               'MATRIX_TOPDIR='    + config.top_dir,
+               'MATRIX_COMPONENT=' + c.name,
+               'MATRIX_ARCH='      + board.arch,
+               'MATRIX_GCC_MARCH=' + board.gcc_march,
+               'MATRIX_GCC_MCPU='  + board.gcc_mcpu,
+               'MATRIX_GCC_MFPU='  + board.gcc_mfpu,
+               'MATRIX_GCC_OPTIONS=' + board.gcc_options,
+               'MATRIX_GNU_HOST='  + board.gnu_host,
+               'MATRIX_LIBC='      + config.libc]
+
+       for flag in config.flags:
+               args.append(flag + '=1')
+
+       if config.verbose:
+               args.append('MATRIX_VERBOSE=1')
+
+       if config.debug:
+               print 'Executing:', ' '.join(args)
+
+       pid = os.spawnvp(os.P_NOWAIT, args[0], args)
+
+       jobs[pid] = c
+       c.active_state = 'running'
+
+def wait_for_job(jobs):
+       if not jobs:
+               return
+
+       pid, status = os.wait()
+
+       c = jobs.get(pid)
+       if not c:
+               return
+
+       del jobs[pid]
+
+       if status == 0:
+               c.active_state = 'built'
+               update_cache(c)
+               print c.name, 'completed'
+       else:
+               c.active_state = 'error'
+               print >>sys.stderr, c.name, 'failed with status:', status
+
+               wait_for_job(jobs)
+               raise Error('Build failed')
+
+def clean_components(targets):
+       if not targets:
+               targets = config.components.keys()
+
+       for name in targets:
+               print 'Cleaning component:', name
+
+               files = git.ls_files(name, ['-o'])
+               paths = [os.path.join(name, i) for i in files]
+               paths.sort()
+               paths.reverse()
+
+               cache = os.path.join(config.cache_dir, name)
+               if os.path.exists(cache):
+                       paths.append(cache)
+
+               for path in paths:
+                       if config.debug:
+                               print 'Deleting', path
+
+                       if os.path.islink(path) or not os.path.isdir(path):
+                               os.remove(path)
+                       else:
+                               os.rmdir(path)
+
+               files = git.ls_files(name, ['-m', '-d'])
+               if files:
+                       print len(files), 'dirty files left in', name
+
+def pull_components(targets):
+       if not targets:
+               targets = config.components.keys()
+
+       for name in targets:
+               print 'Pulling component:', name
+               c = config.components[name]
+               git.pull(name)
+
+def source_dist_components(targets):
+       if not targets:
+               targets = config.components.keys()
+
+       for name in targets:
+               c = config.components[name]
+               generate_component_changes(c, 'dist')
+               package_component_sources(c, 'dist')
+
+def generate_component_changes(c, location):
+       print 'Generating component change log:', c.name
+
+       path = os.path.join(location, c.name) + '.changes'
+
+       pathdir = os.path.dirname(path)
+       if not os.path.exists(pathdir):
+               os.makedirs(pathdir)
+
+       fd = os.open(path, os.O_WRONLY | os.O_CREAT, 0644)
+       git.log(c.name, [c.get_active_tag()], fd=fd)
+       os.close(fd)
+
+def package_component_sources(c, location):
+       print 'Packaging component sources:', c.name
+
+       rev=git.describe(c.name)
+       if rev:
+               rev = '_'+rev
+       else:
+               rev = ''
+       path = os.path.join(location, c.name) + rev + '.tar.bz2'
+       if os.path.exists(path):
+               os.remove(path)
+
+       pathdir = os.path.dirname(path)
+       if not os.path.exists(pathdir):
+               os.makedirs(pathdir)
+
+       git.archive(c.name,path,
+                               prefix=os.path.basename(c.name)+'/',
+                               branch=c.get_active_tag())
+
+def build_rootfs(clean=True, rootfs_only=False, jffs2_only=False, devrootfs_only=False):
+       parse_config('rootfs')
+
+       f = os.popen('sb-conf cu')
+       target = f.read()
+       f.close()
+
+       rootfs = RootFS(target.strip())
+       rootfs.include_paths(config.include_paths)
+       rootfs.include_files(config.include_files)
+       rootfs.filter_paths(config.exclude_paths)
+       rootfs.filter_files(config.exclude_files)
+       rootfs.filter_expressions(config.exclude_expressions)
+       rootfs.add_paths(config.created_paths)
+       rootfs.set_devices(config.devices)
+       rootfs.set_change_owner(config.change_owner)
+       rootfs.set_erase_size(config.boards[config.board].flash_erase_size)
+       rootfs.set_pad_size(config.boards[config.board].flash_pad_size)
+
+       if rootfs_only:
+               rootfs.generate(clean, build_target="rootfs")
+       elif jffs2_only:
+               rootfs.generate(clean, build_target="jffs2")
+       elif devrootfs_only:
+               rootfs.generate(clean, build_target="devrootfs")
+       else:
+               rootfs.generate(clean, build_target="all")
diff --git a/mtxbld/rootfs.py b/mtxbld/rootfs.py
new file mode 100644 (file)
index 0000000..593c6ff
--- /dev/null
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2007-2008 Movial Oy
+# Authors: Kalle Vahlman <kalle.vahlman@movial.fi>
+
+import errno
+import os
+import re
+import shutil
+import sys
+
+class RootFS:
+       builddir = "/tmp"
+       target = None
+
+       # Tools
+       strip = "strip"
+       mknod = "fakeroot -i /tmp/env.faked -s /tmp/env.faked mknod"
+       chmod = "fakeroot -i /tmp/env.faked -s /tmp/env.faked chmod"
+       chown = "fakeroot -i /tmp/env.faked -s /tmp/env.faked chown"
+       mkfs = "fakeroot -i /tmp/env.faked -s /tmp/env.faked mkfs.jffs2"
+       tar = "fakeroot -i /tmp/env.faked -s /tmp/env.faked tar"
+       flash_erase_size = "0x4000"
+       flash_pad_size = "0x3e00000"
+
+       file_list = []
+       remove_list = []
+
+       created_paths = []
+       devices = {}
+       chown_owner = {}
+
+       def __init__(self, mytarget):
+               self.target = mytarget
+
+       def include_paths(self, paths):
+               old_dir = os.getcwd()
+               os.chdir("/targets")
+
+               # Traverse include_paths hierarchies and grab all files there
+               for path in paths:
+                       for root, dirs, files in os.walk(self.target + path):
+                               for f in files:
+                                       self.file_list.append("%s/%s" % (root, f))
+                               if len(files) == 0:
+                                       self.file_list.append(root)
+
+               os.chdir(old_dir)
+
+       def include_files(self, files):
+               old_dir = os.getcwd()
+               os.chdir("/targets")
+
+               # Append included individual files
+               for f in files:
+                       self.file_list.append(self.target + f)
+
+               os.chdir(old_dir)
+
+       def filter_paths(self, paths):
+               # Filter out files in exluded paths
+               for f in self.file_list:
+                       for d in paths:
+                               if f == self.target + d or f.startswith(self.target + d + '/'):
+                                       self.remove_list.append(f)
+
+       def filter_files(self, files):
+               # Filter out exluded files
+               for f in files:
+                       self.remove_list.append(self.target + f)
+
+       def filter_expressions(self, expressions):
+               # Filter out files matching exluded patterns
+               compiled_patterns = []
+               for pattern_str in expressions:
+                       compiled_patterns.append(re.compile(pattern_str))
+
+               for f in self.file_list:
+                       for pattern in compiled_patterns:
+                               if pattern.search(f):
+                                       self.remove_list.append(f)
+
+       def add_paths(self, paths):
+               for path in paths:
+                       self.created_paths.append(path)
+
+       def set_devices(self, devices):
+               self.devices = devices
+
+       def set_change_owner(self, change_owner):
+               self.change_owner= change_owner
+
+       def set_erase_size(self, size):
+               self.flash_erase_size = size
+
+       def set_pad_size(self, size):
+               self.flash_pad_size = size
+
+       def generate(self, clean, build_target="all"):
+               copy_list = self.file_list
+
+               for f in self.remove_list:
+                               try:
+                                       copy_list.remove(f)
+                               except:
+                                       pass
+
+               n_files = len(copy_list)*1.0
+               current_percent = 0.0
+               current_file = 0.0
+
+               old_dir = os.getcwd()
+               os.chdir("/targets")
+
+               if os.path.exists(os.path.join(self.builddir, self.target)):
+                       print "%s exists, please remove it and try again" % os.path.join(self.builddir, self.target)
+                       return
+
+               # Copy the wanted files, strip binaries
+               print "Copying files..."
+               for f in copy_list:
+                       if f[0] == '/':
+                               f = f[1:]
+                       path = os.path.join(self.builddir, os.path.dirname(f))
+                       try:
+                               os.makedirs(path)
+                       except OSError, e:
+                               if e.errno == errno.EEXIST:
+                                       pass
+
+                       if os.path.islink(f):
+                               link_dest = os.readlink(f)
+                               os.symlink(link_dest, os.path.join(self.builddir, f))
+                       elif os.path.isdir(f):
+                               try:
+                                       os.makedirs(os.path.join(self.builddir, f))
+                               except OSError, e:
+                                       if e.errno == errno.EEXIST:
+                                               pass
+                       else:
+                               shutil.copy(f, path)
+                               if not f.endswith(".ko"):
+                                       os.system(self.strip + " " + os.path.join(path,os.path.basename(f)) + " &> /dev/null")
+
+                       if (current_file/n_files)*100 > current_percent:
+                               current_percent += 10.0
+                               print "%0.1f%%" % current_percent,
+                               sys.stdout.flush()
+
+                       current_file += 1.0
+
+               # Create extra directory structure
+               print "\nCreating extra directories..."
+               for d in self.created_paths:
+                       if d[0] == '/':
+                               d = d[1:]
+                       path = os.path.join(self.builddir, self.target, d)
+                       try:
+                               os.makedirs(path)
+                       except OSError, e:
+                               if e.errno == errno.EEXIST:
+                                       pass
+
+               # Remove always the fakeroot environment.
+               if os.path.exists("/tmp/env.faked"):
+                       os.remove("/tmp/env.faked")
+               os.system("touch /tmp/env.faked")
+
+               # Create device nodes
+               print "Creating device nodes..."
+               for d in self.devices.keys():
+                       mode = "664"
+                       if len(self.devices[d]) == 3:
+                               device_type,major,minor = self.devices[d]
+                       else:
+                               device_type,major,minor,mode = self.devices[d]
+                       os.system("%s -m %s %s/%s/dev/%s %s %i %i" % (self.mknod, mode, self.builddir, self.target, d, device_type, major, minor))
+
+               # Fix permissions
+               print "Adjusting ownerships and permissions..."
+               # Make the whole fs root-owned
+               os.system("%s root.root -R %s/%s" % (self.chown, self.builddir, self.target))
+
+               # For sshd:
+               os.system("%s go-r %s/%s/etc/ssh*key*" % (self.chmod, self.builddir, self.target))
+
+               # For /var/empty (sshd requires this):
+               os.system("%s go-rw /%s/%s/var/empty" % (self.chmod, self.builddir, self.target))
+
+               # /dev/null needs to be writable by all:
+               os.system("%s a+rw /%s/%s/dev/null" % (self.chmod, self.builddir, self.target))
+
+               # Set non-root owners
+               print "Setting non-root owner ships..."
+               for d in self.change_owner.keys():
+                       dir = d
+                       if dir[0] == '/':
+                               dir = dir[1:]
+                       if os.path.exists(os.path.join(self.builddir, self.target, dir)):
+                               user,group = self.change_owner[d]
+                               os.system("%s %s.%s -R %s/%s/%s " % (self.chown, user, group, self.builddir, self.target, dir))
+
+               if build_target is "all" or build_target is "rootfs":
+                       print "Creating a rootfs..."
+                       os.system("%s -c --one-file-system -C %s/%s -z -f %s/%s.tgz ." % (self.tar, self.builddir, self.target, self.builddir, self.target))
+               if build_target is "all" or build_target is "jffs2":
+                       print "Creating a root image..."
+                       os.system("%s -p%s -n -e%s -r %s/%s -o %s/%s.jffs2" % (self.mkfs, self.flash_pad_size, self.flash_erase_size, self.builddir, self.target, self.builddir, self.target))
+               if build_target is "all" or build_target is "devrootfs":
+                       print "Creating a rootstrap..."
+                       os.system("%s -c --one-file-system -C /targets/%s -z -f %s/%s-rootstrap.tgz ." % ("tar", self.target, self.builddir, self.target))
+
+               os.chdir(old_dir)
+
+               print "Build finished:"
+               if build_target is "all" or build_target is "rootfs":
+                       s = os.stat(self.builddir + "/" + self.target + ".tgz");
+                       print "\t%s/%s.tgz\t%0.2f MiB" % (self.builddir, self.target, s.st_size/1024.0/1024.0)
+               if build_target is "all" or build_target is "jffs2":
+                       s = os.stat(self.builddir + "/" + self.target + ".jffs2");
+                       print "\t%s/%s.jffs2\t%0.2f MiB" % (self.builddir, self.target, s.st_size/1024.0/1024.0)
+               if build_target is "all" or build_target is "devrootfs":
+                       s = os.stat(self.builddir + "/" + self.target + "-rootstrap.tgz");
+                       print "\t%s/%s-rootstrap.tgz\t%0.2f MiB" % (self.builddir, self.target, s.st_size/1024.0/1024.0)
+
+               if clean:
+                       print "Cleaning up"
+                       os.remove("/tmp/env.faked")
+                       os.system("rm -rf %s/%s" % (self.builddir, self.target))
+
+
+#rootfs = RootFS("ROOTFS")
+#rootfs.include_paths(include_paths)
+#rootfs.include_files(include_files)
+#rootfs.filter_paths(exclude_paths)
+#rootfs.filter_files(exclude_files)
+#rootfs.filter_expressions(exclude_expressions)
+#rootfs.add_paths(created_paths)
+#rootfs.set_devices(devices)
+
+#rootfs.generate()
diff --git a/rootfs b/rootfs
new file mode 100644 (file)
index 0000000..15875f8
--- /dev/null
+++ b/rootfs
@@ -0,0 +1,93 @@
+# List of paths that will be copied (recursively)
+include_paths = [
+  "/bin",
+  "/sbin",
+  "/lib",
+  "/etc",
+  "/home",
+  "/usr/bin",
+  "/usr/sbin",
+  "/usr/lib",
+  "/usr/libexec",
+  "/usr/share/locale/en_GB",
+  "/usr/share/X11",
+  "/usr/share/fonts",
+  "/usr/share/hal",
+  "/usr/share/kilikali",
+  "/usr/share/themes",
+  "/usr/share/dbus-1",
+  "/usr/share/application-registry",
+  "/usr/share/applications",
+  "/usr/share/pixmaps",
+  "/usr/share/icons",
+  "/usr/share/scim/icons",
+  "/usr/share/matchbox",
+  "/usr/share/matchbox-keyboard",
+  "/usr/share/matchbox-panel/battery",
+  "/usr/share/gnome",
+  "/usr/share/gnome-volume-manager",
+  "/usr/share/mime-info",
+  "/usr/share/nm-applet",
+  "/usr/share/alsa"
+]
+
+# List of individual files that will be copied
+include_files = [
+  "/usr/share/usb.ids",
+  "/usr/share/terminfo/x/xterm"
+]      
+
+# List of paths that will be filtered out from the copied dirs
+exclude_paths = [
+  "/usr/lib/pkgconfig",
+# The gconv dir in gconv dir is a bug. This is fixed in new SB toolchains.
+  "/usr/lib/gconv/gconv",
+  "/var/run/NetworkManager",
+  "/usr/lib/xulrunner-devel-1.9a9pre"
+]
+
+# List of individual files that will be filtered out from the copy
+exclude_files = [
+       "/usr/share/hal/fdi/preprobe/20thirdparty/10-nfsroot.fdi"
+]
+
+# List of regular expressions that will cause the matched files to be filtered out
+exclude_expressions = [
+  ".*\.l?a$"
+]
+
+# List of paths that will be created as empty directories (with parents if needed)
+created_paths = [
+  "/boot",
+  "/dev/pts",
+  "/lib",
+  "/media",
+  "/mnt",
+  "/proc",
+  "/root",
+  "/sbin",
+  "/home",
+  "/sys",
+  "/tmp",
+  "/var/empty",
+  "/var/run/sshd",
+  "/var/run/NetworkManager",
+  "/var/state/dhcp"
+]
+
+# List of directories to be chowned to (user,group).
+change_owner = {
+  "/home/aeki": ("10042", "10042")
+}
+
+# List of device nodes to be created
+devices = {
+  "console" : ("c", 5, 1),
+  "null"    : ("c", 1, 3),
+  "random"  : ("c", 1, 8),
+  "urandom" : ("c", 1, 9),
+  "tty0"    : ("c", 4, 0),
+  "tty1"    : ("c", 4, 1),
+  "tty2"    : ("c", 4, 2),
+  "tty3"    : ("c", 4, 3)
+}
diff --git a/scripts/matrix-autotools.mak b/scripts/matrix-autotools.mak
new file mode 100644 (file)
index 0000000..8495652
--- /dev/null
@@ -0,0 +1,88 @@
+# Copyright (C) 2006-2008 Movial Oy
+# Authors: Lauri Leukkunen
+#          Kalle Vahlman <kalle.vahlman@movial.fi>
+#
+# Provides the necessary targets to build a component using
+# standard autotools in the normal 
+# autogen.sh + configure + make + make install way.
+
+__MATRIX_BUILD_STYLE_LOADED=1
+
+include $(MATRIX_TOPDIR)/scripts/matrix-common.mak
+
+t := $(shell if [ -d /usr/share/aclocal ]; then echo yes; else echo no; fi)
+ifeq (yes,$(t))
+ACLOCAL_ARGS := -I /usr/share/aclocal $(ACLOCAL_ARGS)
+endif
+
+ACLOCAL := aclocal $(ACLOCAL_ARGS)
+PKG_CONFIG_PATH := /usr/lib/pkgconfig:/usr/share/pkgconfig:$(PKG_CONFIG_PATH)
+
+export ACLOCAL PKG_CONFIG_PATH
+
+has_configure := $(shell if [ -e ./configure ]; then echo "yes"; else echo "no"; fi)
+
+ifdef no-docs
+MATRIX_CONFIG_FLAGS += --disable-gtk-doc --disable-xml-docs --disable-doxygen-docs --disable-docbook --disable-docs
+endif
+
+ifdef no-examples
+MATRIX_CONFIG_FLAGS += --disable-demos --disable-examples
+endif
+
+ifdef no-tests
+MATRIX_CONFIG_FLAGS += --disable-tests
+endif
+
+ifdef debug
+MATRIX_CONFIG_FLAGS += --enable-debug
+else
+MATRIX_CONFIG_FLAGS += --disable-debug
+endif
+
+ifndef MATRIX_CONFIGURE_ARGS
+MATRIX_CONFIGURE_ARGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
+                        $(MATRIX_CONFIG_FLAGS) \
+                        $(MATRIX_CONFIGURE_EXTRA_ARGS)
+endif
+
+ifneq ($(has_configure),yes)
+MATRIX_AUTOGEN = __autogen
+else
+MATRIX_AUTOGEN = 
+endif
+
+__matrix_build: $(MATRIX_PREPARE_TARGET) $(MATRIX_AUTOGEN) __configure __build  __install_pre_lock
+       @echo "[$(MATRIX_COMPONENT)] Build completed"
+
+__autogen: $(MATRIX_PREPARE_TARGET)
+       @$(MATRIX_AUTOGEN_ENV) ./autogen.sh $(MATRIX_AUTOGEN_ARGS)
+
+__configure: $(MATRIX_AUTOGEN)
+ifdef MATRIX_OBJ_DIR
+       rm -rf $(MATRIX_OBJ_DIR)
+       mkdir -p $(MATRIX_OBJ_DIR)
+       @cd $(MATRIX_OBJ_DIR) && $(MATRIX_CONFIGURE_ENV) $(MATRIX_TOPDIR)/$(MATRIX_COMPONENT)/configure --build=$(MATRIX_AUTOTOOLS_BUILD_ARCH) --host=$(MATRIX_AUTOTOOLS_HOST_ARCH) $(MATRIX_CONFIGURE_ARGS)
+else   
+       @$(MATRIX_CONFIGURE_ENV) $(CCTOOL_BUILD) ./configure $(MATRIX_CONFIGURE_ARGS)
+endif
+
+__build: __configure
+ifdef MATRIX_OBJ_DIR
+       @cd $(MATRIX_OBJ_DIR) && $(MATRIX_BUILD_ENV) $(CCTOOL_BUILD) $(MAKE) $(MATRIX_BUILD_ARGS)
+else
+       @$(MATRIX_BUILD_ENV) $(CCTOOL_BUILD) $(MAKE) $(MATRIX_BUILD_ARGS)
+endif
+
+
+# this can't have any requisites as that would trigger a rebuild
+# __install_pre_lock depends on __build so we're safe here
+
+__install_post_lock:
+ifdef MATRIX_OBJ_DIR
+       @cd $(MATRIX_OBJ_DIR) && $(MATRIX_INSTALL_ENV) $(CCTOOL_INSTALL) $(MAKE) install $(MATRIX_INSTALL_ARGS)
+else
+       @$(MATRIX_INSTALL_ENV) $(CCTOOL_INSTALL) $(MAKE) install $(MATRIX_INSTALL_ARGS)
+endif
+
+
diff --git a/scripts/matrix-common.mak b/scripts/matrix-common.mak
new file mode 100644 (file)
index 0000000..6a8fa33
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright (C) 2006-2008 Movial Oy
+# Authors: Lauri Leukkunen
+#
+# This provides the necessary stuff to guarantee synchronization
+# of component "install" target execution.
+
+MATRIX_INSTALL_LOCK_FILE = $(MATRIX_TOPDIR)/.matrix-install.lock
+
+# re-run make with install lock
+__install_pre_lock: __build
+       if [ ! -e $(MATRIX_INSTALL_LOCK_FILE) ]; then touch $(MATRIX_INSTALL_LOCK_FILE); fi
+       flock $(MATRIX_INSTALL_LOCK_FILE) $(MAKE) -f $(MATRIX_TOPDIR)/scripts/matrix.mak __locked_install
+
+__locked_install:
+       touch $(MATRIX_INSTALL_LOCK_FILE)
+       $(MAKE) -f $(MATRIX_TOPDIR)/scripts/matrix.mak __install_post_lock
+       # generate installed files list
+       #find /targets/$$(sb-conf current) -cnewer $(MATRIX_INSTALL_LOCK_FILE) | sed "s/\/targets\/$$(sb-conf current)//" > .matrix/installed_files
+
diff --git a/scripts/matrix-custom.mak b/scripts/matrix-custom.mak
new file mode 100644 (file)
index 0000000..bae37f4
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright (C) 2006-2008 Movial Oy
+# Authors: Lauri Leukkunen
+
+
+__MATRIX_BUILD_STYLE_LOADED=1
+
+.PHONY: configure build install __configure __build
+
+include $(MATRIX_TOPDIR)/scripts/matrix-common.mak
+
+__matrix_build: __configure __build __install_pre_lock
+
+__configure: configure
+       @$(CCTOOL_BUILD) $(MAKE) -f .matrix/plug configure
+
+__build: __configure build
+       @$(CCTOOL_BUILD) $(MAKE) -f .matrix/plug build
+
+# this can't have any requisites as that would trigger a rebuild
+# __install_pre_lock depends on __build so we're safe here
+__install_post_lock:
+       @$(matrix_install_lock) $(CCTOOL_INSTALL) $(MAKE) -f .matrix/plug install
+
diff --git a/scripts/matrix.mak b/scripts/matrix.mak
new file mode 100644 (file)
index 0000000..7c2d4ed
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (C) 2006-2008 Movial Oy
+# Authors: Lauri Leukkunen
+#          Kalle Vahlman <kalle.vahlman@movial.fi>
+#          Tuomas Kulve <tuomas.kulve@movial.fi>
+#
+# This is the interface from mtxbld to component's own
+# build system. mtxbld runs this file like this:
+# make -f $MATRIX_TOPDIR/scripts/matrix.mak \
+#  -C core/glibc MATRIX_COMPONENT=core/glibc MATRIX_COMPONENT_TAG="2.5" \
+#  flag1=1 flag2=1 flag3=1 flag4=1 build_matrix_component
+
+#CCTOOL_INSTALL=sb2 -e
+#CCTOOL_BUILD=sb2
+
+
+ifdef MATRIX_DEBUG
+MATRIX_MAK_DEBUG = matrix_mak_debug
+else
+MATRIX_MAK_DEBUG =
+endif
+
+include .matrix/plug
+
+ifeq ("$(MATRIX_COMPILER_OPTIONS)","")
+
+ifneq ("$(MATRIX_GCC_OPTIONS)","")
+MATRIX_COMPILER_OPTIONS = $(MATRIX_GCC_OPTIONS)
+endif
+
+ifneq ("$(MATRIX_GCC_MCPU)","")
+MATRIX_COMPILER_OPTIONS += -mcpu=$(MATRIX_GCC_MCPU)
+endif
+
+ifneq ("$(MATRIX_GCC_MFPU)","")
+MATRIX_COMPILER_OPTIONS += -mfpu=$(MATRIX_GCC_MFPU)
+endif
+
+endif
+
+ifneq ("$(MATRIX_COMPILER_EXTRA_OPTIONS)","")
+MATRIX_COMPILER_OPTIONS += $(MATRIX_COMPILER_EXTRA_OPTIONS)
+endif
+
+SBOX_EXTRA_CROSS_COMPILER_ARGS = -march=$(MATRIX_GCC_MARCH)
+
+ifneq ("$(MATRIX_COMPILER_OPTIONS)","")
+SBOX_EXTRA_CROSS_COMPILER_ARGS += $(MATRIX_COMPILER_OPTIONS)
+endif
+
+export SBOX_EXTRA_CROSS_COMPILER_ARGS
+
+ifeq ("$(MATRIX_BUILD_STYLE)", "autotools")
+include $(MATRIX_TOPDIR)/scripts/matrix-autotools.mak
+endif
+ifeq ("$(MATRIX_BUILD_STYLE)", "custom")
+include $(MATRIX_TOPDIR)/scripts/matrix-custom.mak
+endif
+
+ifndef __MATRIX_BUILD_STYLE_LOADED
+$(error "MATRIX_BUILD_STYLE not set, valid values are: autotools custom")
+endif
+
+# __matrix_build is defined in the included build style
+build_matrix_component: 
+ifdef MATRIX_VERBOSE
+       @$(MAKE) $(MATRIX_MAK_DEBUG) -f $(MATRIX_TOPDIR)/scripts/matrix.mak __matrix_build
+else
+       @$(MAKE) $(MATRIX_MAK_DEBUG) -f $(MATRIX_TOPDIR)/scripts/matrix.mak __matrix_build > .matrix/build.log 2>&1 
+endif
+
+
+matrix_mak_debug:
+       @echo MATRIX_TOPDIR=$(MATRIX_TOPDIR)
+       @echo MATRIX_COMPONENT=$(MATRIX_COMPONENT)
+       @echo MATRIX_COMPONENT_TAG=$(MATRIX_COMPONENT_TAG)
diff --git a/scripts/matrixify.sh b/scripts/matrixify.sh
new file mode 100755 (executable)
index 0000000..bbc02e7
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -e
+
+branch="matrix"
+tag="$1"
+name="xorg-$(basename $PWD)"
+
+git checkout -b $branch $tag
+
+mkdir .matrix
+echo "MATRIX_BUILD_STYLE=autotools" > .matrix/plug
+echo "depends=\"@xorg-protos\"" > .matrix/$name.package
+echo "conflicts=\"\"" >> .matrix/$name.package
+echo "description=\"\"" >> .matrix/$name.package
+
+git add .matrix/plug .matrix/$name.package
+git commit -m "* matrixify"
+
+echo "{\"X/lib/$(basename $PWD)\", \"matrix\", repos .. \"/X/lib/$(basename $PWD)\"},"